Skip to content

Commit

Permalink
Support OCTET STRING in declarativ notation #11
Browse files Browse the repository at this point in the history
  • Loading branch information
kellerkindt committed Apr 30, 2020
1 parent 72c7e72 commit 6ae4163
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 1 deletion.
1 change: 1 addition & 0 deletions asn1rs-macros/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ impl Parse for Asn {
let ident = input.step(|c| c.ident().ok_or_else(|| c.error("Expected ASN-Type")))?;
match ident.to_string().to_lowercase().as_str() {
"utf8string" if first => asn.r#type = Some(Type::UTF8String),
"octet_string" if first => asn.r#type = Some(Type::OctetString),
"integer" if first => {
let range = MaybeRanged::parse(input)?;
asn.r#type = Some(Type::Integer(range.0.map(|(min, max)| Range(min, max))));
Expand Down
10 changes: 9 additions & 1 deletion src/syn/io/println.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::prelude::*;
pub struct PrintlnWriter(usize);

impl PrintlnWriter {
fn indented_println(&self, text: &str) {
fn indented_println<T: std::fmt::Display>(&self, text: T) {
println!("{}{}", " ".repeat(self.0), text);
}

Expand Down Expand Up @@ -109,4 +109,12 @@ impl Writer for PrintlnWriter {
));
Ok(())
}

fn write_octet_string<C: octetstring::Constraint>(
&mut self,
value: &[u8],
) -> Result<(), Self::Error> {
self.indented_println(format!("WRITING OctetString {:?}", value));
Ok(())
}
}
22 changes: 22 additions & 0 deletions src/syn/io/uper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ impl Writer for UperWriter {
) -> Result<(), Self::Error> {
self.buffer.write_utf8_string(value)
}

fn write_octet_string<C: octetstring::Constraint>(
&mut self,
value: &[u8],
) -> Result<(), Self::Error> {
self.buffer
.write_octet_string(value, bit_buffer_range::<C>())
}
}

pub struct UperReader {
Expand Down Expand Up @@ -219,4 +227,18 @@ impl Reader for UperReader {
fn read_utf8string<C: utf8string::Constraint>(&mut self) -> Result<String, Self::Error> {
self.buffer.read_utf8_string()
}

fn read_octet_string<C: octetstring::Constraint>(&mut self) -> Result<Vec<u8>, Self::Error> {
self.buffer.read_octet_string(bit_buffer_range::<C>())
}
}

fn bit_buffer_range<C: octetstring::Constraint>() -> Option<(i64, i64)> {
match (C::MIN, C::MAX) {
(None, None) => None,
(min, max) => Some((
min.unwrap_or(0) as i64,
max.unwrap_or(std::i64::MAX as usize) as i64, // TODO never verified!
)),
}
}
9 changes: 9 additions & 0 deletions src/syn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod complex;
pub mod enumerated;
pub mod io;
pub mod numbers;
pub mod octetstring;
pub mod optional;
pub mod sequence;
pub mod utf8string;
Expand All @@ -13,6 +14,7 @@ pub use choice::Choice;
pub use complex::Complex;
pub use enumerated::Enumerated;
pub use numbers::Integer;
pub use octetstring::OctetString;
pub use sequence::Sequence;
pub use utf8string::Utf8String;

Expand Down Expand Up @@ -46,6 +48,8 @@ pub trait Reader {
fn read_int_max(&mut self) -> Result<u64, Self::Error>;

fn read_utf8string<C: utf8string::Constraint>(&mut self) -> Result<String, Self::Error>;

fn read_octet_string<C: octetstring::Constraint>(&mut self) -> Result<Vec<u8>, Self::Error>;
}

pub trait Readable: Sized {
Expand Down Expand Up @@ -102,6 +106,11 @@ pub trait Writer {
&mut self,
value: &str,
) -> Result<(), Self::Error>;

fn write_octet_string<C: octetstring::Constraint>(
&mut self,
value: &[u8],
) -> Result<(), Self::Error>;
}

pub trait Writable {
Expand Down
37 changes: 37 additions & 0 deletions src/syn/octetstring.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use crate::syn::{ReadableType, Reader, WritableType, Writer};
use core::marker::PhantomData;

pub struct OctetString<C: Constraint = NoConstraint>(PhantomData<C>);

impl<C: Constraint> Default for OctetString<C> {
fn default() -> Self {
Self(Default::default())
}
}

pub trait Constraint {
const MIN: Option<usize> = None;
const MAX: Option<usize> = None;
}

#[derive(Default)]
pub struct NoConstraint;
impl Constraint for NoConstraint {}

impl<C: Constraint> WritableType for OctetString<C> {
type Type = Vec<u8>;

#[inline]
fn write_value<W: Writer>(writer: &mut W, value: &Self::Type) -> Result<(), W::Error> {
writer.write_octet_string::<C>(value.as_slice())
}
}

impl<C: Constraint> ReadableType for OctetString<C> {
type Type = Vec<u8>;

#[inline]
fn read_value<R: Reader>(reader: &mut R) -> Result<Self::Type, <R as Reader>::Error> {
reader.read_octet_string::<C>()
}
}
22 changes: 22 additions & 0 deletions tests/basic_proc_macro_attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,25 @@ BEGIN
END
*/

#[asn(sequence)]
#[derive(Debug, PartialOrd, PartialEq)]
pub struct AreWeBinaryYet {
#[asn(octet_string)]
binary: Vec<u8>,
}

#[test]
fn are_we_binary_yet_uper() {
let mut uper = UperWriter::default();
let are_we = AreWeBinaryYet {
binary: vec![0x13, 0x37],
};
uper.write(&are_we).unwrap();
// https://asn1.io/asn1playground/
assert_eq!(&[02, 0x13, 0x37], uper.byte_content());
assert_eq!(3 * 8, uper.bit_len());
let mut uper = uper.into_reader();
assert_eq!(are_we, uper.read::<AreWeBinaryYet>().unwrap());
assert_eq!(0, uper.bits_remaining());
}

0 comments on commit 6ae4163

Please sign in to comment.