1use std::fmt;
30
31#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct AperError(pub String);
35
36impl fmt::Display for AperError {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 f.write_str(&self.0)
39 }
40}
41
42impl std::error::Error for AperError {}
43
44pub type AperResult<T> = Result<T, AperError>;
45
46pub fn err<T>(msg: impl Into<String>) -> AperResult<T> {
47 Err(AperError(msg.into()))
48}
49
50pub const MAX_UNFRAGMENTED: usize = 16_383;
53
54pub fn bits_for_range(range: u64) -> u32 {
56 if range <= 1 {
57 0
58 } else {
59 64 - (range - 1).leading_zeros()
60 }
61}
62
63fn octets_for(value: u64) -> usize {
65 let bits = 64 - value.leading_zeros() as usize;
66 bits.div_ceil(8).max(1)
67}
68
69pub struct Reader<'a> {
75 data: &'a [u8],
76 pos: usize,
78}
79
80impl<'a> Reader<'a> {
81 pub fn new(data: &'a [u8]) -> Self {
82 Self { data, pos: 0 }
83 }
84
85 fn remaining_bits(&self) -> usize {
86 self.data.len() * 8 - self.pos
87 }
88
89 pub fn remaining_octets_aligned(&self) -> usize {
91 let aligned = self.pos.div_ceil(8);
92 self.data.len().saturating_sub(aligned)
93 }
94
95 pub fn align(&mut self) {
96 self.pos = self.pos.div_ceil(8) * 8;
97 }
98
99 pub fn bits(&mut self, n: u32, what: &str) -> AperResult<u64> {
100 if n > 64 {
101 return err(format!("{what}: {n}-bit field is wider than 64"));
102 }
103 if self.remaining_bits() < n as usize {
104 return err(format!(
105 "{what}: needs {n} bits, {} remain",
106 self.remaining_bits()
107 ));
108 }
109 let mut value = 0u64;
110 for _ in 0..n {
111 let byte = self.data[self.pos / 8];
112 let bit = (byte >> (7 - (self.pos % 8))) & 1;
113 value = (value << 1) | bit as u64;
114 self.pos += 1;
115 }
116 Ok(value)
117 }
118
119 pub fn bit(&mut self, what: &str) -> AperResult<bool> {
120 Ok(self.bits(1, what)? == 1)
121 }
122
123 pub fn octets_aligned(&mut self, n: usize, what: &str) -> AperResult<&'a [u8]> {
125 self.align();
126 let start = self.pos / 8;
127 if self.data.len() - start < n {
128 return err(format!(
129 "{what}: declares {n} octets, {} remain",
130 self.data.len() - start
131 ));
132 }
133 self.pos += n * 8;
134 Ok(&self.data[start..start + n])
135 }
136
137 pub fn octets_unaligned(&mut self, n: usize, what: &str) -> AperResult<Vec<u8>> {
139 let mut out = Vec::with_capacity(n);
140 for _ in 0..n {
141 out.push(self.bits(8, what)? as u8);
142 }
143 Ok(out)
144 }
145
146 pub fn constrained(&mut self, lb: u64, ub: u64, what: &str) -> AperResult<u64> {
148 if ub < lb {
149 return err(format!("{what}: empty range"));
150 }
151 let range = (ub - lb).checked_add(1);
152 let value = match range {
153 Some(1) => 0,
154 Some(r) if r <= 255 => self.bits(bits_for_range(r), what)?,
155 Some(256) => {
156 self.align();
157 self.bits(8, what)?
158 }
159 Some(r) if r <= 65_536 => {
160 self.align();
161 self.bits(16, what)?
162 }
163 _ => {
164 let max_octets = octets_for(ub - lb) as u64;
167 let len = self.bits(bits_for_range(max_octets), what)? + 1;
168 let raw = self.octets_aligned(len as usize, what)?;
169 raw.iter().fold(0u64, |acc, b| (acc << 8) | *b as u64)
170 }
171 };
172 let v = lb
173 .checked_add(value)
174 .ok_or_else(|| AperError(format!("{what}: value overflows")))?;
175 if v > ub {
176 return err(format!("{what}: {v} is above the upper bound {ub}"));
177 }
178 Ok(v)
179 }
180
181 pub fn general_length(&mut self, what: &str) -> AperResult<usize> {
184 self.align();
185 let first = self.bits(8, what)? as usize;
186 if first & 0x80 == 0 {
187 return Ok(first);
188 }
189 if first & 0xC0 == 0x80 {
190 let second = self.bits(8, what)? as usize;
191 return Ok(((first & 0x3F) << 8) | second);
192 }
193 err(format!(
194 "{what}: fragmented length (≥16384) is not accepted"
195 ))
196 }
197
198 pub fn size(&mut self, lb: usize, ub: usize, what: &str) -> AperResult<usize> {
200 let n = if ub < 65_536 {
201 self.constrained(lb as u64, ub as u64, what)? as usize
202 } else {
203 self.general_length(what)?
204 };
205 if n < lb || n > ub {
206 return err(format!("{what}: size {n} outside {lb}..{ub}"));
207 }
208 Ok(n)
209 }
210
211 pub fn normally_small(&mut self, what: &str) -> AperResult<u64> {
213 if self.bit(what)? {
214 return err(format!(
215 "{what}: normally-small value above 63 is not accepted"
216 ));
217 }
218 self.bits(6, what)
219 }
220
221 pub fn enumerated(
223 &mut self,
224 root: u64,
225 extensible: bool,
226 what: &str,
227 ) -> AperResult<(bool, u64)> {
228 if extensible && self.bit(what)? {
229 return Ok((true, self.normally_small(what)?));
230 }
231 Ok((false, self.constrained(0, root - 1, what)?))
232 }
233
234 pub fn open_type(&mut self, what: &str) -> AperResult<&'a [u8]> {
236 let len = self.general_length(what)?;
237 if len > self.remaining_octets_aligned() {
238 return err(format!(
239 "{what}: open type declares {len} octets, {} remain",
240 self.remaining_octets_aligned()
241 ));
242 }
243 self.octets_aligned(len, what)
244 }
245
246 pub fn octet_string(&mut self, max: usize, what: &str) -> AperResult<&'a [u8]> {
248 let len = self.general_length(what)?;
249 if len > max {
250 return err(format!(
251 "{what}: {len} octets exceeds the {max}-octet bound"
252 ));
253 }
254 self.octets_aligned(len, what)
255 }
256
257 pub fn fixed_octets(&mut self, n: usize, what: &str) -> AperResult<Vec<u8>> {
259 if n <= 2 {
260 self.octets_unaligned(n, what)
261 } else {
262 Ok(self.octets_aligned(n, what)?.to_vec())
263 }
264 }
265
266 pub fn fixed_bits(&mut self, n: u32, what: &str) -> AperResult<u64> {
268 if n > 16 {
269 self.align();
270 }
271 self.bits(n, what)
272 }
273
274 pub fn varying_bits(&mut self, lb: u32, ub: u32, what: &str) -> AperResult<(u64, u32)> {
277 let n = self.size(lb as usize, ub as usize, what)? as u32;
278 if n > 64 {
279 return err(format!("{what}: {n} bits is wider than 64"));
280 }
281 self.align();
282 Ok((self.bits(n, what)?, n))
283 }
284
285 pub fn extension_bit(&mut self, what: &str) -> AperResult<bool> {
287 self.bit(what)
288 }
289
290 pub fn skip_extension_additions(&mut self, what: &str) -> AperResult<usize> {
293 let n = self.normally_small(what)? as u32 + 1;
294 let mut present = 0usize;
295 for _ in 0..n {
296 if self.bit(what)? {
297 present += 1;
298 }
299 }
300 for _ in 0..present {
301 self.open_type(what)?;
302 }
303 Ok(present)
304 }
305
306 pub fn printable_string(&mut self, lb: usize, ub: usize, what: &str) -> AperResult<String> {
308 let extended = self.bit(what)?;
309 let n = if extended {
310 let n = self.general_length(what)?;
313 if n > ub {
314 return err(format!("{what}: {n} characters exceeds {ub}"));
315 }
316 n
317 } else {
318 self.constrained(lb as u64, ub as u64, what)? as usize
319 };
320 let raw = if ub * 8 > 16 || extended {
322 self.octets_aligned(n, what)?.to_vec()
323 } else {
324 self.octets_unaligned(n, what)?
325 };
326 if !raw.iter().all(|b| is_printable(*b)) {
327 return err(format!("{what}: not a PrintableString"));
328 }
329 Ok(String::from_utf8_lossy(&raw).into_owned())
330 }
331
332 pub fn at_end(&self) -> bool {
334 let aligned = self.pos.div_ceil(8);
335 aligned >= self.data.len()
336 }
337}
338
339pub fn is_printable(b: u8) -> bool {
341 b.is_ascii_alphanumeric() || b" '()+,-./:=?".contains(&b)
342}
343
344#[derive(Default)]
350pub struct Writer {
351 data: Vec<u8>,
352 bit_len: usize,
354}
355
356impl Writer {
357 pub fn new() -> Self {
358 Self::default()
359 }
360
361 pub fn bits(&mut self, value: u64, n: u32) {
362 for i in (0..n).rev() {
363 let bit = ((value >> i) & 1) as u8;
364 if self.bit_len.is_multiple_of(8) {
365 self.data.push(0);
366 }
367 if bit == 1 {
368 let last = self.data.len() - 1;
369 self.data[last] |= 1 << (7 - (self.bit_len % 8));
370 }
371 self.bit_len += 1;
372 }
373 }
374
375 pub fn bit(&mut self, b: bool) {
376 self.bits(b as u64, 1);
377 }
378
379 pub fn align(&mut self) {
380 self.bit_len = self.bit_len.div_ceil(8) * 8;
381 }
382
383 pub fn octets_aligned(&mut self, bytes: &[u8]) {
384 self.align();
385 self.data.extend_from_slice(bytes);
386 self.bit_len += bytes.len() * 8;
387 }
388
389 pub fn octets_unaligned(&mut self, bytes: &[u8]) {
390 for b in bytes {
391 self.bits(*b as u64, 8);
392 }
393 }
394
395 pub fn constrained(&mut self, value: u64, lb: u64, ub: u64, what: &str) -> AperResult<()> {
396 if value < lb || value > ub {
397 return err(format!("{what}: {value} outside {lb}..{ub}"));
398 }
399 let v = value - lb;
400 match (ub - lb).checked_add(1) {
401 Some(1) => {}
402 Some(r) if r <= 255 => self.bits(v, bits_for_range(r)),
403 Some(256) => {
404 self.align();
405 self.bits(v, 8);
406 }
407 Some(r) if r <= 65_536 => {
408 self.align();
409 self.bits(v, 16);
410 }
411 _ => {
412 let max_octets = octets_for(ub - lb) as u64;
413 let len = octets_for(v);
414 self.bits(len as u64 - 1, bits_for_range(max_octets));
415 self.align();
416 for i in (0..len).rev() {
417 self.bits((v >> (8 * i)) & 0xFF, 8);
418 }
419 }
420 }
421 Ok(())
422 }
423
424 pub fn general_length(&mut self, n: usize, what: &str) -> AperResult<()> {
425 self.align();
426 if n < 128 {
427 self.bits(n as u64, 8);
428 } else if n <= MAX_UNFRAGMENTED {
429 self.bits(0x8000 | n as u64, 16);
430 } else {
431 return err(format!(
432 "{what}: {n} would need a fragmented length, which NetGet does not write"
433 ));
434 }
435 Ok(())
436 }
437
438 pub fn size(&mut self, n: usize, lb: usize, ub: usize, what: &str) -> AperResult<()> {
439 if n < lb || n > ub {
440 return err(format!("{what}: size {n} outside {lb}..{ub}"));
441 }
442 if ub < 65_536 {
443 self.constrained(n as u64, lb as u64, ub as u64, what)
444 } else {
445 self.general_length(n, what)
446 }
447 }
448
449 pub fn normally_small(&mut self, value: u64, what: &str) -> AperResult<()> {
450 if value > 63 {
451 return err(format!("{what}: {value} is not a normally-small number"));
452 }
453 self.bit(false);
454 self.bits(value, 6);
455 Ok(())
456 }
457
458 pub fn enumerated(
460 &mut self,
461 index: u64,
462 extended: bool,
463 root: u64,
464 extensible: bool,
465 what: &str,
466 ) -> AperResult<()> {
467 if extensible {
468 self.bit(extended);
469 } else if extended {
470 return err(format!("{what}: not extensible"));
471 }
472 if extended {
473 self.normally_small(index, what)
474 } else {
475 self.constrained(index, 0, root - 1, what)
476 }
477 }
478
479 pub fn open_type(&mut self, inner: &[u8], what: &str) -> AperResult<()> {
481 self.general_length(inner.len(), what)?;
482 self.octets_aligned(inner);
483 Ok(())
484 }
485
486 pub fn octet_string(&mut self, bytes: &[u8], what: &str) -> AperResult<()> {
487 self.general_length(bytes.len(), what)?;
488 self.octets_aligned(bytes);
489 Ok(())
490 }
491
492 pub fn fixed_octets(&mut self, bytes: &[u8]) {
493 if bytes.len() <= 2 {
494 self.octets_unaligned(bytes);
495 } else {
496 self.octets_aligned(bytes);
497 }
498 }
499
500 pub fn fixed_bits(&mut self, value: u64, n: u32) {
501 if n > 16 {
502 self.align();
503 }
504 self.bits(value, n);
505 }
506
507 pub fn varying_bits(
508 &mut self,
509 value: u64,
510 n: u32,
511 lb: u32,
512 ub: u32,
513 what: &str,
514 ) -> AperResult<()> {
515 if n < 64 && value >> n != 0 {
516 return err(format!("{what}: {value} does not fit in {n} bits"));
517 }
518 self.size(n as usize, lb as usize, ub as usize, what)?;
519 self.align();
520 self.bits(value, n);
521 Ok(())
522 }
523
524 pub fn printable_string(
525 &mut self,
526 s: &str,
527 lb: usize,
528 ub: usize,
529 what: &str,
530 ) -> AperResult<()> {
531 let raw = s.as_bytes();
532 if !raw.iter().all(|b| is_printable(*b)) {
533 return err(format!(
534 "{what}: {s:?} is not a PrintableString (letters, digits, space and '()+,-./:=?)"
535 ));
536 }
537 if raw.len() < lb || raw.len() > ub {
538 return err(format!(
539 "{what}: {} characters outside {lb}..{ub}",
540 raw.len()
541 ));
542 }
543 self.bit(false);
544 self.constrained(raw.len() as u64, lb as u64, ub as u64, what)?;
545 if ub * 8 > 16 {
546 self.octets_aligned(raw);
547 } else {
548 self.octets_unaligned(raw);
549 }
550 Ok(())
551 }
552
553 pub fn finish(mut self) -> Vec<u8> {
555 if self.data.is_empty() {
556 self.data.push(0);
557 }
558 self.data
559 }
560}