use crate::error::DecodeError;
use crate::message::Message as _;
use bytes::Bytes;
pub trait MessageView<'a>: Sized {
type Owned: crate::Message;
fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError>;
fn decode_view_with_limit(buf: &'a [u8], _depth: u32) -> Result<Self, DecodeError> {
Self::decode_view(buf)
}
fn to_owned_message(&self) -> Self::Owned;
}
pub unsafe trait DefaultViewInstance: Default + 'static {
fn default_view_instance() -> &'static Self;
}
#[derive(Clone, Debug)]
pub struct MessageFieldView<V> {
inner: Option<alloc::boxed::Box<V>>,
}
impl<V> MessageFieldView<V> {
#[inline]
pub const fn unset() -> Self {
Self { inner: None }
}
#[inline]
pub fn set(v: V) -> Self {
Self {
inner: Some(alloc::boxed::Box::new(v)),
}
}
#[inline]
pub fn is_set(&self) -> bool {
self.inner.is_some()
}
#[inline]
pub fn is_unset(&self) -> bool {
self.inner.is_none()
}
#[inline]
pub fn as_option(&self) -> Option<&V> {
self.inner.as_deref()
}
#[inline]
pub fn as_mut(&mut self) -> Option<&mut V> {
self.inner.as_deref_mut()
}
}
impl<V> Default for MessageFieldView<V> {
#[inline]
fn default() -> Self {
Self::unset()
}
}
pub unsafe trait HasDefaultViewInstance {
type Static: DefaultViewInstance;
fn default_view_ptr() -> *const u8 {
Self::Static::default_view_instance() as *const Self::Static as *const u8
}
}
impl<V: HasDefaultViewInstance> core::ops::Deref for MessageFieldView<V> {
type Target = V;
#[inline]
fn deref(&self) -> &V {
match &self.inner {
Some(v) => v,
None => unsafe { &*(V::default_view_ptr() as *const V) },
}
}
}
impl<V: PartialEq + HasDefaultViewInstance> PartialEq for MessageFieldView<V> {
fn eq(&self, other: &Self) -> bool {
match (&self.inner, &other.inner) {
(None, None) => true,
_ => {
<Self as core::ops::Deref>::deref(self) == <Self as core::ops::Deref>::deref(other)
}
}
}
}
impl<V: Eq + HasDefaultViewInstance> Eq for MessageFieldView<V> {}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RepeatedView<'a, T> {
elements: alloc::vec::Vec<T>,
_marker: core::marker::PhantomData<&'a ()>,
}
impl<'a, T> RepeatedView<'a, T> {
pub fn new(elements: alloc::vec::Vec<T>) -> Self {
Self {
elements,
_marker: core::marker::PhantomData,
}
}
pub fn len(&self) -> usize {
self.elements.len()
}
pub fn is_empty(&self) -> bool {
self.elements.is_empty()
}
#[doc(hidden)]
pub fn push(&mut self, elem: T) {
self.elements.push(elem);
}
pub fn iter(&self) -> core::slice::Iter<'_, T> {
self.elements.iter()
}
}
impl<'a, T> Default for RepeatedView<'a, T> {
fn default() -> Self {
Self {
elements: alloc::vec::Vec::new(),
_marker: core::marker::PhantomData,
}
}
}
impl<'a, T> core::ops::Deref for RepeatedView<'a, T> {
type Target = [T];
fn deref(&self) -> &[T] {
&self.elements
}
}
impl<'a, T> IntoIterator for RepeatedView<'a, T> {
type Item = T;
type IntoIter = alloc::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.elements.into_iter()
}
}
impl<'b, 'a, T> IntoIterator for &'b RepeatedView<'a, T> {
type Item = &'b T;
type IntoIter = core::slice::Iter<'b, T>;
fn into_iter(self) -> Self::IntoIter {
self.elements.iter()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MapView<'a, K, V> {
entries: alloc::vec::Vec<(K, V)>,
_marker: core::marker::PhantomData<&'a ()>,
}
impl<'a, K, V> MapView<'a, K, V> {
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
#[doc(hidden)]
pub fn push(&mut self, key: K, value: V) {
self.entries.push((key, value));
}
pub fn iter(&self) -> core::slice::Iter<'_, (K, V)> {
self.entries.iter()
}
pub fn keys(&self) -> impl Iterator<Item = &K> {
self.entries.iter().map(|(k, _)| k)
}
pub fn values(&self) -> impl Iterator<Item = &V> {
self.entries.iter().map(|(_, v)| v)
}
pub fn get<Q>(&self, key: &Q) -> Option<&V>
where
K: core::borrow::Borrow<Q>,
Q: PartialEq + ?Sized,
{
self.entries
.iter()
.rev()
.find(|(k, _)| k.borrow() == key)
.map(|(_, v)| v)
}
pub fn contains_key<Q>(&self, key: &Q) -> bool
where
K: core::borrow::Borrow<Q>,
Q: PartialEq + ?Sized,
{
self.entries.iter().any(|(k, _)| k.borrow() == key)
}
}
impl<'a, K, V> Default for MapView<'a, K, V> {
fn default() -> Self {
Self {
entries: alloc::vec::Vec::new(),
_marker: core::marker::PhantomData,
}
}
}
impl<'b, 'a, K, V> IntoIterator for &'b MapView<'a, K, V> {
type Item = &'b (K, V);
type IntoIter = core::slice::Iter<'b, (K, V)>;
fn into_iter(self) -> Self::IntoIter {
self.entries.iter()
}
}
impl<'a, K, V> IntoIterator for MapView<'a, K, V> {
type Item = (K, V);
type IntoIter = alloc::vec::IntoIter<(K, V)>;
fn into_iter(self) -> Self::IntoIter {
self.entries.into_iter()
}
}
#[derive(Clone, Debug, Default)]
pub struct UnknownFieldsView<'a> {
raw_spans: alloc::vec::Vec<&'a [u8]>,
}
impl<'a> UnknownFieldsView<'a> {
pub fn new() -> Self {
Self::default()
}
#[doc(hidden)]
pub fn push_raw(&mut self, span: &'a [u8]) {
self.raw_spans.push(span);
}
pub fn is_empty(&self) -> bool {
self.raw_spans.is_empty()
}
pub fn encoded_len(&self) -> usize {
self.raw_spans.iter().map(|s| s.len()).sum()
}
pub fn to_owned(&self) -> Result<crate::UnknownFields, crate::DecodeError> {
use crate::encoding::{decode_unknown_field, Tag};
let mut out = crate::UnknownFields::new();
for span in &self.raw_spans {
let mut cur: &[u8] = span;
let tag = Tag::decode(&mut cur)?;
let field = decode_unknown_field(tag, &mut cur, crate::RECURSION_LIMIT)?;
out.push(field);
}
Ok(out)
}
}
pub struct OwnedView<V> {
view: core::mem::ManuallyDrop<V>,
bytes: Bytes,
}
impl<V> Drop for OwnedView<V> {
fn drop(&mut self) {
unsafe {
core::mem::ManuallyDrop::drop(&mut self.view);
}
}
}
impl<V> OwnedView<V>
where
V: MessageView<'static>,
{
pub fn decode(bytes: Bytes) -> Result<Self, DecodeError> {
let view = unsafe {
let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
V::decode_view(slice)?
};
Ok(Self {
view: core::mem::ManuallyDrop::new(view),
bytes,
})
}
pub fn decode_with_options(
bytes: Bytes,
opts: &crate::DecodeOptions,
) -> Result<Self, DecodeError> {
let view = unsafe {
let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
opts.decode_view::<V>(slice)?
};
Ok(Self {
view: core::mem::ManuallyDrop::new(view),
bytes,
})
}
pub fn from_owned(msg: &V::Owned) -> Result<Self, DecodeError> {
let bytes = Bytes::from(msg.encode_to_vec());
Self::decode(bytes)
}
pub fn to_owned_message(&self) -> V::Owned {
self.view.to_owned_message()
}
pub fn bytes(&self) -> &Bytes {
&self.bytes
}
pub unsafe fn from_parts(bytes: Bytes, view: V) -> Self {
Self {
view: core::mem::ManuallyDrop::new(view),
bytes,
}
}
pub fn into_bytes(mut self) -> Bytes {
unsafe {
core::mem::ManuallyDrop::drop(&mut self.view);
let bytes = core::ptr::read(&self.bytes);
core::mem::forget(self);
bytes
}
}
}
impl<V> core::ops::Deref for OwnedView<V> {
type Target = V;
#[inline]
fn deref(&self) -> &V {
&self.view }
}
impl<V> core::fmt::Debug for OwnedView<V>
where
V: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
(*self.view).fmt(f)
}
}
impl<V> Clone for OwnedView<V>
where
V: Clone,
{
fn clone(&self) -> Self {
Self {
view: self.view.clone(),
bytes: self.bytes.clone(),
}
}
}
impl<V> PartialEq for OwnedView<V>
where
V: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
*self.view == *other.view
}
}
impl<V> Eq for OwnedView<V> where V: Eq {}
#[cfg(test)]
mod send_sync_assertions {
use super::*;
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
#[allow(dead_code)]
fn owned_view_is_send_sync<V: Send + Sync>() {
assert_send::<OwnedView<V>>();
assert_sync::<OwnedView<V>>();
}
#[allow(dead_code)]
fn owned_tiny_view_is_send_sync() {
assert_send::<OwnedView<super::tests::TinyView<'static>>>();
assert_sync::<OwnedView<super::tests::TinyView<'static>>>();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn message_field_view_default_is_unset() {
let v: MessageFieldView<i32> = MessageFieldView::default();
assert!(v.is_unset());
assert!(!v.is_set());
assert_eq!(v.as_option(), None);
}
#[test]
fn message_field_view_set_value() {
let v = MessageFieldView::set(42);
assert!(v.is_set());
assert!(!v.is_unset());
assert_eq!(v.as_option(), Some(&42));
}
#[test]
fn message_field_view_with_non_copy_type() {
let v = MessageFieldView::set(alloc::string::String::from("hello"));
assert!(v.is_set());
assert_eq!(v.as_option().map(|s| s.as_str()), Some("hello"));
let unset: MessageFieldView<alloc::string::String> = MessageFieldView::unset();
assert!(unset.is_unset());
assert_eq!(unset.as_option(), None);
}
#[derive(Clone, Debug, Default, PartialEq)]
pub(super) struct TinyView<'a> {
pub value: &'a str,
}
unsafe impl DefaultViewInstance for TinyView<'static> {
fn default_view_instance() -> &'static Self {
static INST: crate::__private::OnceBox<TinyView<'static>> =
crate::__private::OnceBox::new();
INST.get_or_init(|| alloc::boxed::Box::new(TinyView::default()))
}
}
unsafe impl<'a> HasDefaultViewInstance for TinyView<'a> {
type Static = TinyView<'static>;
}
#[test]
fn message_field_view_deref_set() {
let v = MessageFieldView::set(TinyView { value: "hello" });
assert_eq!(v.value, "hello");
}
#[test]
fn message_field_view_deref_unset_returns_default() {
let v: MessageFieldView<TinyView<'_>> = MessageFieldView::unset();
assert_eq!(v.value, "");
}
#[test]
fn message_field_view_deref_chained_access() {
let v: MessageFieldView<TinyView<'_>> = MessageFieldView::unset();
let len = v.value.len();
assert_eq!(len, 0);
}
#[test]
fn message_field_view_equality() {
fn mk(c: Option<&str>) -> MessageFieldView<TinyView<'_>> {
match c {
None => MessageFieldView::unset(),
Some(v) => MessageFieldView::set(TinyView { value: v }),
}
}
#[rustfmt::skip]
let cases: &[(Option<&str>, Option<&str>, bool)] = &[
(None, None, true ), (None, Some(""), true ), (Some(""), None, true ), (Some(""), Some(""), true ), (None, Some("x"), false), (Some("x"), None, false), (Some("x"), Some("x"), true ), (Some("x"), Some("y"), false), ];
for &(l, r, expect) in cases {
assert_eq!(
mk(l) == mk(r),
expect,
"({l:?} == {r:?}) should be {expect}"
);
}
}
#[test]
fn repeated_view_new_and_accessors() {
let rv = RepeatedView::new(alloc::vec![10, 20, 30]);
assert_eq!(rv.len(), 3);
assert!(!rv.is_empty());
assert_eq!(&*rv, &[10, 20, 30]);
}
#[test]
fn repeated_view_default_is_empty() {
let rv: RepeatedView<'_, u8> = RepeatedView::default();
assert!(rv.is_empty());
assert_eq!(rv.len(), 0);
}
#[test]
fn repeated_view_push_and_iter() {
let mut rv = RepeatedView::<i32>::default();
rv.push(1);
rv.push(2);
let collected: alloc::vec::Vec<_> = rv.iter().copied().collect();
assert_eq!(collected, alloc::vec![1, 2]);
}
#[test]
fn repeated_view_with_borrowed_str() {
let data = alloc::string::String::from("hello world");
let parts: alloc::vec::Vec<&str> = data.split_whitespace().collect();
let rv = RepeatedView::new(parts);
assert_eq!(rv.len(), 2);
assert_eq!(rv[0], "hello");
assert_eq!(rv[1], "world");
}
#[test]
fn repeated_view_into_iter_by_ref() {
let rv = RepeatedView::new(alloc::vec![1, 2, 3]);
let sum: i32 = (&rv).into_iter().sum();
assert_eq!(sum, 6);
let mut count = 0;
for _ in &rv {
count += 1;
}
assert_eq!(count, 3);
}
#[test]
fn repeated_view_into_iter_by_value() {
let rv = RepeatedView::new(alloc::vec![
alloc::string::String::from("a"),
alloc::string::String::from("b"),
]);
let collected: alloc::vec::Vec<_> = rv.into_iter().collect();
assert_eq!(collected, alloc::vec!["a".to_string(), "b".to_string()]);
}
#[test]
fn map_view_get_with_borrow() {
let mut mv = MapView::<&str, i32>::default();
mv.push("apples", 3);
mv.push("bananas", 5);
assert_eq!(mv.get("apples"), Some(&3));
assert_eq!(mv.get("bananas"), Some(&5));
assert_eq!(mv.get("oranges"), None);
assert_eq!(mv.get(&"apples"), Some(&3));
}
#[test]
fn map_view_contains_key_with_borrow() {
let mut mv = MapView::<&str, i32>::default();
mv.push("key", 1);
assert!(mv.contains_key("key"));
assert!(!mv.contains_key("missing"));
}
#[test]
fn map_view_get_last_write_wins() {
let mut mv = MapView::<&str, i32>::default();
mv.push("x", 1);
mv.push("x", 2);
assert_eq!(mv.get("x"), Some(&2));
}
#[test]
fn map_view_keys_and_values() {
let mut mv = MapView::<&str, i32>::default();
mv.push("a", 1);
mv.push("b", 2);
mv.push("c", 3);
let keys: alloc::vec::Vec<_> = mv.keys().copied().collect();
assert_eq!(keys, alloc::vec!["a", "b", "c"]);
let values: alloc::vec::Vec<_> = mv.values().copied().collect();
assert_eq!(values, alloc::vec![1, 2, 3]);
}
#[test]
fn map_view_keys_and_values_empty() {
let mv = MapView::<&str, i32>::default();
assert_eq!(mv.keys().count(), 0);
assert_eq!(mv.values().count(), 0);
}
#[test]
fn map_view_into_iter_collect_to_hashmap() {
let mut mv = MapView::<&str, i32>::default();
mv.push("a", 1);
mv.push("b", 2);
mv.push("a", 3); let m: crate::__private::HashMap<&str, i32> = mv.into_iter().collect();
assert_eq!(m.len(), 2);
assert_eq!(m.get("a"), Some(&3)); assert_eq!(m.get("b"), Some(&2));
}
#[test]
fn unknown_fields_view_new_is_empty() {
let uf = UnknownFieldsView::new();
assert!(uf.is_empty());
assert_eq!(uf.encoded_len(), 0);
}
#[test]
fn unknown_fields_view_push_raw_and_encoded_len() {
let mut uf = UnknownFieldsView::new();
uf.push_raw(&[0x08, 0x01]); uf.push_raw(&[0x10, 0x02]); assert!(!uf.is_empty());
assert_eq!(uf.encoded_len(), 4);
}
#[test]
fn unknown_fields_view_to_owned_single_field() {
let span: &[u8] = &[0x98, 0x06, 0x2A];
let mut uf = UnknownFieldsView::new();
uf.push_raw(span);
let owned = uf.to_owned().expect("valid wire data");
assert_eq!(owned.len(), 1);
let field = owned.iter().next().unwrap();
assert_eq!(field.number, 99);
assert_eq!(
field.data,
crate::unknown_fields::UnknownFieldData::Varint(42)
);
}
#[test]
fn unknown_fields_view_to_owned_multiple_fields() {
let mut uf = UnknownFieldsView::new();
uf.push_raw(&[0x08, 0x07]);
uf.push_raw(&[0x15, 0x04, 0x03, 0x02, 0x01]);
let owned = uf.to_owned().expect("valid wire data");
assert_eq!(owned.len(), 2);
let mut it = owned.iter();
let f1 = it.next().unwrap();
assert_eq!(f1.number, 1);
assert_eq!(f1.data, crate::unknown_fields::UnknownFieldData::Varint(7));
let f2 = it.next().unwrap();
assert_eq!(f2.number, 2);
assert_eq!(
f2.data,
crate::unknown_fields::UnknownFieldData::Fixed32(0x01020304)
);
}
#[test]
fn unknown_fields_view_to_owned_malformed_returns_error() {
let mut uf = UnknownFieldsView::new();
uf.push_raw(&[0x80]);
assert!(uf.to_owned().is_err());
}
use crate::message::Message;
#[derive(Clone, Debug, Default, PartialEq)]
struct SimpleMessage {
pub id: i32,
pub name: alloc::string::String,
}
unsafe impl crate::DefaultInstance for SimpleMessage {
fn default_instance() -> &'static Self {
static INST: crate::__private::OnceBox<SimpleMessage> =
crate::__private::OnceBox::new();
INST.get_or_init(|| alloc::boxed::Box::new(SimpleMessage::default()))
}
}
impl crate::Message for SimpleMessage {
fn compute_size(&self) -> u32 {
let mut size = 0u32;
if self.id != 0 {
size += 1 + crate::types::int32_encoded_len(self.id) as u32;
}
if !self.name.is_empty() {
size += 1 + crate::types::string_encoded_len(&self.name) as u32;
}
size
}
fn write_to(&self, buf: &mut impl bytes::BufMut) {
if self.id != 0 {
crate::encoding::Tag::new(1, crate::encoding::WireType::Varint).encode(buf);
crate::types::encode_int32(self.id, buf);
}
if !self.name.is_empty() {
crate::encoding::Tag::new(2, crate::encoding::WireType::LengthDelimited)
.encode(buf);
crate::types::encode_string(&self.name, buf);
}
}
fn merge_field(
&mut self,
tag: crate::encoding::Tag,
buf: &mut impl bytes::Buf,
_depth: u32,
) -> Result<(), DecodeError> {
match tag.field_number() {
1 => self.id = crate::types::decode_int32(buf)?,
2 => crate::types::merge_string(&mut self.name, buf)?,
_ => crate::encoding::skip_field(tag, buf)?,
}
Ok(())
}
fn cached_size(&self) -> u32 {
0
}
fn clear(&mut self) {
self.id = 0;
self.name.clear();
}
}
#[derive(Clone, Debug, Default, PartialEq)]
struct SimpleMessageView<'a> {
pub id: i32,
pub name: &'a str,
}
impl<'a> MessageView<'a> for SimpleMessageView<'a> {
type Owned = SimpleMessage;
fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError> {
let mut view = SimpleMessageView::default();
let mut cursor: &'a [u8] = buf;
while !cursor.is_empty() {
let tag = crate::encoding::Tag::decode(&mut cursor)?;
match tag.field_number() {
1 => view.id = crate::types::decode_int32(&mut cursor)?,
2 => view.name = crate::types::borrow_str(&mut cursor)?,
_ => crate::encoding::skip_field(tag, &mut cursor)?,
}
}
Ok(view)
}
fn to_owned_message(&self) -> SimpleMessage {
SimpleMessage {
id: self.id,
name: self.name.into(),
}
}
}
fn encode_simple(id: i32, name: &str) -> Bytes {
let msg = SimpleMessage {
id,
name: name.into(),
};
Bytes::from(msg.encode_to_vec())
}
#[test]
fn owned_view_decode_and_deref() {
let bytes = encode_simple(42, "hello");
let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
assert_eq!(view.id, 42);
assert_eq!(view.name, "hello");
}
#[test]
fn owned_view_to_owned_message() {
let bytes = encode_simple(7, "world");
let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
let owned = view.to_owned_message();
assert_eq!(owned.id, 7);
assert_eq!(owned.name, "world");
}
#[test]
fn owned_view_debug_delegates_to_view() {
let bytes = encode_simple(1, "test");
let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
let debug = alloc::format!("{:?}", view);
assert!(debug.contains("test"));
assert!(debug.contains("1"));
}
#[test]
fn owned_view_bytes_accessor() {
let bytes = encode_simple(5, "data");
let original_len = bytes.len();
let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
assert_eq!(view.bytes().len(), original_len);
}
#[test]
fn owned_view_into_bytes_recovers_buffer() {
let bytes = encode_simple(99, "recover");
let expected = bytes.clone();
let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
let recovered = view.into_bytes();
assert_eq!(recovered, expected);
}
#[test]
fn owned_view_decode_invalid_data_returns_error() {
let bad = Bytes::from_static(&[0x08, 0x80]);
let result = OwnedView::<SimpleMessageView<'static>>::decode(bad);
assert!(result.is_err());
}
#[test]
fn owned_view_empty_message() {
let bytes = Bytes::from_static(&[]);
let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
assert_eq!(view.id, 0);
assert_eq!(view.name, "");
}
#[test]
fn owned_view_is_send_and_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<OwnedView<SimpleMessageView<'static>>>();
}
#[test]
fn owned_view_from_owned_roundtrips() {
let msg = SimpleMessage {
id: 99,
name: "roundtrip".into(),
};
let view = OwnedView::<SimpleMessageView<'static>>::from_owned(&msg).expect("from_owned");
assert_eq!(view.id, 99);
assert_eq!(view.name, "roundtrip");
let back = view.to_owned_message();
assert_eq!(back, msg);
}
#[test]
fn owned_view_decode_with_options() {
let bytes = encode_simple(42, "opts");
let opts = crate::DecodeOptions::new().with_max_message_size(1024);
let view =
OwnedView::<SimpleMessageView<'static>>::decode_with_options(bytes, &opts).unwrap();
assert_eq!(view.id, 42);
assert_eq!(view.name, "opts");
}
#[test]
fn owned_view_decode_with_options_rejects_oversized() {
let bytes = encode_simple(42, "too large");
let opts = crate::DecodeOptions::new().with_max_message_size(2);
let result = OwnedView::<SimpleMessageView<'static>>::decode_with_options(bytes, &opts);
assert!(result.is_err());
}
#[test]
fn owned_view_clone_survives_original_drop() {
let bytes = encode_simple(42, "cloned");
let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
let cloned = view.clone();
drop(view); assert_eq!(cloned.id, 42);
assert_eq!(cloned.name, "cloned");
}
#[test]
fn owned_view_clone_equality() {
let bytes = encode_simple(42, "eq");
let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
let cloned = view.clone();
assert_eq!(view, cloned);
}
#[test]
fn owned_view_eq_same_data() {
let a = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
let b = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
assert_eq!(a, b);
}
#[test]
fn owned_view_ne_different_data() {
let a = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
let b = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(2, "y")).unwrap();
assert_ne!(a, b);
}
#[test]
fn owned_view_into_bytes_after_clone() {
let bytes = encode_simple(42, "test");
let expected = bytes.clone();
let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
let cloned = view.clone();
drop(view); let recovered = cloned.into_bytes();
assert_eq!(recovered, expected);
}
#[test]
fn owned_view_drop_count() {
use core::sync::atomic::{AtomicUsize, Ordering};
static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);
struct DropCountingView<'a> {
inner: SimpleMessageView<'a>,
}
impl Drop for DropCountingView<'_> {
fn drop(&mut self) {
DROP_COUNT.fetch_add(1, Ordering::SeqCst);
}
}
impl<'a> MessageView<'a> for DropCountingView<'a> {
type Owned = SimpleMessage;
fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError> {
Ok(DropCountingView {
inner: SimpleMessageView::decode_view(buf)?,
})
}
fn to_owned_message(&self) -> SimpleMessage {
self.inner.to_owned_message()
}
}
DROP_COUNT.store(0, Ordering::SeqCst);
{
let bytes = encode_simple(1, "drop");
let _view = OwnedView::<DropCountingView<'static>>::decode(bytes).unwrap();
}
assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 1, "normal drop");
DROP_COUNT.store(0, Ordering::SeqCst);
{
let bytes = encode_simple(2, "into");
let view = OwnedView::<DropCountingView<'static>>::decode(bytes).unwrap();
let _bytes = view.into_bytes();
}
assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 1, "into_bytes drop");
}
#[test]
fn owned_view_name_borrows_from_bytes_buffer() {
let bytes = encode_simple(42, "borrowed");
let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
let buf = view.bytes();
let buf_start = buf.as_ptr() as usize;
let buf_end = buf_start + buf.len();
let name_ptr = view.name.as_ptr() as usize;
assert!(
(buf_start..buf_end).contains(&name_ptr),
"view.name should point into the Bytes buffer"
);
}
#[test]
fn owned_view_concurrent_read() {
use alloc::sync::Arc;
let bytes = encode_simple(42, "concurrent");
let view = Arc::new(OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap());
let handles: alloc::vec::Vec<_> = (0..4)
.map(|_| {
let v = Arc::clone(&view);
std::thread::spawn(move || {
assert_eq!(v.id, 42);
assert_eq!(v.name, "concurrent");
})
})
.collect();
for h in handles {
h.join().unwrap();
}
}
#[test]
fn owned_view_from_parts_roundtrip() {
let bytes = encode_simple(42, "parts");
let view = unsafe {
let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
let decoded = SimpleMessageView::decode_view(slice).unwrap();
OwnedView::<SimpleMessageView<'static>>::from_parts(bytes, decoded)
};
assert_eq!(view.id, 42);
assert_eq!(view.name, "parts");
}
}