rasn_compiler/generator/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//! The `generator` module is responsible for generating rust code that handles
//! decoding and encoding of the parsed and validated ASN1 data elements.
//! The `generator` uses string templates for generating rust code.

use std::{error::Error, fmt::Debug};

use crate::intermediate::{ExtensibilityEnvironment, TaggingEnvironment, ToplevelDefinition};

use self::error::GeneratorError;

pub mod error;
pub mod rasn;
pub mod typescript;

/// Implementors of the `Backend` trait can be used
/// as a backend to the compiler in order to create bindings
/// for other frameworks and languages than the default backend.
pub trait Backend: Sized + Default {
    type Config: Sized + Default + Debug;

    /// File extension that should be used for output file containing the generated bindings.
    /// For example: `.ts` for Typescript, `.rs` for Rasn bindings.
    const FILE_EXTENSION: &'static str;

    /// generates bindings for an ASN.1 module
    /// ### Params
    /// - `top_level_declarations` vector of [TopLevelDeclaration]s that are defined in the ASN.1 module
    fn generate_module(
        &mut self,
        top_level_declarations: Vec<ToplevelDefinition>,
    ) -> Result<GeneratedModule, GeneratorError>;

    /// generates bindings for a single ASN.1 item
    /// ### Params
    /// - `tld` [TopLevelDeclaration] for which the bindings should be generated
    fn generate(&self, tld: ToplevelDefinition) -> Result<String, GeneratorError>;

    /// Formats the bindings using the language- or framework-specific linters.
    /// For example, the Rust backend uses rustfmt for formatting bindings.
    fn format_bindings(bindings: &str) -> Result<String, Box<dyn Error>> {
        Ok(bindings.to_owned())
    }

    /// Returns a reference to the backend's config
    fn config(&self) -> &Self::Config;

    /// Creates a backend from its config
    fn from_config(config: Self::Config) -> Self;

    /// Creates a backend from its fields.
    /// Usually, the tagging and extensibility environments do not
    /// have to be set manually, but will follow the respective module header.
    fn new(
        config: Self::Config,
        tagging_environment: TaggingEnvironment,
        extensibility_environment: ExtensibilityEnvironment,
    ) -> Self;
}

pub struct GeneratedModule {
    pub generated: Option<String>,
    pub warnings: Vec<Box<dyn Error>>,
}

impl GeneratedModule {
    pub fn empty() -> Self {
        Self {
            generated: None,
            warnings: vec![],
        }
    }
}