#![cfg(feature = "reflect")]
use buffa::{Message, MessageView};
use buffa_descriptor::reflect::{ReflectMessage, ValueRef};
use buffa_types::google::protobuf as wkt;
use buffa_types::google::protobuf::__buffa::oneof::value::Kind as KindOneof;
use buffa_types::google::protobuf::__buffa::view as wkt_view;
#[test]
fn timestamp_view_reflects_scalars() {
let ts = wkt::Timestamp {
seconds: 1_700_000_000,
nanos: 123_456_789,
..Default::default()
};
let bytes = ts.encode_to_vec();
let view = wkt_view::TimestampView::decode_view(&bytes).expect("decode_view");
let r: &dyn ReflectMessage = &view;
let md = r.message_descriptor();
assert!(matches!(
r.get(md.field(1).unwrap()),
ValueRef::I64(1_700_000_000)
));
assert!(matches!(
r.get(md.field(2).unwrap()),
ValueRef::I32(123_456_789)
));
assert!(r.has(md.field(1).unwrap()));
}
#[test]
fn string_value_view_reflects_string() {
let w = wkt::StringValue {
value: "hello".into(),
..Default::default()
};
let bytes = w.encode_to_vec();
let view = wkt_view::StringValueView::decode_view(&bytes).expect("decode_view");
let r: &dyn ReflectMessage = &view;
let md = r.message_descriptor();
assert!(matches!(
r.get(md.field(1).unwrap()),
ValueRef::String("hello")
));
}
#[test]
fn struct_view_reflects_map_of_nested_value_oneof() {
let mut s = wkt::Struct::default();
s.fields.insert(
"pi".to_string(),
wkt::Value {
kind: Some(KindOneof::NumberValue(3.0)),
..Default::default()
},
);
let bytes = s.encode_to_vec();
let view = wkt_view::StructView::decode_view(&bytes).expect("decode_view");
let r: &dyn ReflectMessage = &view;
let md = r.message_descriptor();
let fields_fd = md
.fields()
.iter()
.find(|f| f.name() == "fields")
.expect("fields map");
let ValueRef::Map(m) = r.get(fields_fd) else {
panic!("expected Map")
};
assert_eq!(m.len(), 1);
let Some(ValueRef::Message(value_cow)) = m.get_str("pi") else {
panic!("expected nested Value message")
};
let value_md = value_cow.message_descriptor();
assert!(matches!(
value_cow.get(value_md.field(2).unwrap()),
ValueRef::F64(3.0)
));
}
#[test]
fn wkt_view_to_dynamic_snapshot() {
let d = wkt::Duration {
seconds: 5,
nanos: 250,
..Default::default()
};
let bytes = d.encode_to_vec();
let view = wkt_view::DurationView::decode_view(&bytes).expect("decode_view");
let r: &dyn ReflectMessage = &view;
let snapshot = r.to_dynamic();
let md = snapshot.message_descriptor();
assert!(matches!(
snapshot.get(md.field(1).unwrap()),
ValueRef::I64(5)
));
assert!(matches!(
snapshot.get(md.field(2).unwrap()),
ValueRef::I32(250)
));
}
#[test]
fn deeply_nested_struct_view_converts_instead_of_panicking() {
fn nested(cycles: usize) -> Vec<u8> {
let mut inner = wkt::Struct::default();
for _ in 0..cycles {
let mut s = wkt::Struct::default();
s.fields.insert(
"k".to_string(),
wkt::Value {
kind: Some(KindOneof::StructValue(Box::new(inner))),
..Default::default()
},
);
inner = s;
}
inner.encode_to_vec()
}
let max_cycles = (buffa::RECURSION_LIMIT / 2) as usize;
let mut accepted = 0;
for cycles in 1..max_cycles + 10 {
let wire = nested(cycles);
let Ok(view) = wkt_view::StructView::decode_view(&wire) else {
continue;
};
accepted += 1;
let dynamic = view.to_dynamic();
assert_eq!(
dynamic.message_descriptor().full_name(),
"google.protobuf.Struct"
);
assert!(
wkt::Struct::decode_from_slice(&wire).is_ok(),
"the owned decoder rejected {cycles} cycles that the view accepted"
);
}
assert!(
accepted >= max_cycles - 2,
"expected the view to accept nesting up to ~{max_cycles} cycles; only {accepted} got through"
);
}