use crate::stream::TlvStream;
use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
impl Serialize for TlvStream {
fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
let bytes = self.to_bytes().map_err(serde::ser::Error::custom)?;
serializer.serialize_str(&hex::encode(bytes))
}
}
impl<'de> Deserialize<'de> for TlvStream {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> std::result::Result<Self, D::Error> {
struct V;
impl<'de> serde::de::Visitor<'de> for V {
type Value = TlvStream;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "a hex string representing a Lightning TLV stream")
}
fn visit_str<E: DeError>(self, s: &str) -> std::result::Result<Self::Value, E> {
let bytes = hex::decode(s).map_err(E::custom)?;
TlvStream::from_bytes(&bytes).map_err(E::custom)
}
}
deserializer.deserialize_str(V)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::stream::TlvRecord;
fn rec(type_: u64, value: &[u8]) -> TlvRecord {
TlvRecord {
type_,
value: value.to_vec(),
}
}
#[test]
fn json_hex_roundtrip() {
let stream = TlvStream::from(vec![rec(1, &[0x01, 0x02]), rec(5, &[0xaa])]);
let json = serde_json::to_string(&stream).unwrap();
let s: String = serde_json::from_str(&json).unwrap();
assert_eq!(s, "010201020501aa");
let back: TlvStream = serde_json::from_str(&json).unwrap();
assert_eq!(back.len(), 2);
let recs: Vec<_> = back.iter().collect();
assert_eq!(recs[0].type_, 1);
assert_eq!(recs[0].value, vec![0x01, 0x02]);
assert_eq!(recs[1].type_, 5);
assert_eq!(recs[1].value, vec![0xaa]);
}
#[test]
fn tu64_multi_roundtrip_json() {
let mut s = TlvStream::default();
s.set_tu64(42, 0);
s.set_tu64(7, 256);
let json = serde_json::to_string(&s).unwrap();
let s2: TlvStream = serde_json::from_str(&json).unwrap();
assert_eq!(s2.get_tu64(42).unwrap(), Some(0));
assert_eq!(s2.get_tu64(7).unwrap(), Some(256));
}
}