Skip to content

Commit

Permalink
Rust source code generation continued.
Browse files Browse the repository at this point in the history
  • Loading branch information
eerimoq committed Jan 29, 2019
1 parent 1b278c4 commit 02484ca
Show file tree
Hide file tree
Showing 4 changed files with 1,156 additions and 1,908 deletions.
36 changes: 16 additions & 20 deletions asn1tools/source/rust/uper.py
Expand Up @@ -341,8 +341,7 @@ def generate_type_declaration_process(self, type_, checker):
lines = self.format_enumerated(type_)
lines[0] += ' value;'
elif isinstance(type_, uper.Sequence):
lines = self.format_sequence(type_, checker)[1:-1]
lines = dedent_lines(lines)
lines = self.format_sequence(type_, checker)
elif isinstance(type_, uper.SequenceOf):
lines = self.format_sequence_of(type_, checker)[1:-1]
lines = dedent_lines(lines)
Expand Down Expand Up @@ -401,14 +400,15 @@ def format_integer_inner(self, type_, checker):
return (
[
'encoder.append_non_negative_binary_integer(',
' (uint64_t)(self.{} - {}),'.format(location, checker.minimum),
' (self.{} - {}) as u64,'.format(location, checker.minimum),
' {});'.format(type_.number_of_bits)
],
[
'self.{} = '
'decoder.read_non_negative_binary_integer({});'.format(
'decoder.read_non_negative_binary_integer({}) as {};'.format(
location,
type_.number_of_bits),
type_.number_of_bits,
type_name),
'self.{} += {};'.format(location, checker.minimum)
]
)
Expand Down Expand Up @@ -471,17 +471,16 @@ def format_octet_string_inner(self, type_, checker):

if checker.minimum == checker.maximum:
encode_lines = [
'encoder.append_bytes(&self.{}buf,'.format(location),
' {});'.format(checker.maximum)
'encoder.append_bytes(&self.{}buf);'.format(location)
]
decode_lines = [
'decoder.read_bytes(&mut self.{}buf,'.format(location),
' {});'.format(checker.maximum)
'decoder.read_bytes(&mut self.{}buf);'.format(location)
]
else:
encode_lines = [
'encoder.append_non_negative_binary_integer(',
' self.{}length - {}u,'.format(location, checker.minimum),
' (self.{}length - {}) as u64,'.format(location,
checker.minimum),
' {});'.format(type_.number_of_bits),
'encoder.append_bytes(&self.{}buf,'.format(location),
' self.{}length);'.format(location)
Expand Down Expand Up @@ -552,8 +551,7 @@ def format_choice_inner(self, type_, checker):
encode_lines += [
' {}_choice_{}_e => {{'.format(self.location, member.name)
] + indent_lines(choice_encode_lines, 8) + [
' }',
''
' }'
]

choice_decode_lines = [
Expand All @@ -564,14 +562,12 @@ def format_choice_inner(self, type_, checker):
decode_lines += [
' {} => {{'.format(index)
] + indent_lines(choice_decode_lines, 8) + [
' }',
''
' }'
]

encode_lines = [
'',
'match self.{} {{'.format(choice),
''
'match self.{} {{'.format(choice)
] + encode_lines + [
' _ => encoder.abort(EBADCHOICE);',
'}',
Expand All @@ -583,8 +579,7 @@ def format_choice_inner(self, type_, checker):
unique_choice,
type_.root_number_of_bits),
'',
'match {} {{'.format(unique_choice),
''
'match {} {{'.format(unique_choice)
] + decode_lines + [
' _ => decoder.abort(EBADCHOICE);',
'}',
Expand Down Expand Up @@ -634,7 +629,8 @@ def format_sequence_of_inner(self, type_, checker):
location = self.location_inner('', '.')
first_encode_lines = [
'encoder.append_non_negative_binary_integer(',
' self.{}length - {}u,'.format(location, checker.minimum),
' (self.{}length - {}) as u64,'.format(location,
checker.minimum),
' {});'.format(type_.number_of_bits),
'',
'for {} in 0..self.{}length {{'.format(unique_i, location)
Expand Down Expand Up @@ -773,7 +769,7 @@ def generate_decoder(self, definitions):
if pattern in definitions:
helpers.append(definition)

return helpers + ['}', '']
return helpers + ['}']

def generate_helpers(self, definitions):
helpers = [ENCODER_AND_DECODER_STRUCTS]
Expand Down
90 changes: 57 additions & 33 deletions asn1tools/source/rust/utils.py
Expand Up @@ -5,15 +5,12 @@

TYPE_DECLARATION_FMT = '''\
/// Type {type_name} in module {module_name}.
{helper_types}\
struct {module_name}{type_name} {{
{members}
}};
'''

DEFINITION_FMT = '''
impl {module_name}{type_name} {{
pub fn encode(&mut self, dst: &mut [u8]) -> Result<usize, Error> {{
pub fn encode(&mut self, mut dst: &mut [u8]) -> Result<usize, Error> {{
let mut encoder = Encoder::new(&mut dst);
self.encode_inner(&mut encoder);
Expand Down Expand Up @@ -194,12 +191,11 @@ def format_type_name(self, minimum, maximum):

@property
def location(self):
location = '{}_{}_{}'.format(self.namespace,
self.module_name_snake,
self.type_name_snake)
location = '{}{}'.format(self.module_name,
self.type_name)

if self.asn1_members_backtrace:
location += '_{}'.format('_'.join(self.asn1_members_backtrace))
for member in self.asn1_members_backtrace:
location += make_camel_case(member)

return location

Expand Down Expand Up @@ -287,38 +283,57 @@ def format_octet_string(self, checker):
lines = [' let length: u32;']

return [
'struct {'
'#[derive(Debug, Default, PartialEq, Copy, Clone)]',
'pub struct {} {{'.format(self.location)
] + lines + [
' uint8_t buf[{}];'.format(checker.maximum),
' pub buf: [u8; {}]'.format(checker.maximum),
'}'
]

def format_sequence(self, type_, checker):
helper_lines = []
lines = []

for member in type_.root_members:
member_checker = self.get_member_checker(checker, member.name)

if member.optional:
lines += ['is_{}_present: bool;'.format(member.name)]
lines += ['pub is_{}_present: bool,'.format(member.name)]

with self.members_backtrace_push(member.name):
member_lines = self.format_type(member, member_checker)
member_location = self.location

if not member_lines:
continue

if member_lines:
# member_lines[-1] += ' {};'.format(member.name)
member_lines[-1] = '{}: {};'.format(member.name,
member_lines[-1])
if is_inline_member_lines(member_lines):
member_lines[-1] = 'pub {}: {},'.format(member.name,
member_lines[-1])
else:
helper_lines += member_lines + ['']
member_lines = ['pub {}: {},'.format(member.name,
member_location)]

lines += member_lines

return ['struct {'] + indent_lines(lines) + ['}']
if lines:
lines[-1] = lines[-1][:-1]

return helper_lines + [
'#[derive(Debug, Default, PartialEq, Copy, Clone)]',
'pub struct {} {{'.format(self.location)
] + indent_lines(lines) + [
'}'
]

def format_sequence_of(self, type_, checker):
if not checker.is_bound():
raise self.error('SEQUENCE OF has no maximum length.')

lines = self.format_type(type_.element_type, checker.element_type)
with self.asn1_members_backtrace_push('elem'):
lines = self.format_type(type_.element_type,
checker.element_type)

if lines:
lines[-1] += ' elements[{}];'.format(checker.maximum)
Expand All @@ -333,17 +348,22 @@ def format_sequence_of(self, type_, checker):
return ['struct {'] + indent_lines(length_lines + lines) + ['}']

def format_enumerated(self, type_):
lines = ['enum {}_e'.format(self.location)]

values = [
' {}_{}_e'.format(self.location, value)
lines = [
'#[derive(Debug, PartialEq, Copy, Clone)]',
'pub enum {} {{'.format(self.location)
] + [
' {},'.format(make_camel_case(value))
for value in self.get_enumerated_values(type_)
]
self.helper_lines += [
'enum {}_e {{'.format(self.location)
] + join_lines(values, ',') + [
'};',
''
] + [
'}',
'',
'impl Default for {} {{'.format(self.location),
' fn default() -> Self {',
' {}::{}'.format(self.location,
self.get_enumerated_values(type_)[0].upper()),
' }',
'}'

]

return lines
Expand Down Expand Up @@ -453,15 +473,11 @@ def generate_type_declaration(self, compiled_type):
if not lines:
lines = ['dummy: u8;']

lines = indent_lines(lines)

if self.helper_lines:
self.helper_lines.append('')

return TYPE_DECLARATION_FMT.format(namespace=self.namespace,
module_name=self.module_name,
return TYPE_DECLARATION_FMT.format(module_name=self.module_name,
type_name=self.type_name,
helper_types='\n'.join(self.helper_lines),
members='\n'.join(lines))

def generate_definition(self, compiled_type):
Expand Down Expand Up @@ -552,6 +568,10 @@ def camel_to_snake_case(value):
return value


def make_camel_case(value):
return value[0].upper() + value[1:]


def join_lines(lines, suffix):
return[line + suffix for line in lines[:-1]] + lines[-1:]

Expand Down Expand Up @@ -617,3 +637,7 @@ def sort_user_types_by_used_user_types(user_types):
reversed_sorted_user_types.insert(insert_index, user_type)

return reversed(reversed_sorted_user_types)


def is_inline_member_lines(member_lines):
return len(member_lines) == 1

0 comments on commit 02484ca

Please sign in to comment.