Skip to main content

buffa_reflect/dynamic/
message.rs

1//! [`DynamicMessage`] — a runtime-typed message backed by a
2//! [`MessageDescriptor`].
3
4use std::borrow::Cow;
5
6use buffa::{
7    DecodeError, EncodeError,
8    bytes::{Buf, BufMut, Bytes, BytesMut},
9};
10
11use crate::{
12    dynamic::{
13        fields::{DynamicMessageFieldSet, ValueOrUnknown},
14        message_codec, message_decode,
15        unknown::UnknownFieldSet,
16        value::{SetFieldError, Value},
17    },
18    field::FieldDescriptor,
19    message::MessageDescriptor,
20    pool::DescriptorPool,
21};
22
23/// A protobuf message whose schema is known at runtime via a
24/// [`MessageDescriptor`].
25///
26/// `DynamicMessage` is the workhorse type that lets a single binary
27/// transcode, inspect, or mutate any proto message in any
28/// [`DescriptorPool`]. See the module-level docs for examples.
29#[derive(Clone, Debug)]
30pub struct DynamicMessage {
31    pub(crate) desc: MessageDescriptor,
32    pub(crate) fields: DynamicMessageFieldSet,
33}
34
35impl PartialEq for DynamicMessage {
36    fn eq(&self, other: &Self) -> bool {
37        self.desc == other.desc && self.fields == other.fields
38    }
39}
40
41impl DynamicMessage {
42    /// Construct an empty message of the given descriptor.
43    #[must_use]
44    pub fn new(desc: MessageDescriptor) -> Self {
45        Self {
46            desc,
47            fields: DynamicMessageFieldSet::default(),
48        }
49    }
50
51    /// The owning descriptor.
52    #[must_use]
53    pub fn descriptor(&self) -> MessageDescriptor {
54        self.desc.clone()
55    }
56
57    /// The pool the descriptor was built from. Cloning is `Arc`-cheap.
58    #[must_use]
59    pub fn parent_pool(&self) -> DescriptorPool {
60        self.desc.pool.clone()
61    }
62
63    /// True iff no known or unknown field has been recorded.
64    #[must_use]
65    pub fn is_empty(&self) -> bool {
66        self.fields.is_empty()
67    }
68
69    // ── decode ──────────────────────────────────────────────────────────
70
71    /// Decode `buf` into a fresh [`DynamicMessage`] of the given
72    /// descriptor.
73    ///
74    /// # Errors
75    /// See [`DecodeError`].
76    pub fn decode<B: Buf>(desc: MessageDescriptor, mut buf: B) -> Result<Self, DecodeError> {
77        let mut msg = Self::new(desc);
78        message_decode::merge(&mut msg, &mut buf, buffa::RECURSION_LIMIT)?;
79        Ok(msg)
80    }
81
82    /// Decode with a custom [`buffa::DecodeOptions`].
83    ///
84    /// # Errors
85    /// See [`DecodeError`].
86    pub fn decode_with_options<B: Buf>(
87        desc: MessageDescriptor,
88        mut buf: B,
89        opts: buffa::DecodeOptions,
90    ) -> Result<Self, DecodeError> {
91        if buf.remaining() > opts.max_message_size() {
92            return Err(DecodeError::MessageTooLarge);
93        }
94        let mut msg = Self::new(desc);
95        message_decode::merge(&mut msg, &mut buf, opts.recursion_limit())?;
96        Ok(msg)
97    }
98
99    /// Merge wire bytes into `self`, accumulating fields atop the
100    /// existing ones (matching `Message::merge` semantics).
101    ///
102    /// # Errors
103    /// See [`DecodeError`].
104    pub fn merge<B: Buf>(&mut self, mut buf: B) -> Result<(), DecodeError> {
105        message_decode::merge(self, &mut buf, buffa::RECURSION_LIMIT)
106    }
107
108    // ── encode ──────────────────────────────────────────────────────────
109
110    /// Encoded byte length, including unknown fields.
111    #[must_use]
112    pub fn encoded_len(&self) -> usize {
113        message_codec::encoded_len(self)
114    }
115
116    /// Encode to `buf`. Iterates fields in number order; unknown fields
117    /// re-emit at their original positions.
118    ///
119    /// # Errors
120    /// Bubbles up encoder failures. With well-formed in-memory state
121    /// the only realistic source of failure is `BufMut::remaining_mut`
122    /// running short.
123    pub fn encode<B: BufMut>(&self, buf: &mut B) -> Result<(), EncodeError> {
124        message_codec::encode(self, buf)
125    }
126
127    /// Encode to a fresh `Vec<u8>`.
128    #[must_use]
129    pub fn encode_to_vec(&self) -> Vec<u8> {
130        let mut buf = Vec::with_capacity(self.encoded_len());
131        // BufMut for Vec never errors as long as the heap is OK.
132        let _ = self.encode(&mut buf);
133        buf
134    }
135
136    /// Encode to a fresh [`Bytes`].
137    #[must_use]
138    pub fn encode_to_bytes(&self) -> Bytes {
139        let mut buf = BytesMut::with_capacity(self.encoded_len());
140        let _ = self.encode(&mut buf);
141        buf.freeze()
142    }
143
144    // ── transcode ───────────────────────────────────────────────────────
145
146    /// Merge a typed `T`'s wire bytes into `self`.
147    ///
148    /// # Errors
149    /// See [`DecodeError`]. Errors imply `T`'s schema and `self.descriptor()`
150    /// are incompatible.
151    pub fn transcode_from<T: buffa::Message>(&mut self, value: &T) -> Result<(), DecodeError> {
152        self.merge(value.encode_to_vec().as_slice())
153    }
154
155    /// Decode `self` as the typed `T`.
156    ///
157    /// # Errors
158    /// See [`DecodeError`]. Errors imply `T`'s schema and the dynamic
159    /// message's descriptor are incompatible.
160    pub fn transcode_to<T: buffa::Message + Default>(&self) -> Result<T, DecodeError> {
161        T::decode_from_slice(self.encode_to_vec().as_slice())
162    }
163
164    /// Specialisation of `transcode_to_dynamic` — returns `self.clone()`
165    /// without the wire round-trip a typed `ReflectMessage` would pay.
166    #[must_use]
167    pub fn transcode_to_dynamic(&self) -> Self {
168        self.clone()
169    }
170
171    // ── inspection / iteration ──────────────────────────────────────────
172
173    /// Iterate every populated known field in field-number order.
174    pub fn fields(&self) -> impl Iterator<Item = (FieldDescriptor, &Value)> + '_ {
175        let desc = self.desc.clone();
176        self.fields
177            .iter_known()
178            .filter_map(move |(n, v)| desc.get_field_by_number(n).map(|fd| (fd, v)))
179    }
180
181    /// Iterate fields with explicit knobs over default-omission and
182    /// declaration vs number order. See the design doc §6 for the
183    /// rationale.
184    pub fn iter_with_options<'a>(
185        &'a self,
186        include_default: bool,
187        index_order: bool,
188    ) -> Box<dyn Iterator<Item = (FieldDescriptor, Cow<'a, Value>)> + 'a> {
189        if index_order {
190            Box::new(self.iter_index_order(include_default))
191        } else {
192            Box::new(self.iter_number_order(include_default))
193        }
194    }
195
196    fn iter_number_order<'a>(
197        &'a self,
198        include_default: bool,
199    ) -> impl Iterator<Item = (FieldDescriptor, Cow<'a, Value>)> + 'a {
200        let descriptors = collect_descriptors_in_number_order(&self.desc, include_default);
201        descriptors
202            .into_iter()
203            .filter_map(move |fd| match self.fields.get_value(fd.number()) {
204                Some(v) => Some((fd, Cow::Borrowed(v))),
205                None if include_default => {
206                    let v = Value::default_value_for_field(&fd);
207                    Some((fd, Cow::Owned(v)))
208                }
209                None => None,
210            })
211    }
212
213    fn iter_index_order<'a>(
214        &'a self,
215        include_default: bool,
216    ) -> impl Iterator<Item = (FieldDescriptor, Cow<'a, Value>)> + 'a {
217        self.desc
218            .fields()
219            .filter_map(move |fd| match self.fields.get_value(fd.number()) {
220                Some(v) => Some((fd, Cow::Borrowed(v))),
221                None if include_default => {
222                    let v = Value::default_value_for_field(&fd);
223                    Some((fd, Cow::Owned(v)))
224                }
225                None => None,
226            })
227    }
228
229    /// True iff a known value exists at `field`'s number, or for
230    /// non-presence-tracking fields, the value is non-default.
231    #[must_use]
232    pub fn has_field(&self, field: &FieldDescriptor) -> bool {
233        match self.fields.get_value(field.number()) {
234            Some(v) => field.supports_presence() || !v.is_default(&field.kind()),
235            None => false,
236        }
237    }
238
239    /// Read `field` — borrows the populated value or synthesises a
240    /// default.
241    #[must_use]
242    pub fn get_field(&self, field: &FieldDescriptor) -> Cow<'_, Value> {
243        match self.fields.get_value(field.number()) {
244            Some(v) => Cow::Borrowed(v),
245            None => Cow::Owned(Value::default_value_for_field(field)),
246        }
247    }
248
249    /// Mutable accessor — clears any active oneof sibling first, then
250    /// inserts a default value if the slot was empty.
251    pub fn get_field_mut(&mut self, field: &FieldDescriptor) -> &mut Value {
252        if !self.fields.has_value(field.number()) {
253            let default = Value::default_value_for_field(field);
254            self.fields.set(field, default);
255        } else if let Some(oneof) = field.containing_oneof() {
256            let self_number = field.number();
257            for sibling in oneof.fields() {
258                if sibling.number() != self_number {
259                    self.fields.fields.remove(&sibling.number());
260                }
261            }
262        }
263        self.fields
264            .get_value_mut(field.number())
265            .expect("just-inserted value")
266    }
267
268    /// `has_field` keyed by proto name.
269    #[must_use]
270    pub fn has_field_by_name(&self, name: &str) -> bool {
271        match self.desc.get_field_by_name(name) {
272            Some(fd) => self.has_field(&fd),
273            None => false,
274        }
275    }
276
277    /// `get_field` keyed by proto name.
278    #[must_use]
279    pub fn get_field_by_name(&self, name: &str) -> Option<Cow<'_, Value>> {
280        self.desc
281            .get_field_by_name(name)
282            .map(|fd| self.get_field(&fd))
283    }
284
285    /// `get_field_mut` keyed by proto name.
286    pub fn get_field_by_name_mut(&mut self, name: &str) -> Option<&mut Value> {
287        let fd = self.desc.get_field_by_name(name)?;
288        Some(self.get_field_mut(&fd))
289    }
290
291    /// `has_field` keyed by tag number.
292    #[must_use]
293    pub fn has_field_by_number(&self, number: u32) -> bool {
294        match self.desc.get_field_by_number(number) {
295            Some(fd) => self.has_field(&fd),
296            None => false,
297        }
298    }
299
300    /// `get_field` keyed by tag number.
301    #[must_use]
302    pub fn get_field_by_number(&self, number: u32) -> Option<Cow<'_, Value>> {
303        self.desc
304            .get_field_by_number(number)
305            .map(|fd| self.get_field(&fd))
306    }
307
308    /// `get_field_mut` keyed by tag number.
309    pub fn get_field_by_number_mut(&mut self, number: u32) -> Option<&mut Value> {
310        let fd = self.desc.get_field_by_number(number)?;
311        Some(self.get_field_mut(&fd))
312    }
313
314    // ── mutation: dual API ──────────────────────────────────────────────
315
316    /// Set `field` to `value`. Validates with `debug_assert!` (zero
317    /// cost in release builds); panics on type mismatch in debug. Use
318    /// [`Self::try_set_field`] when the value's shape is data-driven.
319    ///
320    /// # Panics
321    ///
322    /// Panics in debug builds when `value` doesn't match `field`'s
323    /// declared shape. In release builds the bad value is stored and
324    /// will surface as an encode-time mismatch.
325    pub fn set_field(&mut self, field: &FieldDescriptor, value: Value) {
326        self.fields.set(field, value);
327    }
328
329    /// Validating equivalent of [`Self::set_field`]: returns
330    /// [`SetFieldError::InvalidType`] when `value` doesn't match
331    /// `field`.
332    ///
333    /// # Errors
334    ///
335    /// See [`SetFieldError`].
336    pub fn try_set_field(
337        &mut self,
338        field: &FieldDescriptor,
339        value: Value,
340    ) -> Result<(), SetFieldError> {
341        self.fields.try_set(field, value)
342    }
343
344    /// `set_field` keyed by tag number.
345    ///
346    /// # Panics
347    ///
348    /// Panics if `number` is unknown to the descriptor (in addition to
349    /// the type-mismatch panic inherited from [`Self::set_field`]).
350    pub fn set_field_by_number(&mut self, number: u32, value: Value) {
351        let fd = self
352            .desc
353            .get_field_by_number(number)
354            .expect("set_field_by_number: unknown field number");
355        self.fields.set(&fd, value);
356    }
357
358    /// Validating `_by_number` form.
359    ///
360    /// # Errors
361    ///
362    /// Returns [`SetFieldError::NotFound`] when `number` is unknown.
363    pub fn try_set_field_by_number(
364        &mut self,
365        number: u32,
366        value: Value,
367    ) -> Result<(), SetFieldError> {
368        let fd = self
369            .desc
370            .get_field_by_number(number)
371            .ok_or(SetFieldError::NotFound)?;
372        self.fields.try_set(&fd, value)
373    }
374
375    /// `set_field` keyed by proto name.
376    ///
377    /// # Panics
378    ///
379    /// Panics if `name` is unknown to the descriptor (in addition to
380    /// the type-mismatch panic inherited from [`Self::set_field`]).
381    pub fn set_field_by_name(&mut self, name: &str, value: Value) {
382        let fd = self
383            .desc
384            .get_field_by_name(name)
385            .expect("set_field_by_name: unknown field name");
386        self.fields.set(&fd, value);
387    }
388
389    /// Validating `_by_name` form.
390    ///
391    /// # Errors
392    ///
393    /// Returns [`SetFieldError::NotFound`] when `name` is unknown.
394    pub fn try_set_field_by_name(&mut self, name: &str, value: Value) -> Result<(), SetFieldError> {
395        let fd = self
396            .desc
397            .get_field_by_name(name)
398            .ok_or(SetFieldError::NotFound)?;
399        self.fields.try_set(&fd, value)
400    }
401
402    /// Clear `field` (and any sibling oneof member).
403    pub fn clear_field(&mut self, field: &FieldDescriptor) {
404        self.fields.clear(field);
405    }
406
407    /// Clear by name; no-op when the name is unknown.
408    pub fn clear_field_by_name(&mut self, name: &str) {
409        if let Some(fd) = self.desc.get_field_by_name(name) {
410            self.fields.clear(&fd);
411        }
412    }
413
414    /// Clear by number; no-op when the number is unknown.
415    pub fn clear_field_by_number(&mut self, number: u32) {
416        if let Some(fd) = self.desc.get_field_by_number(number) {
417            self.fields.clear(&fd);
418        }
419    }
420
421    /// Iterate every recorded unknown-field set in number order.
422    pub fn unknown_fields(&self) -> impl Iterator<Item = (u32, &UnknownFieldSet)> + '_ {
423        self.fields.iter_unknown()
424    }
425
426    /// Move every unknown-field set out of `self`. The returned vector
427    /// is in number order.
428    pub fn drain_unknown_fields(&mut self) -> impl Iterator<Item = (u32, UnknownFieldSet)> {
429        self.fields.drain_unknown().into_iter()
430    }
431
432    pub(crate) fn fields_set_ref(&self) -> &DynamicMessageFieldSet {
433        &self.fields
434    }
435
436    pub(crate) fn fields_set_mut(&mut self) -> &mut DynamicMessageFieldSet {
437        &mut self.fields
438    }
439
440    /// Iterate over the raw entries in number order — used by the codec
441    /// to interleave known + unknown encoding.
442    pub(crate) fn iter_storage(&self) -> impl Iterator<Item = (u32, &ValueOrUnknown)> + '_ {
443        self.fields.iter_in_order()
444    }
445}
446
447fn collect_descriptors_in_number_order(
448    desc: &MessageDescriptor,
449    _include_default: bool,
450) -> Vec<FieldDescriptor> {
451    let mut fields: Vec<FieldDescriptor> = desc.fields().collect();
452    fields.sort_by_key(|f| f.number());
453    fields
454}