Skip to content

Commit

Permalink
Fix Protobuf serializer for tuple structs with non-vec values
Browse files Browse the repository at this point in the history
  • Loading branch information
kellerkindt committed Apr 14, 2020
1 parent 6e45bf8 commit ee9a214
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 91 deletions.
192 changes: 101 additions & 91 deletions asn1rs-model/src/gen/rust/protobuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,21 @@ impl ProtobufSerializer {
RustType::Complex(custom) => {
block_reader.line(format!("me.0.push({}::read_protobuf(reader)?);", custom))
}
r => block_reader.line(format!(
"me.0.push(reader.read_{}()?{});",
r.to_protobuf().to_string(),
Self::get_as_rust_type_statement(&r),
)),
r => {
if aliased.as_no_option().is_vec() {
block_reader.line(format!(
"me.0.push(reader.read_{}()?{});",
r.to_protobuf().to_string(),
Self::get_as_rust_type_statement(&r),
))
} else {
block_reader.line(format!(
"me.0 = reader.read_{}()?{};",
r.to_protobuf().to_string(),
Self::get_as_rust_type_statement(&r),
))
}
}
};
block_while.push_block(block_reader);
function.push_block(block_while);
Expand Down Expand Up @@ -353,110 +363,110 @@ impl ProtobufSerializer {

fn impl_write_fn_for_tuple_struct(function: &mut Function, aliased: &RustType) {
let mut block_writer = Block::new("");
Self::impl_write_for_vec_attribute(&mut block_writer, aliased, "0", 1);
Self::impl_write_field(1, aliased, "0", &mut block_writer);
function.push_block(block_writer);
}

fn impl_write_fn_for_struct(function: &mut Function, fields: &[(String, RustType)]) {
for (prev_tag, (field_name, field_type)) in fields.iter().enumerate() {
let block_: &mut Function = function;
let field_name = RustCodeGenerator::rust_field_name(field_name, true);
let mut block = if let RustType::Option(_) = field_type {
Block::new(&format!(
"if let Some(ref {}) = self.{}",
RustCodeGenerator::rust_field_name(field_name, true),
RustCodeGenerator::rust_field_name(field_name, true),
&field_name, &field_name,
))
} else {
Block::new("")
};

match &field_type.clone().no_option() {
RustType::Vec(_) => {
Self::impl_write_for_vec_attribute(
&mut block,
field_type,
&RustCodeGenerator::rust_field_name(field_name, true),
prev_tag + 1,
);
}
RustType::Complex(_) => {
let format_line = format!(
"{}{}.{}_format()",
if let RustType::Option(_) = field_type {
""
} else {
"self."
},
RustCodeGenerator::rust_field_name(field_name, true),
Self::CODEC.to_lowercase()
);
block.line(format!(
"writer.write_tag({}, {})?;",
prev_tag + 1,
format_line,
));
let mut block_if = Block::new(&format!(
"if {} == {}Format::LengthDelimited",
format_line,
Self::CODEC
));
block_if.line("let mut vec = Vec::new();");
block_if.line(format!(
"{}{}.write_protobuf(&mut vec as &mut dyn {}Writer)?;",
if let RustType::Option(_) = field_type {
""
} else {
"self."
},
RustCodeGenerator::rust_field_name(field_name, true),
Self::CODEC,
));
block_if.line("writer.write_bytes(&vec[..])?;");
Self::impl_write_field(prev_tag + 1, field_type, &field_name, &mut block);
block_.push_block(block);
}
}

let mut block_el = Block::new("else");
block_el.line(format!(
"{}{}.write_protobuf(writer)?;",
if let RustType::Option(_) = field_type {
""
} else {
"self."
},
RustCodeGenerator::rust_field_name(field_name, true),
));
fn impl_write_field(
tag: usize,
field_type: &RustType,
field_name: &str,
mut block: &mut Block,
) {
match &field_type.clone().no_option() {
RustType::Vec(_) => {
Self::impl_write_for_vec_attribute(&mut block, field_type, &field_name, tag);
}
RustType::Complex(_) => {
let format_line = format!(
"{}{}.{}_format()",
if let RustType::Option(_) = field_type {
""
} else {
"self."
},
&field_name,
Self::CODEC.to_lowercase()
);
block.line(format!("writer.write_tag({}, {})?;", tag, format_line,));
let mut block_if = Block::new(&format!(
"if {} == {}Format::LengthDelimited",
format_line,
Self::CODEC
));
block_if.line("let mut vec = Vec::new();");
block_if.line(format!(
"{}{}.write_protobuf(&mut vec as &mut dyn {}Writer)?;",
if let RustType::Option(_) = field_type {
""
} else {
"self."
},
&field_name,
Self::CODEC,
));
block_if.line("writer.write_bytes(&vec[..])?;");

block.push_block(block_if);
block.push_block(block_el);
}
r => {
block.line(format!(
"writer.write_tagged_{}({}, {})?;",
r.to_protobuf().to_string(),
prev_tag + 1,
Self::get_as_protobuf_type_statement(
format!(
"{}{}",
if ProtobufType::String == r.to_protobuf()
|| RustType::VecU8 == r.to_protobuf().to_rust()
{
if let RustType::Option(_) = field_type {
""
} else {
"&self."
}
} else if let RustType::Option(_) = field_type {
"*"
let mut block_el = Block::new("else");
block_el.line(format!(
"{}{}.write_protobuf(writer)?;",
if let RustType::Option(_) = field_type {
""
} else {
"self."
},
&field_name,
));

block.push_block(block_if);
block.push_block(block_el);
}
r => {
block.line(format!(
"writer.write_tagged_{}({}, {})?;",
r.to_protobuf().to_string(),
tag,
Self::get_as_protobuf_type_statement(
format!(
"{}{}",
if ProtobufType::String == r.to_protobuf()
|| RustType::VecU8 == r.to_protobuf().to_rust()
{
if let RustType::Option(_) = field_type {
""
} else {
"self."
},
RustCodeGenerator::rust_field_name(field_name, true),
),
r
"&self."
}
} else if let RustType::Option(_) = field_type {
"*"
} else {
"self."
},
&field_name,
),
));
}
};
block_.push_block(block);
}
r
),
));
}
};
}

fn impl_write_fn_for_enum(function: &mut Function, name: &str, variants: &[String]) {
Expand Down
38 changes: 38 additions & 0 deletions tests/basic_integer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use asn1rs::io::buffer::BitBuffer;
use asn1rs::macros::asn_to_rust;

asn_to_rust!(
r"BasicInteger DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
RangedMax ::= Integer (0..MAX)
END"
);

#[test]
fn test_uper() {
let mut buffer = BitBuffer::default();
let writer = &mut buffer as &mut dyn UperWriter;
RangedMax(123).write_uper(writer).unwrap();
assert_eq!(&[0x01, 123_u8], buffer.content());

let mut buffer = BitBuffer::default();
let writer = &mut buffer as &mut dyn UperWriter;
RangedMax(66_000).write_uper(writer).unwrap();
let bytes = 66_000_u64.to_be_bytes();
assert_eq!(&[0x03, bytes[5], bytes[6], bytes[7]], buffer.content());
}

#[test]
fn test_protobuf() {
let mut buffer = Vec::default();
let writer = &mut buffer as &mut dyn ProtobufWriter;
RangedMax(123).write_protobuf(writer).unwrap();
assert_eq!(&[0x08, 123_u8], &buffer[..]);

let mut buffer = Vec::default();
let writer = &mut buffer as &mut dyn ProtobufWriter;
RangedMax(66_000).write_protobuf(writer).unwrap();
assert_eq!(&[0x08, 0x80 | 80_u8, 0x80 | 3, 4], &buffer[..]);
}

0 comments on commit ee9a214

Please sign in to comment.