#![allow(missing_docs)]
#[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq)]
struct Payload {
name: String,
#[serde(with = "serde_bytes")]
body: Vec<u8>,
}
#[test]
fn vec_u8_with_serde_bytes_roundtrips_via_binary() {
let original = Payload {
name: "snapshot".into(),
body: vec![0x00, 0x01, 0x02, 0xfe, 0xff, 0x80, 0x7f],
};
let yaml = noyalib::to_string(&original).unwrap();
assert!(
yaml.contains("!!binary"),
"expected !!binary tag in emitted YAML, got: {yaml}"
);
let round: Payload = noyalib::from_str(&yaml).unwrap();
assert_eq!(round, original);
}
#[test]
fn byte_buf_roundtrips_via_binary() {
use serde_bytes::ByteBuf;
#[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq)]
struct Wrapper {
data: ByteBuf,
}
let original = Wrapper {
data: ByteBuf::from(b"Hello, World!".to_vec()),
};
let yaml = noyalib::to_string(&original).unwrap();
assert!(yaml.contains("!!binary"));
assert!(
yaml.contains("SGVsbG8sIFdvcmxkIQ=="),
"expected base64 of \"Hello, World!\" in: {yaml}"
);
let round: Wrapper = noyalib::from_str(&yaml).unwrap();
assert_eq!(round, original);
}
#[test]
fn empty_byte_buf_roundtrips() {
use serde_bytes::ByteBuf;
#[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq)]
struct Wrapper {
data: ByteBuf,
}
let original = Wrapper {
data: ByteBuf::new(),
};
let yaml = noyalib::to_string(&original).unwrap();
let round: Wrapper = noyalib::from_str(&yaml).unwrap();
assert_eq!(round, original);
}
#[test]
fn deserialize_handwritten_binary_scalar() {
let yaml = "\
name: snapshot
body: !!binary |
SGVsbG8s
IFdvcmxk
IQ==
";
let p: Payload = noyalib::from_str(yaml).unwrap();
assert_eq!(p.name, "snapshot");
assert_eq!(p.body, b"Hello, World!");
}
#[test]
fn deserialize_inline_binary_scalar() {
let yaml = "\
name: snapshot
body: !!binary SGVsbG8sIFdvcmxkIQ==
";
let p: Payload = noyalib::from_str(yaml).unwrap();
assert_eq!(p.body, b"Hello, World!");
}
#[test]
fn deserialize_quoted_binary_scalar() {
let yaml = "\
name: snapshot
body: !!binary \"SGVsbG8sIFdvcmxkIQ==\"
";
let p: Payload = noyalib::from_str(yaml).unwrap();
assert_eq!(p.body, b"Hello, World!");
}
#[test]
fn deserialize_rejects_invalid_base64() {
let yaml = "\
name: snapshot
body: !!binary \"this is not base64\"
";
let res: Result<Payload, _> = noyalib::from_str(yaml);
assert!(
res.is_err(),
"non-base64 !!binary content must be a deserialize error"
);
}
#[test]
fn full_byte_range_roundtrips() {
use serde_bytes::ByteBuf;
#[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq)]
struct Wrapper {
data: ByteBuf,
}
let original = Wrapper {
data: ByteBuf::from((0u8..=255).collect::<Vec<u8>>()),
};
let yaml = noyalib::to_string(&original).unwrap();
let round: Wrapper = noyalib::from_str(&yaml).unwrap();
assert_eq!(round, original);
}
#[test]
fn binary_under_strict_parser_config() {
use noyalib::ParserConfig;
let yaml = "\
secret: !!binary SGVsbG8sIFdvcmxkIQ==
";
let cfg = ParserConfig::strict();
#[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq)]
struct S {
#[serde(with = "serde_bytes")]
secret: Vec<u8>,
}
let v: S = noyalib::from_str_with_config(yaml, &cfg).unwrap();
assert_eq!(v.secret, b"Hello, World!");
}
#[derive(Debug, serde::Deserialize)]
struct Bin(#[serde(with = "serde_bytes")] Vec<u8>);
#[derive(Debug, serde::Deserialize)]
struct Holder {
data: Bin,
}
#[test]
fn binary_rejects_non_canonical_padding_bits() {
for bad in ["QR==", "QZ==", "QUJ=", "QUL="] {
let top = noyalib::from_str::<Bin>(&format!("!!binary {bad}\n"));
assert!(top.is_err(), "{bad} must be refused: {top:?}");
let nested = noyalib::from_str::<Holder>(&format!("data: !!binary {bad}\n"));
assert!(
nested.is_err(),
"{bad} must be refused when nested: {nested:?}"
);
}
for (good, bytes) in [
("QQ==", &b"A"[..]),
("QUI=", &b"AB"[..]),
("QUJD", &b"ABC"[..]),
] {
let top = noyalib::from_str::<Bin>(&format!("!!binary {good}\n")).unwrap();
assert_eq!(top.0, bytes);
let nested = noyalib::from_str::<Holder>(&format!("data: !!binary {good}\n")).unwrap();
assert_eq!(nested.data.0, bytes);
}
}