asn1rs 0.3.1

ASN.1 to Rust, Protobuf and SQL compiler/code generator. Supports ASN.1 UPER
Documentation
use crate::gen::protobuf::Error as ProtobufGeneratorError;
use crate::gen::protobuf::ProtobufDefGenerator as ProtobufGenerator;
use crate::gen::rust::RustCodeGenerator as RustGenerator;
use crate::gen::sql::Error as SqlGeneratorError;
use crate::gen::sql::SqlDefGenerator as SqlGenerator;
use crate::gen::Generator;
use crate::model::lor::Error as ResolveError;
use crate::model::protobuf::ToProtobufModel;
use crate::model::sql::ToSqlModel;
use crate::model::Model;
use crate::model::{Error as ModelError, MultiModuleResolver};
use crate::parser::Tokenizer;
use std::collections::HashMap;
use std::io::Error as IoError;
use std::path::Path;

#[derive(Debug)]
pub enum Error {
    RustGenerator,
    ProtobufGenerator(ProtobufGeneratorError),
    SqlGenerator(SqlGeneratorError),
    Model(ModelError),
    Io(IoError),
    ResolveError(ResolveError),
}

impl From<ProtobufGeneratorError> for Error {
    fn from(g: ProtobufGeneratorError) -> Self {
        Error::ProtobufGenerator(g)
    }
}

impl From<SqlGeneratorError> for Error {
    fn from(e: SqlGeneratorError) -> Self {
        Error::SqlGenerator(e)
    }
}

impl From<ModelError> for Error {
    fn from(m: ModelError) -> Self {
        Error::Model(m)
    }
}

impl From<IoError> for Error {
    fn from(e: IoError) -> Self {
        Error::Io(e)
    }
}

impl From<ResolveError> for Error {
    fn from(e: ResolveError) -> Self {
        Error::ResolveError(e)
    }
}

#[derive(Default)]
pub struct Converter {
    models: MultiModuleResolver,
}

impl Converter {
    pub fn load_file<F: AsRef<Path>>(&mut self, file: F) -> Result<(), Error> {
        let input = ::std::fs::read_to_string(file)?;
        let tokens = Tokenizer.parse(&input);
        let model = Model::try_from(tokens)?;
        self.models.push(model);
        Ok(())
    }

    pub fn to_rust<D: AsRef<Path>, A: Fn(&mut RustGenerator)>(
        &self,
        directory: D,
        custom_adjustments: A,
    ) -> Result<HashMap<String, Vec<String>>, Error> {
        let models = self.models.try_resolve_all()?;
        let scope = models.iter().collect::<Vec<_>>();
        let mut files = HashMap::with_capacity(models.len());

        for model in &models {
            let mut generator = RustGenerator::default();
            generator.add_model(model.to_rust_with_scope(&scope[..]));

            custom_adjustments(&mut generator);

            files.insert(
                model.name.clone(),
                generator
                    .to_string()
                    .map_err(|_| Error::RustGenerator)?
                    .into_iter()
                    .map(|(file, content)| {
                        ::std::fs::write(directory.as_ref().join(&file), content)?;
                        Ok::<_, Error>(file)
                    })
                    .collect::<Result<Vec<_>, _>>()?,
            );
        }

        Ok(files)
    }

    pub fn to_protobuf<D: AsRef<Path>>(
        &self,
        directory: D,
    ) -> Result<HashMap<String, Vec<String>>, Error> {
        let models = self.models.try_resolve_all()?;
        let scope = models.iter().collect::<Vec<_>>();
        let mut files = HashMap::with_capacity(models.len());

        for model in &models {
            let mut generator = ProtobufGenerator::default();
            generator.add_model(model.to_rust_with_scope(&scope[..]).to_protobuf());

            files.insert(
                model.name.clone(),
                generator
                    .to_string()?
                    .into_iter()
                    .map(|(file, content)| {
                        ::std::fs::write(directory.as_ref().join(&file), content)?;
                        Ok::<_, Error>(file)
                    })
                    .collect::<Result<Vec<_>, _>>()?,
            );
        }

        Ok(files)
    }

    pub fn to_sql<D: AsRef<Path>>(
        &self,
        directory: D,
    ) -> Result<HashMap<String, Vec<String>>, Error> {
        self.to_sql_with(directory, SqlGenerator::default())
    }

    pub fn to_sql_with<D: AsRef<Path>>(
        &self,
        directory: D,
        mut generator: SqlGenerator,
    ) -> Result<HashMap<String, Vec<String>>, Error> {
        let models = self.models.try_resolve_all()?;
        let scope = models.iter().collect::<Vec<_>>();
        let mut files = HashMap::with_capacity(models.len());

        for model in &models {
            generator.reset();
            generator.add_model(model.to_rust_with_scope(&scope[..]).to_sql());

            files.insert(
                model.name.clone(),
                generator
                    .to_string()?
                    .into_iter()
                    .map(|(file, content)| {
                        ::std::fs::write(directory.as_ref().join(&file), content)?;
                        Ok::<_, Error>(file)
                    })
                    .collect::<Result<Vec<_>, _>>()?,
            );
        }

        Ok(files)
    }
}

#[deprecated(note = "Use the Converter instead")]
pub fn convert_to_rust<F: AsRef<Path>, D: AsRef<Path>, A: Fn(&mut RustGenerator)>(
    file: F,
    dir: D,
    custom_adjustments: A,
) -> Result<Vec<String>, Error> {
    let input = ::std::fs::read_to_string(file)?;
    let tokens = Tokenizer.parse(&input);
    let model = Model::try_from(tokens)?.try_resolve()?;
    let mut generator = RustGenerator::default();
    generator.add_model(model.to_rust());

    custom_adjustments(&mut generator);

    let output = generator.to_string().map_err(|_| Error::RustGenerator)?;

    let mut files = Vec::new();
    for (file, content) in output {
        ::std::fs::write(dir.as_ref().join(&file), content)?;
        files.push(file);
    }
    Ok(files)
}

#[deprecated(note = "Use the Converter instead")]
pub fn convert_to_proto<F: AsRef<Path>, D: AsRef<Path>>(
    file: F,
    dir: D,
) -> Result<Vec<String>, Error> {
    let input = ::std::fs::read_to_string(file)?;
    let tokens = Tokenizer.parse(&input);
    let model = Model::try_from(tokens)?.try_resolve()?;
    let mut generator = ProtobufGenerator::default();
    generator.add_model(model.to_rust().to_protobuf());
    let output = generator.to_string()?;

    let mut files = Vec::new();
    for (file, content) in output {
        ::std::fs::write(dir.as_ref().join(&file), content)?;
        files.push(file);
    }
    Ok(files)
}

#[deprecated(note = "Use the Converter instead")]
pub fn convert_to_sql<F: AsRef<Path>, D: AsRef<Path>>(
    file: F,
    dir: D,
) -> Result<Vec<String>, Error> {
    #[allow(deprecated)]
    convert_to_sql_with(file, dir, SqlGenerator::default())
}

#[deprecated(note = "Use the Converter instead")]
pub fn convert_to_sql_with<F: AsRef<Path>, D: AsRef<Path>>(
    file: F,
    dir: D,
    mut generator: SqlGenerator,
) -> Result<Vec<String>, Error> {
    let input = ::std::fs::read_to_string(file)?;
    let tokens = Tokenizer.parse(&input);
    let model = Model::try_from(tokens)?.try_resolve()?;

    generator.add_model(model.to_rust().to_sql());
    let output = generator.to_string()?;

    let mut files = Vec::new();
    for (file, content) in output {
        ::std::fs::write(dir.as_ref().join(&file), content)?;
        files.push(file);
    }
    Ok(files)
}