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 parts[index].is_none() {
131 if last.is_some_and(|last| index < last) {
132 record(&mut faults, Error::schema(ErrorCode::FieldOrder, FIELD, at))?;
133 }
134 last = Some(last.map_or(index, |last| last.max(index)));
135 }
136 let (value, fault) = inside
137 .integer_reading(&field)
138 .map_err(|error| Error::encoding(error, FIELD))?
139 .into_parts();
140 if let Some(fault) = fault {
141 record(&mut faults, Error::encoding(fault, FIELD))?;
142 }
143 let number = value.as_u64();
144 if number.is_none()
145 || (component != Component::Seconds
146 && !number.is_some_and(|number| (1..=999).contains(&number)))
147 {
148 record(
149 &mut faults,
150 Error::schema(ErrorCode::MalformedValue, FIELD, at),
151 )?;
152 }
153 if let Some(earlier) = parts[index] {
154 if earlier.value.as_bytes().len() != value.as_bytes().len() {
161 return Err(Error::schema(ErrorCode::DuplicateField, FIELD, at));
162 }
163 execution
164 .charge_work(value.as_bytes().len() as u64)
165 .map_err(|reason| Error::resource(reason, FIELD, at))?;
166 if earlier.value.as_bytes() != value.as_bytes() {
167 return Err(Error::schema(ErrorCode::DuplicateField, FIELD, at));
168 }
169 record(
170 &mut faults,
171 Error::schema(ErrorCode::DuplicateField, FIELD, at),
172 )?;
173 continue;
174 }
175 parts[index] = Some(ComponentReading {
176 element: field,
177 value,
178 });
179 }
180 Ok(Self {
181 parts,
182 faults: faults.into_owned(),
183 span: element.span(),
184 })
185 }
186
187 #[must_use]
189 pub fn component(&self, component: Component) -> Option<ComponentReading<'a>> {
190 self.parts[component.index()]
191 }
192 #[must_use]
194 pub fn span(&self) -> Span {
195 self.span
196 }
197 #[must_use]
199 pub fn faults(&self) -> &[Error] {
200 &self.faults
201 }
202 #[must_use]
204 pub fn into_faults(self) -> OwnedVec<Error> {
205 self.faults
206 }
207
208 pub fn deviation(&self) -> core::result::Result<Accuracy, DeviationError> {
211 let mut values = [0; 3];
212 for component in [Component::Seconds, Component::Millis, Component::Micros] {
213 let index = component.index();
214 if let Some(part) = self.parts[index] {
215 values[index] = part.value.as_u64().ok_or_else(|| DeviationError {
216 component,
217 span: part.element.span(),
218 reason: if part.value.is_negative() {
219 DeviationReason::Negative
220 } else {
221 DeviationReason::TooWide
222 },
223 })?;
224 }
225 }
226 Ok(Accuracy::new(values[0], values[1], values[2]))
227 }
228}