use std::io::{self, Write};
use serde::Serialize;
use ssb_json_msg_data::json;
use super::super::{Content, Message};
#[derive(Debug)]
pub enum EncodeJsonError {
Io(io::Error),
Content(json::EncodeJsonError),
}
impl From<io::Error> for EncodeJsonError {
fn from(e: io::Error) -> EncodeJsonError {
EncodeJsonError::Io(e)
}
}
impl From<json::EncodeJsonError> for EncodeJsonError {
fn from(e: json::EncodeJsonError) -> EncodeJsonError {
EncodeJsonError::Content(e)
}
}
pub fn to_legacy<W, T>(msg: &Message<T>, w: &mut W, compact: bool) -> Result<(), EncodeJsonError>
where
W: Write,
T: Serialize,
{
w.write_all(b"{")?;
ws(w, compact)?;
write_key("previous", w, compact)?;
match msg.previous {
None => w.write_all(b"null")?,
Some(ref mh) => {
quote(w)?;
mh.to_legacy(w)?;
quote(w)?;
}
}
end_entry(w, compact)?;
if msg.swapped {
write_key("sequence", w, compact)?;
json::to_writer(w, &msg.sequence, compact)?;
entry("author", w, compact)?;
quote(w)?;
msg.author.to_legacy(w)?;
quote(w)?;
} else {
write_key("author", w, compact)?;
quote(w)?;
msg.author.to_legacy(w)?;
quote(w)?;
entry("sequence", w, compact)?;
json::to_writer(w, &msg.sequence, compact)?;
}
entry("timestamp", w, compact)?;
json::to_writer(w, &msg.timestamp, compact)?;
entry("hash", w, compact)?;
w.write_all(b"\"sha256\"")?;
entry("content", w, compact)?;
match msg.content {
Content::Encrypted(ref mb) => {
quote(w)?;
mb.to_legacy(w)?;
quote(w)?;
}
Content::Plain(ref t) => json::to_writer_indent(w, t, compact, 1)?,
}
if msg.signature.is_some() {
entry("signature", w, compact)?;
quote(w)?;
msg.signature.as_ref().unwrap().to_legacy(w)?;
quote(w)?;
}
w.write_all(b"\n}")?;
Ok(())
}
pub fn to_legacy_vec<T: Serialize>(
msg: &Message<T>,
compact: bool,
) -> Result<Vec<u8>, EncodeJsonError> {
let mut out = Vec::with_capacity(256);
to_legacy(msg, &mut out, compact)?;
Ok(out)
}
pub fn to_legacy_string<T: Serialize>(
msg: &Message<T>,
compact: bool,
) -> Result<String, EncodeJsonError> {
Ok(unsafe { String::from_utf8_unchecked(to_legacy_vec(msg, compact)?) })
}
fn ws<W: Write>(w: &mut W, compact: bool) -> Result<(), io::Error> {
if !compact {
w.write_all(b"\n ")?;
}
Ok(())
}
fn write_key<W: Write>(key: &str, w: &mut W, compact: bool) -> Result<(), io::Error> {
w.write_all(b"\"")?;
w.write_all(key.as_bytes())?;
w.write_all(b"\":")?;
if !compact {
w.write_all(b" ")?;
}
Ok(())
}
fn end_entry<W: Write>(w: &mut W, compact: bool) -> Result<(), io::Error> {
w.write_all(b",")?;
ws(w, compact)
}
fn entry<W: Write>(key: &str, w: &mut W, compact: bool) -> Result<(), io::Error> {
end_entry(w, compact)?;
write_key(key, w, compact)
}
fn quote<W: Write>(w: &mut W) -> Result<(), io::Error> {
w.write_all(b"\"")
}