diff --git a/src/protocol/basic/distinguished/mod.rs b/src/protocol/basic/distinguished/mod.rs index 628d592..55db44f 100644 --- a/src/protocol/basic/distinguished/mod.rs +++ b/src/protocol/basic/distinguished/mod.rs @@ -141,15 +141,17 @@ impl BasicWrite for T { #[inline] fn write_integer_i64(&mut self, value: i64) -> Result<(), Error> { - let offset = value.leading_zeros() / u8::BITS; - self.write_all(&value.to_be_bytes()[offset as usize..])?; + let bytes = value.to_be_bytes(); + let offset = (value.leading_zeros() / u8::BITS).min(bytes.len() as u32 - 1); + self.write_all(&bytes[offset as usize..])?; Ok(()) } #[inline] fn write_integer_u64(&mut self, value: u64) -> Result<(), Error> { - let offset = value.leading_zeros() / u8::BITS; - self.write_all(&value.to_be_bytes()[offset as usize..])?; + let bytes = value.to_be_bytes(); + let offset = (value.leading_zeros() / u8::BITS).min(bytes.len() as u32 - 1); + self.write_all(&bytes[offset as usize..])?; Ok(()) } } diff --git a/src/protocol/basic/err.rs b/src/protocol/basic/err.rs index 2c0bc53..2e7f91a 100644 --- a/src/protocol/basic/err.rs +++ b/src/protocol/basic/err.rs @@ -23,6 +23,12 @@ impl Error { Self::from(ErrorKind::UnexpectedTypeLength { expected, got }) } + #[cold] + #[inline(never)] + pub fn unexpected_choice_index(expected: Range, got: u64) -> Self { + Self::from(ErrorKind::UnexpectedChoiceIndex { expected, got }) + } + #[cold] #[inline(never)] pub fn unsupported_byte_len(max: u8, got: u8) -> Self { @@ -86,6 +92,7 @@ impl From for Inner { pub enum ErrorKind { UnexpectedTypeTag { expected: Tag, got: Tag }, UnexpectedTypeLength { expected: Range, got: u64 }, + UnexpectedChoiceIndex { expected: Range, got: u64 }, UnsupportedByteLen { max: u8, got: u8 }, IoError(std::io::Error), } @@ -99,6 +106,9 @@ impl Display for ErrorKind { ErrorKind::UnexpectedTypeLength { expected, got } => { write!(f, "Expected length in range {expected:?} but got {got:?}") } + ErrorKind::UnexpectedChoiceIndex { expected, got } => { + write!(f, "Expected choice index in {expected:?} but got {got:?}") + } ErrorKind::UnsupportedByteLen { max, got } => { write!( f, diff --git a/src/rw/der.rs b/src/rw/der.rs index 64884b2..9facdbd 100644 --- a/src/rw/der.rs +++ b/src/rw/der.rs @@ -1,9 +1,10 @@ use crate::descriptor::numbers::Number; use crate::descriptor::sequence::Constraint; -use crate::descriptor::{Null, ReadableType, Reader, WritableType, Writer}; +use crate::descriptor::{numbers, Null, ReadableType, Reader, WritableType, Writer}; use crate::protocol::basic::Error; use crate::protocol::basic::{BasicRead, BasicWrite}; use asn1rs_model::asn::Tag; +use std::marker::PhantomData; pub struct BasicWriter { write: W, @@ -54,11 +55,25 @@ impl Writer for BasicWriter { todo!() } + #[inline] fn write_enumerated( &mut self, - _enumerated: &C, + enumerated: &C, ) -> Result<(), Self::Error> { - todo!() + struct IntegerConstraint(PhantomData); + impl crate::descriptor::common::Constraint + for IntegerConstraint + { + const TAG: Tag = ::TAG; + } + impl numbers::Constraint + for IntegerConstraint + { + } + numbers::Integer::>::write_value( + self, + &enumerated.to_choice_index(), + ) } fn write_choice( @@ -90,7 +105,7 @@ impl Writer for BasicWriter { let value = value.to_i64(); let offset = value.leading_zeros() / u8::BITS; let len = value.to_be_bytes().len() as u64 - offset as u64; - self.write.write_length(len)?; + self.write.write_length(len.max(1))?; self.write.write_integer_i64(value)?; Ok(()) } @@ -210,10 +225,24 @@ impl Reader for BasicReader { todo!() } + #[inline] fn read_enumerated( &mut self, ) -> Result { - todo!() + struct IntegerConstraint(PhantomData); + impl crate::descriptor::common::Constraint + for IntegerConstraint + { + const TAG: Tag = ::TAG; + } + impl numbers::Constraint + for IntegerConstraint + { + } + numbers::Integer::>::read_value(self).and_then(|v| { + C::from_choice_index(v) + .ok_or_else(|| Error::unexpected_choice_index(0..C::VARIANT_COUNT, v)) + }) } fn read_choice(&mut self) -> Result { @@ -234,8 +263,8 @@ impl Reader for BasicReader { &mut self, ) -> Result { let identifier = self.read.read_identifier()?; - if identifier.value() != Tag::DEFAULT_INTEGER.value() { - return Err(Error::unexpected_tag(Tag::DEFAULT_INTEGER, identifier)); + if identifier.value() != C::TAG.value() { + return Err(Error::unexpected_tag(C::TAG, identifier)); } let len = self.read.read_length()?; self.read.read_integer_i64(len as u32).map(T::from_i64) @@ -287,8 +316,8 @@ impl Reader for BasicReader { &mut self, ) -> Result { let identifier = self.read.read_identifier()?; - if identifier.value() != Tag::DEFAULT_BOOLEAN.value() { - return Err(Error::unexpected_tag(Tag::DEFAULT_BOOLEAN, identifier)); + if identifier.value() != C::TAG.value() { + return Err(Error::unexpected_tag(C::TAG, identifier)); } let expecting = 1_u64..2_u64; let length = self.read.read_length()?; diff --git a/tests/basic_enumerated.rs b/tests/basic_enumerated.rs index 0c2b04d..8125766 100644 --- a/tests/basic_enumerated.rs +++ b/tests/basic_enumerated.rs @@ -1,6 +1,3 @@ -use asn1rs::rw::UperReader as NewUperReader; -use asn1rs::rw::UperWriter as NewUperWriter; - mod test_utils; use test_utils::*; @@ -35,24 +32,12 @@ asn_to_rust!( END" ); -fn serialize_uper(to_uper: impl Writable) -> (usize, Vec) { - let mut writer = NewUperWriter::default(); - writer.write(&to_uper).unwrap(); - let bits = writer.bit_len(); - (bits, writer.into_bytes_vec()) -} - -fn deserialize_uper(bytes: &[u8], bit_len: usize) -> T { - let mut reader = NewUperReader::from((bytes, bit_len)); - reader.read::().unwrap() -} - #[test] -fn test_predefined_numbers() { - assert_eq!((2, vec![0x00_u8]), serialize_uper(PredefinedNumbers::Abc)); - assert_eq!((2, vec![0x40_u8]), serialize_uper(PredefinedNumbers::Def)); - assert_eq!((8, vec![0x80_u8]), serialize_uper(PredefinedNumbers::Ghi)); - assert_eq!((8, vec![0x81_u8]), serialize_uper(PredefinedNumbers::Jkl)); +fn test_uper_predefined_numbers() { + assert_eq!((2, vec![0x00_u8]), serialize_uper(&PredefinedNumbers::Abc)); + assert_eq!((2, vec![0x40_u8]), serialize_uper(&PredefinedNumbers::Def)); + assert_eq!((8, vec![0x80_u8]), serialize_uper(&PredefinedNumbers::Ghi)); + assert_eq!((8, vec![0x81_u8]), serialize_uper(&PredefinedNumbers::Jkl)); assert_eq!(PredefinedNumbers::Abc, deserialize_uper(&[0x00_u8], 2,)); assert_eq!(PredefinedNumbers::Def, deserialize_uper(&[0x40_u8], 2,)); @@ -61,7 +46,7 @@ fn test_predefined_numbers() { } #[test] -fn test_basic_variants_parsed() { +fn test_uper_basic_variants_parsed() { let _abc = Basic::Abc; let _def = Basic::Def; let _ghi = Basic::Ghi; @@ -73,8 +58,8 @@ fn test_basic_variants_parsed() { } #[test] -pub fn test_basic_uper() { - let mut writer = NewUperWriter::default(); +pub fn test_uper_basic() { + let mut writer = UperWriter::default(); writer.write(&Basic::Abc).unwrap(); writer.write(&Basic::Def).unwrap(); writer.write(&Basic::Ghi).unwrap(); @@ -90,11 +75,18 @@ pub fn test_basic_uper() { } #[test] -fn test_some_enum_with_skipped_numbers() { - test_utils::serialize_and_deserialize_uper(3, &[0x00], &SomeEnum::Abc); - test_utils::serialize_and_deserialize_uper(3, &[0x20], &SomeEnum::Def); - test_utils::serialize_and_deserialize_uper(3, &[0x40], &SomeEnum::Ghi); - test_utils::serialize_and_deserialize_uper(3, &[0x60], &SomeEnum::Jkl); - test_utils::serialize_and_deserialize_uper(3, &[0x80], &SomeEnum::Mno); - test_utils::serialize_and_deserialize_uper(3, &[0xA0], &SomeEnum::Qrs); +fn test_uper_some_enum_with_skipped_numbers() { + serialize_and_deserialize_uper(3, &[0x00], &SomeEnum::Abc); + serialize_and_deserialize_uper(3, &[0x20], &SomeEnum::Def); + serialize_and_deserialize_uper(3, &[0x40], &SomeEnum::Ghi); + serialize_and_deserialize_uper(3, &[0x60], &SomeEnum::Jkl); + serialize_and_deserialize_uper(3, &[0x80], &SomeEnum::Mno); + serialize_and_deserialize_uper(3, &[0xA0], &SomeEnum::Qrs); +} + +#[test] +fn test_der_basic() { + serialize_and_deserialize_der(&[0x0A, 0x01, 0x00], &Basic::Abc); + serialize_and_deserialize_der(&[0x0A, 0x01, 0x01], &Basic::Def); + serialize_and_deserialize_der(&[0x0A, 0x01, 0x02], &Basic::Ghi); } diff --git a/tests/test_utils.rs b/tests/test_utils.rs index c329e2d..fe98a9a 100644 --- a/tests/test_utils.rs +++ b/tests/test_utils.rs @@ -1,5 +1,6 @@ #![allow(unused)] +use asn1rs::prelude::basic::DER; pub use asn1rs::prelude::*; pub fn serialize_uper(to_uper: &impl Writable) -> (usize, Vec) { @@ -39,6 +40,41 @@ pub fn serialize_and_deserialize_uper Vec { + let mut writer = DER::writer(Vec::new()); + writer.write(to_der).unwrap(); + writer.into_inner() +} + +pub fn deserialize_der(data: &[u8]) -> T { + let mut reader = DER::reader(data); + let result = reader.read::().unwrap(); + assert_eq!( + 0, + reader.into_inner().len(), + "After reading, there are still bytes remaining!" + ); + result +} + +pub fn serialize_and_deserialize_der( + data: &[u8], + value: &T, +) { + let serialized = serialize_der(value); + assert_eq!( + data, + &serialized[..], + "Serialized binary data does not match, bad-hex: {:02x?}", + &serialized[..] + ); + assert_eq!( + value, + &deserialize_der::(data), + "Deserialized data struct does not match" + ); +} + #[cfg(feature = "protobuf")] pub fn serialize_protobuf(to_protobuf: &impl Writable) -> Vec { let mut writer = ProtobufWriter::default();