diff --git a/asn1rs-macros/src/ast/mod.rs b/asn1rs-macros/src/ast/mod.rs index 9b78ed14..83c4e6f3 100644 --- a/asn1rs-macros/src/ast/mod.rs +++ b/asn1rs-macros/src/ast/mod.rs @@ -249,8 +249,8 @@ pub(crate) fn parse(attr: TokenStream, item: TokenStream) -> TokenStream { if !model.definitions.is_empty() { let model_rust = model.to_rust(); - use asn1rs_model::gen::rust::walker::AsnDefWalker; - let stringified = AsnDefWalker::stringify(&model_rust); + use asn1rs_model::gen::rust::walker::AsnDefExpander; + let stringified = AsnDefExpander::stringify(&model_rust); additional_impl.push(TokenStream2::from_str(&stringified).unwrap()); } @@ -329,12 +329,13 @@ fn parse_type<'a>(input: &'a ParseBuffer<'a>) -> syn::Result { Ok(Type::Integer(range.0.map(|(min, max)| Range(min, max)))) } "complex" => Ok(Type::TypeReference(String::default())), - "optional" => { + "option" => { let content; parenthesized!(content in input); let inner = parse_type(&content)?; Ok(Type::Optional(Box::new(inner))) } + "boolean" => Ok(Type::Boolean), "sequence_of" => { let content; parenthesized!(content in input); diff --git a/asn1rs-model/src/gen/rust/walker.rs b/asn1rs-model/src/gen/rust/walker.rs index 243983ba..2959832f 100644 --- a/asn1rs-model/src/gen/rust/walker.rs +++ b/asn1rs-model/src/gen/rust/walker.rs @@ -1,4 +1,3 @@ -use crate::gen::rust::GeneratorSupplement; use crate::gen::RustCodeGenerator; use crate::model::rust::{DataEnum, PlainEnum}; use crate::model::{Definition, Model, Range, Rust, RustType}; @@ -7,9 +6,9 @@ use std::fmt::Display; pub const CRATE_SYN_PREFIX: &str = "::asn1rs::syn::"; -pub struct AsnDefWalker; +pub struct AsnDefExpander; -impl AsnDefWalker { +impl AsnDefExpander { fn write_type_definitions( &self, scope: &mut Scope, @@ -53,7 +52,7 @@ impl AsnDefWalker { #[must_use] pub fn type_declaration(r#type: &RustType, name: &str) -> String { match r#type { - RustType::Bool => format!("{}Bool", CRATE_SYN_PREFIX), + RustType::Bool => format!("{}Boolean", CRATE_SYN_PREFIX), RustType::I8(_) => format!("{}Integer", CRATE_SYN_PREFIX, name), RustType::U8(_) => format!("{}Integer", CRATE_SYN_PREFIX, name), RustType::I16(_) => format!("{}Integer", CRATE_SYN_PREFIX, name), @@ -90,7 +89,7 @@ impl AsnDefWalker { #[must_use] pub fn combined_field_type_name(base: &str, name: &str) -> String { format!( - "{}{}", + "{}Field{}", RustCodeGenerator::rust_variant_name(base), RustCodeGenerator::rust_variant_name(name) ) @@ -447,30 +446,20 @@ impl AsnDefWalker { let mut scope = Scope::new(); let myself = Self; - myself.add_imports(&mut scope); - for definition in &model.definitions { - myself.impl_supplement(&mut scope, definition); + myself.write_type_definitions(&mut scope, definition); + myself.write_constraints(&mut scope, definition); + myself.impl_readable(&mut scope, &definition.0); + myself.impl_writable(&mut scope, &definition.0); } scope.to_string() } } -impl GeneratorSupplement for AsnDefWalker { - fn add_imports(&self, _scope: &mut Scope) {} - - fn impl_supplement(&self, scope: &mut Scope, definition: &Definition) { - self.write_type_definitions(scope, definition); - self.write_constraints(scope, definition); - self.impl_readable(scope, &definition.0); - self.impl_writable(scope, &definition.0); - } -} - #[cfg(test)] pub mod tests { - use crate::gen::rust::walker::AsnDefWalker; + use crate::gen::rust::walker::AsnDefExpander; use crate::model::{Definition, Rust, RustType}; use codegen::Scope; @@ -495,7 +484,7 @@ pub mod tests { pub fn test_whatever_struct_type_declaration() { let def = simple_whatever_sequence(); let mut scope = Scope::new(); - AsnDefWalker.write_type_definitions(&mut scope, &def); + AsnDefExpander.write_type_definitions(&mut scope, &def); let string = scope.to_string(); println!("{}", string); let mut lines = string.lines().filter(|l| !l.is_empty()); @@ -504,15 +493,15 @@ pub mod tests { lines.next() ); assert_eq!( - Some("type AsnDefWhateverName = ::asn1rs::syn::Utf8String;"), + Some("type AsnDefWhateverFieldName = ::asn1rs::syn::Utf8String;"), lines.next() ); assert_eq!( - Some("type AsnDefWhateverOpt = Option<::asn1rs::syn::Utf8String>;"), + Some("type AsnDefWhateverFieldOpt = Option<::asn1rs::syn::Utf8String>;"), lines.next() ); assert_eq!( - Some("type AsnDefWhateverSome = Option<::asn1rs::syn::Utf8String>;"), + Some("type AsnDefWhateverFieldSome = Option<::asn1rs::syn::Utf8String>;"), lines.next() ); } @@ -521,9 +510,9 @@ pub mod tests { pub fn test_whatever_struct_constraint_and_read_write_impl() { let def = simple_whatever_sequence(); let mut scope = Scope::new(); - AsnDefWalker.write_constraints(&mut scope, &def); - AsnDefWalker.impl_readable(&mut scope, &def.0); - AsnDefWalker.impl_writable(&mut scope, &def.0); + AsnDefExpander.write_constraints(&mut scope, &def); + AsnDefExpander.impl_readable(&mut scope, &def.0); + AsnDefExpander.impl_writable(&mut scope, &def.0); let string = scope.to_string(); println!("{}", string); @@ -551,16 +540,16 @@ pub mod tests { where Self: Sized, { Ok(Self { - name: AsnDefWhateverName::read_value(reader)?, - opt: AsnDefWhateverOpt::read_value(reader)?, - some: AsnDefWhateverSome::read_value(reader)?, + name: AsnDefWhateverFieldName::read_value(reader)?, + opt: AsnDefWhateverFieldOpt::read_value(reader)?, + some: AsnDefWhateverFieldSome::read_value(reader)?, }) } fn write_seq(&self, writer: &mut W) -> Result<(), W::Error> { - AsnDefWhateverName::write_value(writer, &self.name)?; - AsnDefWhateverOpt::write_value(writer, &self.opt)?; - AsnDefWhateverSome::write_value(writer, &self.some)?; + AsnDefWhateverFieldName::write_value(writer, &self.name)?; + AsnDefWhateverFieldOpt::write_value(writer, &self.opt)?; + AsnDefWhateverFieldSome::write_value(writer, &self.some)?; Ok(()) } } diff --git a/src/syn/boolean.rs b/src/syn/boolean.rs new file mode 100644 index 00000000..d782c2be --- /dev/null +++ b/src/syn/boolean.rs @@ -0,0 +1,35 @@ +use crate::syn::{ReadableType, Reader, WritableType, Writer}; +use core::marker::PhantomData; + +pub struct Boolean(PhantomData); + +impl Default for Boolean { + fn default() -> Self { + Boolean(Default::default()) + } +} + +pub trait Constraint {} + +#[derive(Default)] +pub struct NoConstraint; +impl Constraint for NoConstraint {} + +impl WritableType for Boolean { + type Type = bool; + + fn write_value( + writer: &mut W, + value: &Self::Type, + ) -> Result<(), ::Error> { + writer.write_boolean::(*value) + } +} + +impl ReadableType for Boolean { + type Type = bool; + + fn read_value(reader: &mut R) -> Result::Error> { + reader.read_boolean::() + } +} diff --git a/src/syn/io/println.rs b/src/syn/io/println.rs index f4601615..ae7d5c38 100644 --- a/src/syn/io/println.rs +++ b/src/syn/io/println.rs @@ -138,4 +138,9 @@ impl Writer for PrintlnWriter { self.indented_println(format!("WRITING OctetString {:?}", value)); Ok(()) } + + fn write_boolean(&mut self, value: bool) -> Result<(), Self::Error> { + self.indented_println(format!("WRITING Boolean {}", value)); + Ok(()) + } } diff --git a/src/syn/io/uper.rs b/src/syn/io/uper.rs index d8d69965..260c293c 100644 --- a/src/syn/io/uper.rs +++ b/src/syn/io/uper.rs @@ -192,6 +192,10 @@ impl Writer for UperWriter { self.buffer .write_octet_string(value, bit_buffer_range::()) } + + fn write_boolean(&mut self, value: bool) -> Result<(), Self::Error> { + self.buffer.write_bit(value) + } } pub struct UperReader { @@ -335,6 +339,10 @@ impl Reader for UperReader { fn read_octet_string(&mut self) -> Result, Self::Error> { self.buffer.read_octet_string(bit_buffer_range::()) } + + fn read_boolean(&mut self) -> Result { + self.buffer.read_bit() + } } fn bit_buffer_range() -> Option<(i64, i64)> { diff --git a/src/syn/mod.rs b/src/syn/mod.rs index a6333078..38bac5ff 100644 --- a/src/syn/mod.rs +++ b/src/syn/mod.rs @@ -1,5 +1,6 @@ use std::marker::PhantomData; +pub mod boolean; pub mod choice; pub mod complex; pub mod enumerated; @@ -11,6 +12,7 @@ pub mod sequence; pub mod sequenceof; pub mod utf8string; +pub use boolean::Boolean; pub use choice::Choice; pub use complex::Complex; pub use enumerated::Enumerated; @@ -56,6 +58,8 @@ pub trait Reader { fn read_utf8string(&mut self) -> Result; fn read_octet_string(&mut self) -> Result, Self::Error>; + + fn read_boolean(&mut self) -> Result; } pub trait Readable: Sized { @@ -122,6 +126,8 @@ pub trait Writer { &mut self, value: &[u8], ) -> Result<(), Self::Error>; + + fn write_boolean(&mut self, value: bool) -> Result<(), Self::Error>; } pub trait Writable { diff --git a/tests/basic_proc_macro_attribute.rs b/tests/basic_proc_macro_attribute.rs index 5a58ef88..972feafd 100644 --- a/tests/basic_proc_macro_attribute.rs +++ b/tests/basic_proc_macro_attribute.rs @@ -253,7 +253,7 @@ fn are_we_binary_yet_uper() { #[asn(sequence)] #[derive(Debug, PartialOrd, PartialEq)] pub struct Optional { - #[asn(optional(integer))] + #[asn(option(integer))] value: Option, } @@ -273,7 +273,7 @@ fn test_optional_uper() { #[asn(sequence)] #[derive(Debug, PartialOrd, PartialEq)] pub struct CrazyList { - #[asn(sequence_of(optional(optional(sequence_of(integer)))))] + #[asn(sequence_of(option(option(sequence_of(integer)))))] values: Vec>>>, } @@ -387,7 +387,7 @@ fn test_flat_list_uper() { #[asn(transparent)] #[derive(Debug, PartialOrd, PartialEq)] -pub struct Important(#[asn(optional(integer))] Option); +pub struct Important(#[asn(option(integer))] Option); #[test] fn test_transparent_important_println() { @@ -442,3 +442,31 @@ fn test_transparent_important_uper_none() { assert_eq!(v, uper.read::().unwrap()); assert_eq!(0, uper.bits_remaining()); } + +#[asn(sequence)] +#[derive(Debug, Default, PartialOrd, PartialEq)] +pub struct BoolContainer { + #[asn(boolean)] + bool1: bool, + #[asn(boolean)] + bool2: bool, + #[asn(boolean)] + bool3: bool, +} + +#[test] +fn test_bool_container_uper() { + let mut uper = UperWriter::default(); + let v = BoolContainer { + bool1: false, + bool2: true, + bool3: true, + }; + uper.write(&v).unwrap(); + assert_eq!(&[0b011_0_0000], uper.byte_content()); + assert_eq!(3, uper.bit_len()); + + let mut uper = uper.into_reader(); + assert_eq!(v, uper.read::().unwrap()); + assert_eq!(0, uper.bits_remaining()); +}