Skip to main content

capnp/
dynamic_struct.rs

1//! Dynamically-typed structs.
2
3use crate::introspect::TypeVariant;
4use crate::private::layout;
5use crate::schema::{Field, StructSchema};
6use crate::schema_capnp::{field, node, value};
7use crate::{dynamic_list, dynamic_value};
8use crate::{Error, ErrorKind, Result};
9
10fn has_discriminant_value(reader: field::Reader) -> bool {
11    reader.get_discriminant_value() != field::NO_DISCRIMINANT
12}
13
14pub(crate) fn struct_size_from_schema(schema: StructSchema) -> Result<layout::StructSize> {
15    if let node::Struct(s) = schema.proto.which()? {
16        Ok(layout::StructSize {
17            data: s.get_data_word_count(),
18            pointers: s.get_pointer_count(),
19        })
20    } else {
21        Err(Error::from_kind(ErrorKind::NotAStruct))
22    }
23}
24
25/// A read-only dynamically-typed struct.
26#[derive(Clone, Copy)]
27pub struct Reader<'a> {
28    pub(crate) reader: layout::StructReader<'a>,
29    pub(crate) schema: StructSchema,
30}
31
32impl<'a> From<Reader<'a>> for dynamic_value::Reader<'a> {
33    fn from(x: Reader<'a>) -> dynamic_value::Reader<'a> {
34        dynamic_value::Reader::Struct(x)
35    }
36}
37
38impl<'a> Reader<'a> {
39    pub fn new(reader: layout::StructReader<'a>, schema: StructSchema) -> Self {
40        Self { reader, schema }
41    }
42
43    pub fn total_size(&self) -> crate::Result<crate::MessageSize> {
44        self.reader.total_size()
45    }
46
47    pub fn get_schema(&self) -> StructSchema {
48        self.schema
49    }
50
51    pub fn get(self, field: Field) -> Result<dynamic_value::Reader<'a>> {
52        assert_eq!(self.schema, field.parent);
53        let ty = field.get_type();
54        match field.get_proto().which()? {
55            field::Slot(slot) => {
56                let offset = slot.get_offset();
57                let default_value = slot.get_default_value()?;
58
59                match (ty.which(), default_value.which()?) {
60                    (TypeVariant::Void, _) => Ok(dynamic_value::Reader::Void),
61                    (TypeVariant::Bool, value::Bool(b)) => Ok(dynamic_value::Reader::Bool(
62                        self.reader.get_bool_field_mask(offset as usize, b),
63                    )),
64                    (TypeVariant::Int8, value::Int8(x)) => Ok(dynamic_value::Reader::Int8(
65                        self.reader.get_data_field_mask::<i8>(offset as usize, x),
66                    )),
67                    (TypeVariant::Int16, value::Int16(x)) => Ok(dynamic_value::Reader::Int16(
68                        self.reader.get_data_field_mask::<i16>(offset as usize, x),
69                    )),
70                    (TypeVariant::Int32, value::Int32(x)) => Ok(dynamic_value::Reader::Int32(
71                        self.reader.get_data_field_mask::<i32>(offset as usize, x),
72                    )),
73                    (TypeVariant::Int64, value::Int64(x)) => Ok(dynamic_value::Reader::Int64(
74                        self.reader.get_data_field_mask::<i64>(offset as usize, x),
75                    )),
76                    (TypeVariant::UInt8, value::Uint8(x)) => Ok(dynamic_value::Reader::UInt8(
77                        self.reader.get_data_field_mask::<u8>(offset as usize, x),
78                    )),
79                    (TypeVariant::UInt16, value::Uint16(x)) => Ok(dynamic_value::Reader::UInt16(
80                        self.reader.get_data_field_mask::<u16>(offset as usize, x),
81                    )),
82                    (TypeVariant::UInt32, value::Uint32(x)) => Ok(dynamic_value::Reader::UInt32(
83                        self.reader.get_data_field_mask::<u32>(offset as usize, x),
84                    )),
85                    (TypeVariant::UInt64, value::Uint64(x)) => Ok(dynamic_value::Reader::UInt64(
86                        self.reader.get_data_field_mask::<u64>(offset as usize, x),
87                    )),
88                    (TypeVariant::Float32, value::Float32(x)) => {
89                        Ok(dynamic_value::Reader::Float32(
90                            self.reader
91                                .get_data_field_mask::<f32>(offset as usize, x.to_bits()),
92                        ))
93                    }
94                    (TypeVariant::Float64, value::Float64(x)) => {
95                        Ok(dynamic_value::Reader::Float64(
96                            self.reader
97                                .get_data_field_mask::<f64>(offset as usize, x.to_bits()),
98                        ))
99                    }
100                    (TypeVariant::Enum(schema), value::Enum(d)) => Ok(dynamic_value::Enum::new(
101                        self.reader.get_data_field_mask::<u16>(offset as usize, d),
102                        schema.into(),
103                    )
104                    .into()),
105                    (TypeVariant::Text, dval) => {
106                        let p = self.reader.get_pointer_field(offset as usize);
107                        // If the type is a generic, then the default value
108                        // is always an empty AnyPointer. Ignore that case.
109                        let t1 = if let (true, value::Text(t)) = (p.is_null(), dval) {
110                            t?
111                        } else {
112                            p.get_text(None)?
113                        };
114                        Ok(dynamic_value::Reader::Text(t1))
115                    }
116                    (TypeVariant::Data, dval) => {
117                        let p = self.reader.get_pointer_field(offset as usize);
118                        // If the type is a generic, then the default value
119                        // is always an empty AnyPointer. Ignore that case.
120                        let d1 = if let (true, value::Data(d)) = (p.is_null(), dval) {
121                            d?
122                        } else {
123                            p.get_data(None)?
124                        };
125                        Ok(dynamic_value::Reader::Data(d1))
126                    }
127                    (TypeVariant::Struct(schema), dval) => {
128                        let p = self.reader.get_pointer_field(offset as usize);
129                        // If the type is a generic, then the default value
130                        // is always an empty AnyPointer. Ignore that case.
131                        let p1 = if let (true, value::Struct(s)) = (p.is_null(), dval) {
132                            s.reader
133                        } else {
134                            p
135                        };
136                        let r = p1.get_struct(None)?;
137                        Ok(Reader::new(r, schema.into()).into())
138                    }
139                    (TypeVariant::List(element_type), dval) => {
140                        let p = self.reader.get_pointer_field(offset as usize);
141                        // If the type is a generic, then the default value
142                        // is always an empty AnyPointer. Ignore that case.
143                        let p1 = if let (true, value::List(l)) = (p.is_null(), dval) {
144                            l.reader
145                        } else {
146                            p
147                        };
148                        let l = p1.get_list(element_type.expected_element_size(), None)?;
149                        Ok(dynamic_list::Reader::new(l, element_type).into())
150                    }
151                    (TypeVariant::AnyPointer, value::AnyPointer(a)) => {
152                        let p = self.reader.get_pointer_field(offset as usize);
153                        let a1 = if p.is_null() {
154                            a
155                        } else {
156                            crate::any_pointer::Reader::new(p)
157                        };
158                        Ok(dynamic_value::Reader::AnyPointer(a1))
159                    }
160                    (TypeVariant::Capability, value::Interface(())) => {
161                        Ok(dynamic_value::Reader::Capability(dynamic_value::Capability))
162                    }
163                    _ => Err(Error::from_kind(ErrorKind::FieldAndDefaultMismatch)),
164                }
165            }
166            field::Group(_) => {
167                if let TypeVariant::Struct(schema) = ty.which() {
168                    Ok(Reader::new(self.reader, schema.into()).into())
169                } else {
170                    Err(Error::from_kind(ErrorKind::GroupFieldButTypeIsNotStruct))
171                }
172            }
173        }
174    }
175
176    /// Gets the field with the given name.
177    pub fn get_named(self, field_name: &str) -> Result<dynamic_value::Reader<'a>> {
178        self.get(self.schema.get_field_by_name(field_name)?)
179    }
180
181    /// If this struct has union fields, returns the one that is currently active.
182    /// Otherwise, returns None.
183    pub fn which(&self) -> Result<Option<Field>> {
184        let node::Struct(st) = self.schema.get_proto().which()? else {
185            return Err(Error::from_kind(ErrorKind::NotAStruct));
186        };
187        if st.get_discriminant_count() == 0 {
188            Ok(None)
189        } else {
190            let discrim = self
191                .reader
192                .get_data_field::<u16>(st.get_discriminant_offset() as usize);
193            self.schema.get_field_by_discriminant(discrim)
194        }
195    }
196
197    /// On a field that is part of a union, returns `true` if the field
198    /// is active in the union and is not a null pointer. On non-union fields,
199    /// returns `true` if the field is not a null pointer.
200    pub fn has(&self, field: Field) -> Result<bool> {
201        assert_eq!(self.schema, field.parent);
202        let proto = field.get_proto();
203        if has_discriminant_value(proto) {
204            let node::Struct(st) = self.schema.get_proto().which()? else {
205                return Err(Error::from_kind(ErrorKind::NotAStruct));
206            };
207
208            let discrim = self
209                .reader
210                .get_data_field::<u16>(st.get_discriminant_offset() as usize);
211            if discrim != proto.get_discriminant_value() {
212                // Field is not active in the union.
213                return Ok(false);
214            }
215        }
216        let slot = match proto.which()? {
217            field::Group(_) => return Ok(true),
218            field::Slot(s) => s,
219        };
220        let ty = field.get_type();
221        if ty.is_pointer_type() {
222            Ok(!self
223                .reader
224                .get_pointer_field(slot.get_offset() as usize)
225                .is_null())
226        } else {
227            Ok(true)
228        }
229    }
230
231    pub fn has_named(&self, field_name: &str) -> Result<bool> {
232        let field = self.schema.get_field_by_name(field_name)?;
233        self.has(field)
234    }
235
236    /// Downcasts the `Reader` into a specific struct type. Panics if the
237    /// expected type does not match the value.
238    pub fn downcast<T: crate::traits::OwnedStruct>(self) -> T::Reader<'a> {
239        assert!(
240            crate::introspect::Type::from(crate::introspect::TypeVariant::Struct(self.schema.raw))
241                == T::introspect()
242        );
243        self.reader.into()
244    }
245}
246
247/// A mutable dynamically-typed struct.
248pub struct Builder<'a> {
249    pub(crate) builder: layout::StructBuilder<'a>,
250    pub(crate) schema: StructSchema,
251}
252
253impl<'a> From<Builder<'a>> for dynamic_value::Builder<'a> {
254    fn from(x: Builder<'a>) -> dynamic_value::Builder<'a> {
255        dynamic_value::Builder::Struct(x)
256    }
257}
258
259impl<'a> Builder<'a> {
260    pub fn new(builder: layout::StructBuilder<'a>, schema: StructSchema) -> Self {
261        Self { builder, schema }
262    }
263
264    pub fn reborrow(&mut self) -> Builder<'_> {
265        Builder {
266            builder: self.builder.reborrow(),
267            schema: self.schema,
268        }
269    }
270
271    pub fn reborrow_as_reader(&self) -> Reader<'_> {
272        Reader {
273            reader: self.builder.as_reader(),
274            schema: self.schema,
275        }
276    }
277
278    pub fn into_reader(self) -> Reader<'a> {
279        Reader {
280            schema: self.schema,
281            reader: self.builder.into_reader(),
282        }
283    }
284
285    pub fn get_schema(&self) -> StructSchema {
286        self.schema
287    }
288
289    pub fn get(self, field: Field) -> Result<dynamic_value::Builder<'a>> {
290        assert_eq!(self.schema, field.parent);
291        let ty = field.get_type();
292        match field.get_proto().which()? {
293            field::Slot(slot) => {
294                let offset = slot.get_offset();
295                let default_value = slot.get_default_value()?;
296
297                match (ty.which(), default_value.which()?) {
298                    (TypeVariant::Void, _) => Ok(dynamic_value::Builder::Void),
299                    (TypeVariant::Bool, value::Bool(b)) => Ok(dynamic_value::Builder::Bool(
300                        self.builder.get_bool_field_mask(offset as usize, b),
301                    )),
302                    (TypeVariant::Int8, value::Int8(x)) => Ok(dynamic_value::Builder::Int8(
303                        self.builder.get_data_field_mask::<i8>(offset as usize, x),
304                    )),
305                    (TypeVariant::Int16, value::Int16(x)) => Ok(dynamic_value::Builder::Int16(
306                        self.builder.get_data_field_mask::<i16>(offset as usize, x),
307                    )),
308                    (TypeVariant::Int32, value::Int32(x)) => Ok(dynamic_value::Builder::Int32(
309                        self.builder.get_data_field_mask::<i32>(offset as usize, x),
310                    )),
311                    (TypeVariant::Int64, value::Int64(x)) => Ok(dynamic_value::Builder::Int64(
312                        self.builder.get_data_field_mask::<i64>(offset as usize, x),
313                    )),
314                    (TypeVariant::UInt8, value::Uint8(x)) => Ok(dynamic_value::Builder::UInt8(
315                        self.builder.get_data_field_mask::<u8>(offset as usize, x),
316                    )),
317                    (TypeVariant::UInt16, value::Uint16(x)) => Ok(dynamic_value::Builder::UInt16(
318                        self.builder.get_data_field_mask::<u16>(offset as usize, x),
319                    )),
320                    (TypeVariant::UInt32, value::Uint32(x)) => Ok(dynamic_value::Builder::UInt32(
321                        self.builder.get_data_field_mask::<u32>(offset as usize, x),
322                    )),
323                    (TypeVariant::UInt64, value::Uint64(x)) => Ok(dynamic_value::Builder::UInt64(
324                        self.builder.get_data_field_mask::<u64>(offset as usize, x),
325                    )),
326                    (TypeVariant::Float32, value::Float32(x)) => {
327                        Ok(dynamic_value::Builder::Float32(
328                            self.builder
329                                .get_data_field_mask::<f32>(offset as usize, x.to_bits()),
330                        ))
331                    }
332                    (TypeVariant::Float64, value::Float64(x)) => {
333                        Ok(dynamic_value::Builder::Float64(
334                            self.builder
335                                .get_data_field_mask::<f64>(offset as usize, x.to_bits()),
336                        ))
337                    }
338                    (TypeVariant::Enum(schema), value::Enum(d)) => Ok(dynamic_value::Enum::new(
339                        self.builder.get_data_field_mask::<u16>(offset as usize, d),
340                        schema.into(),
341                    )
342                    .into()),
343                    (TypeVariant::Text, dval) => {
344                        let mut p = self.builder.get_pointer_field(offset as usize);
345                        if p.is_null() {
346                            // If the type is a generic, then the default value
347                            // is always an empty AnyPointer. Ignore that case.
348                            if let value::Text(t) = dval {
349                                p.set_text(t?);
350                            }
351                        }
352                        Ok(dynamic_value::Builder::Text(p.get_text(None)?))
353                    }
354                    (TypeVariant::Data, dval) => {
355                        let mut p = self.builder.get_pointer_field(offset as usize);
356                        if p.is_null() {
357                            // If the type is a generic, then the default value
358                            // is always an empty AnyPointer. Ignore that case.
359                            if let value::Data(d) = dval {
360                                p.set_data(d?);
361                            }
362                        }
363                        Ok(dynamic_value::Builder::Data(p.get_data(None)?))
364                    }
365                    (TypeVariant::Struct(schema), dval) => {
366                        let mut p = self.builder.get_pointer_field(offset as usize);
367                        if p.is_null() {
368                            // If the type is a generic, then the default value
369                            // is always an empty AnyPointer. Ignore that case.
370                            if let value::Struct(s) = dval {
371                                p.copy_from(s.reader, false)?;
372                            }
373                        }
374                        Ok(Builder::new(
375                            p.get_struct(struct_size_from_schema(schema.into())?, None)?,
376                            schema.into(),
377                        )
378                        .into())
379                    }
380                    (TypeVariant::List(element_type), dval) => {
381                        let mut p = self.builder.get_pointer_field(offset as usize);
382                        if p.is_null() {
383                            if let value::List(l) = dval {
384                                p.copy_from(l.reader, false)?;
385                            }
386                        }
387                        let l = if let TypeVariant::Struct(ss) = element_type.which() {
388                            p.get_struct_list(struct_size_from_schema(ss.into())?, None)?
389                        } else {
390                            p.get_list(element_type.expected_element_size(), None)?
391                        };
392
393                        Ok(dynamic_list::Builder::new(l, element_type).into())
394                    }
395                    (TypeVariant::AnyPointer, value::AnyPointer(_a)) => {
396                        // AnyPointer fields can't have a nontrivial default.
397                        Ok(crate::any_pointer::Builder::new(
398                            self.builder.get_pointer_field(offset as usize),
399                        )
400                        .into())
401                    }
402                    (TypeVariant::Capability, value::Interface(())) => Ok(
403                        dynamic_value::Builder::Capability(dynamic_value::Capability),
404                    ),
405                    _ => Err(Error::from_kind(ErrorKind::FieldAndDefaultMismatch)),
406                }
407            }
408            field::Group(_) => {
409                if let TypeVariant::Struct(schema) = ty.which() {
410                    Ok(Builder::new(self.builder, schema.into()).into())
411                } else {
412                    Err(Error::from_kind(ErrorKind::GroupFieldButTypeIsNotStruct))
413                }
414            }
415        }
416    }
417
418    pub fn get_named(self, field_name: &str) -> Result<dynamic_value::Builder<'a>> {
419        let field = self.schema.get_field_by_name(field_name)?;
420        self.get(field)
421    }
422
423    pub fn which(&self) -> Result<Option<Field>> {
424        let node::Struct(st) = self.schema.get_proto().which()? else {
425            return Err(Error::from_kind(ErrorKind::NotAStruct));
426        };
427        if st.get_discriminant_count() == 0 {
428            Ok(None)
429        } else {
430            let discrim = self
431                .builder
432                .get_data_field::<u16>(st.get_discriminant_offset() as usize);
433            self.schema.get_field_by_discriminant(discrim)
434        }
435    }
436
437    pub fn has(&self, field: Field) -> Result<bool> {
438        self.reborrow_as_reader().has(field)
439    }
440
441    pub fn has_named(&self, field_name: &str) -> Result<bool> {
442        let field = self.schema.get_field_by_name(field_name)?;
443        self.has(field)
444    }
445
446    pub fn set(&mut self, field: Field, value: dynamic_value::Reader<'_>) -> Result<()> {
447        assert_eq!(self.schema, field.parent);
448        self.set_in_union(field)?;
449        let ty = field.get_type();
450        match field.get_proto().which()? {
451            field::Slot(slot) => {
452                let dval = slot.get_default_value()?;
453                let offset = slot.get_offset() as usize;
454                match (ty.which(), value, dval.which()?) {
455                    (TypeVariant::Void, _, _) => Ok(()),
456                    (TypeVariant::Bool, dynamic_value::Reader::Bool(v), value::Bool(b)) => {
457                        self.builder.set_bool_field_mask(offset, v, b);
458                        Ok(())
459                    }
460                    (TypeVariant::Int8, dynamic_value::Reader::Int8(v), value::Int8(d)) => {
461                        self.builder.set_data_field_mask::<i8>(offset, v, d);
462                        Ok(())
463                    }
464                    (TypeVariant::Int16, dynamic_value::Reader::Int16(v), value::Int16(d)) => {
465                        self.builder.set_data_field_mask::<i16>(offset, v, d);
466                        Ok(())
467                    }
468                    (TypeVariant::Int32, dynamic_value::Reader::Int32(v), value::Int32(d)) => {
469                        self.builder.set_data_field_mask::<i32>(offset, v, d);
470                        Ok(())
471                    }
472                    (TypeVariant::Int64, dynamic_value::Reader::Int64(v), value::Int64(d)) => {
473                        self.builder.set_data_field_mask::<i64>(offset, v, d);
474                        Ok(())
475                    }
476                    (TypeVariant::UInt8, dynamic_value::Reader::UInt8(v), value::Uint8(d)) => {
477                        self.builder.set_data_field_mask::<u8>(offset, v, d);
478                        Ok(())
479                    }
480                    (TypeVariant::UInt16, dynamic_value::Reader::UInt16(v), value::Uint16(d)) => {
481                        self.builder.set_data_field_mask::<u16>(offset, v, d);
482                        Ok(())
483                    }
484                    (TypeVariant::UInt32, dynamic_value::Reader::UInt32(v), value::Uint32(d)) => {
485                        self.builder.set_data_field_mask::<u32>(offset, v, d);
486                        Ok(())
487                    }
488                    (TypeVariant::UInt64, dynamic_value::Reader::UInt64(v), value::Uint64(d)) => {
489                        self.builder.set_data_field_mask::<u64>(offset, v, d);
490                        Ok(())
491                    }
492                    (
493                        TypeVariant::Float32,
494                        dynamic_value::Reader::Float32(v),
495                        value::Float32(d),
496                    ) => {
497                        self.builder
498                            .set_data_field_mask::<f32>(offset, v, d.to_bits());
499                        Ok(())
500                    }
501                    (
502                        TypeVariant::Float64,
503                        dynamic_value::Reader::Float64(v),
504                        value::Float64(d),
505                    ) => {
506                        self.builder
507                            .set_data_field_mask::<f64>(offset, v, d.to_bits());
508                        Ok(())
509                    }
510                    (TypeVariant::Enum(_), dynamic_value::Reader::Enum(ev), value::Enum(d)) => {
511                        self.builder
512                            .set_data_field_mask::<u16>(offset, ev.get_value(), d);
513                        Ok(())
514                    }
515                    (TypeVariant::Text, dynamic_value::Reader::Text(tv), _) => {
516                        let mut p = self.builder.reborrow().get_pointer_field(offset);
517                        p.set_text(tv);
518                        Ok(())
519                    }
520                    (TypeVariant::Data, dynamic_value::Reader::Data(v), _) => {
521                        let mut p = self.builder.reborrow().get_pointer_field(offset);
522                        p.set_data(v);
523                        Ok(())
524                    }
525                    (TypeVariant::List(_), dynamic_value::Reader::List(l), _) => {
526                        let mut p = self.builder.reborrow().get_pointer_field(offset);
527                        p.set_list(&l.reader, false)
528                    }
529                    (TypeVariant::Struct(_), dynamic_value::Reader::Struct(v), _) => {
530                        let mut p = self.builder.reborrow().get_pointer_field(offset);
531                        p.set_struct(&v.reader, false)
532                    }
533                    (TypeVariant::AnyPointer, _, _) => {
534                        let mut target = crate::any_pointer::Builder::new(
535                            self.builder.reborrow().get_pointer_field(offset),
536                        );
537                        match value {
538                            dynamic_value::Reader::Text(t) => target.set_as(t),
539                            dynamic_value::Reader::Data(t) => {
540                                target.set_as::<crate::data::Owned>(t)
541                            }
542                            dynamic_value::Reader::Struct(s) => target.set_as(s),
543                            dynamic_value::Reader::List(l) => target.set_as(l),
544                            dynamic_value::Reader::Capability(_) => Err(Error::from_kind(
545                                ErrorKind::SettingDynamicCapabilitiesIsUnsupported,
546                            )),
547                            _ => Err(Error::from_kind(
548                                ErrorKind::CannotSetAnyPointerFieldToAPrimitiveValue,
549                            )),
550                        }
551                    }
552                    (TypeVariant::Capability, _, _) => Err(Error::from_kind(
553                        ErrorKind::SettingDynamicCapabilitiesIsUnsupported,
554                    )),
555                    _ => Err(Error::from_kind(ErrorKind::TypeMismatch)),
556                }
557            }
558            field::Group(_group) => {
559                let dynamic_value::Reader::Struct(src) = value else {
560                    return Err(Error::from_kind(ErrorKind::NotAStruct));
561                };
562                let dynamic_value::Builder::Struct(mut dst) = self.reborrow().init(field)? else {
563                    return Err(Error::from_kind(ErrorKind::NotAStruct));
564                };
565                if let Some(union_field) = src.which()? {
566                    dst.set(union_field, src.get(union_field)?)?;
567                }
568
569                let non_union_fields = src.schema.get_non_union_fields()?;
570                for idx in 0..non_union_fields.len() {
571                    let field = non_union_fields.get(idx);
572                    if src.has(field)? {
573                        dst.set(field, src.get(field)?)?;
574                    }
575                }
576                Ok(())
577            }
578        }
579    }
580
581    pub fn set_named(&mut self, field_name: &str, value: dynamic_value::Reader<'_>) -> Result<()> {
582        let field = self.schema.get_field_by_name(field_name)?;
583        self.set(field, value)
584    }
585
586    pub fn init(mut self, field: Field) -> Result<dynamic_value::Builder<'a>> {
587        assert_eq!(self.schema, field.parent);
588        self.set_in_union(field)?;
589        let ty = field.get_type();
590        match field.get_proto().which()? {
591            field::Slot(slot) => {
592                let offset = slot.get_offset() as usize;
593                match ty.which() {
594                    TypeVariant::Struct(ss) => Ok(Builder {
595                        schema: ss.into(),
596                        builder: self
597                            .builder
598                            .get_pointer_field(offset)
599                            .init_struct(struct_size_from_schema(ss.into())?),
600                    }
601                    .into()),
602                    TypeVariant::AnyPointer => {
603                        let mut p = self.builder.get_pointer_field(offset);
604                        p.clear();
605                        Ok(crate::any_pointer::Builder::new(p).into())
606                    }
607                    _ => Err(Error::from_kind(
608                        ErrorKind::InitIsOnlyValidForStructAndAnyPointerFields,
609                    )),
610                }
611            }
612            field::Group(_) => {
613                self.clear(field)?;
614                let TypeVariant::Struct(schema) = ty.which() else {
615                    return Err(Error::from_kind(ErrorKind::NotAStruct));
616                };
617                Ok((Builder::new(self.builder, schema.into())).into())
618            }
619        }
620    }
621
622    pub fn init_named(self, field_name: &str) -> Result<dynamic_value::Builder<'a>> {
623        let field = self.schema.get_field_by_name(field_name)?;
624        self.init(field)
625    }
626
627    pub fn initn(mut self, field: Field, size: u32) -> Result<dynamic_value::Builder<'a>> {
628        assert_eq!(self.schema, field.parent);
629        self.set_in_union(field)?;
630        let ty = field.get_type();
631        match field.get_proto().which()? {
632            field::Slot(slot) => {
633                let offset = slot.get_offset() as usize;
634                match ty.which() {
635                    TypeVariant::List(element_type) => match element_type.which() {
636                        TypeVariant::Struct(ss) => Ok(dynamic_list::Builder::new(
637                            self.builder
638                                .get_pointer_field(offset)
639                                .init_struct_list(size, struct_size_from_schema(ss.into())?),
640                            element_type,
641                        )
642                        .into()),
643                        _ => Ok(dynamic_list::Builder::new(
644                            self.builder
645                                .get_pointer_field(offset)
646                                .init_list(element_type.expected_element_size(), size),
647                            element_type,
648                        )
649                        .into()),
650                    },
651                    TypeVariant::Text => Ok(self
652                        .builder
653                        .get_pointer_field(offset)
654                        .init_text(size)
655                        .into()),
656                    TypeVariant::Data => Ok(self
657                        .builder
658                        .get_pointer_field(offset)
659                        .init_data(size)
660                        .into()),
661
662                    _ => Err(Error::from_kind(
663                        ErrorKind::InitnIsOnlyValidForListTextOrDataFields,
664                    )),
665                }
666            }
667            field::Group(_) => Err(Error::from_kind(
668                ErrorKind::InitnIsOnlyValidForListTextOrDataFields,
669            )),
670        }
671    }
672
673    pub fn initn_named(self, field_name: &str, size: u32) -> Result<dynamic_value::Builder<'a>> {
674        let field = self.schema.get_field_by_name(field_name)?;
675        self.initn(field, size)
676    }
677
678    /// Clears a field, setting it to its default value. For pointer fields,
679    /// this makes the field null.
680    pub fn clear(&mut self, field: Field) -> Result<()> {
681        assert_eq!(self.schema, field.parent);
682        self.set_in_union(field)?;
683        let ty = field.get_type();
684        match field.get_proto().which()? {
685            field::Slot(slot) => {
686                let offset = slot.get_offset() as usize;
687                match ty.which() {
688                    TypeVariant::Void => Ok(()),
689                    TypeVariant::Bool => {
690                        self.builder.set_bool_field(offset, false);
691                        Ok(())
692                    }
693                    TypeVariant::Int8 => {
694                        self.builder.set_data_field::<i8>(offset, 0);
695                        Ok(())
696                    }
697                    TypeVariant::Int16 => {
698                        self.builder.set_data_field::<i16>(offset, 0);
699                        Ok(())
700                    }
701                    TypeVariant::Int32 => {
702                        self.builder.set_data_field::<i32>(offset, 0);
703                        Ok(())
704                    }
705                    TypeVariant::Int64 => {
706                        self.builder.set_data_field::<i64>(offset, 0);
707                        Ok(())
708                    }
709                    TypeVariant::UInt8 => {
710                        self.builder.set_data_field::<u8>(offset, 0);
711                        Ok(())
712                    }
713                    TypeVariant::UInt16 => {
714                        self.builder.set_data_field::<u16>(offset, 0);
715                        Ok(())
716                    }
717                    TypeVariant::UInt32 => {
718                        self.builder.set_data_field::<u32>(offset, 0);
719                        Ok(())
720                    }
721                    TypeVariant::UInt64 => {
722                        self.builder.set_data_field::<u64>(offset, 0);
723                        Ok(())
724                    }
725                    TypeVariant::Float32 => {
726                        self.builder.set_data_field::<f32>(offset, 0f32);
727                        Ok(())
728                    }
729                    TypeVariant::Float64 => {
730                        self.builder.set_data_field::<f64>(offset, 0f64);
731                        Ok(())
732                    }
733                    TypeVariant::Enum(_) => {
734                        self.builder.set_data_field::<u16>(offset, 0);
735                        Ok(())
736                    }
737                    TypeVariant::Text
738                    | TypeVariant::Data
739                    | TypeVariant::Struct(_)
740                    | TypeVariant::List(_)
741                    | TypeVariant::AnyPointer
742                    | TypeVariant::Capability => {
743                        self.builder.reborrow().get_pointer_field(offset).clear();
744                        Ok(())
745                    }
746                }
747            }
748            field::Group(_) => {
749                let TypeVariant::Struct(schema) = ty.which() else {
750                    return Err(Error::from_kind(ErrorKind::NotAStruct));
751                };
752                let mut group = Builder::new(self.builder.reborrow(), schema.into());
753
754                // We clear the union field with discriminant 0 rather than the one that
755                // is set because we want the union to end up with its default field active.
756                if let Some(union_field) = group.schema.get_field_by_discriminant(0)? {
757                    group.clear(union_field)?;
758                }
759
760                let non_union_fields = group.schema.get_non_union_fields()?;
761                for idx in 0..non_union_fields.len() {
762                    group.clear(non_union_fields.get(idx))?;
763                }
764                Ok(())
765            }
766        }
767    }
768
769    pub fn clear_named(&mut self, field_name: &str) -> Result<()> {
770        let field = self.schema.get_field_by_name(field_name)?;
771        self.clear(field)
772    }
773
774    fn set_in_union(&mut self, field: Field) -> Result<()> {
775        if has_discriminant_value(field.get_proto()) {
776            let node::Struct(st) = self.schema.get_proto().which()? else {
777                return Err(Error::from_kind(ErrorKind::NotAStruct));
778            };
779            self.builder.set_data_field::<u16>(
780                st.get_discriminant_offset() as usize,
781                field.get_proto().get_discriminant_value(),
782            );
783        }
784        Ok(())
785    }
786
787    /// Downcasts the `Builder` into a specific struct type. Panics if the
788    /// expected type does not match the value.
789    pub fn downcast<T: crate::traits::OwnedStruct>(self) -> T::Builder<'a> {
790        assert!(
791            crate::introspect::Type::from(crate::introspect::TypeVariant::Struct(self.schema.raw))
792                == T::introspect()
793        );
794        self.builder.into()
795    }
796}
797
798impl<'a> crate::traits::SetterInput<crate::any_pointer::Owned> for Reader<'a> {
799    fn set_pointer_builder<'b>(
800        mut pointer: crate::private::layout::PointerBuilder<'b>,
801        value: Reader<'a>,
802        canonicalize: bool,
803    ) -> Result<()> {
804        pointer.set_struct(&value.reader, canonicalize)
805    }
806}
807
808impl core::fmt::Debug for Reader<'_> {
809    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
810        core::fmt::Debug::fmt(&crate::dynamic_value::Reader::from(*self), f)
811    }
812}