capnp/
struct_list.rs

1// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
2// Licensed under the MIT License:
3//
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20// THE SOFTWARE.
21
22//! List of structs.
23
24use core::marker::PhantomData;
25
26use crate::introspect;
27use crate::private::layout::{
28    InlineComposite, ListBuilder, ListReader, PointerBuilder, PointerReader,
29};
30use crate::traits::{FromPointerBuilder, FromPointerReader, HasStructSize, IndexMove, ListIter};
31use crate::Result;
32
33#[derive(Copy, Clone)]
34pub struct Owned<T>
35where
36    T: crate::traits::OwnedStruct,
37{
38    marker: PhantomData<T>,
39}
40
41impl<T> introspect::Introspect for Owned<T>
42where
43    T: introspect::Introspect + crate::traits::OwnedStruct,
44{
45    fn introspect() -> introspect::Type {
46        introspect::Type::list_of(T::introspect())
47    }
48}
49
50impl<T> crate::traits::Owned for Owned<T>
51where
52    T: crate::traits::OwnedStruct,
53{
54    type Reader<'a> = Reader<'a, T>;
55    type Builder<'a> = Builder<'a, T>;
56}
57
58pub struct Reader<'a, T>
59where
60    T: crate::traits::OwnedStruct,
61{
62    marker: PhantomData<T>,
63    reader: ListReader<'a>,
64}
65
66impl<'a, T> Clone for Reader<'a, T>
67where
68    T: crate::traits::OwnedStruct,
69{
70    fn clone(&self) -> Reader<'a, T> {
71        *self
72    }
73}
74impl<T> Copy for Reader<'_, T> where T: crate::traits::OwnedStruct {}
75
76impl<'a, T> Reader<'a, T>
77where
78    T: crate::traits::OwnedStruct,
79{
80    pub fn len(&self) -> u32 {
81        self.reader.len()
82    }
83
84    pub fn is_empty(&self) -> bool {
85        self.len() == 0
86    }
87
88    pub fn iter(self) -> ListIter<Reader<'a, T>, T::Reader<'a>> {
89        ListIter::new(self, self.len())
90    }
91}
92
93impl<T> Reader<'_, T>
94where
95    T: crate::traits::OwnedStruct,
96{
97    pub fn reborrow(&self) -> Reader<'_, T> {
98        Reader {
99            reader: self.reader,
100            marker: PhantomData,
101        }
102    }
103}
104
105impl<'a, T> FromPointerReader<'a> for Reader<'a, T>
106where
107    T: crate::traits::OwnedStruct,
108{
109    fn get_from_pointer(
110        reader: &PointerReader<'a>,
111        default: Option<&'a [crate::Word]>,
112    ) -> Result<Reader<'a, T>> {
113        Ok(Reader {
114            reader: reader.get_list(InlineComposite, default)?,
115            marker: PhantomData,
116        })
117    }
118}
119
120impl<'a, T> IndexMove<u32, T::Reader<'a>> for Reader<'a, T>
121where
122    T: crate::traits::OwnedStruct,
123{
124    fn index_move(&self, index: u32) -> T::Reader<'a> {
125        self.get(index)
126    }
127}
128
129impl<'a, T> Reader<'a, T>
130where
131    T: crate::traits::OwnedStruct,
132{
133    /// Gets the element at position `index`. Panics if `index` is greater than or
134    /// equal to `len()`.
135    pub fn get(self, index: u32) -> T::Reader<'a> {
136        assert!(index < self.len());
137        self.reader.get_struct_element(index).into()
138    }
139
140    /// Gets the element at position `index`. Returns `None` if `index`
141    /// is greater than or equal to `len()`.
142    pub fn try_get(self, index: u32) -> Option<T::Reader<'a>> {
143        if index < self.len() {
144            Some(self.reader.get_struct_element(index).into())
145        } else {
146            None
147        }
148    }
149}
150
151impl<'a, T> crate::traits::IntoInternalListReader<'a> for Reader<'a, T>
152where
153    T: crate::traits::OwnedStruct,
154{
155    fn into_internal_list_reader(self) -> ListReader<'a> {
156        self.reader
157    }
158}
159
160pub struct Builder<'a, T>
161where
162    T: crate::traits::OwnedStruct,
163{
164    marker: PhantomData<T>,
165    builder: ListBuilder<'a>,
166}
167
168impl<'a, T> Builder<'a, T>
169where
170    T: crate::traits::OwnedStruct,
171{
172    pub fn len(&self) -> u32 {
173        self.builder.len()
174    }
175
176    pub fn is_empty(&self) -> bool {
177        self.len() == 0
178    }
179
180    pub fn into_reader(self) -> Reader<'a, T> {
181        Reader {
182            marker: PhantomData,
183            reader: self.builder.into_reader(),
184        }
185    }
186
187    /// Sets the list element, with the following limitation based on the fact that structs in a
188    /// struct list are allocated inline: if the source struct is larger than the target struct
189    /// (as can happen if it was created with a newer version of the schema), then it will be
190    /// truncated, losing fields.
191    pub fn set_with_caveats<'b>(&mut self, index: u32, value: T::Reader<'b>) -> Result<()>
192    where
193        T::Reader<'b>: crate::traits::IntoInternalStructReader<'b>,
194    {
195        assert!(index < self.len());
196        use crate::traits::IntoInternalStructReader;
197        self.builder
198            .reborrow()
199            .get_struct_element(index)
200            .copy_content_from(&value.into_internal_struct_reader())
201    }
202}
203
204impl<T> Builder<'_, T>
205where
206    T: crate::traits::OwnedStruct,
207{
208    pub fn reborrow(&mut self) -> Builder<'_, T> {
209        Builder {
210            builder: self.builder.reborrow(),
211            marker: PhantomData,
212        }
213    }
214}
215
216impl<'a, T> FromPointerBuilder<'a> for Builder<'a, T>
217where
218    T: crate::traits::OwnedStruct,
219{
220    fn init_pointer(builder: PointerBuilder<'a>, size: u32) -> Builder<'a, T> {
221        Builder {
222            marker: PhantomData,
223            builder: builder.init_struct_list(size, T::Builder::STRUCT_SIZE),
224        }
225    }
226    fn get_from_pointer(
227        builder: PointerBuilder<'a>,
228        default: Option<&'a [crate::Word]>,
229    ) -> Result<Builder<'a, T>> {
230        Ok(Builder {
231            marker: PhantomData,
232            builder: builder.get_struct_list(T::Builder::STRUCT_SIZE, default)?,
233        })
234    }
235}
236
237impl<'a, T> Builder<'a, T>
238where
239    T: crate::traits::OwnedStruct,
240{
241    /// Gets the element at position `index`. Panics if `index` is greater than or
242    /// equal to `len()`.
243    pub fn get(self, index: u32) -> T::Builder<'a> {
244        assert!(index < self.len());
245        self.builder.get_struct_element(index).into()
246    }
247
248    /// Gets the element at position `index`. Returns `None` if `index`
249    /// is greater than or equal to `len()`.
250    pub fn try_get(self, index: u32) -> Option<T::Builder<'a>> {
251        if index < self.len() {
252            Some(self.builder.get_struct_element(index).into())
253        } else {
254            None
255        }
256    }
257}
258
259impl<'a, T> crate::traits::SetterInput<Owned<T>> for Reader<'a, T>
260where
261    T: crate::traits::OwnedStruct,
262{
263    #[inline]
264    fn set_pointer_builder<'b>(
265        mut pointer: crate::private::layout::PointerBuilder<'b>,
266        value: Reader<'a, T>,
267        canonicalize: bool,
268    ) -> Result<()> {
269        pointer.set_list(&value.reader, canonicalize)
270    }
271}
272
273impl<'a, T> ::core::iter::IntoIterator for Reader<'a, T>
274where
275    T: crate::traits::OwnedStruct,
276{
277    type Item = T::Reader<'a>;
278    type IntoIter = ListIter<Reader<'a, T>, Self::Item>;
279
280    fn into_iter(self) -> Self::IntoIter {
281        self.iter()
282    }
283}
284
285impl<'a, T: crate::traits::OwnedStruct> From<Reader<'a, T>> for crate::dynamic_value::Reader<'a> {
286    fn from(t: Reader<'a, T>) -> crate::dynamic_value::Reader<'a> {
287        crate::dynamic_value::Reader::List(crate::dynamic_list::Reader::new(
288            t.reader,
289            T::introspect(),
290        ))
291    }
292}
293
294impl<'a, T: crate::traits::OwnedStruct> crate::dynamic_value::DowncastReader<'a> for Reader<'a, T> {
295    fn downcast_reader(v: crate::dynamic_value::Reader<'a>) -> Self {
296        let dl: crate::dynamic_list::Reader = v.downcast();
297        assert!(dl.element_type().loose_equals(T::introspect()));
298        Reader {
299            reader: dl.reader,
300            marker: PhantomData,
301        }
302    }
303}
304
305impl<'a, T: crate::traits::OwnedStruct> From<Builder<'a, T>> for crate::dynamic_value::Builder<'a> {
306    fn from(t: Builder<'a, T>) -> crate::dynamic_value::Builder<'a> {
307        crate::dynamic_value::Builder::List(crate::dynamic_list::Builder::new(
308            t.builder,
309            T::introspect(),
310        ))
311    }
312}
313
314impl<'a, T: crate::traits::OwnedStruct> crate::dynamic_value::DowncastBuilder<'a>
315    for Builder<'a, T>
316{
317    fn downcast_builder(v: crate::dynamic_value::Builder<'a>) -> Self {
318        let dl: crate::dynamic_list::Builder = v.downcast();
319        assert!(dl.element_type().loose_equals(T::introspect()));
320        Builder {
321            builder: dl.builder,
322            marker: PhantomData,
323        }
324    }
325}
326
327impl<T: crate::traits::OwnedStruct> core::fmt::Debug for Reader<'_, T> {
328    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
329        core::fmt::Debug::fmt(
330            &::core::convert::Into::<crate::dynamic_value::Reader<'_>>::into(*self),
331            f,
332        )
333    }
334}