#![allow(clippy::expect_used, clippy::panic, clippy::unwrap_used)]
use zerodds_wire::{
Endianness, Reader, WcharFraming, WcharPosition, WcharWidth, WireError, Writer,
};
#[test]
fn a_char_above_u00ff_is_refused_and_not_narrowed() {
let mut w = Writer::little_endian();
match w.write_char('\u{100}') {
Err(WireError::OutOfRange { at, expected }) => {
assert_eq!(at, 0);
assert!(expected.contains("U+0100"), "{expected}");
}
other => panic!("U+0100 was accepted into one byte: {other:?}"),
}
assert!(
w.as_bytes().is_empty(),
"a byte went out for a refused value: {:?}",
w.as_bytes()
);
}
#[test]
fn the_narrowed_byte_is_not_written_where_it_would_read_back_as_another_char() {
let mut w = Writer::little_endian();
assert!(w.write_char('\u{161}').is_err());
w.write_char('z').expect("`z` is one byte");
let bytes = w.finish();
assert_eq!(bytes, [b'z'], "the refused character left a byte behind");
let mut r = Reader::new(&bytes, Endianness::Little);
assert_eq!(r.read_char().expect("char"), 'z');
}
#[test]
fn every_code_point_a_char_can_hold_round_trips() {
for point in 0u32..=0xFF {
let value = char::from_u32(point).expect("Latin-1 is a subset of Unicode");
let mut w = Writer::little_endian();
w.write_char(value).expect("one byte");
let bytes = w.finish();
assert_eq!(bytes.len(), 1, "U+{point:04X} took more than a byte");
let mut r = Reader::new(&bytes, Endianness::Little);
assert_eq!(r.read_char().expect("char"), value, "U+{point:04X}");
}
}
#[test]
fn a_wchar_above_the_bmp_is_refused_and_not_narrowed() {
let mut w = Writer::little_endian();
match w.write_wchar_member('\u{1F600}') {
Err(WireError::OutOfRange { at, expected }) => {
assert_eq!(at, 0);
assert!(expected.contains("U+1F600"), "{expected}");
}
other => panic!("U+1F600 was accepted into two bytes: {other:?}"),
}
assert!(
w.as_bytes().is_empty(),
"bytes went out for a refused value: {:?}",
w.as_bytes()
);
}
#[test]
fn the_last_bmp_code_point_is_written() {
let mut w = Writer::big_endian();
w.write_wchar_member('\u{FFFD}').expect("the BMP");
assert_eq!(w.finish(), [0xFF, 0xFD]);
}
#[test]
fn the_refusal_names_where_the_value_would_have_gone() {
let mut w = Writer::little_endian();
w.write_u8(1);
match w.write_wchar_member('\u{10000}') {
Err(WireError::OutOfRange { at, .. }) => assert_eq!(at, 1),
other => panic!("{other:?}"),
}
assert_eq!(w.finish(), [1], "the alignment padding was written anyway");
}
#[test]
fn the_reader_refuses_a_surrogate_rather_than_returning_something_else() {
let bytes = [0x00, 0xD8];
let mut r = Reader::new(&bytes, Endianness::Little);
match r.read_wchar_member() {
Err(WireError::OutOfRange { at, .. }) => assert_eq!(at, 0),
other => panic!("a lone surrogate came back as a character: {other:?}"),
}
}
#[test]
fn the_four_byte_wchar_is_the_one_rti_writes_under_xcdr1() {
for (endianness, expected) in [
(Endianness::Little, [0x61, 0x00, 0x00, 0x00, 0xAB]),
(Endianness::Big, [0x00, 0x00, 0x00, 0x61, 0xAB]),
] {
let mut w = Writer::with_max_align(endianness, 8).with_wchar_width(WcharWidth::Four);
w.write_wchar_member('a').expect("the BMP");
w.write_u8(0xAB);
assert_eq!(w.finish(), expected, "{endianness:?}");
}
for (endianness, expected) in [
(Endianness::Little, [0x61, 0x00, 0xAB]),
(Endianness::Big, [0x00, 0x61, 0xAB]),
] {
let mut w = Writer::with_max_align(endianness, 8);
w.write_wchar_member('a').expect("the BMP");
w.write_u8(0xAB);
assert_eq!(w.finish(), expected, "{endianness:?}");
}
}
#[test]
fn the_four_byte_wchar_aligns_to_four() {
let mut w = Writer::with_max_align(Endianness::Little, 8).with_wchar_width(WcharWidth::Four);
w.write_u8(1);
w.write_wchar_member('a').expect("the BMP");
assert_eq!(w.finish(), [1, 0, 0, 0, 0x61, 0x00, 0x00, 0x00]);
}
#[test]
fn a_four_byte_wchar_read_two_bytes_wide_does_not_return_a_wrong_sample() {
let bytes = [0x61, 0x00, 0x00, 0x00, 0xAB];
let mut wide =
Reader::with_max_align(&bytes, Endianness::Little, 8).with_wchar_width(WcharWidth::Four);
assert_eq!(wide.read_wchar_member().expect("a wchar"), 'a');
assert_eq!(wide.read_u8().expect("the tail"), 0xAB);
let mut narrow = Reader::with_max_align(&bytes, Endianness::Little, 8);
assert_eq!(narrow.read_wchar_member().expect("a wchar"), 'a');
assert_eq!(narrow.read_u8().expect("a byte"), 0x00);
}
#[test]
fn a_four_byte_wchar_holding_more_than_a_code_unit_is_refused() {
let bytes = [0x1E, 0xD1, 0x01, 0x00];
let mut r =
Reader::with_max_align(&bytes, Endianness::Little, 8).with_wchar_width(WcharWidth::Four);
match r.read_wchar_member() {
Err(WireError::OutOfRange { at, expected }) => {
assert_eq!(at, 0);
assert!(expected.contains("one UTF-16 code unit"), "{expected}");
}
other => panic!("a two-unit value came back as a character: {other:?}"),
}
}
#[test]
fn the_four_byte_form_still_refuses_a_code_point_above_the_bmp() {
let mut w = Writer::little_endian().with_wchar_width(WcharWidth::Four);
assert!(w.write_wchar_member('\u{1F600}').is_err());
assert!(w.as_bytes().is_empty());
}
#[test]
fn taos_wchar_carries_its_count_as_a_member_and_not_as_an_element() {
let member = |framing| {
let mut w = Writer::little_endian()
.with_wchar_width(WcharWidth::Four)
.with_wchar_framing(framing);
w.write_wchar('\u{e4}', WcharPosition::Member)
.expect("the BMP");
w.finish()
};
let element = |framing| {
let mut w = Writer::little_endian()
.with_wchar_width(WcharWidth::Four)
.with_wchar_framing(framing);
w.write_wchar('\u{e4}', WcharPosition::Element)
.expect("the BMP");
w.finish()
};
assert_eq!(
member(WcharFraming::GiopLengthPrefixedMemberOnly),
vec![0x04, 0xE4, 0x00, 0x00, 0x00]
);
assert_eq!(
element(WcharFraming::GiopLengthPrefixedMemberOnly),
vec![0xE4, 0x00, 0x00, 0x00]
);
assert_eq!(
member(WcharFraming::GiopLengthPrefixed),
element(WcharFraming::GiopLengthPrefixed)
);
assert_eq!(member(WcharFraming::Fixed), element(WcharFraming::Fixed));
}
#[test]
fn an_element_read_as_a_member_is_refused_rather_than_returned() {
let bytes = [0xE4, 0x00, 0x00, 0x00];
let reader = || {
Reader::with_max_align(&bytes, Endianness::Little, 8)
.with_wchar_width(WcharWidth::Four)
.with_wchar_framing(WcharFraming::GiopLengthPrefixedMemberOnly)
};
assert_eq!(
reader()
.read_wchar(WcharPosition::Element)
.expect("a wchar"),
'\u{e4}'
);
assert!(reader().read_wchar(WcharPosition::Member).is_err());
}