1use crate::types::{Tag, TagTree};
4
5#[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 #[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 #[must_use]
40 pub const fn len(&self) -> usize {
41 self.fields.len()
42 }
43
44 #[must_use]
46 pub const fn is_empty(&self) -> bool {
47 self.fields.is_empty()
48 }
49
50 #[must_use]
52 pub const fn is_not_empty(&self) -> bool {
53 !self.is_empty()
54 }
55 #[must_use]
57 pub const fn has_required_field(&self) -> bool {
58 self.has_required
59 }
60
61 pub fn optional_and_default_fields(&self) -> impl Iterator<Item = Field> + '_ {
64 self.iter().filter(Field::is_optional_or_default)
65 }
66
67 #[must_use]
70 pub const fn number_of_optional_and_default_fields(&self) -> usize {
71 self.number_optional_default
72 }
73
74 #[must_use]
76 pub const fn canonised(&self) -> Self {
77 self.canonical_sort()
78 }
79
80 #[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 pub fn iter(&self) -> impl Iterator<Item = Field> + '_ {
104 self.fields.iter().copied()
105 }
106
107 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#[derive(Debug, Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
123pub struct Field {
124 pub index: usize,
126 pub tag: Tag,
128 pub tag_tree: TagTree,
130 pub presence: FieldPresence,
132 pub name: &'static str,
134}
135
136impl Field {
137 #[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 #[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 #[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 #[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 #[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 #[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 #[must_use]
237 pub const fn is_optional_or_default(&self) -> bool {
238 self.presence.is_optional_or_default()
239 }
240
241 #[must_use]
243 pub const fn is_not_optional_or_default(&self) -> bool {
244 !self.is_optional_or_default()
245 }
246}
247
248#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
252pub enum FieldPresence {
253 Required,
255 Optional,
257 #[default]
259 Default,
260}
261
262impl FieldPresence {
263 #[must_use]
266 pub const fn is_optional_or_default(&self) -> bool {
267 matches!(self, Self::Optional | Self::Default)
268 }
269}