From 075e5d9e1e69852051f8ea341b81c0cc3154b6b7 Mon Sep 17 00:00:00 2001 From: Michael Watzko Date: Thu, 30 Apr 2020 19:27:52 +0200 Subject: [PATCH] Support SEQUENCE OF in fields #11 --- asn1rs-macros/src/ast/mod.rs | 6 + src/io/uper.rs | 6 + src/syn/io/println.rs | 21 +++ src/syn/io/uper.rs | 202 +++++++++++++++++++++------- src/syn/mod.rs | 11 ++ src/syn/sequenceof.rs | 37 +++++ tests/basic_proc_macro_attribute.rs | 87 +++++++++++- 7 files changed, 319 insertions(+), 51 deletions(-) create mode 100644 src/syn/sequenceof.rs diff --git a/asn1rs-macros/src/ast/mod.rs b/asn1rs-macros/src/ast/mod.rs index 19cb235e..9579c86a 100644 --- a/asn1rs-macros/src/ast/mod.rs +++ b/asn1rs-macros/src/ast/mod.rs @@ -276,6 +276,12 @@ fn parse_type<'a>(input: &'a ParseBuffer<'a>) -> syn::Result { let inner = parse_type(&content)?; Ok(Type::Optional(Box::new(inner))) } + "sequence_of" => { + let content; + parenthesized!(content in input); + let inner = parse_type(&content)?; + Ok(Type::SequenceOf(Box::new(inner))) + } r#type => Err(input.error(format!("Unexpected attribute: `{}`", r#type))), } } diff --git a/src/io/uper.rs b/src/io/uper.rs index 39bbf4c3..f8cf1629 100644 --- a/src/io/uper.rs +++ b/src/io/uper.rs @@ -17,6 +17,7 @@ pub enum Error { InsufficientDataInSourceBuffer, InvalidChoiceIndex(usize, usize), ValueNotInRange(i64, i64, i64), + SizeNotInRange(usize, usize, usize), EndOfStream, } @@ -45,6 +46,11 @@ impl std::fmt::Display for Error { "The value {} is not within the inclusive range of {} and {}", value, min, max ), + Error::SizeNotInRange(size, min, max) => write!( + f, + "The size {} is not within the inclusive range of {} and {}", + size, min, max + ), Error::EndOfStream => write!( f, "Can no longer read or write any bytes from the underlying dataset" diff --git a/src/syn/io/println.rs b/src/syn/io/println.rs index 9b694c23..f4601615 100644 --- a/src/syn/io/println.rs +++ b/src/syn/io/println.rs @@ -27,6 +27,27 @@ impl Writer for PrintlnWriter { self.with_increased_indentation(|w| f(w)) } + fn write_sequence_of( + &mut self, + slice: &[T::Type], + ) -> Result<(), Self::Error> { + self.indented_println(format!( + "Writing sequence-of ({}..{})", + C::MIN + .map(|v| format!("{}", v)) + .unwrap_or_else(|| String::from("MIN")), + C::MAX + .map(|v| format!("{}", v)) + .unwrap_or_else(|| String::from("MAX")), + )); + self.with_increased_indentation(|w| { + for value in slice { + T::write_value(w, value)?; + } + Ok(()) + }) + } + fn write_enumerated( &mut self, enumerated: &C, diff --git a/src/syn/io/uper.rs b/src/syn/io/uper.rs index 099b92b7..d8d69965 100644 --- a/src/syn/io/uper.rs +++ b/src/syn/io/uper.rs @@ -4,10 +4,37 @@ use crate::io::uper::Reader as _UperReader; use crate::io::uper::Writer as _UperWriter; use crate::prelude::*; +#[derive(Default)] +pub struct ScopeStack { + scopes: Vec>, + scope: Vec, +} + +impl ScopeStack { + pub fn current_mut(&mut self) -> &mut Vec { + &mut self.scope + } + + pub fn stash(&mut self) { + self.push(Vec::default()) + } + + pub fn push(&mut self, mut scope: Vec) { + std::mem::swap(&mut scope, &mut self.scope); + self.scopes.push(scope); + } + + pub fn pop(&mut self) -> Vec { + let mut scope = self.scopes.pop().unwrap_or_default(); + std::mem::swap(&mut scope, &mut self.scope); + scope + } +} + #[derive(Default)] pub struct UperWriter { buffer: BitBuffer, - optional_positions: Vec, + scope: ScopeStack, } impl UperWriter { @@ -28,6 +55,23 @@ impl UperWriter { let bytes = self.into_bytes_vec(); UperReader::from_bits(bytes, bits) } + + pub fn scope_pushed R>( + &mut self, + scope: Vec, + f: F, + ) -> (R, Vec) { + self.scope.push(scope); + let result = f(self); + (result, self.scope.pop()) + } + + pub fn scope_stashed R>(&mut self, f: F) -> R { + self.scope.stash(); + let result = f(self); + self.scope.pop(); + result + } } impl Writer for UperWriter { @@ -40,22 +84,41 @@ impl Writer for UperWriter { // In UPER the optional flag for all OPTIONAL values are written before any field // value is written. This reserves the bits, so that on a later call of `write_opt` // the value can be set to the actual state. - let before = self.optional_positions.len(); + let mut list = Vec::default(); let write_pos = self.buffer.write_position; for i in (0..C::OPTIONAL_FIELDS).rev() { // insert in reverse order so that a simple pop() in `write_opt` retrieves // the relevant position - self.optional_positions.push(write_pos + i); + list.push(write_pos + i); if let Err(e) = self.buffer.write_bit(false) { self.buffer.write_position = write_pos; // undo write_bits return Err(e); } } - f(self)?; - assert_eq!(before, self.optional_positions.len()); + let (result, scope) = self.scope_pushed(list, f); + result?; // first error on this before throwing non-informative assert errors + assert!(scope.is_empty()); Ok(()) } + fn write_sequence_of( + &mut self, + slice: &[T::Type], + ) -> Result<(), Self::Error> { + let min = C::MIN.unwrap_or(0); + let max = C::MAX.unwrap_or(std::usize::MAX); + if slice.len() < min || slice.len() > max { + return Err(UperError::SizeNotInRange(slice.len(), min, max)); + } + self.scope_stashed(|w| { + w.buffer.write_length_determinant(slice.len() - min)?; // TODO untested for MIN != 0 + for value in slice { + T::write_value(w, value)?; + } + Ok(()) + }) + } + fn write_enumerated( &mut self, enumerated: &C, @@ -74,28 +137,34 @@ impl Writer for UperWriter { } fn write_choice(&mut self, choice: &C) -> Result<(), Self::Error> { - if C::EXTENSIBLE { - self.buffer.write_choice_index_extensible( - choice.to_choice_index() as u64, - C::STD_VARIANT_COUNT as u64, - )?; - } else { - self.buffer - .write_choice_index(choice.to_choice_index() as u64, C::STD_VARIANT_COUNT as u64)?; - } - choice.write_content(self) + self.scope_stashed(|w| { + if C::EXTENSIBLE { + w.buffer.write_choice_index_extensible( + choice.to_choice_index() as u64, + C::STD_VARIANT_COUNT as u64, + )?; + } else { + w.buffer.write_choice_index( + choice.to_choice_index() as u64, + C::STD_VARIANT_COUNT as u64, + )?; + } + choice.write_content(w) + }) } fn write_opt( &mut self, value: Option<&::Type>, ) -> Result<(), Self::Error> { - self.buffer - .with_write_position_at(self.optional_positions.pop().unwrap(), |buffer| { - buffer.write_bit(value.is_some()) - })?; + if let Some(position) = self.scope.current_mut().pop() { + self.buffer + .with_write_position_at(position, |buffer| buffer.write_bit(value.is_some()))?; + } else { + self.buffer.write_bit(value.is_some())?; + } if let Some(value) = value { - T::write_value(self, value) + self.scope_stashed(|w| T::write_value(w, value)) } else { Ok(()) } @@ -127,20 +196,37 @@ impl Writer for UperWriter { pub struct UperReader { buffer: BitBuffer, - optionals: Vec, + scope: ScopeStack, } impl UperReader { pub fn from_bits>>(bytes: I, bit_len: usize) -> Self { Self { buffer: BitBuffer::from_bits(bytes.into(), bit_len), - optionals: Vec::default(), + scope: Default::default(), } } pub fn bits_remaining(&self) -> usize { self.buffer.write_position - self.buffer.read_position } + + pub fn scope_pushed R>( + &mut self, + scope: Vec, + f: F, + ) -> (R, Vec) { + self.scope.push(scope); + let result = f(self); + (result, self.scope.pop()) + } + + pub fn scope_stashed R>(&mut self, f: F) -> R { + self.scope.stash(); + let result = f(self); + self.scope.pop(); + result + } } impl Reader for UperReader { @@ -157,21 +243,32 @@ impl Reader for UperReader { // In UPER the optional flag for all OPTIONAL values are written before any field // value is written. This loads those bits, so that on a later call of `read_opt` can // retrieve them by a simple call of `pop` on the optionals buffer - let position = self.optionals.len(); - self.optionals.resize(position + C::OPTIONAL_FIELDS, false); + let mut optionals = vec![false; C::OPTIONAL_FIELDS]; for i in (0..C::OPTIONAL_FIELDS).rev() { - self.optionals[position + i] = match self.buffer.read_bit() { - Ok(bit) => bit, - Err(e) => { - // need to remove eagerly added values - self.optionals.resize(position, false); - return Err(e); - } - } + optionals[i] = self.buffer.read_bit()?; } - let result = f(self); - assert_eq!(position, self.optionals.len()); - result + let (result, scope) = self.scope_pushed(optionals, f); + let result = result?; // first error on this before throwing non-informative assert errors + assert!(scope.is_empty()); + Ok(result) + } + + fn read_sequence_of( + &mut self, + ) -> Result, Self::Error> { + let min = C::MIN.unwrap_or(0); + let max = C::MAX.unwrap_or(std::usize::MAX); + let len = self.buffer.read_length_determinant()? + min; // TODO untested for MIN != 0 + if len > max { + return Err(UperError::SizeNotInRange(len, min, max)); + } + self.scope_stashed(|w| { + let mut vec = Vec::with_capacity(len); + for _ in 0..len { + vec.push(T::read_value(w)?); + } + Ok(vec) + }) } fn read_enumerated(&mut self) -> Result { @@ -191,26 +288,33 @@ impl Reader for UperReader { } fn read_choice(&mut self) -> Result { - if C::EXTENSIBLE { - self.buffer - .read_choice_index_extensible(C::STD_VARIANT_COUNT as u64) - .map(|v| v as usize) - } else { - self.buffer - .read_choice_index(C::STD_VARIANT_COUNT as u64) - .map(|v| v as usize) - } - .and_then(|index| { - C::read_content(index, self)? - .ok_or_else(|| UperError::InvalidChoiceIndex(index, C::VARIANT_COUNT)) + self.scope_stashed(|w| { + if C::EXTENSIBLE { + w.buffer + .read_choice_index_extensible(C::STD_VARIANT_COUNT as u64) + .map(|v| v as usize) + } else { + w.buffer + .read_choice_index(C::STD_VARIANT_COUNT as u64) + .map(|v| v as usize) + } + .and_then(|index| { + C::read_content(index, w)? + .ok_or_else(|| UperError::InvalidChoiceIndex(index, C::VARIANT_COUNT)) + }) }) } fn read_opt( &mut self, ) -> Result::Type>, Self::Error> { - if self.optionals.pop().unwrap() { - T::read_value(self).map(Some) + let value = if let Some(pre_fetched) = self.scope.current_mut().pop() { + pre_fetched + } else { + self.buffer.read_bit()? + }; + if value { + self.scope_stashed(T::read_value).map(Some) } else { Ok(None) } diff --git a/src/syn/mod.rs b/src/syn/mod.rs index fb56021a..a6333078 100644 --- a/src/syn/mod.rs +++ b/src/syn/mod.rs @@ -8,6 +8,7 @@ pub mod numbers; pub mod octetstring; pub mod optional; pub mod sequence; +pub mod sequenceof; pub mod utf8string; pub use choice::Choice; @@ -16,6 +17,7 @@ pub use enumerated::Enumerated; pub use numbers::Integer; pub use octetstring::OctetString; pub use sequence::Sequence; +pub use sequenceof::SequenceOf; pub use utf8string::Utf8String; pub trait Reader { @@ -37,6 +39,10 @@ pub trait Reader { f: F, ) -> Result; + fn read_sequence_of( + &mut self, + ) -> Result, Self::Error>; + fn read_enumerated(&mut self) -> Result; fn read_choice(&mut self) -> Result; @@ -89,6 +95,11 @@ pub trait Writer { f: F, ) -> Result<(), Self::Error>; + fn write_sequence_of( + &mut self, + slice: &[T::Type], + ) -> Result<(), Self::Error>; + fn write_enumerated( &mut self, enumerated: &C, diff --git a/src/syn/sequenceof.rs b/src/syn/sequenceof.rs new file mode 100644 index 00000000..0d8ef3d7 --- /dev/null +++ b/src/syn/sequenceof.rs @@ -0,0 +1,37 @@ +use crate::syn::{ReadableType, Reader, WritableType, Writer}; +use core::marker::PhantomData; + +pub struct SequenceOf(PhantomData, PhantomData); + +impl Default for SequenceOf { + fn default() -> Self { + Self(Default::default(), Default::default()) + } +} + +pub trait Constraint { + const MIN: Option = None; + const MAX: Option = None; +} + +#[derive(Default)] +pub struct NoConstraint; +impl Constraint for NoConstraint {} + +impl WritableType for SequenceOf { + type Type = Vec; + + #[inline] + fn write_value(writer: &mut W, value: &Self::Type) -> Result<(), W::Error> { + writer.write_sequence_of::(value.as_slice()) + } +} + +impl ReadableType for SequenceOf { + type Type = Vec; + + #[inline] + fn read_value(reader: &mut R) -> Result::Error> { + reader.read_sequence_of::() + } +} diff --git a/tests/basic_proc_macro_attribute.rs b/tests/basic_proc_macro_attribute.rs index 04265088..a0614f67 100644 --- a/tests/basic_proc_macro_attribute.rs +++ b/tests/basic_proc_macro_attribute.rs @@ -1,6 +1,6 @@ #![allow(unused)] -use asn1rs::syn::io::{UperReader, UperWriter}; +use asn1rs::syn::io::{PrintlnWriter, UperReader, UperWriter}; use asn1rs::syn::Reader; use asn1rs_macros::asn; @@ -262,7 +262,7 @@ pub struct Optional { } #[test] -fn optional_test_uper() { +fn test_optional_uper() { let mut uper = UperWriter::default(); let v = Optional { value: Some(1337) }; uper.write(&v).unwrap(); @@ -273,3 +273,86 @@ fn optional_test_uper() { assert_eq!(v, uper.read::().unwrap()); assert_eq!(0, uper.bits_remaining()); } + +#[asn(sequence)] +#[derive(Debug, PartialOrd, PartialEq)] +pub struct CrazyList { + #[asn(sequence_of(optional(optional(sequence_of(integer)))))] + values: Vec>>>, +} + +#[test] +fn test_crazy_list_println() { + let mut writer = PrintlnWriter::default(); + let list = CrazyList { + values: vec![Some(Some(vec![13])), Some(Some(vec![37])), Some(None), None], + }; + // Prints something like + // + // Writing sequence CrazyList + // Writing sequence-of (MIN..MAX) + // Writing OPTIONAL + // Some + // Writing OPTIONAL + // Some + // Writing sequence-of (MIN..MAX) + // WRITING Integer 13 + // Writing OPTIONAL + // Some + // Writing OPTIONAL + // Some + // Writing sequence-of (MIN..MAX) + // WRITING Integer 37 + // Writing OPTIONAL + // Some + // Writing OPTIONAL + // None + // Writing OPTIONAL + // None + list.write(&mut writer).unwrap(); +} + +#[test] +fn test_crazy_list_uper() { + let mut uper = UperWriter::default(); + let list = CrazyList { + values: vec![Some(Some(vec![13])), Some(Some(vec![37])), Some(None), None], + }; + uper.write(&list).unwrap(); + assert_eq!( + &[ + // from analytic, I hate myself for it and I am sorry to everyone that needs to adjust this + // ...well... probably myself in the future... so self.await ... hehe ... + // -- 0 + 0x04, // 4 elements in the list + // -- 1 + 0b11 << 6 // first element: Some, Some + | 0x01 >> 2, // length of inner list, part 1 + // -- 2 + 0x01 << 6 // length of inner list, part2 + | 0x01 >> 2, // length of integer, part 1 + // -- 3 + 0x01 << 6 // length of integer, part 2 + | (13 >> 2), // value of integer, part 1 + // -- 4 + 13 << 6 // value of integer, part 2, end of element + | 0b11 << 4 // second element: Some, Some + | 0x01 >> 4, // length of inner list, part 1 + // -- 5 + 0x01 << 4 // length of inner list, part 2 + | 0x01 >> 4, // length of integer, part 1 + // -- 6 + 0x01 << 4 // length of integer, part 2 + | 37 >> 4, // value of integer, part 1 + // -- 7 + 37 << 4 // value of integer, part 2, end of element + | 0b10 << 2 // third element: Some, None + | 0b0 << 1 // fourth element: None + ], + uper.byte_content() + ); + assert_eq!(7 * 8 + 7, uper.bit_len()); + let mut uper = uper.into_reader(); + assert_eq!(list, uper.read::().unwrap()); + assert_eq!(0, uper.bits_remaining()); +}