Skip to main content

rasn/types/
fields.rs

1//! Representing all fields for a `SEQUENCE` or `SET` type.
2
3use crate::types::{Tag, TagTree};
4
5/// Represents all of the values that make up a given value in ASN.1.
6#[derive(Debug, Clone, Copy)]
7pub struct Fields<const N: usize> {
8    fields: [Field; N],
9    has_required: bool,
10    number_optional_default: usize,
11}
12
13impl<const N: usize> Fields<N> {
14    /// Creates a set of fields from a static set.
15    #[must_use]
16    pub const fn from_static(fields: [Field; N]) -> Self {
17        let mut i = 0;
18        let (has_required, number_optional_default) = {
19            let mut required = false;
20            let mut number_opts = 0;
21            while i < fields.len() {
22                if fields[i].is_not_optional_or_default() {
23                    required = true;
24                } else {
25                    number_opts += 1;
26                }
27                i += 1;
28            }
29            (required, number_opts)
30        };
31        Self {
32            fields,
33            has_required,
34            number_optional_default,
35        }
36    }
37
38    /// Returns the number of fields.
39    #[must_use]
40    pub const fn len(&self) -> usize {
41        self.fields.len()
42    }
43
44    /// Returns whether the set doesn't contain any fields.
45    #[must_use]
46    pub const fn is_empty(&self) -> bool {
47        self.fields.is_empty()
48    }
49
50    /// Returns whether the set contains any fields.
51    #[must_use]
52    pub const fn is_not_empty(&self) -> bool {
53        !self.is_empty()
54    }
55    /// Checks if any field is required.
56    #[must_use]
57    pub const fn has_required_field(&self) -> bool {
58        self.has_required
59    }
60
61    /// Returns an iterator over all fields which are [`FieldPresence::Optional`] or
62    /// [`FieldPresence::Default`].
63    pub fn optional_and_default_fields(&self) -> impl Iterator<Item = Field> + '_ {
64        self.iter().filter(Field::is_optional_or_default)
65    }
66
67    /// Returns the number of fields which are [`FieldPresence::Optional`] or
68    /// [`FieldPresence::Default`].
69    #[must_use]
70    pub const fn number_of_optional_and_default_fields(&self) -> usize {
71        self.number_optional_default
72    }
73
74    /// Returns the canonical sorted version of `self`.
75    #[must_use]
76    pub const fn canonised(&self) -> Self {
77        self.canonical_sort()
78    }
79
80    /// Sorts the fields by their canonical tag order in constant matter.
81    #[must_use]
82    pub const fn canonical_sort(mut self) -> Self {
83        let len = self.fields.len();
84        let mut i = 0;
85        while i < len {
86            let mut j = i + 1;
87            while j < len {
88                let tag_i = self.fields[i].tag_tree.smallest_tag();
89                let tag_j = self.fields[j].tag_tree.smallest_tag();
90                if tag_i.const_cmp(&tag_j) as usize == core::cmp::Ordering::Greater as usize {
91                    let temp = self.fields[i];
92                    self.fields[i] = self.fields[j];
93                    self.fields[j] = temp;
94                }
95                j += 1;
96            }
97            i += 1;
98        }
99        self
100    }
101
102    /// Returns an iterator over all fields.
103    pub fn iter(&self) -> impl Iterator<Item = Field> + '_ {
104        self.fields.iter().copied()
105    }
106
107    /// Returns an iterator over identifiers for all fields.
108    pub fn identifiers(&self) -> impl Iterator<Item = &str> + '_ {
109        self.fields.iter().map(|f| f.name)
110    }
111}
112
113impl<const N: usize> core::ops::Deref for Fields<N> {
114    type Target = [Field];
115
116    fn deref(&self) -> &Self::Target {
117        &self.fields
118    }
119}
120
121/// Represents a field in a `SET` or `SEQUENCE` type.
122#[derive(Debug, Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
123pub struct Field {
124    /// The index of the field (order number in `SEQUENCE` or `SET`).
125    pub index: usize,
126    /// The tag for the field.
127    pub tag: Tag,
128    /// The tree of tags for the field, if the field is a `CHOICE` type.
129    pub tag_tree: TagTree,
130    /// The presence requirement of the field.
131    pub presence: FieldPresence,
132    /// The name of the field.
133    pub name: &'static str,
134}
135
136impl Field {
137    /// Creates a new field with [`FieldPresence::Required`] from the given values.
138    #[must_use]
139    pub const fn new_required(
140        index: usize,
141        tag: Tag,
142        tag_tree: TagTree,
143        name: &'static str,
144    ) -> Self {
145        Self {
146            index,
147            tag,
148            tag_tree,
149            presence: FieldPresence::Required,
150            name,
151        }
152    }
153
154    /// Creates a new field with [`FieldPresence::Required`] from `T::AsnType`.
155    #[must_use]
156    pub const fn new_required_type<T: crate::types::AsnType>(
157        index: usize,
158        name: &'static str,
159    ) -> Self {
160        Self {
161            index,
162            tag: T::TAG,
163            tag_tree: T::TAG_TREE,
164            presence: FieldPresence::Required,
165            name,
166        }
167    }
168
169    /// Creates a new field with [`FieldPresence::Optional`] from the given values.
170    #[must_use]
171    pub const fn new_optional(
172        index: usize,
173        tag: Tag,
174        tag_tree: TagTree,
175        name: &'static str,
176    ) -> Self {
177        Self {
178            index,
179            tag,
180            tag_tree,
181            presence: FieldPresence::Optional,
182            name,
183        }
184    }
185
186    /// Creates a new field with [`FieldPresence::Optional`] from `T::AsnType`.
187    #[must_use]
188    pub const fn new_optional_type<T: crate::types::AsnType>(
189        index: usize,
190        name: &'static str,
191    ) -> Self {
192        Self {
193            index,
194            tag: T::TAG,
195            tag_tree: T::TAG_TREE,
196            presence: FieldPresence::Optional,
197            name,
198        }
199    }
200
201    /// Creates a new field with [`FieldPresence::Default`] from the given values.
202    #[must_use]
203    pub const fn new_default(
204        index: usize,
205        tag: Tag,
206        tag_tree: TagTree,
207        name: &'static str,
208    ) -> Self {
209        Self {
210            index,
211            tag,
212            tag_tree,
213            presence: FieldPresence::Default,
214            name,
215        }
216    }
217
218    /// Creates a new field with [`FieldPresence::Default`] from `T::AsnType`.
219    #[must_use]
220    pub const fn new_default_type<T: crate::types::AsnType>(
221        index: usize,
222        name: &'static str,
223    ) -> Self {
224        Self {
225            index,
226            tag: T::TAG,
227            tag_tree: T::TAG_TREE,
228            presence: FieldPresence::Default,
229            name,
230        }
231    }
232}
233
234impl Field {
235    /// Returns whether the field is [`FieldPresence::Optional`] or`FieldPresence::Default`lt].
236    #[must_use]
237    pub const fn is_optional_or_default(&self) -> bool {
238        self.presence.is_optional_or_default()
239    }
240
241    /// Returns whether the field is [`FieldPresence::Required`].
242    #[must_use]
243    pub const fn is_not_optional_or_default(&self) -> bool {
244        !self.is_optional_or_default()
245    }
246}
247
248/// The presence of a field in constructed type, used to determine whether to
249/// expect a given field when encoding or decoding, and how to react when it
250/// is not present.
251#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
252pub enum FieldPresence {
253    /// Value for the field is required, and will cause an error if not found.
254    Required,
255    /// Value for the field is optional, and will return none value if not found.
256    Optional,
257    /// Value for the field is default, and will return a default value if not found.
258    #[default]
259    Default,
260}
261
262impl FieldPresence {
263    /// Returns whether the current values matches [`FieldPresence::Optional`] or
264    /// [`FieldPresence::Default`].
265    #[must_use]
266    pub const fn is_optional_or_default(&self) -> bool {
267        matches!(self, Self::Optional | Self::Default)
268    }
269}