rasn/types/
fields.rs

1use alloc::borrow::Cow;
2
3use crate::types::{Tag, TagTree};
4
5#[derive(Debug, Clone)]
6pub struct Fields {
7    fields: Cow<'static, [Field]>,
8}
9
10impl Fields {
11    pub const fn new(fields: Cow<'static, [Field]>) -> Self {
12        Self { fields }
13    }
14
15    pub const fn empty() -> Self {
16        Self::new(Cow::Borrowed(&[]))
17    }
18
19    pub const fn from_static(fields: &'static [Field]) -> Self {
20        Self {
21            fields: Cow::Borrowed(fields),
22        }
23    }
24
25    pub fn len(&self) -> usize {
26        self.fields.len()
27    }
28
29    pub fn is_empty(&self) -> bool {
30        self.fields.is_empty()
31    }
32
33    pub fn is_not_empty(&self) -> bool {
34        !self.is_empty()
35    }
36
37    pub fn optional_and_default_fields(&self) -> impl Iterator<Item = Field> + '_ {
38        self.iter().filter(Field::is_optional_or_default)
39    }
40
41    pub fn number_of_optional_and_default_fields(&self) -> usize {
42        self.optional_and_default_fields().count()
43    }
44
45    /// Returns the canonical sorted version of `self`.
46    pub fn canonised(mut self) -> Self {
47        self.canonical_sort();
48        self
49    }
50
51    /// Sorts the fields by their canonical tag order.
52    pub fn canonical_sort(&mut self) {
53        self.fields
54            .to_mut()
55            .sort_by(|a, b| a.tag_tree.smallest_tag().cmp(&b.tag_tree.smallest_tag()));
56    }
57
58    pub fn iter(&self) -> impl Iterator<Item = Field> + '_ {
59        self.fields.iter().cloned()
60    }
61
62    pub fn identifiers(&self) -> impl Iterator<Item = &str> + '_ {
63        self.fields.iter().map(|f| f.name)
64    }
65}
66
67impl From<Cow<'static, [Field]>> for Fields {
68    fn from(fields: Cow<'static, [Field]>) -> Self {
69        Self::new(fields)
70    }
71}
72
73#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)]
74pub struct Field {
75    pub tag: Tag,
76    pub tag_tree: TagTree,
77    pub presence: FieldPresence,
78    pub name: &'static str,
79}
80
81impl Field {
82    pub const fn new_required(tag: Tag, tag_tree: TagTree, name: &'static str) -> Self {
83        Self {
84            tag,
85            tag_tree,
86            presence: FieldPresence::Required,
87            name,
88        }
89    }
90
91    pub const fn new_optional(tag: Tag, tag_tree: TagTree, name: &'static str) -> Self {
92        Self {
93            tag,
94            tag_tree,
95            presence: FieldPresence::Optional,
96            name,
97        }
98    }
99
100    pub const fn new_default(tag: Tag, tag_tree: TagTree, name: &'static str) -> Self {
101        Self {
102            tag,
103            tag_tree,
104            presence: FieldPresence::Default,
105            name,
106        }
107    }
108}
109
110impl Field {
111    pub const fn is_optional_or_default(&self) -> bool {
112        self.presence.is_optional_or_default()
113    }
114
115    pub const fn is_not_optional_or_default(&self) -> bool {
116        !self.is_optional_or_default()
117    }
118}
119
120#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
121pub enum FieldPresence {
122    Required,
123    Optional,
124    #[default]
125    Default,
126}
127
128impl FieldPresence {
129    pub const fn is_optional_or_default(&self) -> bool {
130        matches!(self, Self::Optional | Self::Default)
131    }
132}