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