diff --git a/Makefile b/Makefile index c9375ba..373cff4 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ ci: @set -eu; \ export RUSTFLAGS='-D warnings'; \ - make fmt clippy; \ + make fmt clippy check; \ make ci-examples ci-crates; \ echo "Success!" @@ -23,6 +23,10 @@ clean: cd - > /dev/null; \ done +check: + @set -eu; \ + diff std/rust/primitive_types.mol tools/codegen/primitive_types.mol + fmt: @set -eu; \ for dir in ${RUST_PROJS}; do \ diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml index 4171ebc..48ae9f0 100644 --- a/bindings/rust/Cargo.toml +++ b/bindings/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "molecule" -version = "0.7.3" +version = "0.8.0" authors = ["Nervos Core Dev "] edition = "2018" description = "Rust bindings for molecule." diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 528c57b..a7084d3 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -21,7 +21,7 @@ cfg_if::cfg_if! { pub mod error; pub mod prelude; -mod primitive; +pub mod primitive; // Little Endian pub type Number = u32; diff --git a/std/rust/.gitignore b/std/rust/.gitignore new file mode 100644 index 0000000..66ba3f1 --- /dev/null +++ b/std/rust/.gitignore @@ -0,0 +1,3 @@ +target/ +Cargo.lock + diff --git a/std/rust/Cargo.toml b/std/rust/Cargo.toml new file mode 100644 index 0000000..f28a76d --- /dev/null +++ b/std/rust/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "molecule-std" +version = "0.0.1" +authors = ["Nervos Core Dev "] +edition = "2018" +description = "std primitive types for molecule." +homepage = "https://github.com/nervosnetwork/molecule" +repository = "https://github.com/nervosnetwork/molecule" +keywords = ["molecule", "code-generation", "serialization"] +categories = [ + "parser-implementations", + "development-tools::build-utils", + "encoding", + "data-structures" +] +license = "MIT" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +molecule = { path = "../../bindings/rust" } + +[features] +default = ["std"] +with-primitive-types = [] +std = ["molecule/bytes", "molecule/faster-hex"] + +[build-dependencies] +codegen = {package ="molecule-codegen", version = "=0.8.0", path = "../../tools/codegen" } + diff --git a/std/rust/build.rs b/std/rust/build.rs new file mode 100644 index 0000000..25ce379 --- /dev/null +++ b/std/rust/build.rs @@ -0,0 +1,20 @@ +use codegen::{Compiler, Language}; + +fn compile_schema(schema: &str) { + let mut compiler = Compiler::new(); + compiler + .input_schema_file(schema) + .generate_code(Language::Rust) + .output_dir_set_default() + .expand_primitive(true) + .run() + .unwrap(); + println!("cargo:rerun-if-changed={}", schema); +} + +fn main() { + println!("cargo:rerun-if-changed=primitive_types.mol"); + compile_schema("primitive_types.mol"); + let out_dir = ::std::env::var("OUT_DIR").unwrap(); + println!("{}", out_dir); +} diff --git a/std/rust/primitive_types.mol b/std/rust/primitive_types.mol new file mode 100644 index 0000000..8ddbaf8 --- /dev/null +++ b/std/rust/primitive_types.mol @@ -0,0 +1,14 @@ +// Unsigned integers +array uint64 [byte; 8]; +array uint32 [byte; 4]; +array uint16 [byte; 2]; +array uint8 [byte; 1]; + +// Signed integers +array int64 [byte; 8]; +array int32 [byte; 4]; +array int16 [byte; 2]; +array int8 [byte; 1]; + +// Bool +array bool [byte; 1]; diff --git a/std/rust/src/lib.rs b/std/rust/src/lib.rs new file mode 100644 index 0000000..852e743 --- /dev/null +++ b/std/rust/src/lib.rs @@ -0,0 +1,35 @@ +pub use crate as molecule_std; + +pub use molecule::*; + +#[cfg(feature = "with-primitive-types")] +pub mod primitives { + include!(concat!(env!("OUT_DIR"), "/primitive_types.rs")); +} + +pub mod prelude { + pub use molecule::prelude::*; + + #[cfg(feature = "with-primitive-types")] + pub use crate::primitives::*; +} + +#[cfg(feature = "with-primitive-types")] +mod primitives_pack; + +pub mod pack { + use crate::prelude::Entity; + pub trait Unpack { + /// Unpack binary data into rust types. + fn unpack(&self) -> T; + } + + /// A syntactic sugar to convert a rust type into binary data. + pub trait Pack { + /// Packs a rust type into binary data. + fn pack(&self) -> T; + } + + #[cfg(feature = "with-primitive-types")] + pub use crate::primitives_pack::*; +} diff --git a/std/rust/src/primitives_pack.rs b/std/rust/src/primitives_pack.rs new file mode 100644 index 0000000..23011a3 --- /dev/null +++ b/std/rust/src/primitives_pack.rs @@ -0,0 +1,154 @@ +use crate::bytes::*; +use crate::pack::*; +use crate::prelude::*; + +macro_rules! impl_conversion_for_entity_unpack { + ($original:ty, $entity:ident) => { + impl Unpack<$original> for $entity { + fn unpack(&self) -> $original { + self.as_reader().unpack() + } + } + }; +} + +impl Pack for u64 { + fn pack(&self) -> Uint64 { + Uint64::new_unchecked(Bytes::from(self.to_le_bytes().to_vec())) + } +} + +impl<'r> Unpack for Uint64Reader<'r> { + fn unpack(&self) -> u64 { + let mut b = [0u8; 8]; + b.copy_from_slice(self.as_slice()); + u64::from_le_bytes(b) + } +} +impl_conversion_for_entity_unpack!(u64, Uint64); + +impl Pack for u32 { + fn pack(&self) -> Uint32 { + Uint32::new_unchecked(Bytes::from(self.to_le_bytes().to_vec())) + } +} + +impl<'r> Unpack for Uint32Reader<'r> { + fn unpack(&self) -> u32 { + let mut b = [0u8; 4]; + b.copy_from_slice(self.as_slice()); + u32::from_le_bytes(b) + } +} +impl_conversion_for_entity_unpack!(u32, Uint32); + +impl Pack for u16 { + fn pack(&self) -> Uint16 { + Uint16::new_unchecked(Bytes::from(self.to_le_bytes().to_vec())) + } +} + +impl<'r> Unpack for Uint16Reader<'r> { + fn unpack(&self) -> u16 { + let mut b = [0u8; 2]; + b.copy_from_slice(self.as_slice()); + u16::from_le_bytes(b) + } +} +impl_conversion_for_entity_unpack!(u16, Uint16); + +impl Pack for u8 { + fn pack(&self) -> Uint8 { + Uint8::new_unchecked(Bytes::from(self.to_le_bytes().to_vec())) + } +} + +impl<'r> Unpack for Uint8Reader<'r> { + fn unpack(&self) -> u8 { + let mut b = [0u8; 1]; + b.copy_from_slice(self.as_slice()); + u8::from_le_bytes(b) + } +} +impl_conversion_for_entity_unpack!(u8, Uint8); + +// Signed integers + +impl Pack for i64 { + fn pack(&self) -> Int64 { + Int64::new_unchecked(Bytes::from(self.to_le_bytes().to_vec())) + } +} + +impl<'r> Unpack for Int64Reader<'r> { + fn unpack(&self) -> i64 { + let mut b = [0u8; 8]; + b.copy_from_slice(self.as_slice()); + i64::from_le_bytes(b) + } +} +impl_conversion_for_entity_unpack!(i64, Int64); + +impl Pack for i32 { + fn pack(&self) -> Int32 { + Int32::new_unchecked(Bytes::from(self.to_le_bytes().to_vec())) + } +} + +impl<'r> Unpack for Int32Reader<'r> { + fn unpack(&self) -> i32 { + let mut b = [0u8; 4]; + b.copy_from_slice(self.as_slice()); + i32::from_le_bytes(b) + } +} +impl_conversion_for_entity_unpack!(i32, Int32); + +impl Pack for i16 { + fn pack(&self) -> Int16 { + Int16::new_unchecked(Bytes::from(self.to_le_bytes().to_vec())) + } +} + +impl<'r> Unpack for Int16Reader<'r> { + fn unpack(&self) -> i16 { + let mut b = [0u8; 2]; + b.copy_from_slice(self.as_slice()); + i16::from_le_bytes(b) + } +} +impl_conversion_for_entity_unpack!(i16, Int16); + +impl Pack for i8 { + fn pack(&self) -> Int8 { + Int8::new_unchecked(Bytes::from(self.to_le_bytes().to_vec())) + } +} + +impl<'r> Unpack for Int8Reader<'r> { + fn unpack(&self) -> i8 { + let mut b = [0u8; 1]; + b.copy_from_slice(self.as_slice()); + i8::from_le_bytes(b) + } +} +impl_conversion_for_entity_unpack!(i8, Int8); + +// Bool +impl Pack for bool { + fn pack(&self) -> Bool { + let b = u8::from(*self); + Bool::new_unchecked(Bytes::from(vec![b])) + } +} + +impl<'r> Unpack for BoolReader<'r> { + fn unpack(&self) -> bool { + match self.as_slice()[0] { + 0 => false, + 1 => true, + _ => unreachable!(), + } + } +} +impl_conversion_for_entity_unpack!(bool, Bool); diff --git a/tools/codegen/Cargo.toml b/tools/codegen/Cargo.toml index 4c1202c..b4da504 100644 --- a/tools/codegen/Cargo.toml +++ b/tools/codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "molecule-codegen" -version = "0.7.3" +version = "0.8.0" authors = ["Nervos Core Dev "] edition = "2018" description = "Code generator for molecule." @@ -16,7 +16,7 @@ categories = [ license = "MIT" [dependencies] -molecule = { version = "=0.7.3", path = "../../bindings/rust", default-features = false } +molecule = { version = "=0.8.0", path = "../../bindings/rust", default-features = false } property = "0.3.3" pest = "2.1.3" pest_derive = "2.1.0" diff --git a/tools/codegen/primitive_types.mol b/tools/codegen/primitive_types.mol new file mode 100644 index 0000000..8ddbaf8 --- /dev/null +++ b/tools/codegen/primitive_types.mol @@ -0,0 +1,14 @@ +// Unsigned integers +array uint64 [byte; 8]; +array uint32 [byte; 4]; +array uint16 [byte; 2]; +array uint8 [byte; 1]; + +// Signed integers +array int64 [byte; 8]; +array int32 [byte; 4]; +array int16 [byte; 2]; +array int8 [byte; 1]; + +// Bool +array bool [byte; 1]; diff --git a/tools/codegen/src/ast/raw/mod.rs b/tools/codegen/src/ast/raw/mod.rs index 6b97274..6765ced 100644 --- a/tools/codegen/src/ast/raw/mod.rs +++ b/tools/codegen/src/ast/raw/mod.rs @@ -44,7 +44,7 @@ pub(crate) struct UnionDecl { imported_depth: usize, } -#[derive(Debug, Property)] +#[derive(Debug, Property, Clone)] pub(crate) struct ArrayDecl { name: String, item: ItemDecl, @@ -73,7 +73,7 @@ pub(crate) struct TableDecl { imported_depth: usize, } -#[derive(Debug, Property)] +#[derive(Debug, Property, Clone)] pub(crate) struct ItemDecl { typ: String, } diff --git a/tools/codegen/src/ast/verified/complete.rs b/tools/codegen/src/ast/verified/complete.rs index 70f6ac5..a8282b1 100644 --- a/tools/codegen/src/ast/verified/complete.rs +++ b/tools/codegen/src/ast/verified/complete.rs @@ -3,7 +3,9 @@ use std::{ rc::Rc, }; -use super::super::raw; +use super::must_get_primitive_types; + +use super::{super::raw, Primitive}; trait CompleteRawDecl { fn complete(&self, deps: &super::Deps) -> Option; @@ -162,23 +164,38 @@ impl CompleteRawDecl for raw::TableDecl { } impl super::Ast { - pub(crate) fn complete(raw: raw::Ast) -> Self { + pub(crate) fn complete(raw: raw::Ast, expand_primitive: bool) -> Self { let mut decls_idx = HashMap::new(); let mut decls_keys = HashSet::new(); for decl in raw.decls() { let name = decl.name(); - if super::TopDecl::new_primitive(name.to_lowercase().as_str()).is_some() { + if super::TopDecl::new_primitive(name.to_lowercase().as_str(), !expand_primitive) + .is_some() + { panic!("the name `{}` is reserved", name); } if decls_idx.insert(name, decl).is_some() || !decls_keys.insert(name) { panic!("the name `{}` is used more than once", name); }; } + + let mut primitives = vec![Primitive { + name: "byte".to_string(), + size: 1, + }]; + + if !expand_primitive { + primitives.extend(must_get_primitive_types()); + } + let mut decls_result = HashMap::new(); - decls_result.insert( - "byte", - Rc::new(super::TopDecl::new_primitive("byte").unwrap()), - ); + primitives.iter().for_each(|primitive_type| { + decls_result.insert( + primitive_type.name(), + Rc::new(super::TopDecl::new_primitive(primitive_type.name(), true).unwrap()), + ); + }); + loop { if decls_keys.is_empty() { break; diff --git a/tools/codegen/src/ast/verified/mod.rs b/tools/codegen/src/ast/verified/mod.rs index 3f49e40..23e0fa3 100644 --- a/tools/codegen/src/ast/verified/mod.rs +++ b/tools/codegen/src/ast/verified/mod.rs @@ -14,6 +14,25 @@ pub use has_name::HasName; type Deps<'a> = HashMap<&'a str, Rc>; +pub fn must_get_primitive_types() -> Vec { + use crate::utils::ParserUtils; + crate::parser::Parser::preprocess(&std::path::PathBuf::from(concat!( + env!("CARGO_MANIFEST_DIR"), + "/primitive_types.mol" + ))) + .unwrap() + .decls() + .iter() + .map(|decl| match decl { + crate::ast::raw::TopDecl::Array(array) => Primitive { + name: array.name().to_string(), + size: array.item_count(), + }, + _ => panic!("primitive types is not array"), + }) + .collect::>() +} + #[derive(Debug, Property)] #[property(get(public))] pub struct Ast { @@ -42,7 +61,7 @@ pub enum TopDecl { Table(Table), } -#[derive(Debug, Property)] +#[derive(Debug, Property, Clone)] #[property(get(public))] pub struct Primitive { name: String, @@ -133,15 +152,21 @@ impl Ast { } impl TopDecl { - fn new_primitive(name: &str) -> Option { - match name { - "byte" => Some(Primitive { + fn new_primitive(name: &str, with_primitive_ext: bool) -> Option { + if name.eq("byte") { + return Some(Primitive { name: name.to_owned(), size: 1, - }), - _ => None, + }) + .map(Self::Primitive); } - .map(Self::Primitive) + if !with_primitive_ext { + return None; + } + must_get_primitive_types() + .iter() + .find(|primitive_decl| primitive_decl.name().eq(name)) + .map(|v| Self::Primitive(v.clone())) } pub fn is_byte(&self) -> bool { diff --git a/tools/codegen/src/ast/verified/recover.rs b/tools/codegen/src/ast/verified/recover.rs index 84b6096..9520e01 100644 --- a/tools/codegen/src/ast/verified/recover.rs +++ b/tools/codegen/src/ast/verified/recover.rs @@ -1,3 +1,4 @@ +use crate::ast::verified; use std::{ collections::{HashMap, HashSet}, rc::Rc, @@ -5,6 +6,8 @@ use std::{ use crate::ir; +use super::must_get_primitive_types; + trait RecoverFromIr { fn recover(&self, deps: &super::Deps) -> Option; } @@ -169,23 +172,37 @@ impl RecoverFromIr for ir::Table { } impl super::Ast { - pub(crate) fn recover(ir: ir::Ir) -> Self { + pub(crate) fn recover(ir: ir::Ir, expand_primitive: bool) -> Self { let mut decls_idx = HashMap::new(); let mut decls_keys = HashSet::new(); for decl in ir.decls() { let name = decl.name(); - if super::TopDecl::new_primitive(name.to_lowercase().as_str()).is_some() { + if super::TopDecl::new_primitive(name.to_lowercase().as_str(), !expand_primitive) + .is_some() + { panic!("the name `{}` is reserved", name); } if decls_idx.insert(name, decl).is_some() || !decls_keys.insert(name) { panic!("the name `{}` is used more than once", name); }; } + let mut primitives = vec![verified::Primitive { + name: "byte".to_string(), + size: 1, + }]; + + if !expand_primitive { + primitives.extend(must_get_primitive_types()); + } + let mut decls_result = HashMap::new(); - decls_result.insert( - "byte", - Rc::new(super::TopDecl::new_primitive("byte").unwrap()), - ); + primitives.iter().for_each(|primitive_type| { + decls_result.insert( + primitive_type.name(), + Rc::new(super::TopDecl::new_primitive(primitive_type.name(), true).unwrap()), + ); + }); + loop { if decls_keys.is_empty() { break; diff --git a/tools/codegen/src/compiler.rs b/tools/codegen/src/compiler.rs index 3eb262c..1073901 100644 --- a/tools/codegen/src/compiler.rs +++ b/tools/codegen/src/compiler.rs @@ -12,6 +12,7 @@ pub struct Compiler { target: Option, input: Option, output: Option, + expand_primitive: bool, } pub(crate) enum Input { @@ -39,6 +40,7 @@ impl Compiler { target: None, input: None, output: Some(Output::Stdout), + expand_primitive: false, } } @@ -82,6 +84,11 @@ impl Compiler { self } + pub fn expand_primitive(&mut self, trigger: bool) -> &mut Self { + self.expand_primitive = trigger; + self + } + pub fn run(&mut self) -> Result<(), String> { let Self { target, @@ -90,6 +97,7 @@ impl Compiler { ref output, #[cfg(feature = "compiler-plugin")] ref mut output, + expand_primitive: _expand_primitive, } = self; let target = target.ok_or("target is not set: generate code or intermediate data")?; let input = input @@ -113,16 +121,18 @@ impl Compiler { .file_name() .and_then(ffi::OsStr::to_str) .to_owned(); - parser::Parser::parse(file_path) + parser::Parser::parse(file_path, self.expand_primitive) } #[cfg(feature = "compiler-plugin")] - Input::Intermediate(format, ref data) => format.recover(data)?, + Input::Intermediate(format, ref data) => { + format.recover(data, self.expand_primitive)? + } }; let generator = generator::Generator::new(ast); let mut output_data = Vec::::new(); generator - .generate(target, &mut output_data) + .generate(target, &mut output_data, self.expand_primitive) .map_err(|err| format!("failed to write data by generator: {}", err))?; match output { diff --git a/tools/codegen/src/generator/languages/c/mod.rs b/tools/codegen/src/generator/languages/c/mod.rs index 8faa078..28ae156 100644 --- a/tools/codegen/src/generator/languages/c/mod.rs +++ b/tools/codegen/src/generator/languages/c/mod.rs @@ -72,7 +72,11 @@ impl Generator { } impl super::LanguageGenerator for Generator { - fn generate(writer: &mut W, ast: &ast::Ast) -> io::Result<()> { + fn generate( + writer: &mut W, + ast: &ast::Ast, + _expand_primitive: bool, + ) -> io::Result<()> { writeln!(writer, "// Generated by Molecule {}", VERSION)?; writeln!(writer)?; Self::define_version(writer)?; diff --git a/tools/codegen/src/generator/languages/mod.rs b/tools/codegen/src/generator/languages/mod.rs index 6b15a44..410c0cd 100644 --- a/tools/codegen/src/generator/languages/mod.rs +++ b/tools/codegen/src/generator/languages/mod.rs @@ -12,7 +12,11 @@ pub enum Language { } pub(super) trait LanguageGenerator { - fn generate(writer: &mut W, ast: &ast::Ast) -> io::Result<()>; + fn generate( + writer: &mut W, + ast: &ast::Ast, + expand_primitive: bool, + ) -> io::Result<()>; } impl fmt::Display for Language { @@ -43,10 +47,15 @@ impl Language { } } - pub(crate) fn generate(self, writer: &mut W, ast: &ast::Ast) -> io::Result<()> { + pub(crate) fn generate( + self, + writer: &mut W, + ast: &ast::Ast, + expand_primitive: bool, + ) -> io::Result<()> { match self { - Self::C => c::Generator::generate(writer, ast), - Self::Rust => rust::Generator::generate(writer, ast), + Self::C => c::Generator::generate(writer, ast, expand_primitive), + Self::Rust => rust::Generator::generate(writer, ast, expand_primitive), } } } diff --git a/tools/codegen/src/generator/languages/rust/mod.rs b/tools/codegen/src/generator/languages/rust/mod.rs index 86bebb3..9702d1c 100644 --- a/tools/codegen/src/generator/languages/rust/mod.rs +++ b/tools/codegen/src/generator/languages/rust/mod.rs @@ -37,13 +37,27 @@ use generator::Generator as _; pub(crate) struct Generator; impl super::LanguageGenerator for Generator { - fn generate(writer: &mut W, ast: &ast::Ast) -> io::Result<()> { + fn generate( + writer: &mut W, + ast: &ast::Ast, + expand_primitive: bool, + ) -> io::Result<()> { writeln!(writer, "// Generated by Molecule {}", VERSION)?; writeln!(writer)?; - let code = quote!( - use molecule::prelude::*; - ); - write!(writer, "{}", code)?; + + if expand_primitive { + let code = quote!( + use molecule::prelude::*; + ); + write!(writer, "{}", code)?; + } else { + let code = quote!( + use molecule_std as molecule; + use molecule::prelude::*; + ); + write!(writer, "{}", code)?; + } + let imports = ast.imports(); if !imports.is_empty() { writeln!(writer)?; diff --git a/tools/codegen/src/generator/mod.rs b/tools/codegen/src/generator/mod.rs index aef206f..cba1e0d 100644 --- a/tools/codegen/src/generator/mod.rs +++ b/tools/codegen/src/generator/mod.rs @@ -36,9 +36,14 @@ impl Generator { Self { ast } } - pub(crate) fn generate(&self, target: Target, writer: &mut W) -> io::Result<()> { + pub(crate) fn generate( + &self, + target: Target, + writer: &mut W, + expand_primitive: bool, + ) -> io::Result<()> { match target { - Target::Language(lang) => lang.generate(writer, &self.ast), + Target::Language(lang) => lang.generate(writer, &self.ast, expand_primitive), #[cfg(feature = "compiler-plugin")] Target::Intermediate(format) => format.generate(writer, &self.ast.to_ir()), } diff --git a/tools/codegen/src/ir/format.rs b/tools/codegen/src/ir/format.rs index 9778f56..cf65aa8 100644 --- a/tools/codegen/src/ir/format.rs +++ b/tools/codegen/src/ir/format.rs @@ -77,7 +77,8 @@ impl Format { writer.write_all(&data) } - pub fn recover(self, bytes: &[u8]) -> Result { - self.deserialize(bytes).map(ast::Ast::recover) + pub fn recover(self, bytes: &[u8], expand_primitive: bool) -> Result { + self.deserialize(bytes) + .map(|ir| ast::Ast::recover(ir, expand_primitive)) } } diff --git a/tools/codegen/src/parser/mod.rs b/tools/codegen/src/parser/mod.rs index 25e0300..99c2085 100644 --- a/tools/codegen/src/parser/mod.rs +++ b/tools/codegen/src/parser/mod.rs @@ -8,8 +8,8 @@ pub(crate) use inner::{Parser as InnerParser, Rule}; pub struct Parser; impl Parser { - pub fn parse>(path: &P) -> ast::Ast { + pub fn parse>(path: &P, expand_primitive: bool) -> ast::Ast { let ast_raw = Self::preprocess(path).unwrap(); - ast::Ast::complete(ast_raw) + ast::Ast::complete(ast_raw, expand_primitive) } } diff --git a/tools/compiler/Cargo.lock b/tools/compiler/Cargo.lock index 6dc56f7..d344469 100644 --- a/tools/compiler/Cargo.lock +++ b/tools/compiler/Cargo.lock @@ -183,14 +183,14 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "molecule" -version = "0.7.3" +version = "0.8.0" dependencies = [ "cfg-if", ] [[package]] name = "molecule-codegen" -version = "0.7.3" +version = "0.8.0" dependencies = [ "case", "molecule", @@ -208,7 +208,7 @@ dependencies = [ [[package]] name = "moleculec" -version = "0.7.3" +version = "0.8.0" dependencies = [ "clap", "molecule-codegen", diff --git a/tools/compiler/Cargo.toml b/tools/compiler/Cargo.toml index a56ed9b..d049ad1 100644 --- a/tools/compiler/Cargo.toml +++ b/tools/compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "moleculec" -version = "0.7.3" +version = "0.8.0" authors = ["Nervos Core Dev "] edition = "2018" description = "Schema compiler for molecule." @@ -30,7 +30,7 @@ path = "src/compiler-rust.rs" [dependencies] clap = { version = "3", features = ["yaml", "cargo"] } which = "4.0.2" -molecule-codegen = { version = "=0.7.3", path = "../codegen", features = ["compiler-plugin"] } +molecule-codegen = { version = "=0.8.0", path = "../codegen", features = ["compiler-plugin"] } [badges] maintenance = { status = "experimental" } diff --git a/tools/compiler/src/cli/compiler-plugin.yaml b/tools/compiler/src/cli/compiler-plugin.yaml index b09846d..fc86a55 100644 --- a/tools/compiler/src/cli/compiler-plugin.yaml +++ b/tools/compiler/src/cli/compiler-plugin.yaml @@ -5,3 +5,7 @@ args: help: Output the supported format for the intermediate data. long: format takes_value: false + - expand-primitive: + help: Weather to expand primitive types (like uint64, int32) or not. Default is false + long: expand-primitive + takes_value: false diff --git a/tools/compiler/src/cli/compiler.yaml b/tools/compiler/src/cli/compiler.yaml index 0b02053..b501b02 100644 --- a/tools/compiler/src/cli/compiler.yaml +++ b/tools/compiler/src/cli/compiler.yaml @@ -7,6 +7,10 @@ args: long: schema-file takes_value: true required: true + - expand-primitive: + help: Weather to expand primitive types (like uint64, int32) or not. Default is false + long: expand-primitive + takes_value: false - language: help: | Specify a language, then generate source code for the specified language and output the generated code to the stdout. diff --git a/tools/compiler/src/compiler.rs b/tools/compiler/src/compiler.rs index 0a0f26d..beb284c 100644 --- a/tools/compiler/src/compiler.rs +++ b/tools/compiler/src/compiler.rs @@ -18,6 +18,7 @@ pub(crate) mod config { pub(crate) struct AppConfig { pub(crate) schema_file: PathBuf, pub(crate) output_config: OutputConfig, + pub(crate) expand_primitive: bool, } pub(crate) fn build_commandline() -> AppConfig { @@ -32,6 +33,8 @@ pub(crate) mod config { fn from(matches: &'a clap::ArgMatches) -> Self { let schema_file = value_t_or_exit!(matches, "schema-file", PathBuf); let language = value_t_or_exit!(matches, "language", String); + let expand_primitive = matches.is_present("expand-primitive"); + if !schema_file.as_path().is_file() { eprintln!( "Error: schema-file [{}] should be a file", @@ -67,6 +70,7 @@ pub(crate) mod config { Self { schema_file, output_config, + expand_primitive, } } } @@ -108,6 +112,7 @@ fn main() { }; compiler .input_schema_file(config.schema_file.as_path()) + .expand_primitive(config.expand_primitive) .run() .unwrap() } diff --git a/tools/compiler/src/lib.rs b/tools/compiler/src/lib.rs index 93e8e26..f7fd80b 100644 --- a/tools/compiler/src/lib.rs +++ b/tools/compiler/src/lib.rs @@ -14,6 +14,7 @@ pub struct AppConfig { action: AppAction, lang: Language, format: IntermediateFormat, + expand_primitive: bool, } type RawAppConfig<'a> = (Language, IntermediateFormat, &'a clap::ArgMatches); @@ -41,10 +42,12 @@ impl<'a> From<&'a RawAppConfig<'a>> for AppConfig { }; AppAction::ProcessIntermediate(input) }; + let expand_primitive = matches.is_present("expand-primitive"); Self { action, lang: *lang, format: *format, + expand_primitive, } } } @@ -59,6 +62,7 @@ impl AppConfig { Compiler::new() .generate_code(self.lang) .input_intermediate(self.format, input.to_owned()) + .expand_primitive(self.expand_primitive) .run() .unwrap(); }