From e367718638ede17515837390ba5f7186495fa5eb Mon Sep 17 00:00:00 2001 From: Michael Watzko Date: Tue, 14 Apr 2020 15:42:35 +0200 Subject: [PATCH] Parse INTEGER types without range as INTEGER(0..MAX) #6 --- asn1rs-model/src/model/mod.rs | 88 ++++++++++++++++++++--------------- tests/basic_integer.rs | 9 ++++ 2 files changed, 60 insertions(+), 37 deletions(-) diff --git a/asn1rs-model/src/model/mod.rs b/asn1rs-model/src/model/mod.rs index 9fefd486..7c51bef9 100644 --- a/asn1rs-model/src/model/mod.rs +++ b/asn1rs-model/src/model/mod.rs @@ -13,6 +13,7 @@ use backtrace::Backtrace; use std::convert::TryFrom; use std::error::Error as StdError; use std::fmt::{Debug, Display, Formatter}; +use std::iter::Peekable; use std::vec::IntoIter; macro_rules! loop_ctrl_separator { @@ -234,7 +235,7 @@ impl Default for Model { impl Model { pub fn try_from(value: Vec) -> Result { let mut model = Model::default(); - let mut iter = value.into_iter(); + let mut iter = value.into_iter().peekable(); model.name = Self::read_name(&mut iter)?; Self::skip_until_after_text_ignore_ascii_case(&mut iter, "BEGIN")?; @@ -257,14 +258,14 @@ impl Model { Err(Error::unexpected_end_of_stream()) } - fn read_name(iter: &mut IntoIter) -> Result { + fn read_name(iter: &mut Peekable>) -> Result { iter.next() .and_then(|token| token.into_text()) .ok_or(Error::missing_module_name()) } fn skip_until_after_text_ignore_ascii_case( - iter: &mut IntoIter, + iter: &mut Peekable>, text: &str, ) -> Result<(), Error> { for t in iter { @@ -275,7 +276,7 @@ impl Model { Err(Error::unexpected_end_of_stream()) } - fn read_imports(iter: &mut IntoIter) -> Result, Error> { + fn read_imports(iter: &mut Peekable>) -> Result, Error> { let mut imports = Vec::new(); let mut import = Import::default(); while let Some(token) = iter.next() { @@ -296,7 +297,10 @@ impl Model { } Err(Error::unexpected_end_of_stream()) } - fn read_definition(iter: &mut IntoIter, name: String) -> Result, Error> { + fn read_definition( + iter: &mut Peekable>, + name: String, + ) -> Result, Error> { Self::next_separator_ignore_case(iter, ':')?; Self::next_separator_ignore_case(iter, ':')?; Self::next_separator_ignore_case(iter, '=')?; @@ -328,7 +332,9 @@ impl Model { } } - fn next_with_opt_tag(iter: &mut IntoIter) -> Result<(Token, Option), Error> { + fn next_with_opt_tag( + iter: &mut Peekable>, + ) -> Result<(Token, Option), Error> { let token = Self::next(iter)?; if token.eq_separator('[') { let tag = Tag::try_from(&mut *iter)?; @@ -340,31 +346,39 @@ impl Model { } } - fn read_role(iter: &mut IntoIter) -> Result { + fn read_role(iter: &mut Peekable>) -> Result { let text = Self::next_text(iter)?; Self::read_role_given_text(iter, text) } - fn read_role_given_text(iter: &mut IntoIter, text: String) -> Result { + fn read_role_given_text( + iter: &mut Peekable>, + text: String, + ) -> Result { if text.eq_ignore_ascii_case("INTEGER") { - Self::next_separator_ignore_case(iter, '(')?; - let start = Self::next(iter)?; - Self::next_separator_ignore_case(iter, '.')?; - Self::next_separator_ignore_case(iter, '.')?; - let end = Self::next(iter)?; - Self::next_separator_ignore_case(iter, ')')?; - if start.eq_text("0") && end.eq_text_ignore_ascii_case("MAX") { - Ok(Type::Integer(None)) - } else { - Ok(Type::Integer(Some(Range( - start - .text() - .and_then(|t| t.parse::().ok()) - .ok_or_else(|| Error::invalid_range_value(start))?, - end.text() - .and_then(|t| t.parse::().ok()) - .ok_or_else(|| Error::invalid_range_value(end))?, - )))) + match iter.peek() { + Some(peeked) if peeked.eq_separator('(') => { + Self::next_separator_ignore_case(iter, '(')?; + let start = Self::next(iter)?; + Self::next_separator_ignore_case(iter, '.')?; + Self::next_separator_ignore_case(iter, '.')?; + let end = Self::next(iter)?; + Self::next_separator_ignore_case(iter, ')')?; + if start.eq_text("0") && end.eq_text_ignore_ascii_case("MAX") { + Ok(Type::Integer(None)) + } else { + Ok(Type::Integer(Some(Range( + start + .text() + .and_then(|t| t.parse::().ok()) + .ok_or_else(|| Error::invalid_range_value(start))?, + end.text() + .and_then(|t| t.parse::().ok()) + .ok_or_else(|| Error::invalid_range_value(end))?, + )))) + } + } + _ => Ok(Type::Integer(None)), } } else if text.eq_ignore_ascii_case("BOOLEAN") { Ok(Type::Boolean) @@ -388,7 +402,7 @@ impl Model { } } - fn read_sequence_or_sequence_of(iter: &mut IntoIter) -> Result { + fn read_sequence_or_sequence_of(iter: &mut Peekable>) -> Result { let token = Self::next(iter)?; if token.eq_text_ignore_ascii_case("OF") { @@ -410,7 +424,7 @@ impl Model { } } - fn read_field(iter: &mut IntoIter) -> Result<(Field, bool), Error> { + fn read_field(iter: &mut Peekable>) -> Result<(Field, bool), Error> { let name = Self::next_text(iter)?; let (token, tag) = Self::next_with_opt_tag(iter)?; let mut field = Field { @@ -436,16 +450,16 @@ impl Model { } } - fn next(iter: &mut IntoIter) -> Result { + fn next(iter: &mut Peekable>) -> Result { iter.next().ok_or_else(Error::unexpected_end_of_stream) } - fn next_text(iter: &mut IntoIter) -> Result { + fn next_text(iter: &mut Peekable>) -> Result { Self::next(iter)?.into_text_or_else(Error::no_text) } fn next_separator_ignore_case( - iter: &mut IntoIter, + iter: &mut Peekable>, separator: char, ) -> Result<(), Error> { let token = Self::next(iter)?; @@ -540,10 +554,10 @@ pub enum Tag { ContextSpecific(usize), } -impl TryFrom<&mut IntoIter> for Tag { +impl TryFrom<&mut Peekable>> for Tag { type Error = Error; - fn try_from(iter: &mut IntoIter) -> Result { + fn try_from(iter: &mut Peekable>) -> Result { macro_rules! parse_tag_number { () => { parse_tag_number!(Model::::next(iter)?) @@ -710,10 +724,10 @@ impl Choice { } } -impl TryFrom<&mut IntoIter> for Choice { +impl TryFrom<&mut Peekable>> for Choice { type Error = Error; - fn try_from(iter: &mut IntoIter) -> Result { + fn try_from(iter: &mut Peekable>) -> Result { Model::::next_separator_ignore_case(iter, '{')?; let mut choice = Choice { variants: Vec::new(), @@ -836,10 +850,10 @@ impl Enumerated { } } -impl TryFrom<&mut IntoIter> for Enumerated { +impl TryFrom<&mut Peekable>> for Enumerated { type Error = Error; - fn try_from(iter: &mut IntoIter) -> Result { + fn try_from(iter: &mut Peekable>) -> Result { Model::::next_separator_ignore_case(iter, '{')?; let mut enumerated = Self { variants: Vec::new(), diff --git a/tests/basic_integer.rs b/tests/basic_integer.rs index 177d673d..e5ff8723 100644 --- a/tests/basic_integer.rs +++ b/tests/basic_integer.rs @@ -7,9 +7,18 @@ asn_to_rust!( RangedMax ::= Integer (0..MAX) + NotRanged ::= Integer + END" ); +#[test] +fn test_default_range() { + assert_eq!(RangedMax::value_min(), NotRanged::value_min()); + assert_eq!(RangedMax::value_max(), NotRanged::value_max()); + let _ = NotRanged(123_u64); // does not compile if the inner type is not u64 +} + #[test] fn test_uper() { let mut buffer = BitBuffer::default();