use std::borrow::Cow;
use std::collections::BTreeMap;
use deser::adapters::{As, Borrowed};
use deser::adapters::{Base64Url, BytesEncoding, BytesFallback, IntSeq};
use deser::de::{DeserializeDriver, DeserializeOwned};
use deser::ser::SerializeDriver;
use deser::{Atom, BytesFormat, Deserialize, Error, ErrorKind, Event, Serialize};
fn without_len(event: deser::Event<'static>) -> deser::Event<'static> {
match event {
deser::Event::MapStart(shape) => {
deser::Event::MapStart(deser::ContainerShape::new().with_order(shape.order()))
}
deser::Event::SeqStart(shape) => {
deser::Event::SeqStart(deser::ContainerShape::new().with_order(shape.order()))
}
event => event,
}
}
fn deserialize<T: DeserializeOwned>(events: Vec<Event<'_>>) -> Result<T, Error> {
deserialize_with(events, None)
}
fn deserialize_with<T: DeserializeOwned>(
events: Vec<Event<'_>>,
format: Option<BytesFormat>,
) -> Result<T, Error> {
let mut out = None;
{
let mut driver = DeserializeDriver::new(&mut out);
if let Some(format) = format {
format.set(driver.state_mut());
}
for event in events {
driver.emit(event)?;
}
}
Ok(out.unwrap())
}
fn serialize(value: &dyn Serialize) -> Vec<(Event<'static>, Option<BytesFormat>)> {
let mut events = Vec::new();
SerializeDriver::new(value)
.drive(|event, _| {
let (event, format) = match event {
Event::Atom(Atom::Bytes(bytes)) => {
let format = bytes.fallback.copied();
(
Event::Atom(Atom::Bytes(deser::Bytes::new(bytes.into_data()))),
format,
)
}
event => (event, None),
};
events.push((without_len(event.to_static()), format));
Ok(())
})
.unwrap();
events
}
struct Dotted;
impl BytesEncoding for Dotted {
const NAME: &'static str = "dotted";
fn encode(bytes: &[u8], out: &mut String) {
let parts = bytes.iter().map(|x| x.to_string()).collect::<Vec<_>>();
out.push_str(&parts.join("."));
}
fn decode(s: &str) -> Result<Vec<u8>, Error> {
s.split('.')
.map(|x| {
x.parse()
.map_err(|_| Error::new(ErrorKind::Unexpected, "invalid byte"))
})
.collect()
}
}
fn bytes(value: &[u8]) -> Event<'static> {
Event::Atom(Atom::Bytes(deser::Bytes::new(Cow::Owned(value.to_vec()))))
}
#[test]
fn test_bytes_from_strings() {
let value: Vec<u8> = deserialize(vec!["Af8=".into()]).unwrap();
assert_eq!(value, [1, 255]);
let value: Vec<u8> = deserialize(vec!["-_8".into()]).unwrap();
assert_eq!(value, [251, 255]);
let value: [u8; 2] = deserialize(vec!["Af8".into()]).unwrap();
assert_eq!(value, [1, 255]);
let value: Cow<'static, [u8]> = deserialize(vec!["Af8=".into()]).unwrap();
assert_eq!(&*value, [1, 255]);
let value: Option<Vec<u8>> = deserialize(vec!["".into()]).unwrap();
assert_eq!(value, Some(vec![]));
let value: Vec<u8> = deserialize(vec![
Event::seq_start(),
1u64.into(),
255u64.into(),
Event::SeqEnd,
])
.unwrap();
assert_eq!(value, [1, 255]);
let err = deserialize::<Vec<u8>>(vec!["A".into()]).unwrap_err();
assert_eq!(err.to_string(), "Unexpected: invalid base64 string");
let err = deserialize::<[u8; 3]>(vec!["Af8=".into()]).unwrap_err();
assert_eq!(err.kind(), ErrorKind::WrongLength);
assert!(deserialize::<Vec<u16>>(vec!["Af8=".into()]).is_err());
assert!(deserialize::<[u16; 2]>(vec!["Af8=".into()]).is_err());
let mut out = None::<&[u8]>;
let mut driver = DeserializeDriver::new(&mut out);
let err = driver.emit_borrowed("Af8=").unwrap_err();
assert!(err.to_string().contains("cannot be borrowed"));
}
#[test]
fn test_borrowed_bytes_from_strings() {
let mut out = None::<As<Cow<[u8]>, Borrowed>>;
{
let mut driver = DeserializeDriver::new(&mut out);
driver.emit_borrowed("Af8=").unwrap();
}
assert_eq!(&**out.unwrap(), [1, 255]);
}
#[test]
fn test_bytes_format_in_state() {
let dotted = Some(BytesFormat::encoded::<Dotted>());
let value: Vec<u8> = deserialize_with(vec!["1.255".into()], dotted).unwrap();
assert_eq!(value, [1, 255]);
let value: [u8; 2] = deserialize_with(vec!["1.255".into()], dotted).unwrap();
assert_eq!(value, [1, 255]);
let value: Cow<'static, [u8]> = deserialize_with(vec!["1.255".into()], dotted).unwrap();
assert_eq!(&*value, [1, 255]);
let value: Vec<u8> = deserialize_with(vec!["Af8=".into()], Some(BytesFormat::SEQ)).unwrap();
assert_eq!(value, [1, 255]);
let value: As<Vec<u8>, Base64Url> = deserialize_with(vec!["Af8".into()], dotted).unwrap();
assert_eq!(*value, [1, 255]);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Blob {
plain: Vec<u8>,
#[deser(as = BytesFallback<Dotted>)]
array: [u8; 2],
#[deser(as = BytesFallback<Dotted>)]
encoded: Vec<u8>,
#[deser(as = Dotted)]
forced: Vec<u8>,
#[deser(as = BytesFallback<IntSeq>)]
seq: Vec<u8>,
#[deser(as = Option<BytesFallback<Dotted>>)]
optional: Option<Vec<u8>>,
#[deser(as = Vec<BytesFallback<Dotted>>)]
many: Vec<Vec<u8>>,
#[deser(as = BTreeMap<BytesFallback<Dotted>, _>)]
keys: BTreeMap<Vec<u8>, u32>,
#[deser(as = BytesFallback<Dotted>)]
cow: Cow<'static, [u8]>,
#[deser(as = Option<Dotted>)]
forced_optional: Option<[u8; 1]>,
#[deser(as = Dotted)]
forced_cow: Cow<'static, [u8]>,
}
fn blob() -> Blob {
Blob {
plain: vec![1],
array: [2, 3],
encoded: vec![4],
forced: vec![5],
seq: vec![6],
optional: Some(vec![7]),
many: vec![vec![8]],
keys: [(vec![9], 10)].into_iter().collect(),
cow: Cow::Borrowed(&[11]),
forced_optional: Some([12]),
forced_cow: Cow::Borrowed(&[13]),
}
}
#[test]
fn test_adapters_serialize() {
let dotted = Some(BytesFormat::encoded::<Dotted>());
let seq = Some(BytesFormat::SEQ);
let events = serialize(&blob());
let expected = vec![
(Event::map_start(), None),
("plain".into(), None),
(bytes(&[1]), None),
("array".into(), None),
(bytes(&[2, 3]), dotted),
("encoded".into(), None),
(bytes(&[4]), dotted),
("forced".into(), None),
("5".into(), None),
("seq".into(), None),
(bytes(&[6]), seq),
("optional".into(), None),
(bytes(&[7]), dotted),
("many".into(), None),
(Event::seq_start(), None),
(bytes(&[8]), dotted),
(Event::SeqEnd, None),
("keys".into(), None),
(
Event::MapStart(deser::ContainerShape::new().with_order(deser::Order::Sorted)),
None,
),
(bytes(&[9]), dotted),
(10u64.into(), None),
(Event::MapEnd, None),
("cow".into(), None),
(bytes(&[11]), dotted),
("forced_optional".into(), None),
("12".into(), None),
("forced_cow".into(), None),
("13".into(), None),
(Event::MapEnd, None),
];
assert_eq!(events, expected);
}
#[test]
fn test_adapters_deserialize() {
let events = serialize(&blob())
.into_iter()
.map(|(event, _)| event)
.collect::<Vec<_>>();
assert_eq!(deserialize::<Blob>(events).unwrap(), blob());
let events = vec![
Event::map_start(),
"plain".into(),
"AQ==".into(),
"array".into(),
"2.3".into(),
"encoded".into(),
"4".into(),
"forced".into(),
"5".into(),
"seq".into(),
Event::seq_start(),
6u64.into(),
Event::SeqEnd,
"optional".into(),
"7".into(),
"many".into(),
Event::seq_start(),
"8".into(),
Event::SeqEnd,
"keys".into(),
Event::map_start(),
"9".into(),
10u64.into(),
Event::MapEnd,
"cow".into(),
"11".into(),
"forced_optional".into(),
"12".into(),
"forced_cow".into(),
"13".into(),
Event::MapEnd,
];
assert_eq!(deserialize::<Blob>(events).unwrap(), blob());
let err = deserialize::<As<[u8; 2], Dotted>>(vec!["x".into()]).unwrap_err();
assert_eq!(err.to_string(), "Unexpected: invalid byte");
let err = deserialize::<As<[u8; 2], Dotted>>(vec!["1".into()]).unwrap_err();
assert_eq!(err.kind(), ErrorKind::WrongLength);
let err = deserialize::<As<Vec<u8>, Dotted>>(vec![1u64.into()]).unwrap_err();
assert_eq!(
err.to_string(),
"Unexpected: unexpected unsigned integer, expected bytes or dotted string"
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Custom {
#[deser(as = BytesFallback<Dotted>)]
hint: Vec<u8>,
#[deser(as = Dotted)]
forced: Vec<u8>,
}
#[test]
fn test_custom_encoding() {
let value = Custom {
hint: vec![1, 2],
forced: vec![3, 4],
};
let events = serialize(&value);
assert_eq!(events[2].1, Some(BytesFormat::encoded::<Dotted>()));
assert_eq!(events[2].1.unwrap().name(), "dotted");
assert_eq!(events[4].0, "3.4".into());
let value: Custom = deserialize(vec![
Event::map_start(),
"hint".into(),
"1.2".into(),
"forced".into(),
"3.4".into(),
Event::MapEnd,
])
.unwrap();
assert_eq!(value.hint, [1, 2]);
assert_eq!(value.forced, [3, 4]);
}