Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add primitive types to molecule for syntax = 2 #62

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 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 All @@ -40,6 +44,7 @@ clippy:
cd - > /dev/null; \
done


ci-msrv:
@set -eu; \
for dir in ${RUST_PROD_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

30 changes: 30 additions & 0 deletions std/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[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 = ["std"]
with-primitive-types = []
std = ["molecule/bytes", "molecule/faster-hex"]

[build-dependencies]
codegen = {package ="molecule-codegen", version = "=0.7.5", path = "../../tools/codegen" }

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];
35 changes: 35 additions & 0 deletions std/rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<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::*;
}
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);
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];
2 changes: 2 additions & 0 deletions tools/codegen/src/ast/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
pub(crate) mod raw;
pub(crate) mod verified;

pub use raw::SyntaxVersion;

pub use verified::{
Array, Ast, DefaultContent, DynVec, FieldDecl, FixVec, HasName, ImportStmt, ItemDecl, Option_,
Primitive, Struct, Table, TopDecl, Union, UnionItemDecl,
Expand Down
31 changes: 29 additions & 2 deletions tools/codegen/src/ast/raw/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,43 @@
use std::path::PathBuf;

#[cfg(feature = "compiler-plugin")]
use serde::{Deserialize, Serialize};

use property::Property;

mod utils;

#[derive(Debug, Default, Property)]
pub(crate) struct Ast {
syntax_version: Option<SyntaxVersion>,
namespace: String,
imports: Vec<ImportStmt>,
decls: Vec<TopDecl>,
}

impl Default for SyntaxVersion {
fn default() -> Self {
Self { version: 1 }
}
}

#[derive(Debug, Clone, PartialEq, Eq, Property)]
#[property(get(public))]
#[cfg_attr(
feature = "compiler-plugin",
derive(Deserialize, Serialize),
serde(deny_unknown_fields)
)]
pub struct SyntaxVersion {
version: usize,
}

impl SyntaxVersion {
pub fn support_primitive_types(&self) -> bool {
self.version >= 2
}
}

#[derive(Debug, Clone, Property)]
pub(crate) struct ImportStmt {
name: String,
Expand Down Expand Up @@ -44,7 +71,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 +100,7 @@ pub(crate) struct TableDecl {
imported_depth: usize,
}

#[derive(Debug, Property)]
#[derive(Debug, Property, Clone)]
pub(crate) struct ItemDecl {
typ: String,
}
Expand Down
Loading