use verit::{encode, Dt, Message, Ref, Resolver, SchemaBuilder, SchemaMode, Value};
fn contains<T>(buf: &[u8], ptr: *const T, len: usize) -> bool {
let start = buf.as_ptr() as usize;
let end = start + buf.len();
let p = ptr as usize;
p >= start && p + len <= end
}
#[test]
fn strings_and_bytes_borrow_the_message_buffer() {
let schema = SchemaBuilder::new()
.add_struct("Rec", vec![(1, "tag", Dt::Str)])
.add_struct(
"Doc",
vec![
(1, "title", Dt::Str),
(2, "payload", Dt::Bytes),
(3, "recs", Dt::list(Dt::named("Rec"))),
],
)
.build("Doc")
.unwrap();
let bytes = encode(
&schema,
&Value::Struct(vec![
(1, Value::str("zero copies given")),
(2, Value::Bytes(vec![1, 2, 3, 4, 5])),
(
3,
Value::List(vec![Value::Struct(vec![(1, Value::str("inner"))])]),
),
]),
SchemaMode::HashOnly,
)
.unwrap();
let resolver = Resolver::identity(&schema).unwrap();
let msg = Message::parse(&bytes).unwrap();
let root = msg.root(&resolver).unwrap();
let title = root.get_str(1).unwrap().unwrap();
assert_eq!(title, "zero copies given");
assert!(
contains(&bytes, title.as_ptr(), title.len()),
"returned &str must point into the message buffer"
);
let payload = root.get_bytes(2).unwrap().unwrap();
assert!(contains(&bytes, payload.as_ptr(), payload.len()));
let recs = root.get_list(3).unwrap().unwrap();
let rec = match recs.get(0).unwrap() {
Ref::Struct(s) => s,
other => panic!("expected struct, got {}", other.kind()),
};
let inner = rec.get_str(1).unwrap().unwrap();
assert_eq!(inner, "inner");
assert!(contains(&bytes, inner.as_ptr(), inner.len()));
}