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