Skip to main content

capnp/
traits.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
22use crate::private::layout::CapTable;
23use crate::private::layout::{
24    ListReader, PointerBuilder, PointerReader, StructBuilder, StructReader, StructSize,
25};
26use crate::Result;
27
28use core::marker::PhantomData;
29
30pub trait HasStructSize {
31    const STRUCT_SIZE: StructSize;
32}
33
34/// Trait for all types that can be converted to a low-level `StructReader`.
35pub trait IntoInternalStructReader<'a> {
36    fn into_internal_struct_reader(self) -> StructReader<'a>;
37}
38
39/// Trait for all types that can be converted to a low-level `StructBuilder`.
40pub trait IntoInternalStructBuilder<'a> {
41    fn into_internal_struct_builder(self) -> StructBuilder<'a>;
42}
43
44/// Trait for all types that can be converted to a low-level `ListReader`.
45pub trait IntoInternalListReader<'a> {
46    fn into_internal_list_reader(self) -> ListReader<'a>;
47}
48
49pub trait FromPointerReader<'a>: Sized {
50    fn get_from_pointer(
51        reader: &PointerReader<'a>,
52        default: Option<&'a [crate::Word]>,
53    ) -> Result<Self>;
54}
55
56/// A trait to encode relationships between readers and builders.
57///
58/// If `Foo` is a Cap'n Proto struct and `Bar` is a Rust-native struct, then
59/// `foo::Reader<'a>` is to `foo::Owned` as `&'a Bar` is to `Bar`, and
60/// `foo::Builder<'a>` is to `foo::Owned` as `&'a mut Bar` is to `Bar`.
61/// The relationship is formalized by an `impl capnp::traits::Owned for foo::Owned`.
62/// Because Cap'n Proto struct layout differs from Rust struct layout, a `foo::Owned` value
63/// cannot be used for anything interesting on its own; the `foo::Owned` type is useful
64/// nonetheless as a type parameter, e.g. for a generic container that owns a Cap'n Proto
65/// message of type `T: capnp::traits::Owned`.
66pub trait Owned: crate::introspect::Introspect {
67    type Reader<'a>: FromPointerReader<'a> + SetterInput<Self>;
68    type Builder<'a>: FromPointerBuilder<'a>;
69}
70
71pub trait OwnedStruct: crate::introspect::Introspect {
72    type Reader<'a>: From<StructReader<'a>> + SetterInput<Self> + IntoInternalStructReader<'a>;
73    type Builder<'a>: From<StructBuilder<'a>> + HasStructSize;
74}
75
76pub trait Pipelined {
77    type Pipeline;
78}
79
80pub trait FromPointerBuilder<'a>: Sized {
81    fn init_pointer(builder: PointerBuilder<'a>, length: u32) -> Self;
82    fn get_from_pointer(
83        builder: PointerBuilder<'a>,
84        default: Option<&'a [crate::Word]>,
85    ) -> Result<Self>;
86}
87
88/// A trait marking types that can be passed as inputs to setter methods.
89/// `Receiver` is intended to be an `Owned`, representing the destination type.
90///
91/// This trait allows setters to support multiple types of input. For example,
92/// a text field setter accepts values of type `&str` and of type `text::Reader`.
93pub trait SetterInput<Receiver: ?Sized> {
94    /// Copies the values from `input` into `builder`, where `builder`
95    /// represents the backing memory of a `<Receiver as Owned>::Builder`.
96    ///
97    /// End user code should never need to call this method directly.
98    fn set_pointer_builder(
99        builder: PointerBuilder<'_>,
100        input: Self,
101        canonicalize: bool,
102    ) -> Result<()>;
103}
104
105/// A trait for types that can be "imbued" with capabilities.
106///
107/// A newly-read message from the network might contain capability pointers
108/// but until the message has been imbued with the actual capabilities,
109/// those pointers will not be usable.
110pub trait Imbue<'a> {
111    fn imbue(&mut self, caps: &'a CapTable);
112}
113
114/// Like `Imbue`, but the capability table is mutable.
115pub trait ImbueMut<'a> {
116    fn imbue_mut(&mut self, caps: &'a mut CapTable);
117}
118
119/// User-defined Cap'n Proto structs and interfaces are statically assigned a
120/// 64-bit type ID. This trait allows the ID to be retrieved.
121pub trait HasTypeId {
122    const TYPE_ID: u64;
123}
124
125pub trait IndexMove<I, T> {
126    fn index_move(&self, index: I) -> T;
127}
128
129pub struct ListIter<T, U> {
130    marker: PhantomData<U>,
131    list: T,
132    index: u32,
133    size: u32,
134}
135
136impl<T, U> ListIter<T, U> {
137    pub fn new(list: T, size: u32) -> Self {
138        Self {
139            list,
140            index: 0,
141            size,
142            marker: PhantomData,
143        }
144    }
145}
146
147impl<U, T: IndexMove<u32, U>> ::core::iter::Iterator for ListIter<T, U> {
148    type Item = U;
149    fn next(&mut self) -> ::core::option::Option<U> {
150        if self.index < self.size {
151            let result = self.list.index_move(self.index);
152            self.index += 1;
153            Some(result)
154        } else {
155            None
156        }
157    }
158
159    fn size_hint(&self) -> (usize, Option<usize>) {
160        let remaining = self.size as usize - self.index as usize;
161        (remaining, Some(remaining))
162    }
163
164    fn nth(&mut self, p: usize) -> Option<U> {
165        let Some(p) = p.try_into().ok() else {
166            self.index = self.size;
167            return None;
168        };
169        let Some(nth_index) = self.index.checked_add(p) else {
170            self.index = self.size;
171            return None;
172        };
173        if nth_index < self.size {
174            self.index = nth_index;
175            let result = self.list.index_move(self.index);
176            self.index += 1;
177            Some(result)
178        } else {
179            self.index = self.size;
180            None
181        }
182    }
183}
184
185impl<U, T: IndexMove<u32, U>> ::core::iter::ExactSizeIterator for ListIter<T, U> {
186    fn len(&self) -> usize {
187        self.size as usize - self.index as usize
188    }
189}
190
191impl<U, T: IndexMove<u32, U>> ::core::iter::DoubleEndedIterator for ListIter<T, U> {
192    fn next_back(&mut self) -> ::core::option::Option<U> {
193        if self.size > self.index {
194            self.size -= 1;
195            Some(self.list.index_move(self.size))
196        } else {
197            None
198        }
199    }
200}
201
202/// Iterator for a list whose indices are of type `u16`.
203pub struct ShortListIter<T, U> {
204    marker: PhantomData<U>,
205    list: T,
206    index: u16,
207    size: u16,
208}
209
210impl<T, U> ShortListIter<T, U> {
211    pub fn new(list: T, size: u16) -> Self {
212        Self {
213            list,
214            index: 0,
215            size,
216            marker: PhantomData,
217        }
218    }
219}
220
221impl<U, T: IndexMove<u16, U>> ::core::iter::Iterator for ShortListIter<T, U> {
222    type Item = U;
223    fn next(&mut self) -> ::core::option::Option<U> {
224        if self.index < self.size {
225            let result = self.list.index_move(self.index);
226            self.index += 1;
227            Some(result)
228        } else {
229            None
230        }
231    }
232
233    fn size_hint(&self) -> (usize, Option<usize>) {
234        let remaining = self.size as usize - self.index as usize;
235        (remaining, Some(remaining))
236    }
237
238    fn nth(&mut self, p: usize) -> Option<U> {
239        let Some(p) = p.try_into().ok() else {
240            self.index = self.size;
241            return None;
242        };
243        let Some(nth_index) = self.index.checked_add(p) else {
244            self.index = self.size;
245            return None;
246        };
247        if nth_index < self.size {
248            self.index = nth_index;
249            let result = self.list.index_move(self.index);
250            self.index += 1;
251            Some(result)
252        } else {
253            self.index = self.size;
254            None
255        }
256    }
257}
258
259impl<U, T: IndexMove<u16, U>> ::core::iter::ExactSizeIterator for ShortListIter<T, U> {
260    fn len(&self) -> usize {
261        self.size as usize - self.index as usize
262    }
263}
264
265impl<U, T: IndexMove<u16, U>> ::core::iter::DoubleEndedIterator for ShortListIter<T, U> {
266    fn next_back(&mut self) -> ::core::option::Option<U> {
267        if self.size > self.index {
268            self.size -= 1;
269            Some(self.list.index_move(self.size))
270        } else {
271            None
272        }
273    }
274}