abi_stable/type_layout/
tl_fields.rs

1use super::*;
2
3use std::{iter, slice};
4
5/// The layout of all compressed fields in a type definition,
6/// one can access the expanded fields by calling the expand method.
7#[repr(C)]
8#[derive(Copy, Clone, StableAbi)]
9#[sabi(unsafe_sabi_opaque_fields)]
10pub struct CompTLFields {
11    /// All TLField fields which map 1:1.
12    comp_fields: *const CompTLField,
13
14    /// All the function pointer types in the field.
15    functions: Option<&'static TLFunctions>,
16
17    comp_fields_len: u16,
18}
19
20unsafe impl Sync for CompTLFields {}
21unsafe impl Send for CompTLFields {}
22
23impl CompTLFields {
24    /// A `CompTLFields` with no fields.
25    pub const EMPTY: Self = Self::from_fields(rslice![]);
26
27    /// Constructs a `CompTLFields`.
28    pub const fn new(
29        comp_fields: RSlice<'static, CompTLFieldRepr>,
30        functions: Option<&'static TLFunctions>,
31    ) -> Self {
32        Self {
33            comp_fields: comp_fields.as_ptr() as *const CompTLFieldRepr as *const CompTLField,
34            comp_fields_len: comp_fields.len() as u16,
35
36            functions,
37        }
38    }
39
40    /// Constructs a `CompTLFields` with fields,and without functions.
41    pub const fn from_fields(comp_fields: RSlice<'static, CompTLField>) -> Self {
42        Self {
43            comp_fields: comp_fields.as_ptr(),
44            comp_fields_len: comp_fields.len() as u16,
45
46            functions: None,
47        }
48    }
49
50    /// Accesses a slice of all the compressed fields in this `CompTLFields`.
51    pub fn comp_fields(&self) -> &'static [CompTLField] {
52        unsafe { slice::from_raw_parts(self.comp_fields, self.comp_fields_len as usize) }
53    }
54
55    /// Accesses a slice of all the compressed fields in this `CompTLFields`.
56    pub const fn comp_fields_rslice(&self) -> RSlice<'static, CompTLField> {
57        unsafe { RSlice::from_raw_parts(self.comp_fields, self.comp_fields_len as usize) }
58    }
59
60    /// Constructs an iterator over all the field names.
61    pub fn field_names(
62        &self,
63        shared_vars: &MonoSharedVars,
64    ) -> impl ExactSizeIterator<Item = &'static str> + Clone + 'static {
65        let fields = self.comp_fields();
66        let strings = shared_vars.strings();
67
68        fields.iter().map(move |field| field.name(strings))
69    }
70
71    /// Gets the name of the nth field.
72    pub fn get_field_name(
73        &self,
74        index: usize,
75        shared_vars: &MonoSharedVars,
76    ) -> Option<&'static str> {
77        let strings = shared_vars.strings();
78
79        self.comp_fields().get(index).map(|f| f.name(strings))
80    }
81
82    /// The amount of fields this represents
83    pub const fn len(&self) -> usize {
84        self.comp_fields_len as usize
85    }
86
87    /// Whether there are no fields.
88    pub const fn is_empty(&self) -> bool {
89        self.comp_fields_len == 0
90    }
91
92    /// Expands this into a TLFields,allowing access to expanded fields.
93    pub const fn expand(self, shared_vars: &'static SharedVars) -> TLFields {
94        TLFields {
95            shared_vars,
96            comp_fields: self.comp_fields_rslice(),
97            functions: self.functions,
98        }
99    }
100}
101
102///////////////////////////////////////////////////////////////////////////////
103
104/// The layout of all the fields in a type definition.
105#[repr(C)]
106#[derive(Copy, Clone, StableAbi)]
107pub struct TLFields {
108    shared_vars: &'static SharedVars,
109
110    comp_fields: RSlice<'static, CompTLField>,
111
112    /// All the function pointer types in the field.
113    functions: Option<&'static TLFunctions>,
114}
115
116impl TLFields {
117    /// Constructs a TLFields from the compressed fields,without any functions.
118    pub const fn from_fields(
119        comp_fields: &'static [CompTLField],
120        shared_vars: &'static SharedVars,
121    ) -> Self {
122        Self {
123            comp_fields: RSlice::from_slice(comp_fields),
124            shared_vars,
125            functions: None,
126        }
127    }
128
129    /// The amount of fields this represents
130    pub const fn len(&self) -> usize {
131        self.comp_fields.len()
132    }
133
134    /// Whether this contains any fields
135    pub const fn is_empty(&self) -> bool {
136        self.comp_fields.is_empty()
137    }
138
139    /// Gets the ith expanded field.Returns None there is no ith field.
140    pub fn get(&self, i: usize) -> Option<TLField> {
141        self.comp_fields
142            .get(i)
143            .map(|field| field.expand(i, self.functions, self.shared_vars))
144    }
145
146    /// Gets an iterator over the expanded fields.
147    pub fn iter(&self) -> TLFieldsIterator {
148        TLFieldsIterator {
149            shared_vars: self.shared_vars,
150            comp_fields: self.comp_fields.as_slice().iter().enumerate(),
151            functions: self.functions,
152        }
153    }
154
155    /// Collects the expanded fields into a `Vec<TLField>`.
156    pub fn to_vec(&self) -> Vec<TLField> {
157        self.iter().collect()
158    }
159}
160
161impl IntoIterator for TLFields {
162    type IntoIter = TLFieldsIterator;
163    type Item = TLField;
164
165    #[inline]
166    fn into_iter(self) -> Self::IntoIter {
167        self.iter()
168    }
169}
170
171impl Debug for TLFields {
172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173        f.debug_list().entries(self.iter()).finish()
174    }
175}
176
177impl Display for TLFields {
178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179        for field in self.iter() {
180            Display::fmt(&field, f)?;
181            writeln!(f)?;
182        }
183        Ok(())
184    }
185}
186
187impl Eq for TLFields {}
188impl PartialEq for TLFields {
189    fn eq(&self, other: &Self) -> bool {
190        self.iter().eq(other.iter())
191    }
192}
193
194///////////////////////////////////////////////////////////////////////////////
195
196/// An iterator over all the fields in a type definition.
197#[derive(Clone, Debug)]
198pub struct TLFieldsIterator {
199    shared_vars: &'static SharedVars,
200
201    comp_fields: iter::Enumerate<slice::Iter<'static, CompTLField>>,
202
203    /// All the function pointer types in the field.
204    functions: Option<&'static TLFunctions>,
205}
206
207impl Iterator for TLFieldsIterator {
208    type Item = TLField;
209
210    fn next(&mut self) -> Option<TLField> {
211        self.comp_fields
212            .next()
213            .map(|(i, field)| field.expand(i, self.functions, self.shared_vars))
214    }
215
216    fn size_hint(&self) -> (usize, Option<usize>) {
217        let len = self.comp_fields.len();
218        (len, Some(len))
219    }
220    fn count(self) -> usize {
221        self.comp_fields.len()
222    }
223}
224
225impl std::iter::ExactSizeIterator for TLFieldsIterator {}