use crate::error::DecodeError;
use crate::message::Message as _;
use bytes::{BufMut, Bytes};
pub trait MessageView<'a>: Sized {
type Owned: crate::Message;
fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError>;
fn decode_view_with_ctx(
buf: &'a [u8],
_ctx: crate::DecodeContext<'_>,
) -> Result<Self, DecodeError> {
Self::decode_view(buf)
}
fn decode_view_ctx(buf: &'a [u8], ctx: crate::DecodeContext<'_>) -> Result<Self, DecodeError>
where
Self: Default,
{
let mut view = Self::default();
view.merge_into_view(buf, ctx)?;
Ok(view)
}
fn merge_into_view(
&mut self,
buf: &'a [u8],
ctx: crate::DecodeContext<'_>,
) -> Result<(), DecodeError> {
let mut cur: &'a [u8] = buf;
while !cur.is_empty() {
let before_tag = cur;
let tag = crate::encoding::Tag::decode(&mut cur)?;
cur = self.merge_view_field(tag, cur, before_tag, ctx)?;
}
Ok(())
}
fn merge_view_field(
&mut self,
tag: crate::encoding::Tag,
cur: &'a [u8],
before_tag: &'a [u8],
ctx: crate::DecodeContext<'_>,
) -> Result<&'a [u8], DecodeError>;
fn to_owned_message(&self) -> Result<Self::Owned, DecodeError>;
fn to_owned_from_source(&self, source: Option<&Bytes>) -> Result<Self::Owned, DecodeError> {
let _ = source;
self.to_owned_message()
}
}
#[rustversion::attr(
since(1.78),
diagnostic::on_unimplemented(
message = "`{Self}` does not implement `ViewReborrow` — required by `OwnedView::reborrow`",
note = "for a generated view type, this impl is emitted automatically by codegen",
note = "for a hand-written view type `MyView<'a>`, add:\n impl ViewReborrow for MyView<'static> {{\n type Reborrowed<'b> = MyView<'b>;\n fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b> {{ this }}\n }}",
note = "your `MessageView` impl must be parametric over the lifetime — `impl<'a> MessageView<'a> for MyView<'a>` — so that both `Self: MessageView<'static>` and `Reborrowed<'b>: MessageView<'b>` hold",
note = "`MyView` must be covariant in its lifetime — fields like `&'a T` and `MessageFieldView<...>` are covariant; `Cell<&'a T>` and `&'a mut T` are not, and the trait body `{{ this }}` will fail to compile for invariant types"
)
)]
pub trait ViewReborrow: MessageView<'static> {
type Reborrowed<'b>: MessageView<'b, Owned = <Self as MessageView<'static>>::Owned>
where
Self: 'b;
fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b>;
}
#[macro_export]
macro_rules! impl_view_reborrow {
($ty:ident) => {
impl $crate::ViewReborrow for $ty<'static> {
type Reborrowed<'b> = $ty<'b>;
fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b> {
this
}
}
};
}
#[rustversion::attr(
since(1.78),
diagnostic::on_unimplemented(
message = "`{Self}` does not implement `HasMessageView` — its message-view family was not generated or is not enabled",
note = "the `HasMessageView` impl is emitted next to each message's view types: \
regenerate the crate that defines `{Self}` with buffa 0.7.0 or newer and \
views enabled — `generate_views(true)` (on by default) in a buffa-build / \
buffa-codegen config, or `views=true` for protoc-gen-buffa",
note = "if the defining crate feature-gates its generated impls, enabling its views \
feature is enough — no regeneration needed"
)
)]
pub trait HasMessageView: crate::Message + Sized {
type View<'a>: MessageView<'a, Owned = Self> + Send + Sync;
type ViewHandle: From<OwnedView<Self::View<'static>>>
+ AsRef<OwnedView<Self::View<'static>>>
+ Send
+ Sync
+ 'static;
#[inline]
fn decode_view(buf: &[u8]) -> Result<Self::View<'_>, DecodeError> {
<Self::View<'_> as MessageView<'_>>::decode_view(buf)
}
#[inline]
fn decode_view_with_options<'a>(
buf: &'a [u8],
opts: &crate::DecodeOptions,
) -> Result<Self::View<'a>, DecodeError> {
opts.decode_view(buf)
}
fn decode_view_handle(bytes: Bytes) -> Result<Self::ViewHandle, DecodeError> {
Ok(Self::ViewHandle::from(
OwnedView::<Self::View<'static>>::decode(bytes)?,
))
}
fn decode_view_handle_with_options(
bytes: Bytes,
opts: &crate::DecodeOptions,
) -> Result<Self::ViewHandle, DecodeError> {
Ok(Self::ViewHandle::from(
OwnedView::<Self::View<'static>>::decode_with_options(bytes, opts)?,
))
}
}
#[doc(hidden)]
#[inline]
pub fn bytes_from_source(source: Option<&Bytes>, slice: &[u8]) -> Bytes {
if slice.is_empty() {
return Bytes::new();
}
if let Some(b) = source {
let b_start = b.as_ptr() as usize;
let s_start = slice.as_ptr() as usize;
if let (Some(b_end), Some(s_end)) = (
b_start.checked_add(b.len()),
s_start.checked_add(slice.len()),
) {
if s_start >= b_start && s_end <= b_end {
return b.slice_ref(slice);
}
}
}
Bytes::copy_from_slice(slice)
}
#[rustversion::attr(
since(1.78),
diagnostic::on_unimplemented(
message = "`{Self}` does not implement `ViewEncode` — view types were not generated for this message",
note = "ViewEncode is implemented on every generated `*View<'a>` type; enable `generate_views(true)` (on by default) in your buffa-build / buffa-codegen config"
)
)]
pub trait ViewEncode<'a>: MessageView<'a> {
fn compute_size(&self, cache: &mut crate::SizeCache) -> u32;
fn write_to(&self, cache: &mut crate::SizeCache, buf: &mut impl BufMut);
fn encode(&self, buf: &mut impl BufMut) {
let mut cache = crate::SizeCache::new();
self.compute_size(&mut cache);
self.write_to(&mut cache, buf);
}
fn encode_with_cache(&self, cache: &mut crate::SizeCache, buf: &mut impl BufMut) {
cache.clear();
self.compute_size(cache);
self.write_to(cache, buf);
}
#[must_use]
fn encoded_len(&self) -> u32 {
self.compute_size(&mut crate::SizeCache::new())
}
fn encode_length_delimited(&self, buf: &mut impl BufMut) {
let mut cache = crate::SizeCache::new();
let len = self.compute_size(&mut cache);
crate::encoding::encode_varint(len as u64, buf);
self.write_to(&mut cache, buf);
}
#[must_use]
fn encode_to_vec(&self) -> alloc::vec::Vec<u8> {
let mut cache = crate::SizeCache::new();
let size = self.compute_size(&mut cache) as usize;
let mut buf = alloc::vec::Vec::with_capacity(size);
self.write_to(&mut cache, &mut buf);
buf
}
#[must_use]
fn encode_to_bytes(&self) -> Bytes {
let mut cache = crate::SizeCache::new();
let size = self.compute_size(&mut cache) as usize;
let mut buf = bytes::BytesMut::with_capacity(size);
self.write_to(&mut cache, &mut buf);
buf.freeze()
}
}
pub trait DefaultViewInstance {
fn default_view_instance<'a>() -> &'a Self
where
Self: 'a;
}
#[macro_export]
macro_rules! impl_default_view_instance {
($ty:ident) => {
impl<'v> $crate::DefaultViewInstance for $ty<'v> {
fn default_view_instance<'a>() -> &'a Self
where
Self: 'a,
{
static VALUE: $crate::__private::OnceBox<$ty<'static>> =
$crate::__private::OnceBox::new();
VALUE.get_or_init(|| {
$crate::alloc::boxed::Box::new(
<$ty<'static> as ::core::default::Default>::default(),
)
})
}
}
};
}
#[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 some(v: V) -> Self {
Self::set(v)
}
#[inline]
pub const fn is_set(&self) -> bool {
self.inner.is_some()
}
#[inline]
pub const 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<'a, V: ViewEncode<'a>> MessageFieldView<V> {
#[inline]
pub fn compute_size(&self, cache: &mut crate::SizeCache) -> u32 {
self.inner.as_deref().map_or(0, |v| v.compute_size(cache))
}
#[inline]
pub fn write_to(&self, cache: &mut crate::SizeCache, buf: &mut impl BufMut) {
if let Some(v) = self.inner.as_deref() {
v.write_to(cache, buf);
}
}
}
impl<V> Default for MessageFieldView<V> {
#[inline]
fn default() -> Self {
Self::unset()
}
}
impl<V> From<V> for MessageFieldView<V> {
#[inline]
fn from(v: V) -> Self {
Self::set(v)
}
}
impl<V: DefaultViewInstance> core::ops::Deref for MessageFieldView<V> {
type Target = V;
#[inline]
fn deref(&self) -> &V {
self.inner
.as_deref()
.unwrap_or_else(V::default_view_instance)
}
}
impl<V: PartialEq + DefaultViewInstance> 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 + DefaultViewInstance> Eq for MessageFieldView<V> {}
pub trait LazyMessageView<'a>: Sized {
type Owned: crate::Message;
fn decode_lazy(buf: &'a [u8]) -> Result<Self, DecodeError>;
fn decode_lazy_with_ctx(
buf: &'a [u8],
ctx: crate::DecodeContext<'_>,
) -> Result<Self, DecodeError> {
let _ = ctx;
Self::decode_lazy(buf)
}
fn merge_lazy(
&mut self,
buf: &'a [u8],
ctx: crate::DecodeContext<'_>,
) -> Result<(), DecodeError>;
fn to_owned_message(&self) -> Result<Self::Owned, DecodeError>;
}
#[derive(Clone)]
enum LazyFragments<'a> {
None,
One(&'a [u8]),
Many(alloc::vec::Vec<&'a [u8]>),
}
pub struct LazyMessageFieldView<'a, V> {
raw: LazyFragments<'a>,
depth: u32,
allowance: usize,
_marker: core::marker::PhantomData<fn() -> V>,
}
impl<'a, V> LazyMessageFieldView<'a, V> {
#[inline]
pub const fn unset() -> Self {
Self {
raw: LazyFragments::None,
depth: u32::MAX,
allowance: usize::MAX,
_marker: core::marker::PhantomData,
}
}
#[inline]
pub const fn from_bytes(raw: &'a [u8]) -> Self {
Self {
raw: LazyFragments::One(raw),
depth: crate::RECURSION_LIMIT,
allowance: crate::DEFAULT_UNKNOWN_FIELD_LIMIT,
_marker: core::marker::PhantomData,
}
}
#[doc(hidden)]
#[inline]
pub fn push_fragment(&mut self, raw: &'a [u8], ctx: crate::DecodeContext<'_>) {
self.depth = self.depth.min(ctx.depth());
self.allowance = self.allowance.min(ctx.remaining_unknown_fields());
self.raw = match core::mem::replace(&mut self.raw, LazyFragments::None) {
LazyFragments::None => LazyFragments::One(raw),
LazyFragments::One(first) => LazyFragments::Many(alloc::vec![first, raw]),
LazyFragments::Many(mut frags) => {
frags.push(raw);
LazyFragments::Many(frags)
}
};
}
#[inline]
pub const fn is_set(&self) -> bool {
!matches!(self.raw, LazyFragments::None)
}
#[inline]
pub const fn is_unset(&self) -> bool {
matches!(self.raw, LazyFragments::None)
}
#[inline]
pub fn fragments(&self) -> &[&'a [u8]] {
match &self.raw {
LazyFragments::None => &[],
LazyFragments::One(raw) => core::slice::from_ref(raw),
LazyFragments::Many(frags) => frags,
}
}
}
impl<'a, V: LazyMessageView<'a>> LazyMessageFieldView<'a, V> {
#[inline]
pub fn get(&self) -> Result<Option<V>, DecodeError> {
let allowance = core::cell::Cell::new(self.allowance);
let ctx = crate::DecodeContext::new(self.depth, &allowance);
match &self.raw {
LazyFragments::None => Ok(None),
LazyFragments::One(raw) => V::decode_lazy_with_ctx(raw, ctx).map(Some),
LazyFragments::Many(frags) => {
let mut iter = frags.iter();
let Some(first) = iter.next() else {
return Ok(None);
};
let mut view = V::decode_lazy_with_ctx(first, ctx)?;
for frag in iter {
view.merge_lazy(frag, ctx)?;
}
Ok(Some(view))
}
}
}
#[inline]
pub fn get_or_default(&self) -> Result<V, DecodeError>
where
V: Default,
{
Ok(self.get()?.unwrap_or_default())
}
}
impl<V> Clone for LazyMessageFieldView<'_, V> {
#[inline]
fn clone(&self) -> Self {
Self {
raw: self.raw.clone(),
depth: self.depth,
allowance: self.allowance,
_marker: core::marker::PhantomData,
}
}
}
impl<V> Default for LazyMessageFieldView<'_, V> {
#[inline]
fn default() -> Self {
Self::unset()
}
}
impl<V> core::fmt::Debug for LazyMessageFieldView<'_, V> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("LazyMessageFieldView")
.field("is_set", &self.is_set())
.field("fragments", &self.fragments().len())
.finish()
}
}
pub struct LazyRepeatedView<'a, V> {
elements: alloc::vec::Vec<&'a [u8]>,
depth: u32,
allowance: usize,
_marker: core::marker::PhantomData<fn() -> V>,
}
impl<'a, V> LazyRepeatedView<'a, V> {
#[inline]
pub fn new() -> Self {
Self {
elements: alloc::vec::Vec::new(),
depth: u32::MAX,
allowance: usize::MAX,
_marker: core::marker::PhantomData,
}
}
#[inline]
pub fn len(&self) -> usize {
self.elements.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.elements.is_empty()
}
#[inline]
pub fn raw_elements(&self) -> &[&'a [u8]] {
&self.elements
}
#[doc(hidden)]
#[inline]
pub fn push_bytes(&mut self, raw: &'a [u8], ctx: crate::DecodeContext<'_>) {
self.depth = self.depth.min(ctx.depth());
self.allowance = self.allowance.min(ctx.remaining_unknown_fields());
self.elements.push(raw);
}
}
#[inline]
fn decode_deferred<'a, V: LazyMessageView<'a>>(
raw: &'a [u8],
depth: u32,
allowance: usize,
) -> Result<V, DecodeError> {
let cell = core::cell::Cell::new(allowance);
V::decode_lazy_with_ctx(raw, crate::DecodeContext::new(depth, &cell))
}
impl<'a, V: LazyMessageView<'a>> LazyRepeatedView<'a, V> {
#[inline]
pub fn get(&self, index: usize) -> Option<Result<V, DecodeError>> {
self.elements
.get(index)
.map(|b| decode_deferred(b, self.depth, self.allowance))
}
#[inline]
pub fn try_get(&self, index: usize) -> Result<Option<V>, DecodeError> {
self.get(index).transpose()
}
#[inline]
pub fn iter(&self) -> LazyRepeatedIter<'_, 'a, V> {
LazyRepeatedIter {
inner: self.elements.iter(),
depth: self.depth,
allowance: self.allowance,
_marker: core::marker::PhantomData,
}
}
}
impl<'s, 'a, V: LazyMessageView<'a>> IntoIterator for &'s LazyRepeatedView<'a, V> {
type Item = Result<V, DecodeError>;
type IntoIter = LazyRepeatedIter<'s, 'a, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Clone, Debug)]
pub struct LazyRepeatedIter<'s, 'a, V> {
inner: core::slice::Iter<'s, &'a [u8]>,
depth: u32,
allowance: usize,
_marker: core::marker::PhantomData<fn() -> V>,
}
impl<'a, V: LazyMessageView<'a>> Iterator for LazyRepeatedIter<'_, 'a, V> {
type Item = Result<V, DecodeError>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner
.next()
.map(|b| decode_deferred(b, self.depth, self.allowance))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, V: LazyMessageView<'a>> DoubleEndedIterator for LazyRepeatedIter<'_, 'a, V> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner
.next_back()
.map(|b| decode_deferred(b, self.depth, self.allowance))
}
}
impl<'a, V: LazyMessageView<'a>> ExactSizeIterator for LazyRepeatedIter<'_, 'a, V> {}
impl<V> Clone for LazyRepeatedView<'_, V> {
#[inline]
fn clone(&self) -> Self {
Self {
elements: self.elements.clone(),
depth: self.depth,
allowance: self.allowance,
_marker: core::marker::PhantomData,
}
}
}
impl<V> Default for LazyRepeatedView<'_, V> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<V> core::fmt::Debug for LazyRepeatedView<'_, V> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("LazyRepeatedView")
.field("len", &self.len())
.finish()
}
}
#[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);
}
#[doc(hidden)]
pub fn reserve(&mut self, additional: usize) {
self.elements.reserve(additional);
}
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()
}
}
impl<'a, T> From<alloc::vec::Vec<T>> for RepeatedView<'a, T> {
fn from(elements: alloc::vec::Vec<T>) -> Self {
Self::new(elements)
}
}
impl<'a, T> FromIterator<T> for RepeatedView<'a, T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self::new(iter.into_iter().collect())
}
}
#[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 new(entries: alloc::vec::Vec<(K, V)>) -> Self {
Self {
entries,
_marker: core::marker::PhantomData,
}
}
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)
}
pub fn iter_unique(&self) -> impl Iterator<Item = &(K, V)>
where
K: PartialEq,
{
let entries = &self.entries;
entries.iter().enumerate().filter_map(move |(i, entry)| {
if entries[i + 1..]
.iter()
.any(|(later_k, _)| *later_k == entry.0)
{
None
} else {
Some(entry)
}
})
}
pub fn len_unique(&self) -> usize
where
K: PartialEq,
{
self.iter_unique().count()
}
}
impl<'a, K, V> From<alloc::vec::Vec<(K, V)>> for MapView<'a, K, V> {
fn from(entries: alloc::vec::Vec<(K, V)>) -> Self {
Self::new(entries)
}
}
impl<'a, K, V> FromIterator<(K, V)> for MapView<'a, K, V> {
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
Self::new(iter.into_iter().collect())
}
}
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, Default)]
pub struct UnknownFieldsView<'a> {
raw_spans: alloc::vec::Vec<&'a [u8]>,
last_tail: Option<&'a [u8]>,
to_owned_allowance: Option<usize>,
}
impl core::fmt::Debug for UnknownFieldsView<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("UnknownFieldsView")
.field("raw_spans", &self.raw_spans)
.finish_non_exhaustive()
}
}
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);
self.last_tail = None;
}
#[doc(hidden)]
pub fn push_record(
&mut self,
tail: &'a [u8],
span_len: usize,
ctx: crate::DecodeContext<'_>,
) -> Result<(), crate::DecodeError> {
if span_len > tail.len() {
return Err(crate::DecodeError::UnexpectedEof);
}
if self.to_owned_allowance.is_none() {
self.to_owned_allowance = Some(ctx.remaining_unknown_fields());
}
if let (Some(last), Some(prev_tail)) = (self.raw_spans.last_mut(), self.last_tail) {
let prev_len = last.len();
if prev_tail.len() >= prev_len + span_len
&& core::ptr::eq(prev_tail[prev_len..].as_ptr(), tail.as_ptr())
{
*last = &prev_tail[..prev_len + span_len];
return Ok(());
}
}
ctx.register_unknown_field()?;
self.raw_spans.push(&tail[..span_len]);
self.last_tail = Some(tail);
Ok(())
}
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 write_to(&self, buf: &mut impl BufMut) {
for span in &self.raw_spans {
buf.put_slice(span);
}
}
pub fn to_owned(&self) -> Result<crate::UnknownFields, crate::DecodeError> {
use crate::encoding::{decode_unknown_field, Tag};
let limit = core::cell::Cell::new(
self.to_owned_allowance
.unwrap_or(crate::DEFAULT_UNKNOWN_FIELD_LIMIT),
);
let ctx = crate::DecodeContext::new(crate::RECURSION_LIMIT, &limit);
let mut out = crate::UnknownFields::new();
for span in &self.raw_spans {
let mut cur: &[u8] = span;
while !cur.is_empty() {
let tag = Tag::decode(&mut cur)?;
let field = decode_unknown_field(tag, &mut cur, ctx)?;
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) -> Result<V::Owned, DecodeError> {
self.view.to_owned_from_source(Some(&self.bytes))
}
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
}
}
#[must_use = "reborrow returns a tied-lifetime view; discarding it is a no-op"]
pub fn reborrow<'b>(&'b self) -> &'b V::Reborrowed<'b>
where
V: ViewReborrow,
{
V::reborrow(&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(feature = "json")]
impl<V: ::serde::Serialize> ::serde::Serialize for OwnedView<V> {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
::serde::Serialize::serialize(&*self.view, s)
}
}
#[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>>>();
}
#[allow(dead_code)]
fn reborrowed_view_is_send_sync<V>()
where
V: ViewReborrow + Send + Sync,
for<'b> V::Reborrowed<'b>: Send + Sync,
{
assert_send::<OwnedView<V>>();
assert_sync::<OwnedView<V>>();
}
}
#[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,
}
crate::impl_default_view_instance!(TinyView);
#[test]
fn impl_default_view_instance_macro_returns_singleton() {
let a: &TinyView<'_> = TinyView::default_view_instance();
let b: &TinyView<'_> = TinyView::default_view_instance();
assert!(core::ptr::eq(a, b), "singleton must be a single allocation");
assert_eq!(a, &TinyView::default());
}
#[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]);
}
fn record_ctx(n: usize) -> crate::DecodeContext<'static> {
let limit = alloc::boxed::Box::leak(alloc::boxed::Box::new(core::cell::Cell::new(n)));
crate::DecodeContext::new(crate::RECURSION_LIMIT, limit)
}
#[test]
fn push_record_coalesces_adjacent_records() {
let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
let ctx = record_ctx(1); let mut ufv = UnknownFieldsView::new();
ufv.push_record(&buf[0..], 2, ctx).unwrap();
ufv.push_record(&buf[2..], 2, ctx).unwrap();
ufv.push_record(&buf[4..], 2, ctx).unwrap();
assert_eq!(ufv.encoded_len(), 6);
let mut out = alloc::vec::Vec::new();
ufv.write_to(&mut out);
assert_eq!(out, buf);
assert_eq!(ctx.remaining_unknown_fields(), 0, "single slot consumed");
}
#[test]
fn push_record_non_adjacent_records_use_separate_slots() {
let buf: &[u8] = &[0x08, 0x00, 0xFF, 0x08, 0x01];
let ctx = record_ctx(2);
let mut ufv = UnknownFieldsView::new();
ufv.push_record(&buf[0..], 2, ctx).unwrap();
ufv.push_record(&buf[3..], 2, ctx).unwrap();
assert_eq!(ufv.encoded_len(), 4);
assert_eq!(ctx.remaining_unknown_fields(), 0, "two slots consumed");
}
#[test]
fn push_record_enforces_limit_for_new_spans() {
let buf: &[u8] = &[0x08, 0x00, 0xFF, 0x08, 0x01];
let ctx = record_ctx(1);
let mut ufv = UnknownFieldsView::new();
ufv.push_record(&buf[0..], 2, ctx).unwrap();
assert_eq!(
ufv.push_record(&buf[3..], 2, ctx),
Err(crate::DecodeError::UnknownFieldLimitExceeded)
);
ufv.push_record(&buf[2..], 1, ctx)
.expect("adjacent record coalesces without a slot");
}
#[test]
fn push_raw_disables_coalescing_for_next_record() {
let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01];
let ctx = record_ctx(2);
let mut ufv = UnknownFieldsView::new();
ufv.push_raw(&buf[0..2]);
ufv.push_record(&buf[2..], 2, ctx).unwrap();
assert_eq!(ctx.remaining_unknown_fields(), 1);
assert_eq!(ufv.encoded_len(), 4);
}
#[test]
fn push_record_rejects_span_past_tail_end() {
let buf: &[u8] = &[0x08, 0x00];
let ctx = record_ctx(1);
let mut ufv = UnknownFieldsView::new();
assert_eq!(
ufv.push_record(buf, 3, ctx),
Err(crate::DecodeError::UnexpectedEof)
);
}
#[test]
fn coalesced_span_to_owned_parses_every_record() {
let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
let ctx = record_ctx(3);
let mut ufv = UnknownFieldsView::new();
for i in 0..3 {
ufv.push_record(&buf[2 * i..], 2, ctx).unwrap();
}
let owned = ufv.to_owned().unwrap();
assert_eq!(owned.iter().count(), 3, "all records parsed");
}
#[test]
fn to_owned_enforces_decode_time_allowance() {
let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
let ctx = record_ctx(1);
let mut ufv = UnknownFieldsView::new();
for i in 0..3 {
ufv.push_record(&buf[2 * i..], 2, ctx).unwrap();
}
assert_eq!(
ufv.to_owned(),
Err(crate::DecodeError::UnknownFieldLimitExceeded)
);
}
#[test]
fn to_owned_of_manual_view_uses_default_allowance() {
let mut ufv = UnknownFieldsView::new();
ufv.push_raw(&[0x08, 0x00]);
let owned = ufv.to_owned().unwrap();
assert_eq!(owned.iter().count(), 1);
}
#[test]
fn repeated_view_reserve_grows_capacity() {
let mut rv = RepeatedView::<u32>::default();
rv.reserve(64);
assert!(rv.elements.capacity() >= 64);
assert!(rv.is_empty());
rv.reserve(0);
rv.push(1);
rv.push(2);
rv.reserve(100);
assert_eq!(rv.len(), 2);
assert!(rv.elements.capacity() >= 102);
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_iter_unique_dedups_last_write_wins() {
let mut mv = MapView::<&str, i32>::default();
mv.push("a", 1);
mv.push("b", 2);
mv.push("a", 3); mv.push("c", 4);
mv.push("b", 5);
assert_eq!(mv.len(), 5, "iter() preserves all wire entries");
assert_eq!(mv.len_unique(), 3, "len_unique() counts distinct keys");
let unique: alloc::vec::Vec<_> = mv.iter_unique().collect();
assert_eq!(unique, [&("a", 3), &("c", 4), &("b", 5)]);
}
#[test]
fn map_view_iter_unique_all_duplicates() {
let mut mv = MapView::<&str, i32>::default();
mv.push("a", 1);
mv.push("a", 2);
mv.push("a", 3);
assert_eq!(mv.len_unique(), 1);
assert_eq!(
mv.iter_unique().collect::<alloc::vec::Vec<_>>(),
[&("a", 3)]
);
}
#[test]
fn map_view_iter_unique_no_duplicates() {
let mut mv = MapView::<i32, &str>::default();
mv.push(1, "x");
mv.push(2, "y");
assert_eq!(mv.len_unique(), 2);
assert_eq!(
mv.iter_unique().collect::<alloc::vec::Vec<_>>(),
[&(1, "x"), &(2, "y")]
);
}
#[test]
fn map_view_iter_unique_empty() {
let mv = MapView::<&str, i32>::default();
assert_eq!(mv.len_unique(), 0);
assert_eq!(mv.iter_unique().count(), 0);
}
#[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 bytes_from_source_none_copies() {
let data: &[u8] = b"hello";
let out = bytes_from_source(None, data);
assert_eq!(&out[..], data);
assert_ne!(out.as_ptr(), data.as_ptr()); }
#[test]
fn bytes_from_source_some_within_is_slice_ref() {
let parent = Bytes::copy_from_slice(b"hello world");
let slice = &parent[6..11];
let out = bytes_from_source(Some(&parent), slice);
assert_eq!(&out[..], b"world");
assert_eq!(out.as_ptr(), slice.as_ptr());
}
#[test]
fn bytes_from_source_some_outside_falls_back_to_copy() {
let parent = Bytes::copy_from_slice(b"hello");
let outside: &[u8] = b"world"; let out = bytes_from_source(Some(&parent), outside);
assert_eq!(&out[..], b"world");
assert_ne!(out.as_ptr(), outside.as_ptr());
}
#[test]
fn bytes_from_source_empty_returns_new() {
let parent = Bytes::copy_from_slice(b"hello");
assert!(bytes_from_source(Some(&parent), &[]).is_empty());
assert!(bytes_from_source(None, &[]).is_empty());
}
#[test]
fn bytes_from_source_full_range() {
let parent = Bytes::copy_from_slice(b"hello");
let out = bytes_from_source(Some(&parent), &parent[..]);
assert_eq!(out.as_ptr(), parent.as_ptr());
assert_eq!(out.len(), parent.len());
}
#[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,
}
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, _cache: &mut crate::SizeCache) -> 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, _cache: &mut crate::SizeCache, 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,
_ctx: crate::DecodeContext<'_>,
) -> 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 clear(&mut self) {
self.id = 0;
self.name.clear();
}
}
#[derive(Clone, Debug, Default, PartialEq)]
struct SimpleMessageView<'a> {
pub id: i32,
pub name: &'a str,
}
crate::impl_view_reborrow!(SimpleMessageView);
impl<'a> MessageView<'a> for SimpleMessageView<'a> {
type Owned = SimpleMessage;
fn merge_view_field(
&mut self,
_tag: crate::encoding::Tag,
cur: &'a [u8],
_before_tag: &'a [u8],
_ctx: crate::DecodeContext<'_>,
) -> Result<&'a [u8], DecodeError> {
Ok(cur)
}
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) -> Result<SimpleMessage, DecodeError> {
Ok(SimpleMessage {
id: self.id,
name: self.name.into(),
})
}
}
impl<'a> ViewEncode<'a> for SimpleMessageView<'a> {
fn compute_size(&self, _cache: &mut crate::SizeCache) -> 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, _cache: &mut crate::SizeCache, 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 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_reborrow() {
let bytes = encode_simple(42, "hello");
let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
assert_eq!(view.reborrow().id, 42);
assert_eq!(view.reborrow().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().unwrap();
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.reborrow().id, 0);
assert_eq!(view.reborrow().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.reborrow().id, 99);
assert_eq!(view.reborrow().name, "roundtrip");
let back = view.to_owned_message().unwrap();
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.reborrow().id, 42);
assert_eq!(view.reborrow().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.reborrow().id, 42);
assert_eq!(cloned.reborrow().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 merge_view_field(
&mut self,
_tag: crate::encoding::Tag,
cur: &'a [u8],
_before_tag: &'a [u8],
_ctx: crate::DecodeContext<'_>,
) -> Result<&'a [u8], DecodeError> {
Ok(cur)
}
fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError> {
Ok(DropCountingView {
inner: SimpleMessageView::decode_view(buf)?,
})
}
fn to_owned_message(&self) -> Result<SimpleMessage, DecodeError> {
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.reborrow().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.reborrow().id, 42);
assert_eq!(v.reborrow().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.reborrow().id, 42);
assert_eq!(view.reborrow().name, "parts");
}
#[test]
fn reborrow_fields_match_original() {
let bytes = encode_simple(7, "hello");
let owned = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
let reborrowed: &SimpleMessageView<'_> = owned.reborrow();
assert_eq!(reborrowed.id, 7);
assert_eq!(reborrowed.name, "hello");
let buf_start = owned.bytes().as_ptr() as usize;
let buf_end = buf_start + owned.bytes().len();
assert!((buf_start..buf_end).contains(&(reborrowed.name.as_ptr() as usize)));
}
#[test]
fn reborrow_does_not_consume_owned_view() {
let bytes = encode_simple(1, "world");
let owned = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
let r1: &SimpleMessageView<'_> = owned.reborrow();
let r2: &SimpleMessageView<'_> = owned.reborrow();
assert_eq!(r1.name, r2.name);
assert_eq!(owned.reborrow().name, "world");
}
#[derive(Clone, Debug, Default, PartialEq)]
struct SimpleLazyView<'a> {
pub id: i32,
pub name: &'a str,
}
impl<'a> LazyMessageView<'a> for SimpleLazyView<'a> {
type Owned = SimpleMessage;
fn decode_lazy(buf: &'a [u8]) -> Result<Self, DecodeError> {
let limit = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
Self::decode_lazy_with_ctx(
buf,
crate::DecodeContext::new(crate::RECURSION_LIMIT, &limit),
)
}
fn decode_lazy_with_ctx(
buf: &'a [u8],
ctx: crate::DecodeContext<'_>,
) -> Result<Self, DecodeError> {
let mut view = SimpleLazyView::default();
view.merge_lazy(buf, ctx)?;
Ok(view)
}
fn merge_lazy(
&mut self,
buf: &'a [u8],
ctx: crate::DecodeContext<'_>,
) -> Result<(), DecodeError> {
let mut cursor: &'a [u8] = buf;
while !cursor.is_empty() {
let tag = crate::encoding::Tag::decode(&mut cursor)?;
match tag.field_number() {
1 => self.id = crate::types::decode_int32(&mut cursor)?,
2 => self.name = crate::types::borrow_str(&mut cursor)?,
_ => crate::encoding::skip_field_depth(tag, &mut cursor, ctx.depth())?,
}
}
Ok(())
}
fn to_owned_message(&self) -> Result<SimpleMessage, DecodeError> {
Ok(SimpleMessage {
id: self.id,
name: self.name.into(),
})
}
}
fn full_budget_ctx(cell: &core::cell::Cell<usize>) -> crate::DecodeContext<'_> {
crate::DecodeContext::new(crate::RECURSION_LIMIT, cell)
}
#[test]
fn lazy_message_field_view_decodes_on_access() {
let bytes = encode_simple(42, "lazy");
let unset = LazyMessageFieldView::<SimpleLazyView<'_>>::unset();
assert!(unset.is_unset());
assert!(unset.fragments().is_empty());
assert!(unset.get().unwrap().is_none());
assert_eq!(unset.get_or_default().unwrap(), SimpleLazyView::default());
let lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::from_bytes(&bytes);
assert!(lazy.is_set());
assert_eq!(lazy.fragments(), &[&bytes[..]]);
let v = lazy.get().unwrap().expect("set");
assert_eq!((v.id, v.name), (42, "lazy"));
assert_eq!(lazy.get().unwrap().unwrap().id, 42);
assert_eq!(v.to_owned_message().unwrap().name, "lazy");
}
#[test]
fn lazy_message_field_view_merges_fragments() {
let frag1 = encode_simple(0, "from-frag-1");
let frag2 = encode_simple(7, "");
let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
let mut lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::unset();
lazy.push_fragment(&frag1, full_budget_ctx(&cell));
assert_eq!(lazy.fragments().len(), 1);
lazy.push_fragment(&frag2, full_budget_ctx(&cell));
assert_eq!(lazy.fragments(), &[&frag1[..], &frag2[..]]);
let v = lazy.get().unwrap().expect("set");
assert_eq!((v.id, v.name), (7, "from-frag-1"));
let frag3 = encode_simple(9, "final");
lazy.push_fragment(&frag3, full_budget_ctx(&cell));
assert_eq!(lazy.fragments().len(), 3);
let v = lazy.get().unwrap().expect("set");
assert_eq!((v.id, v.name), (9, "final"));
}
#[test]
fn lazy_message_field_view_records_smallest_budgets() {
let bytes = encode_simple(1, "x");
let cell_big = core::cell::Cell::new(500);
let cell_small = core::cell::Cell::new(3);
let mut lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::unset();
lazy.push_fragment(&bytes, crate::DecodeContext::new(80, &cell_big));
lazy.push_fragment(&bytes, crate::DecodeContext::new(50, &cell_small));
assert!(lazy.get().unwrap().is_some());
}
#[test]
fn lazy_message_field_view_clone_default_debug() {
let bytes = encode_simple(1, "x");
let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
let mut lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::default();
assert!(lazy.is_unset());
lazy.push_fragment(&bytes, full_budget_ctx(&cell));
lazy.push_fragment(&bytes, full_budget_ctx(&cell));
let cloned = lazy.clone();
assert_eq!(cloned.fragments(), lazy.fragments());
let dbg = alloc::format!("{lazy:?}");
assert!(dbg.contains("is_set: true"), "{dbg}");
assert!(dbg.contains("fragments: 2"), "{dbg}");
}
#[test]
fn lazy_message_field_view_malformed_errors_on_access() {
let malformed = [0xFFu8; 3];
let lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::from_bytes(&malformed);
assert!(lazy.is_set());
assert!(lazy.get().is_err());
}
#[test]
fn lazy_repeated_view_decodes_per_element() {
let b0 = encode_simple(1, "a");
let b1 = encode_simple(2, "b");
let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
let mut rep = LazyRepeatedView::<SimpleLazyView<'_>>::new();
assert!(rep.is_empty());
rep.push_bytes(&b0, full_budget_ctx(&cell));
rep.push_bytes(&b1, full_budget_ctx(&cell));
assert_eq!(rep.len(), 2);
assert_eq!(rep.raw_elements(), &[&b0[..], &b1[..]]);
assert_eq!(rep.get(0).unwrap().unwrap().name, "a");
assert_eq!(rep.get(1).unwrap().unwrap().id, 2);
assert!(rep.get(2).is_none());
}
#[test]
fn lazy_repeated_view_iter() {
let bufs: alloc::vec::Vec<Bytes> = (1..=3)
.map(|i| encode_simple(i, core::str::from_utf8(&[b'a' + i as u8]).unwrap()))
.collect();
let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
let mut rep = LazyRepeatedView::<SimpleLazyView<'_>>::new();
for b in &bufs {
rep.push_bytes(b, full_budget_ctx(&cell));
}
let iter = rep.iter();
assert_eq!(iter.len(), 3);
let ids: alloc::vec::Vec<i32> = iter.map(|r| r.unwrap().id).collect();
assert_eq!(ids, [1, 2, 3]);
let names: alloc::vec::Vec<&str> = (&rep).into_iter().map(|r| r.unwrap().name).collect();
assert_eq!(names, ["b", "c", "d"]);
let rev_ids: alloc::vec::Vec<i32> = rep.iter().rev().map(|r| r.unwrap().id).collect();
assert_eq!(rev_ids, [3, 2, 1]);
}
#[test]
fn lazy_repeated_view_iter_surfaces_element_errors() {
let good = encode_simple(1, "ok");
let malformed = [0xFFu8; 3];
let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
let mut rep = LazyRepeatedView::<SimpleLazyView<'_>>::new();
rep.push_bytes(&good, full_budget_ctx(&cell));
rep.push_bytes(&malformed, full_budget_ctx(&cell));
let results: alloc::vec::Vec<_> = rep.iter().collect();
assert!(results[0].is_ok());
assert!(results[1].is_err());
let cloned = rep.clone();
assert_eq!(cloned.len(), 2);
}
}