Skip to content

Commit

Permalink
attempt to add primitive types
Browse files Browse the repository at this point in the history
Signed-off-by: Eval EXEC <execvy@gmail.com>
  • Loading branch information
eval-exec committed Jan 12, 2023
1 parent 5f94aa8 commit a58bf91
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 4 deletions.
2 changes: 1 addition & 1 deletion bindings/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
14 changes: 14 additions & 0 deletions std/primitive_types.mol
Original file line number Diff line number Diff line change
@@ -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];
2 changes: 2 additions & 0 deletions std/rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target/
Cargo.lock
28 changes: 28 additions & 0 deletions std/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "molecule-std"
version = "0.0.1"
authors = ["Nervos Core Dev <dev@nervos.org>"]
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 = []
with-primitive-types = []

[build-dependencies]
codegen = { package ="molecule-codegen", path = "../../tools/codegen" , features = ["gen-primitive-types"]}
19 changes: 19 additions & 0 deletions std/rust/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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()
.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);
}
24 changes: 24 additions & 0 deletions std/rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pub mod pack;

pub mod io {
pub use molecule::io::{self, *};
}
pub mod error {
pub use molecule::error::{self, *};
}

pub mod bytes {
pub use molecule::bytes::{self, *};
}

pub mod prelude {
pub use molecule::prelude::*;
}

pub mod primitive {
pub use molecule::primitive::{self, *};
}

pub mod primitives {
include!(concat!(env!("OUT_DIR"), "/primitive_types.rs"));
}
164 changes: 164 additions & 0 deletions std/rust/src/pack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
use crate::prelude::*;
use crate::primitives::*;

pub trait Unpack<T> {
/// Unpack binary data into rust types.
fn unpack(&self) -> T;
}

/// A syntactic sugar to convert a rust type into binary data.
pub trait Pack<T: Entity> {
/// Packs a rust type into binary data.
fn pack(&self) -> T;
}

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<Uint64> for u64 {
fn pack(&self) -> Uint64 {
Uint64::new_unchecked(Bytes::from(self.to_le_bytes().to_vec()))
}
}

impl<'r> Unpack<u64> 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<Uint32> for u32 {
fn pack(&self) -> Uint32 {
Uint32::new_unchecked(Bytes::from(self.to_le_bytes().to_vec()))
}
}

impl<'r> Unpack<u32> 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<Uint16> for u16 {
fn pack(&self) -> Uint16 {
Uint16::new_unchecked(Bytes::from(self.to_le_bytes().to_vec()))
}
}

impl<'r> Unpack<u16> 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<Uint8> for u8 {
fn pack(&self) -> Uint8 {
Uint8::new_unchecked(Bytes::from(self.to_le_bytes().to_vec()))
}
}

impl<'r> Unpack<u8> 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<Int64> for i64 {
fn pack(&self) -> Int64 {
Int64::new_unchecked(Bytes::from(self.to_le_bytes().to_vec()))
}
}

impl<'r> Unpack<i64> 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<Int32> for i32 {
fn pack(&self) -> Int32 {
Int32::new_unchecked(Bytes::from(self.to_le_bytes().to_vec()))
}
}

impl<'r> Unpack<i32> 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<Int16> for i16 {
fn pack(&self) -> Int16 {
Int16::new_unchecked(Bytes::from(self.to_le_bytes().to_vec()))
}
}

impl<'r> Unpack<i16> 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<Int8> for i8 {
fn pack(&self) -> Int8 {
Int8::new_unchecked(Bytes::from(self.to_le_bytes().to_vec()))
}
}

impl<'r> Unpack<i8> 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<Bool> for bool {
fn pack(&self) -> Bool {
let b = u8::from(*self);
Bool::new_unchecked(Bytes::from(vec![b]))
}
}

impl<'r> Unpack<bool> for BoolReader<'r> {
fn unpack(&self) -> bool {
match self.as_slice()[0] {
0 => false,
1 => true,
_ => unreachable!(),
}
}
}
impl_conversion_for_entity_unpack!(bool, Bool);
1 change: 1 addition & 0 deletions tools/codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ serde_yaml = { version = "0.8.15", optional = true }
[features]
default = []
compiler-plugin = ["serde", "serde_json", "serde_yaml"]
gen-primitive-types = []

[badges]
maintenance = { status = "experimental" }
4 changes: 2 additions & 2 deletions tools/codegen/src/ast/raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -73,7 +73,7 @@ pub(crate) struct TableDecl {
imported_depth: usize,
}

#[derive(Debug, Property)]
#[derive(Debug, Property, Clone)]
pub(crate) struct ItemDecl {
typ: String,
}
Expand Down
34 changes: 33 additions & 1 deletion tools/codegen/src/ast/verified/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,25 @@ pub use has_name::HasName;

type Deps<'a> = HashMap<&'a str, Rc<super::TopDecl>>;

#[cfg(feature = "gen-primitive-types")]
use std::path::PathBuf;

#[cfg(feature = "gen-primitive-types")]
fn primitive_types(
path: &PathBuf,
) -> Result<Vec<crate::ast::raw::ArrayDecl>, pest::error::Error<crate::parser::Rule>> {
use crate::utils::PairsUtils;
crate::parser::Parser::preprocess(path).map(|ast| {
ast.decls()
.iter()
.map(|decl| match decl {
crate::ast::raw::TopDecl::Array(array) => array.clone(),
_ => panic!("primitive types is not array"),
})
.collect::<Vec<crate::ast::raw::ArrayDecl>>()
})
}

#[derive(Debug, Property)]
#[property(get(public))]
pub struct Ast {
Expand Down Expand Up @@ -139,7 +158,20 @@ impl TopDecl {
name: name.to_owned(),
size: 1,
}),
_ => None,
_ => {
#[cfg(not(feature = "gen-primitive-types"))]
return None;

#[cfg(feature = "gen-primitive-types")]
primitive_types(&PathBuf::from("../../../../../std/primitive_types.mol"))
.unwrap()
.iter()
.find(|primitive_decl| x.name().eq(name))
.map(|primitive_decl| Primitive {
name: primitive_decl.name().to_string(),
size: primitive_decl.item_count(),
})
}
}
.map(Self::Primitive)
}
Expand Down
4 changes: 4 additions & 0 deletions tools/codegen/src/generator/languages/rust/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ impl super::LanguageGenerator for Generator {
writeln!(writer, "// Generated by Molecule {}", VERSION)?;
writeln!(writer)?;
let code = quote!(
use molecule_std as molecule;

use molecule::prelude::*;
#[cfg(feature = "with-primitive-types")]
use molecule::primitives::*;
);
write!(writer, "{}", code)?;
let imports = ast.imports();
Expand Down

0 comments on commit a58bf91

Please sign in to comment.