structured_cms/timestamp/
accuracy.rs1use super::{Accuracy, record};
4use crate::{Error, ErrorCode, Result};
5use structured_asn1::memory::{OwnedVec, Work};
6use structured_asn1::{Element, Integer, Reader, Span, Tag, universal};
7
8const FIELD: &str = "tstInfo.accuracy";
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum Component {
13 Seconds,
15 Millis,
17 Micros,
19}
20
21impl Component {
22 const fn index(self) -> usize {
23 match self {
24 Self::Seconds => 0,
25 Self::Millis => 1,
26 Self::Micros => 2,
27 }
28 }
29}
30
31#[derive(Debug, Clone, Copy)]
33pub struct ComponentReading<'a> {
34 element: Element<'a>,
35 value: Integer<'a>,
36}
37impl<'a> ComponentReading<'a> {
38 #[must_use]
40 pub fn element(self) -> Element<'a> {
41 self.element
42 }
43 #[must_use]
45 pub fn value(self) -> Integer<'a> {
46 self.value
47 }
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub enum DeviationReason {
53 Negative,
55 TooWide,
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub struct DeviationError {
62 pub component: Component,
64 pub span: Span,
66 pub reason: DeviationReason,
68}
69
70#[derive(Debug)]
79pub struct AccuracyReading<'a> {
80 parts: [Option<ComponentReading<'a>>; 3],
81 faults: OwnedVec<Error>,
82 span: Span,
83}
84
85impl<'a> AccuracyReading<'a> {
86 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
94 if element.tag() != Tag::constructed(universal::SEQUENCE) {
95 return Err(Error::schema(
96 ErrorCode::UnexpectedTag,
97 FIELD,
98 element.span().start,
99 ));
100 }
101 let mut inside = parent
102 .enter(element)
103 .map_err(|error| Error::encoding(error, FIELD))?;
104 let execution = parent.execution();
105 let mut faults = execution.vector();
106 let mut parts: [Option<ComponentReading<'a>>; 3] = [None; 3];
107 let mut last = None;
108 while let Some(field) = inside
109 .next_element()
110 .map_err(|error| Error::encoding(error, FIELD))?
111 {
112 let at = field.span().start;
113 execution
114 .charge_work(1)
115 .map_err(|reason| Error::resource(reason, FIELD, at))?;
116 let component = if field.tag() == Tag::primitive(universal::INTEGER) {
117 Component::Seconds
118 } else if field.tag() == Tag::context(false, 0) {
119 Component::Millis
120 } else if field.tag() == Tag::context(false, 1) {
121 Component::Micros
122 } else {
123 record(
124 &mut faults,
125 Error::schema(ErrorCode::UnknownField, FIELD, at),
126 )?;
127 continue;
128 };
129 let index = component.index();
130 if let Some(earlier) = parts[index] {
131 if earlier.element.as_bytes().len() != field.as_bytes().len() {
132 return Err(Error::schema(ErrorCode::DuplicateField, FIELD, at));
133 }
134 execution
135 .charge_work(field.as_bytes().len() as u64)
136 .map_err(|reason| Error::resource(reason, FIELD, at))?;
137 if earlier.element.as_bytes() != field.as_bytes() {
138 return Err(Error::schema(ErrorCode::DuplicateField, FIELD, at));
139 }
140 record(
141 &mut faults,
142 Error::schema(ErrorCode::DuplicateField, FIELD, at),
143 )?;
144 continue;
145 }
146 if last.is_some_and(|last| index < last) {
147 record(&mut faults, Error::schema(ErrorCode::FieldOrder, FIELD, at))?;
148 }
149 last = Some(last.map_or(index, |last| last.max(index)));
150 let (value, fault) = inside
151 .integer_reading(&field)
152 .map_err(|error| Error::encoding(error, FIELD))?
153 .into_parts();
154 if let Some(fault) = fault {
155 record(&mut faults, Error::encoding(fault, FIELD))?;
156 }
157 let number = value.as_u64();
158 if number.is_none()
159 || (component != Component::Seconds
160 && !number.is_some_and(|number| (1..=999).contains(&number)))
161 {
162 record(
163 &mut faults,
164 Error::schema(ErrorCode::MalformedValue, FIELD, at),
165 )?;
166 }
167 parts[index] = Some(ComponentReading {
168 element: field,
169 value,
170 });
171 }
172 Ok(Self {
173 parts,
174 faults: faults.into_owned(),
175 span: element.span(),
176 })
177 }
178
179 #[must_use]
181 pub fn component(&self, component: Component) -> Option<ComponentReading<'a>> {
182 self.parts[component.index()]
183 }
184 #[must_use]
186 pub fn span(&self) -> Span {
187 self.span
188 }
189 #[must_use]
191 pub fn faults(&self) -> &[Error] {
192 &self.faults
193 }
194 #[must_use]
196 pub fn into_faults(self) -> OwnedVec<Error> {
197 self.faults
198 }
199
200 pub fn deviation(&self) -> core::result::Result<Accuracy, DeviationError> {
203 let mut values = [0; 3];
204 for component in [Component::Seconds, Component::Millis, Component::Micros] {
205 let index = component.index();
206 if let Some(part) = self.parts[index] {
207 values[index] = part.value.as_u64().ok_or_else(|| DeviationError {
208 component,
209 span: part.element.span(),
210 reason: if part.value.is_negative() {
211 DeviationReason::Negative
212 } else {
213 DeviationReason::TooWide
214 },
215 })?;
216 }
217 }
218 Ok(Accuracy::new(values[0], values[1], values[2]))
219 }
220}