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 <[email protected]>
  • Loading branch information
eval-exec committed Jan 12, 2023
1 parent 5f94aa8 commit a0bdf01
Show file tree
Hide file tree
Showing 15 changed files with 351 additions and 10 deletions.
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -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!"

Expand All @@ -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 \
Expand Down
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
3 changes: 3 additions & 0 deletions std/rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
target/
Cargo.lock

29 changes: 29 additions & 0 deletions std/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[package]
name = "molecule-std"
version = "0.0.1"
authors = ["Nervos Core Dev <[email protected]>"]
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);
}
14 changes: 14 additions & 0 deletions std/rust/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];
37 changes: 37 additions & 0 deletions std/rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
pub use crate as molecule_std;

pub use molecule::*;

pub mod prelude {
pub use crate::primitive::{Byte, ByteReader};
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<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;
}
#[cfg(feature = "with-primitive-types")]
pub use crate::primitives_pack::*;

#[cfg(feature = "with-primitive-types")]
pub use crate::primitives::*;
}

pub mod primitives {
include!(concat!(env!("OUT_DIR"), "/primitive_types.rs"));
}
154 changes: 154 additions & 0 deletions std/rust/src/primitives_pack.rs
Original file line number Diff line number Diff line change
@@ -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<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" }
14 changes: 14 additions & 0 deletions tools/codegen/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];
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
14 changes: 14 additions & 0 deletions tools/codegen/src/ast/verified/complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use std::{
rc::Rc,
};

#[cfg(not(feature = "gen-primitive-types"))]
use super::must_get_primitive_types;

use super::super::raw;

trait CompleteRawDecl {
Expand Down Expand Up @@ -179,6 +182,17 @@ impl super::Ast {
"byte",
Rc::new(super::TopDecl::new_primitive("byte").unwrap()),
);

#[cfg(not(feature = "gen-primitive-types"))]
let bindings = must_get_primitive_types();
#[cfg(not(feature = "gen-primitive-types"))]
bindings.iter().for_each(|primitive_type| {
decls_result.insert(
primitive_type.name(),
Rc::new(super::TopDecl::new_primitive(primitive_type.name()).unwrap()),
);
});

loop {
if decls_keys.is_empty() {
break;
Expand Down
Loading

0 comments on commit a0bdf01

Please sign in to comment.