Skip to main content

capnp/
dynamic_list.rs

1//! Dynamically-typed lists.
2
3use crate::dynamic_value;
4use crate::introspect::{Type, TypeVariant};
5use crate::private::layout::{self, PrimitiveElement};
6use crate::traits::{IndexMove, ListIter};
7use crate::{Error, ErrorKind, Result};
8
9/// A read-only dynamically-typed list.
10#[derive(Copy, Clone)]
11pub struct Reader<'a> {
12    pub(crate) reader: layout::ListReader<'a>,
13    pub(crate) element_type: Type,
14}
15
16impl<'a> From<Reader<'a>> for dynamic_value::Reader<'a> {
17    fn from(x: Reader<'a>) -> dynamic_value::Reader<'a> {
18        dynamic_value::Reader::List(x)
19    }
20}
21
22impl<'a> Reader<'a> {
23    pub(crate) fn new(reader: layout::ListReader<'a>, element_type: Type) -> Self {
24        Self {
25            reader,
26            element_type,
27        }
28    }
29
30    pub fn len(&self) -> u32 {
31        self.reader.len()
32    }
33
34    pub fn is_empty(&self) -> bool {
35        self.len() == 0
36    }
37
38    pub fn element_type(&self) -> Type {
39        self.element_type
40    }
41
42    pub fn get(self, index: u32) -> Result<crate::dynamic_value::Reader<'a>> {
43        assert!(index < self.reader.len());
44        match self.element_type.which() {
45            TypeVariant::Void => Ok(dynamic_value::Reader::Void),
46            TypeVariant::Bool => Ok(dynamic_value::Reader::Bool(PrimitiveElement::get(
47                &self.reader,
48                index,
49            ))),
50            TypeVariant::Int8 => Ok(dynamic_value::Reader::Int8(PrimitiveElement::get(
51                &self.reader,
52                index,
53            ))),
54            TypeVariant::Int16 => Ok(dynamic_value::Reader::Int16(PrimitiveElement::get(
55                &self.reader,
56                index,
57            ))),
58            TypeVariant::Int32 => Ok(dynamic_value::Reader::Int32(PrimitiveElement::get(
59                &self.reader,
60                index,
61            ))),
62            TypeVariant::Int64 => Ok(dynamic_value::Reader::Int64(PrimitiveElement::get(
63                &self.reader,
64                index,
65            ))),
66            TypeVariant::UInt8 => Ok(dynamic_value::Reader::UInt8(PrimitiveElement::get(
67                &self.reader,
68                index,
69            ))),
70            TypeVariant::UInt16 => Ok(dynamic_value::Reader::UInt16(PrimitiveElement::get(
71                &self.reader,
72                index,
73            ))),
74            TypeVariant::UInt32 => Ok(dynamic_value::Reader::UInt32(PrimitiveElement::get(
75                &self.reader,
76                index,
77            ))),
78            TypeVariant::UInt64 => Ok(dynamic_value::Reader::UInt64(PrimitiveElement::get(
79                &self.reader,
80                index,
81            ))),
82            TypeVariant::Float32 => Ok(dynamic_value::Reader::Float32(PrimitiveElement::get(
83                &self.reader,
84                index,
85            ))),
86            TypeVariant::Float64 => Ok(dynamic_value::Reader::Float64(PrimitiveElement::get(
87                &self.reader,
88                index,
89            ))),
90            TypeVariant::Enum(e) => Ok(dynamic_value::Enum::new(
91                PrimitiveElement::get(&self.reader, index),
92                e.into(),
93            )
94            .into()),
95            TypeVariant::Text => Ok(dynamic_value::Reader::Text(
96                self.reader.get_pointer_element(index).get_text(None)?,
97            )),
98            TypeVariant::Data => Ok(dynamic_value::Reader::Data(
99                self.reader.get_pointer_element(index).get_data(None)?,
100            )),
101            TypeVariant::List(element_type) => Ok(Reader {
102                reader: self
103                    .reader
104                    .get_pointer_element(index)
105                    .get_list(element_type.expected_element_size(), None)?,
106                element_type,
107            }
108            .into()),
109            TypeVariant::Struct(ss) => {
110                let r = self.reader.get_struct_element(index);
111                Ok(dynamic_value::Reader::Struct(
112                    crate::dynamic_struct::Reader::new(r, ss.into()),
113                ))
114            }
115            TypeVariant::AnyPointer => {
116                Ok(crate::any_pointer::Reader::new(self.reader.get_pointer_element(index)).into())
117            }
118            TypeVariant::Capability => {
119                Ok(dynamic_value::Reader::Capability(dynamic_value::Capability))
120            }
121        }
122    }
123
124    pub fn iter(self) -> ListIter<Reader<'a>, Result<dynamic_value::Reader<'a>>> {
125        ListIter::new(self, self.len())
126    }
127}
128
129impl<'a> IndexMove<u32, Result<dynamic_value::Reader<'a>>> for Reader<'a> {
130    fn index_move(&self, index: u32) -> Result<dynamic_value::Reader<'a>> {
131        self.get(index)
132    }
133}
134
135impl<'a> ::core::iter::IntoIterator for Reader<'a> {
136    type Item = Result<dynamic_value::Reader<'a>>;
137    type IntoIter = ListIter<Reader<'a>, Self::Item>;
138
139    fn into_iter(self) -> Self::IntoIter {
140        self.iter()
141    }
142}
143
144/// A mutable dynamically-typed list.
145pub struct Builder<'a> {
146    pub(crate) builder: layout::ListBuilder<'a>,
147    pub(crate) element_type: Type,
148}
149
150impl<'a> From<Builder<'a>> for dynamic_value::Builder<'a> {
151    fn from(x: Builder<'a>) -> dynamic_value::Builder<'a> {
152        dynamic_value::Builder::List(x)
153    }
154}
155
156impl<'a> Builder<'a> {
157    pub(crate) fn new(builder: layout::ListBuilder<'a>, element_type: Type) -> Self {
158        Self {
159            builder,
160            element_type,
161        }
162    }
163
164    pub fn reborrow(&mut self) -> Builder<'_> {
165        Builder {
166            builder: self.builder.reborrow(),
167            element_type: self.element_type,
168        }
169    }
170
171    pub fn into_reader(self) -> Reader<'a> {
172        Reader {
173            reader: self.builder.into_reader(),
174            element_type: self.element_type,
175        }
176    }
177
178    pub fn len(&self) -> u32 {
179        self.builder.len()
180    }
181
182    pub fn is_empty(&self) -> bool {
183        self.len() == 0
184    }
185
186    pub fn element_type(&self) -> Type {
187        self.element_type
188    }
189
190    pub fn get(self, index: u32) -> Result<dynamic_value::Builder<'a>> {
191        assert!(index < self.builder.len());
192        match self.element_type.which() {
193            TypeVariant::Void => Ok(dynamic_value::Builder::Void),
194            TypeVariant::Bool => Ok(dynamic_value::Builder::Bool(
195                PrimitiveElement::get_from_builder(&self.builder, index),
196            )),
197            TypeVariant::Int8 => Ok(dynamic_value::Builder::Int8(
198                PrimitiveElement::get_from_builder(&self.builder, index),
199            )),
200            TypeVariant::Int16 => Ok(dynamic_value::Builder::Int16(
201                PrimitiveElement::get_from_builder(&self.builder, index),
202            )),
203            TypeVariant::Int32 => Ok(dynamic_value::Builder::Int32(
204                PrimitiveElement::get_from_builder(&self.builder, index),
205            )),
206            TypeVariant::Int64 => Ok(dynamic_value::Builder::Int64(
207                PrimitiveElement::get_from_builder(&self.builder, index),
208            )),
209            TypeVariant::UInt8 => Ok(dynamic_value::Builder::UInt8(
210                PrimitiveElement::get_from_builder(&self.builder, index),
211            )),
212            TypeVariant::UInt16 => Ok(dynamic_value::Builder::UInt16(
213                PrimitiveElement::get_from_builder(&self.builder, index),
214            )),
215            TypeVariant::UInt32 => Ok(dynamic_value::Builder::UInt32(
216                PrimitiveElement::get_from_builder(&self.builder, index),
217            )),
218            TypeVariant::UInt64 => Ok(dynamic_value::Builder::UInt64(
219                PrimitiveElement::get_from_builder(&self.builder, index),
220            )),
221            TypeVariant::Float32 => Ok(dynamic_value::Builder::Float32(
222                PrimitiveElement::get_from_builder(&self.builder, index),
223            )),
224            TypeVariant::Float64 => Ok(dynamic_value::Builder::Float64(
225                PrimitiveElement::get_from_builder(&self.builder, index),
226            )),
227            TypeVariant::Enum(e) => Ok(dynamic_value::Enum::new(
228                PrimitiveElement::get_from_builder(&self.builder, index),
229                e.into(),
230            )
231            .into()),
232            TypeVariant::Text => Ok(dynamic_value::Builder::Text(
233                self.builder.get_pointer_element(index).get_text(None)?,
234            )),
235            TypeVariant::Data => Ok(dynamic_value::Builder::Data(
236                self.builder.get_pointer_element(index).get_data(None)?,
237            )),
238            TypeVariant::List(element_type) => Ok(Builder {
239                builder: self
240                    .builder
241                    .get_pointer_element(index)
242                    .get_list(element_type.expected_element_size(), None)?,
243                element_type,
244            }
245            .into()),
246            TypeVariant::Struct(ss) => {
247                let r = self.builder.get_struct_element(index);
248                Ok(dynamic_value::Builder::Struct(
249                    crate::dynamic_struct::Builder::new(r, ss.into()),
250                ))
251            }
252            TypeVariant::AnyPointer => Ok(crate::any_pointer::Builder::new(
253                self.builder.get_pointer_element(index),
254            )
255            .into()),
256            TypeVariant::Capability => Ok(dynamic_value::Builder::Capability(
257                dynamic_value::Capability,
258            )),
259        }
260    }
261
262    pub fn set(&mut self, index: u32, value: dynamic_value::Reader<'_>) -> Result<()> {
263        assert!(index < self.builder.len());
264        match (self.element_type.which(), value) {
265            (TypeVariant::Void, _) => Ok(()),
266            (TypeVariant::Bool, dynamic_value::Reader::Bool(b)) => {
267                PrimitiveElement::set(&self.builder, index, b);
268                Ok(())
269            }
270            (TypeVariant::Int8, dynamic_value::Reader::Int8(x)) => {
271                PrimitiveElement::set(&self.builder, index, x);
272                Ok(())
273            }
274            (TypeVariant::Int16, dynamic_value::Reader::Int16(x)) => {
275                PrimitiveElement::set(&self.builder, index, x);
276                Ok(())
277            }
278            (TypeVariant::Int32, dynamic_value::Reader::Int32(x)) => {
279                PrimitiveElement::set(&self.builder, index, x);
280                Ok(())
281            }
282            (TypeVariant::Int64, dynamic_value::Reader::Int64(x)) => {
283                PrimitiveElement::set(&self.builder, index, x);
284                Ok(())
285            }
286            (TypeVariant::UInt8, dynamic_value::Reader::UInt8(x)) => {
287                PrimitiveElement::set(&self.builder, index, x);
288                Ok(())
289            }
290            (TypeVariant::UInt16, dynamic_value::Reader::UInt16(x)) => {
291                PrimitiveElement::set(&self.builder, index, x);
292                Ok(())
293            }
294            (TypeVariant::UInt32, dynamic_value::Reader::UInt32(x)) => {
295                PrimitiveElement::set(&self.builder, index, x);
296                Ok(())
297            }
298            (TypeVariant::UInt64, dynamic_value::Reader::UInt64(x)) => {
299                PrimitiveElement::set(&self.builder, index, x);
300                Ok(())
301            }
302            (TypeVariant::Float32, dynamic_value::Reader::Float32(x)) => {
303                PrimitiveElement::set(&self.builder, index, x);
304                Ok(())
305            }
306            (TypeVariant::Float64, dynamic_value::Reader::Float64(x)) => {
307                PrimitiveElement::set(&self.builder, index, x);
308                Ok(())
309            }
310            (TypeVariant::Enum(_es), dynamic_value::Reader::Enum(e)) => {
311                PrimitiveElement::set(&self.builder, index, e.get_value());
312                Ok(())
313            }
314            (TypeVariant::Text, dynamic_value::Reader::Text(t)) => {
315                self.builder
316                    .reborrow()
317                    .get_pointer_element(index)
318                    .set_text(t);
319                Ok(())
320            }
321            (TypeVariant::Data, dynamic_value::Reader::Data(d)) => {
322                self.builder
323                    .reborrow()
324                    .get_pointer_element(index)
325                    .set_data(d);
326                Ok(())
327            }
328            (TypeVariant::Struct(ss), dynamic_value::Reader::Struct(s)) => {
329                assert_eq!(ss, s.get_schema().raw);
330                self.builder
331                    .reborrow()
332                    .get_struct_element(index)
333                    .copy_content_from(&s.reader)
334            }
335            (TypeVariant::List(_element_type), dynamic_value::Reader::List(list)) => self
336                .builder
337                .reborrow()
338                .get_pointer_element(index)
339                .set_list(&list.reader, false),
340            (TypeVariant::AnyPointer, _) => {
341                Err(Error::from_kind(ErrorKind::ListAnyPointerNotSupported))
342            }
343            (TypeVariant::Capability, dynamic_value::Reader::Capability(_)) => {
344                Err(Error::from_kind(ErrorKind::ListCapabilityNotSupported))
345            }
346            (_, _) => Err(Error::from_kind(ErrorKind::TypeMismatch)),
347        }
348    }
349
350    pub fn init(self, index: u32, size: u32) -> Result<dynamic_value::Builder<'a>> {
351        assert!(index < self.builder.len());
352        match self.element_type.which() {
353            TypeVariant::Void
354            | TypeVariant::Bool
355            | TypeVariant::Int8
356            | TypeVariant::Int16
357            | TypeVariant::Int32
358            | TypeVariant::Int64
359            | TypeVariant::UInt8
360            | TypeVariant::UInt16
361            | TypeVariant::UInt32
362            | TypeVariant::UInt64
363            | TypeVariant::Float32
364            | TypeVariant::Float64
365            | TypeVariant::Enum(_)
366            | TypeVariant::Struct(_)
367            | TypeVariant::Capability => Err(Error::from_kind(ErrorKind::ExpectedAListOrBlob)),
368            TypeVariant::Text => Ok(self
369                .builder
370                .get_pointer_element(index)
371                .init_text(size)
372                .into()),
373            TypeVariant::Data => Ok(self
374                .builder
375                .get_pointer_element(index)
376                .init_data(size)
377                .into()),
378            TypeVariant::List(inner_element_type) => match inner_element_type.which() {
379                TypeVariant::Struct(rbs) => Ok(Builder::new(
380                    self.builder.get_pointer_element(index).init_struct_list(
381                        size,
382                        crate::dynamic_struct::struct_size_from_schema(rbs.into())?,
383                    ),
384                    inner_element_type,
385                )
386                .into()),
387                _ => Ok(Builder::new(
388                    self.builder
389                        .get_pointer_element(index)
390                        .init_list(inner_element_type.expected_element_size(), size),
391                    inner_element_type,
392                )
393                .into()),
394            },
395            TypeVariant::AnyPointer => Err(Error::from_kind(ErrorKind::ListAnyPointerNotSupported)),
396        }
397    }
398}
399
400impl<'a> crate::traits::SetterInput<crate::any_pointer::Owned> for Reader<'a> {
401    fn set_pointer_builder<'b>(
402        mut pointer: crate::private::layout::PointerBuilder<'b>,
403        value: Reader<'a>,
404        canonicalize: bool,
405    ) -> Result<()> {
406        pointer.set_list(&value.reader, canonicalize)
407    }
408}
409
410impl core::fmt::Debug for Reader<'_> {
411    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
412        core::fmt::Debug::fmt(&crate::dynamic_value::Reader::from(*self), f)
413    }
414}