Skip to content

Commit

Permalink
Support custom union id (#3)
Browse files Browse the repository at this point in the history
* support custom unicode id
* Array get item return Vec<u8>
* union uses Enum
  • Loading branch information
joii2020 authored and XuJiandong committed Mar 18, 2024
1 parent 47f6fb7 commit ecc64af
Show file tree
Hide file tree
Showing 20 changed files with 634 additions and 293 deletions.
36 changes: 33 additions & 3 deletions bindings/rust/src/lazy_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@ pub enum Error {
Overflow(String),
Read(String),
Verify(String),
Unknow(String),
}
impl From<core::convert::Infallible> for Error {
fn from(value: core::convert::Infallible) -> Self {
Self::Unknow(format!("conver failed: {:?}", value))
}
}

pub trait Read {
/**
* try to read `buf.len()` bytes from data source with `offset`, then fill it in `buf`.
Expand Down Expand Up @@ -470,10 +477,9 @@ impl_cursor_primitive!(i8);
impl TryFrom<Cursor> for Vec<u8> {
type Error = Error;
fn try_from(cur: Cursor) -> Result<Self, Error> {
let mut buf = Vec::<u8>::new();
buf.resize(cur.size, 0);
let mut buf = vec![0u8; cur.size];

let size = cur.read_at(buf.as_mut_slice())?;
let size = cur.read_at(&mut buf[..])?;
if size != buf.len() {
return Err(Error::Read(format!(
"TryFrom<Cursor>: size({}) != buf.len()({})",
Expand All @@ -485,6 +491,24 @@ impl TryFrom<Cursor> for Vec<u8> {
}
}

impl<const N: usize> TryFrom<Cursor> for [u8; N] {
type Error = Error;
fn try_from(cur: Cursor) -> Result<Self, Error> {
let mut buf = [0u8; N];

let size = cur.read_at(&mut buf[..])?;
if size != N || size != cur.size {
return Err(Error::Read(format!(
"TryFrom<Cursor>: size({}) != buf.len()({})",
size,
buf.len()
)));
}

Ok(buf)
}
}

// it's an example about how to build a data source from memory
impl Read for Vec<u8> {
fn read(&self, buf: &mut [u8], offset: usize) -> Result<usize, Error> {
Expand Down Expand Up @@ -515,4 +539,10 @@ impl From<Vec<u8>> for Cursor {
Cursor::new(mem.len(), Box::new(mem))
}
}

impl<const N: usize> From<[u8; N]> for Cursor {
fn from(mem: [u8; N]) -> Self {
Cursor::new(mem.len(), Box::new(mem.to_vec()))
}
}
// end of example
50 changes: 23 additions & 27 deletions examples/ci-tests/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/ci-tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ C_DEPS = ${MOL_DEPS} \

CC = gcc
CXX = g++
CFLAGS = -Wall -Werror
CFLAGS = -Wall -Werror -Wno-array-bounds

clean:
@cargo clean
Expand Down
4 changes: 2 additions & 2 deletions examples/ci-tests/c/simple-example.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ void test_build_simple() {
mol_seg_t uniona;
{
const uint8_t expected[] = {
____, ____, ____, ____,
0x02, ____, ____, ____,
0x12,
};
MolBuilder_UnionA_init(&b);
Expand All @@ -148,7 +148,7 @@ void test_build_simple() {
}
{
const uint8_t expected[] = {
0x03, ____, ____, ____,
0x0b, ____, ____, ____,
0x03, ____, ____, ____,
0x12, 0x34, 0x56,
};
Expand Down
2 changes: 1 addition & 1 deletion examples/ci-tests/tests/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ fn union_default() {
test_default!(
UnionA,
s!("0x\
00000000\
02000000\
00\
")
);
Expand Down
9 changes: 8 additions & 1 deletion examples/lazy-reader-tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@ use std::{
fn compile_schema_rust(schema: &str) {
let mut compiler = Compiler::new();
let out_dir = path::PathBuf::from(&env::var("OUT_DIR").unwrap_or_else(|_| ".".to_string()));
let mut file_path = out_dir.clone();
compiler
.input_schema_file(schema)
.generate_code(Language::Rust)
.output_dir(out_dir)
.run()
.unwrap();

file_path.push("types.rs");
Command::new("rustfmt")
.arg(<PathBuf as AsRef<OsStr>>::as_ref(&file_path))
.spawn()
.unwrap()
.wait()
.unwrap();
println!("cargo:rerun-if-changed={}", schema);
}

Expand Down
147 changes: 139 additions & 8 deletions examples/lazy-reader-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod types_struct;
pub mod types_table;
pub mod types_vec;

use molecule::lazy_reader::Cursor;
use molecule::prelude::{Builder, Entity};
use rand::{rngs::ThreadRng, thread_rng, Rng};
use std::fmt::Debug;
Expand Down Expand Up @@ -144,9 +145,15 @@ impl From<molecule::lazy_reader::Error> for TypesCheckErr {
Overflow(v) => Self::Mol2Err(format!("Overflow({})", v)),
Read(v) => Self::Mol2Err(format!("Read({})", v)),
Verify(v) => Self::Mol2Err(format!("Verify({})", v)),
Unknow(v) => Self::Mol2Err(format!("Unknow({})", v)),
}
}
}
impl From<std::convert::Infallible> for TypesCheckErr {
fn from(value: std::convert::Infallible) -> Self {
Self::Mol2Err(format!("conver failed: {:?}", value))
}
}

pub enum TypesUnionA {
Byte(TypesArray<u8, 1>),
Expand Down Expand Up @@ -203,14 +210,138 @@ impl TypesUnionA {
// let item_id = d.item_id();

match self {
Self::Byte(v) => v.check(&d.as_byte()?),
Self::Word(v) => v.check2(&d.as_word()?.into()),
Self::StructA(v) => v.check(&d.as_struct_a()?),
Self::Bytes(v) => v.check(&d.as_bytes()?.try_into().unwrap()),
Self::Words(v) => v.check(&d.as_words()?.into()),
Self::Table0(v) => v.check(&d.as_table0()?),
Self::Table6(v) => v.check(&d.as_table6()?),
Self::Table6Opt(v) => v.check(&d.as_table6_opt()?),
Self::Byte(v) => match d {
types_api2::UnionA::Byte(v2) => v.check(v2),
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
Self::Word(v) => match d {
types_api2::UnionA::Word(v2) => v.check2(v2),
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
Self::StructA(v) => match d {
types_api2::UnionA::StructA(v2) => v.check(v2),
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
Self::Bytes(v) => match d {
types_api2::UnionA::Bytes(v2) => {
v.check(&v2.clone().try_into()?)
}
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
Self::Words(v) => match d {
types_api2::UnionA::Words(v2) => v.check(v2),
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
Self::Table0(v) => match d {
types_api2::UnionA::Table0(v2) => v.check(v2),
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
Self::Table6(v) => match d {
types_api2::UnionA::Table6(v2) => v.check(v2),
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
Self::Table6Opt(v) => match d {
types_api2::UnionA::Table6Opt(v2) => v.check(v2),
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
}
}
}

pub enum TypesUnionB {
Byte(TypesArray<u8, 1>), // 2
Word(TypesArrayWord), //4
}
impl BaseTypes for TypesUnionB {
fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self {
let v = if config.min_size {
0 // Self::Byte
} else {
rng.gen_range(0..1)
};
match v {
0 => Self::Byte(TypesArray::new_rng(rng, config)),
1 => Self::Word(TypesArrayWord::new_rng(rng, config)),

_ => panic!("unknow error"),
}
}
}
impl Default for TypesUnionB {
fn default() -> Self {
Self::new_rng(&mut thread_rng(), &TypesConfig::default())
}
}
impl TypesUnionB {
pub fn to_mol(&self) -> types_api::UnionB {
let t = match self {
Self::Byte(v) => types_api::UnionBUnion::Byte(v.to_mol()),
Self::Word(v) => types_api::UnionBUnion::Word(v.to_mol2()),
};
types_api::UnionB::new_builder().set(t).build()
}

pub fn check(&self, d: &types_api2::UnionB) -> ResCheckErr {
// let item_id = d.item_id();

match self {
Self::Byte(v) => match d {
types_api2::UnionB::Byte(v2) => v.check(v2),
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
Self::Word(v) => match d {
types_api2::UnionB::Word(v2) => v.check2(v2),
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
}
}
}

pub enum TypesUnionD {
Word(TypesArrayWord), //2
Byte(TypesArray<u8, 1>), // 4
}
impl BaseTypes for TypesUnionD {
fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self {
let v = if config.min_size {
0 // Self::Byte
} else {
rng.gen_range(0..1)
};
match v {
0 => Self::Word(TypesArrayWord::new_rng(rng, config)),
1 => Self::Byte(TypesArray::new_rng(rng, config)),

_ => panic!("unknow error"),
}
}
}
impl Default for TypesUnionD {
fn default() -> Self {
Self::new_rng(&mut thread_rng(), &TypesConfig::default())
}
}
impl TypesUnionD {
pub fn to_mol(&self) -> types_api::UnionD {
let t = match self {
Self::Word(v) => types_api::UnionDUnion::Word(v.to_mol2()),
Self::Byte(v) => types_api::UnionDUnion::Byte(v.to_mol()),
};
types_api::UnionD::new_builder().set(t).build()
}

pub fn check(&self, d: &types_api2::UnionD) -> ResCheckErr {
// let item_id = d.item_id();

match self {
Self::Word(v) => match d {
types_api2::UnionD::Word(v2) => v.check2(v2),
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
Self::Byte(v) => match d {
types_api2::UnionD::Byte(v2) => v.check(v2),
_ => Err(TypesCheckErr::Data(format!("check union type is failed"))),
},
}
}
}
Loading

0 comments on commit ecc64af

Please sign in to comment.