//! A batch as the coordinator takes it (lib/edge/wire.ts toWire): JSON with //! the TypeScript names, chunk payloads in base64. use crate::indexer::{Batch, Candidate, ReleaseChunk}; use base64::Engine; use serde::Serialize; #[derive(Serialize)] #[serde(rename_all = "camelCase")] struct WireRelease<'a> { key: &'a str, upload: usize, name: &'a str, source: &'a str, file_total: Option, poster: &'a str, groups: &'a [String], posted_at: Option, posted_last: Option, files: usize, segments: usize, bytes: i64, first_article: i64, last_article: i64, readable: bool, has_par2: bool, finished: bool, edge: bool, partial: bool, payload: String, #[serde(skip_serializing_if = "Option::is_none")] rule: Option<&'a str>, #[serde(skip_serializing_if = "Option::is_none")] rule_key: Option<&'a str>, } #[derive(Serialize)] #[serde(rename_all = "camelCase")] struct WireCandidate<'a> { release_key: &'a str, upload: usize, kind: &'a str, message_id: &'a str, file: &'a str, } #[derive(Serialize)] struct WireCount<'a> { rule: &'a str, key: &'a str, articles: u64, files: u64, } #[derive(Serialize)] #[serde(rename_all = "camelCase")] struct WireBatch<'a> { from: i64, next: i64, headers: u64, posted_low: Option, posted_high: Option, releases: Vec>, samples: Vec>, candidates: Vec>, counts: Vec>, } fn release<'a>(r: &'a ReleaseChunk, rule: Option<(&'a str, &'a str)>) -> WireRelease<'a> { WireRelease { key: &r.key, upload: r.upload, name: &r.name, source: r.source, file_total: r.file_total, poster: &r.poster, groups: &r.groups, posted_at: r.posted_at, posted_last: r.posted_last, files: r.files, segments: r.segments, bytes: r.bytes, first_article: r.first_article, last_article: r.last_article, readable: r.readable, has_par2: r.has_par2, finished: r.finished, edge: r.edge, partial: r.partial, payload: base64::engine::general_purpose::STANDARD.encode(&r.payload), rule: rule.map(|(rule, _)| rule), rule_key: rule.map(|(_, key)| key), } } fn candidate(c: &Candidate) -> WireCandidate<'_> { WireCandidate { release_key: &c.release_key, upload: c.upload, kind: c.kind, message_id: &c.message_id, file: &c.file } } /// toWire(batch) as JSON bytes. pub fn to_json(batch: &Batch) -> Vec { let wire = WireBatch { from: batch.from, next: batch.next, headers: batch.headers, posted_low: batch.posted_low, posted_high: batch.posted_high, releases: batch.releases.iter().map(|r| release(r, None)).collect(), samples: batch.samples.iter().map(|(r, rule, key)| release(r, Some((rule, key.as_str())))).collect(), candidates: batch.candidates.iter().map(candidate).collect(), counts: batch.counts.iter().map(|(rule, key, articles, files)| WireCount { rule, key, articles: *articles, files: *files }).collect(), }; serde_json::to_vec(&wire).unwrap() }