diff --git a/Makefile b/Makefile index ccaa5ab..15a9e0c 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ ci: @set -eu; \ export RUSTFLAGS='-D warnings'; \ make fmt clippy; \ + make ci-lazy-reader; \ make cargo-test ci-examples ci-crates; \ echo "Success!" @@ -35,7 +36,6 @@ clippy: @set -eu; \ for dir in ${RUST_PROJS}; do \ cd "$${dir}"; \ - cargo clean; \ cargo clippy --all --all-targets --all-features; \ cd - > /dev/null; \ done @@ -72,4 +72,13 @@ ci-crates: ci-examples: @set -eu; \ cd examples/ci-tests; \ - make clean test + make clean test; \ + cd - > /dev/null; \ + +ci-lazy-reader: + @set -eu; \ + cd examples/lazy-reader-tests; \ + make test; \ + cd - > /dev/null; \ + + diff --git a/bindings/rust/src/lazy_reader.rs b/bindings/rust/src/lazy_reader.rs new file mode 100644 index 0000000..6c75068 --- /dev/null +++ b/bindings/rust/src/lazy_reader.rs @@ -0,0 +1,464 @@ +extern crate alloc; + +use alloc::boxed::Box; +use alloc::rc::Rc; +use alloc::vec; +use alloc::vec::Vec; +use core::cell::RefCell; +use core::cmp::min; +use core::convert::{From, TryFrom}; + +#[derive(Debug)] +pub enum Error { + Common, + TotalSize(usize, usize), + Header(usize, usize), + Offset, + UnknownItem, + OutOfBound(usize, usize), + FieldCount(usize), + Data, + Overflow, + Read(usize, usize), + Verify, + Unknown, +} + +impl From for Error { + fn from(_: core::convert::Infallible) -> Self { + Self::Unknown + } +} + +pub trait Read { + // Pull some bytes from this source into the specified buffer with `offset`, returning how many bytes were read. + fn read(&self, buf: &mut [u8], offset: usize) -> Result; +} + +pub const MAX_CACHE_SIZE: usize = 2048; +pub const MIN_CACHE_SIZE: usize = 64; +pub const NUMBER_SIZE: usize = 4; + +pub struct DataSource { + reader: Box, + total_size: usize, + cache_start_point: usize, + // cache actual size may be smaller than cache.len() + cache_actual_size: usize, + cache: Vec, +} + +impl DataSource { + pub fn new(total_size: usize, reader: Box) -> Self { + DataSource { + reader, + total_size, + cache_start_point: 0, + cache_actual_size: 0, + cache: vec![0u8; MAX_CACHE_SIZE], + } + } + + // Pull some bytes from this source into the specified buffer with `offset` and `read_len`, returning how many bytes were read. + // If the requested range is out of bound, an `Error::Read` will be returned. + pub fn read_at( + &mut self, + buf: &mut [u8], + offset: usize, + read_len: usize, + ) -> Result { + // Read directly if the requested length is larger than maximum cache size + if read_len == 0 { + return Ok(0); + } + if read_len > self.cache.len() { + return self.reader.read(buf, offset); + } + // Check if the requested data is in cache + if offset >= self.cache_start_point + && offset + read_len <= self.cache_start_point + self.cache_actual_size + { + let read_point = offset - self.cache_start_point; + buf[..read_len].copy_from_slice(&self.cache[read_point..(read_point + read_len)]); + return Ok(read_len); + } + // Cache miss, read from reader and update cache + let read_actual_size = self.reader.read(&mut self.cache[..], offset)?; + self.cache_start_point = offset; + self.cache_actual_size = read_actual_size; + if read_actual_size < read_len { + return Err(Error::Read(read_actual_size, read_len)); + } + buf[..read_len].copy_from_slice(&self.cache[0..read_len]); + Ok(read_len) + } +} + +#[derive(Clone)] +pub struct Cursor { + pub offset: usize, + pub size: usize, + pub data_source: Rc>, +} + +pub struct Union { + pub item_id: usize, + pub cursor: Cursor, +} + +impl Cursor { + /** + total_size: the size of cursor. If it's set a smaller value, + `out of bound` will occur when `reader` try to read the data beyond that. + reader: interface to read underlying data + */ + pub fn new(total_size: usize, reader: Box) -> Self { + let data_source = DataSource::new(total_size, reader); + Cursor { + offset: 0, + size: total_size, + data_source: Rc::new(RefCell::new(data_source)), + } + } + + pub fn read_at(&self, buf: &mut [u8]) -> Result { + let read_len = min(self.size, buf.len()); + let mut data_source = self.data_source.borrow_mut(); + data_source.read_at(buf, self.offset, read_len) + } + + pub fn add_offset(&mut self, offset: usize) -> Result<(), Error> { + self.offset = self.offset.checked_add(offset).ok_or(Error::Overflow)?; + Ok(()) + } + + pub fn sub_size(&mut self, shrink_size: usize) -> Result<(), Error> { + self.size = self.size.checked_sub(shrink_size).ok_or(Error::Overflow)?; + Ok(()) + } + + pub fn validate(&self) -> Result<(), Error> { + if let Some(size) = self.offset.checked_add(self.size) { + if size > self.data_source.borrow().total_size { + Err(Error::TotalSize(size, self.data_source.borrow().total_size)) + } else { + Ok(()) + } + } else { + Err(Error::Overflow) + } + } + + pub fn unpack_number(&self) -> Result { + let mut src = [0u8; 4]; + let size = self.read_at(&mut src[..])?; + if size != 4 { + Err(Error::FieldCount(size)) + } else { + let res = u32::from_le_bytes(src); + Ok(res as usize) + } + } + pub fn verify_fixed_size(&self, size: usize) -> Result<(), Error> { + if self.size != size { + return Err(Error::Header(self.size, size)); + } + Ok(()) + } + pub fn verify_table(&self, expected_field_count: usize, compatible: bool) -> Result<(), Error> { + self.verify_dynvec()?; + let mut cur = self.clone(); + cur.add_offset(NUMBER_SIZE)?; + if self.size == cur.size { + // empty table + return Ok(()); + } + let first_offset = cur.unpack_number()?; + let field_count = first_offset / NUMBER_SIZE - 1; + if field_count < expected_field_count || !compatible && field_count > expected_field_count { + return Err(Error::Verify); + }; + Ok(()) + } + + pub fn verify_dynvec(&self) -> Result<(), Error> { + let total_size = self.unpack_number()?; + if self.size != total_size { + return Err(Error::Verify); + } + if total_size == NUMBER_SIZE { + return Ok(()); + } + if total_size < NUMBER_SIZE * 2 { + return Err(Error::Verify); + } + let mut cur = self.clone(); + cur.add_offset(NUMBER_SIZE)?; + let first_offset = cur.unpack_number()?; + if first_offset % NUMBER_SIZE != 0 || first_offset < NUMBER_SIZE * 2 { + return Err(Error::Verify); + } + if total_size < first_offset { + return Err(Error::Verify); + } + // offsets are ordered increasingly + let count = first_offset / 4 - 1; + let mut last_offset = None; + for _ in 0..count { + let offset = cur.unpack_number()?; + if last_offset.is_some() && last_offset.unwrap() > offset { + return Err(Error::Verify); + } + last_offset = Some(offset); + cur.add_offset(NUMBER_SIZE)?; + } + Ok(()) + } + pub fn verify_fixvec(&self, item_size: usize) -> Result<(), Error> { + if self.size < NUMBER_SIZE { + return Err(Error::Verify); + } + let item_count = self.unpack_number()?; + if item_count == 0 { + if self.size == NUMBER_SIZE { + return Ok(()); + } else { + return Err(Error::Verify); + } + } + + let total_size = calculate_offset(item_size, item_count, NUMBER_SIZE)?; + if self.size == total_size { + Ok(()) + } else { + Err(Error::Verify) + } + } + + pub fn option_is_none(&self) -> bool { + self.size == 0 + } + pub fn fixvec_length(&self) -> Result { + self.unpack_number() + } + + pub fn dynvec_length(&self) -> Result { + if self.size == NUMBER_SIZE { + Ok(0) + } else { + let mut cur2 = self.clone(); + cur2.add_offset(NUMBER_SIZE)?; + cur2.sub_size(NUMBER_SIZE)?; + cur2.validate()?; + cur2.get_item_count() + } + } + + pub fn get_item_count(&self) -> Result { + let len = self.unpack_number()?; + if len % 4 != 0 { + return Err(Error::UnknownItem); + } + let count = len / 4; + if count == 0 { + Err(Error::UnknownItem) + } else { + Ok(count - 1) + } + } + + pub fn table_actual_field_count(&self) -> Result { + self.dynvec_length() + } + + pub fn table_has_extra_fields(&self, field_count: usize) -> Result { + let count = self.table_actual_field_count()?; + Ok(count > field_count) + } + + pub fn slice_by_offset(&self, offset: usize, size: usize) -> Result { + let mut cur2 = self.clone(); + cur2.add_offset(offset)?; + cur2.size = size; + cur2.validate()?; + Ok(cur2) + } + + pub fn slice_by_start(&self, delta: usize) -> Result { + let mut cur2 = self.clone(); + cur2.add_offset(delta)?; + cur2.sub_size(delta)?; + cur2.validate()?; + Ok(cur2) + } + + pub fn fixvec_slice_by_index( + &self, + item_size: usize, + item_index: usize, + ) -> Result { + let mut cur2 = self.clone(); + let item_count = self.unpack_number()?; + if item_index >= item_count { + Err(Error::OutOfBound(item_index, item_count)) + } else { + let offset = calculate_offset(item_size, item_index, NUMBER_SIZE)?; + cur2.add_offset(offset)?; + cur2.size = item_size; + cur2.validate()?; + Ok(cur2) + } + } + + pub fn dynvec_slice_by_index(&self, item_index: usize) -> Result { + let mut res = self.clone(); + let mut temp = self.clone(); + let total_size = self.unpack_number()?; + temp.add_offset(NUMBER_SIZE)?; + let item_count = temp.get_item_count()?; + if item_index >= item_count { + return Err(Error::OutOfBound(item_index, item_count)); + } + temp.offset = self.offset; + let temp_offset = calculate_offset(NUMBER_SIZE, item_index + 1, 0)?; + temp.add_offset(temp_offset)?; + let item_start = temp.unpack_number()?; + if (item_index + 1) == item_count { + res.offset = self.offset; + res.add_offset(item_start)?; + res.size = total_size; + res.sub_size(item_start)?; + } else { + temp.offset = self.offset; + let calc_offset = calculate_offset(NUMBER_SIZE, item_index + 2, 0)?; + temp.add_offset(calc_offset)?; + + let item_end = temp.unpack_number()?; + res.offset = self.offset; + res.add_offset(item_start)?; + res.size = item_end; + res.sub_size(item_start)?; + } + res.validate()?; + Ok(res) + } + + pub fn table_slice_by_index(&self, field_index: usize) -> Result { + self.dynvec_slice_by_index(field_index) + } + + pub fn fixvec_slice_raw_bytes(&self) -> Result { + let mut res = self.clone(); + res.add_offset(NUMBER_SIZE)?; + res.size = self.unpack_number()?; + res.validate()?; + Ok(res) + } + + pub fn convert_to_array(&self) -> Result { + Ok(self.clone()) + } + + pub fn convert_to_rawbytes(&self) -> Result { + self.fixvec_slice_raw_bytes() + } + + pub fn union_unpack(&self) -> Result { + let item_id = self.unpack_number()?; + let mut cursor = self.clone(); + cursor.add_offset(NUMBER_SIZE)?; + cursor.sub_size(NUMBER_SIZE)?; + cursor.validate()?; + Ok(Union { item_id, cursor }) + } +} + +fn calculate_offset(item_size: usize, item_count: usize, offset: usize) -> Result { + let res = item_size.checked_mul(item_count).ok_or(Error::Overflow)?; + res.checked_add(offset).ok_or(Error::Overflow) +} + +macro_rules! impl_cursor_primitive { + ($type: ty) => { + impl TryFrom for $type { + type Error = Error; + fn try_from(cur: Cursor) -> Result { + let mut buf = [0u8; (<$type>::BITS / 8) as usize]; + let size = cur.read_at(&mut buf[..])?; + if size != buf.len() { + Err(Error::FieldCount(<$type>::BITS as usize / 8)) + } else { + Ok(<$type>::from_le_bytes(buf)) + } + } + } + }; +} + +impl_cursor_primitive!(u64); +impl_cursor_primitive!(i64); +impl_cursor_primitive!(u32); +impl_cursor_primitive!(i32); +impl_cursor_primitive!(u16); +impl_cursor_primitive!(i16); +impl_cursor_primitive!(u8); +impl_cursor_primitive!(i8); + +impl TryFrom for Vec { + type Error = Error; + fn try_from(cur: Cursor) -> Result { + let mut buf = vec![0u8; cur.size]; + + let size = cur.read_at(&mut buf[..])?; + if size != buf.len() { + return Err(Error::Read(size, buf.len())); + } + Ok(buf) + } +} + +impl TryFrom for [u8; N] { + type Error = Error; + fn try_from(cur: Cursor) -> Result { + let mut buf = [0u8; N]; + + let size = cur.read_at(&mut buf[..])?; + if size != N || size != cur.size { + return Err(Error::Read(size, buf.len())); + } + + Ok(buf) + } +} + +// it's an example about how to build a data source from memory +impl Read for Vec { + fn read(&self, buf: &mut [u8], offset: usize) -> Result { + let mem_len = self.len(); + if offset >= mem_len { + return Err(Error::OutOfBound(offset, mem_len)); + } + + let remaining_len = mem_len - offset; + let min_len = min(remaining_len, buf.len()); + + if (offset + min_len) > mem_len { + return Err(Error::OutOfBound(offset + min_len, mem_len)); + } + buf[0..min_len].copy_from_slice(&self.as_slice()[offset..offset + min_len]); + Ok(min_len) + } +} + +impl From> for Cursor { + fn from(mem: Vec) -> Self { + Cursor::new(mem.len(), Box::new(mem)) + } +} + +impl From<[u8; N]> for Cursor { + fn from(mem: [u8; N]) -> Self { + Cursor::new(mem.len(), Box::new(mem.to_vec())) + } +} +// end of example diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 42eab96..01c363e 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -23,6 +23,7 @@ cfg_if::cfg_if! { } pub mod error; +pub mod lazy_reader; pub mod prelude; mod primitive; diff --git a/examples/ci-tests/Makefile b/examples/ci-tests/Makefile index e4246fa..ee10a06 100644 --- a/examples/ci-tests/Makefile +++ b/examples/ci-tests/Makefile @@ -22,11 +22,12 @@ C_DEPS = ${MOL_DEPS} \ CC = gcc CXX = g++ -CFLAGS = -Wall -Werror +CFLAGS = -Wall -Werror -Wno-array-bounds clean: @cargo clean @rm -rf ${TMP} + @rm -rf c/test-vector-default.c c/test-vector-simple.c c/tests-api.h c/tests-gen.h tmpdir: @if [ ! -d "${TARGET_TMP_DIR}" ]; then mkdir -p "${TARGET_TMP_DIR}"; fi diff --git a/examples/ci-tests/c/simple-example.c b/examples/ci-tests/c/simple-example.c index b0927f9..aa683d7 100644 --- a/examples/ci-tests/c/simple-example.c +++ b/examples/ci-tests/c/simple-example.c @@ -138,7 +138,7 @@ void test_build_simple() { mol_seg_t uniona; { const uint8_t expected[] = { - ____, ____, ____, ____, + 0x02, ____, ____, ____, 0x12, }; MolBuilder_UnionA_init(&b); @@ -148,7 +148,7 @@ void test_build_simple() { } { const uint8_t expected[] = { - 0x03, ____, ____, ____, + 0x0b, ____, ____, ____, 0x03, ____, ____, ____, 0x12, 0x34, 0x56, }; diff --git a/examples/ci-tests/tests/simple.rs b/examples/ci-tests/tests/simple.rs index 020909e..514ab93 100644 --- a/examples/ci-tests/tests/simple.rs +++ b/examples/ci-tests/tests/simple.rs @@ -100,7 +100,7 @@ fn union_default() { test_default!( UnionA, s!("0x\ - 00000000\ + 02000000\ 00\ ") ); diff --git a/examples/lazy-reader-tests/.gitignore b/examples/lazy-reader-tests/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/examples/lazy-reader-tests/.gitignore @@ -0,0 +1 @@ +target diff --git a/examples/lazy-reader-tests/Cargo.lock b/examples/lazy-reader-tests/Cargo.lock new file mode 100644 index 0000000..f9c152a --- /dev/null +++ b/examples/lazy-reader-tests/Cargo.lock @@ -0,0 +1,391 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "case" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6c0e7b807d60291f42f33f58480c0bfafe28ed08286446f45e463728cf9c1c" + +[[package]] +name = "cc" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy-reader-tests" +version = "0.1.0" +dependencies = [ + "cc", + "lazy_static", + "molecule", + "molecule-codegen", + "rand", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "molecule" +version = "0.7.5" +dependencies = [ + "bytes", + "cfg-if", +] + +[[package]] +name = "molecule-codegen" +version = "0.7.5" +dependencies = [ + "case", + "molecule", + "pest", + "pest_derive", + "proc-macro2", + "property", + "quote", + "same-file", + "semver", +] + +[[package]] +name = "once_cell" +version = "1.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" + +[[package]] +name = "pest" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122" +dependencies = [ + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "pest_meta" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "property" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "889bff6ebe76dbef2685598944997eb7f15c9854a2e34db853a51c6ac158b9d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dedd246497092a89beedfe2c9f176d44c1b672ea6090edc20544ade01fbb7ea0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d7b1fadccbbc7e19ea64708629f9d8dccd007c260d66485f20a6d41bc1cf4b3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/examples/lazy-reader-tests/Cargo.toml b/examples/lazy-reader-tests/Cargo.toml new file mode 100644 index 0000000..b8a2089 --- /dev/null +++ b/examples/lazy-reader-tests/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "lazy-reader-tests" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +molecule = { path = "../../bindings/rust", default-features = false } +lazy_static = "1.4.0" +rand = "0.8.5" + +[build-dependencies] +codegen = { package ="molecule-codegen", path = "../../tools/codegen" } +cc = "1.0.66" diff --git a/examples/lazy-reader-tests/Makefile b/examples/lazy-reader-tests/Makefile new file mode 100644 index 0000000..38cad81 --- /dev/null +++ b/examples/lazy-reader-tests/Makefile @@ -0,0 +1,2 @@ +test: + cargo test diff --git a/examples/lazy-reader-tests/build.rs b/examples/lazy-reader-tests/build.rs new file mode 100644 index 0000000..a01260b --- /dev/null +++ b/examples/lazy-reader-tests/build.rs @@ -0,0 +1,54 @@ +use codegen::{Compiler, Language}; +use std::ffi::OsStr; +use std::process::Command; +use std::{ + env, fs, + path::{self, PathBuf}, +}; + +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(>::as_ref(&file_path)) + .spawn() + .unwrap() + .wait() + .unwrap(); + println!("cargo:rerun-if-changed={}", schema); +} + +fn compile_schema_rust_lazy_reader(schema: &str) { + let mut compiler = Compiler::new(); + let mut out_dir = path::PathBuf::from(&env::var("OUT_DIR").unwrap_or_else(|_| ".".to_string())); + out_dir.push("lazy_reader"); + drop(fs::create_dir(&out_dir)); + let mut file_path = out_dir.clone(); + compiler + .input_schema_file(schema) + .generate_code(Language::RustLazyReader) + .output_dir(out_dir) + .run() + .unwrap(); + file_path.push("types.rs"); + Command::new("rustfmt") + .arg(>::as_ref(&file_path)) + .spawn() + .unwrap() + .wait() + .unwrap(); + println!("cargo:rerun-if-changed={}", schema); +} + +fn main() { + compile_schema_rust("../../test/schemas/types.mol"); + compile_schema_rust_lazy_reader("../../test/schemas/types.mol"); +} diff --git a/examples/lazy-reader-tests/fuzz/.gitignore b/examples/lazy-reader-tests/fuzz/.gitignore new file mode 100644 index 0000000..ee85b42 --- /dev/null +++ b/examples/lazy-reader-tests/fuzz/.gitignore @@ -0,0 +1,5 @@ +target +corpus +artifacts +coverage +coverage.html diff --git a/examples/lazy-reader-tests/fuzz/Cargo.lock b/examples/lazy-reader-tests/fuzz/Cargo.lock new file mode 100644 index 0000000..35d5f4c --- /dev/null +++ b/examples/lazy-reader-tests/fuzz/Cargo.lock @@ -0,0 +1,154 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arbitrary" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "faster-hex" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e2ce894d53b295cf97b05685aa077950ff3e8541af83217fc720a6437169f8" + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + +[[package]] +name = "lazy-reader-tests" +version = "0.1.0" +dependencies = [ + "lazy_static", + "molecule", + "rand", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beb09950ae85a0a94b27676cccf37da5ff13f27076aa1adbc6545dd0d0e1bd4e" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] + +[[package]] +name = "molecule" +version = "0.7.5" +dependencies = [ + "bytes", + "cfg-if", + "faster-hex", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "types_rust-fuzz" +version = "0.0.0" +dependencies = [ + "lazy-reader-tests", + "libfuzzer-sys", + "molecule", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/examples/lazy-reader-tests/fuzz/Cargo.toml b/examples/lazy-reader-tests/fuzz/Cargo.toml new file mode 100644 index 0000000..497a994 --- /dev/null +++ b/examples/lazy-reader-tests/fuzz/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "types_rust-fuzz" +version = "0.0.0" +publish = false +edition = "2021" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.4" +molecule = { path = "../../../bindings/rust" } + +[dependencies.lazy-reader-tests] +path = ".." + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[profile.release] +debug = 1 + +[[bin]] +name = "fuzz_target_1" +path = "fuzz_targets/fuzz_target_1.rs" +test = false +doc = false diff --git a/examples/lazy-reader-tests/fuzz/Makefile b/examples/lazy-reader-tests/fuzz/Makefile new file mode 100644 index 0000000..2aa8702 --- /dev/null +++ b/examples/lazy-reader-tests/fuzz/Makefile @@ -0,0 +1,28 @@ + + +# To accelerate the fuzzing process, please download the pre-made corpus file +# from the following link: +# https://gist.github.com/joii2020/ce55af204f946eebd83269ef8da3f3d1 Save the +# file named corpus.bin to the corpus/fuzz_target_1/ folder. + +all: + cargo fuzz run -j30 fuzz_target_1 + +DEFAUTL_TARGET = `rustup show | grep 'Default host' | grep -o ': .*' | sed 's/: //'` +cov: + cargo fuzz coverage fuzz_target_1 + cargo-cov -- \ + show target/$(DEFAUTL_TARGET)/coverage/$(DEFAUTL_TARGET)/release/fuzz_target_1 \ + --format=html \ + --ignore-filename-regex="(\/.*\/registry\/*)|(\/rustc\/*)|(\/types_api.rs)" \ + -instr-profile=coverage/fuzz_target_1/coverage.profdata \ + > coverage.html + +install: + rustup component add llvm-tools-preview + cargo install cargo-fuzz + cargo install cargo-binutils + +.PHONY: + all cov install + diff --git a/examples/lazy-reader-tests/fuzz/fuzz_targets/fuzz_target_1.rs b/examples/lazy-reader-tests/fuzz/fuzz_targets/fuzz_target_1.rs new file mode 100644 index 0000000..441fb31 --- /dev/null +++ b/examples/lazy-reader-tests/fuzz/fuzz_targets/fuzz_target_1.rs @@ -0,0 +1,754 @@ +#![no_main] + +use lazy_reader_tests::{types_api, types_api2, types_moleculec_check::*, TypesCheckErr}; +use libfuzzer_sys::fuzz_target; +use molecule::lazy_reader::Cursor; +use molecule::prelude::{Entity, Reader}; + +fn fuzz_f0(_data: &[u8], _cursor: Cursor) { + // byte pass + + // let +} +fn fuzz_f1(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte2 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte2Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte2::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f1(&d1, &d2).expect("f1"); +} + +fn fuzz_f2(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte3 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte3Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte3::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f2(&d1, &d2).expect("f2"); +} +fn fuzz_f3(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte4 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte4Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte4::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f3(&d1, &d2).expect("f3"); +} +fn fuzz_f4(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte5 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte5Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte5::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f4(&d1, &d2).expect("f4"); +} +fn fuzz_f5(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte6 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte6Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte6::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f5(&d1, &d2).expect("f5"); +} +fn fuzz_f6(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte7 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte7Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte7::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f6(&d1, &d2).expect("f6"); +} +fn fuzz_f7(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte8 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte8Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte8::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f7(&d1, &d2).expect("f7"); +} +fn fuzz_f8(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte9 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte9Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte9::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f8(&d1, &d2).expect("f8"); +} +fn fuzz_f9(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte10 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte10Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte10::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f9(&d1, &d2).expect("f9"); +} +fn fuzz_f10(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte11 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte11Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte11::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f10(&d1, &d2).expect("f10"); +} +fn fuzz_f11(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte12 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte12Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte12::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f11(&d1, &d2).expect("f11"); +} +fn fuzz_f12(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte13 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte13Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte13::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f12(&d1, &d2).expect("f12"); +} +fn fuzz_f13(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte14 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte14Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte14::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f13(&d1, &d2).expect("f13"); +} +fn fuzz_f14(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte15 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte15Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte15::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f14(&d1, &d2).expect("f14"); +} +fn fuzz_f15(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte16 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte16Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte16::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f15(&d1, &d2).expect("f15"); +} +fn fuzz_f16(data: &[u8], cursor: Cursor) { + let d2: types_api2::Word = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::WordReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Word::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f16(&d1, &d2).expect("f16"); +} +fn fuzz_f17(data: &[u8], cursor: Cursor) { + let d2: types_api2::Word2 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Word2Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Word2::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f17(&d1, &d2).expect("f17"); +} +fn fuzz_f18(data: &[u8], cursor: Cursor) { + let d2: types_api2::Word3 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Word3Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Word3::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f18(&d1, &d2).expect("f18"); +} +fn fuzz_f19(data: &[u8], cursor: Cursor) { + let d2: types_api2::Word4 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Word4Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Word4::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f19(&d1, &d2).expect("f19"); +} +fn fuzz_f20(data: &[u8], cursor: Cursor) { + let d2: types_api2::Word5 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Word5Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Word5::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f20(&d1, &d2).expect("f20"); +} +fn fuzz_f21(data: &[u8], cursor: Cursor) { + let d2: types_api2::Word6 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Word6Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Word6::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f21(&d1, &d2).expect("f21"); +} +fn fuzz_f22(data: &[u8], cursor: Cursor) { + let d2: types_api2::Word7 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Word7Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Word7::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f22(&d1, &d2).expect("f22"); +} +fn fuzz_f23(data: &[u8], cursor: Cursor) { + let d2: types_api2::Word8 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Word8Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Word8::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f23(&d1, &d2).expect("f23"); +} +fn fuzz_f24(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte3x3 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte3x3Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte3x3::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f24(&d1, &d2).expect("f24"); +} +fn fuzz_f25(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte5x3 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte5x3Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte5x3::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f25(&d1, &d2).expect("f25"); +} +fn fuzz_f26(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte7x3 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte7x3Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte7x3::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f26(&d1, &d2).expect("f26"); +} +fn fuzz_f27(data: &[u8], cursor: Cursor) { + let d2: types_api2::Byte9x3 = cursor.into(); + let _r2 = try_get_vec(&d2); + + if types_api::Byte9x3Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Byte9x3::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f27(&d1, &d2).expect("f27"); +} +fn fuzz_f28(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructA = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + let _ = d2.f3(); + let _ = d2.f4(); + + if types_api::StructAReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructA::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f28(&d1, &d2).expect("f28"); +} +fn fuzz_f29(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructB = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + let _ = d2.f3(); + let _ = d2.f4(); + + if types_api::StructBReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructB::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f29(&d1, &d2).expect("f29"); +} +fn fuzz_f30(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructC = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + let _ = d2.f3(); + let _ = d2.f4(); + + if types_api::StructCReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructC::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f30(&d1, &d2).expect("f30"); +} +fn fuzz_f31(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructD = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + let _ = d2.f3(); + let _ = d2.f4(); + + if types_api::StructDReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructD::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f31(&d1, &d2).expect("f31"); +} +fn fuzz_f32(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructE = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + let _ = d2.f3(); + let _ = d2.f4(); + + if types_api::StructEReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructE::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f32(&d1, &d2).expect("f32"); +} +fn fuzz_f33(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructF = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + let _ = d2.f3(); + + if types_api::StructFReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructF::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f33(&d1, &d2).expect("f33"); +} +fn fuzz_f34(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructG = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + let _ = d2.f3(); + let _ = d2.f4(); + + if types_api::StructGReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructG::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f34(&d1, &d2).expect("f34"); +} +fn fuzz_f35(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructH = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + let _ = d2.f3(); + let _ = d2.f4(); + + if types_api::StructHReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructH::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f35(&d1, &d2).expect("f35"); +} +fn fuzz_f36(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructI = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + + if types_api::StructIReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructI::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f36(&d1, &d2).expect("f36"); +} +fn fuzz_f37(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructJ = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + + if types_api::StructJReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructJ::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f37(&d1, &d2).expect("f37"); +} +fn fuzz_f38(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructIx3 = cursor.into(); + let _ = try_get_vec(&d2); + + if types_api::StructIx3Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructIx3::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f38(&d1, &d2).expect("f38"); +} +fn fuzz_f39(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructO = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + + if types_api::StructOReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructO::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f39(&d1, &d2).expect("f39"); +} +fn fuzz_f40(data: &[u8], cursor: Cursor) { + let d2: types_api2::StructP = cursor.into(); + let _ = d2.f1(); + let _ = d2.f2(); + + if types_api::StructPReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::StructP::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f40(&d1, &d2).expect("f40"); +} +fn fuzz_f41(data: &[u8], cursor: Cursor) { + if types_api::BytesReader::verify(data, true).is_err() { + return; + } + let d1 = types_api::Bytes::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let d2: types_api2::Bytes = cursor.clone().into(); + + for i in 0..d1.len() { + TypesCheckErr::check_1_data(&d1.get(i).unwrap(), &d2.get(i).expect("get d2").into()) + .expect("check 1 data"); + } +} +fn fuzz_f42(data: &[u8], cursor: Cursor) { + if types_api::WordsReader::verify(data, true).is_err() { + return; + } + let d1 = types_api::Words::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let d2: types_api2::Words = cursor.clone().into(); + + for i in 0..d1.len() { + check_f16(&d1.get(i).unwrap(), &d2.get(i).expect("get d2").into()).expect("check 1 data"); + } +} +fn fuzz_f43(data: &[u8], cursor: Cursor) { + if types_api::Byte3VecReader::verify(data, true).is_err() { + return; + } + let d1 = types_api::Byte3Vec::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let d2: types_api2::Byte3Vec = cursor.clone().into(); + + for i in 0..d1.len() { + check_f2(&d1.get(i).unwrap(), &d2.get(i).expect("get d2").into()).expect("check 1 data"); + } +} +fn fuzz_f44(data: &[u8], cursor: Cursor) { + if types_api::Byte7VecReader::verify(data, true).is_err() { + return; + } + let d1 = types_api::Byte7Vec::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let d2: types_api2::Byte7Vec = cursor.clone().into(); + + for i in 0..d1.len() { + check_f6(&d1.get(i).unwrap(), &d2.get(i).expect("get d2").into()).expect("check 1 data"); + } +} +fn fuzz_f45(data: &[u8], cursor: Cursor) { + if types_api::StructIVecReader::verify(data, true).is_err() { + return; + } + let d1 = types_api::StructIVec::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let d2: types_api2::StructIVec = cursor.clone().into(); + + for i in 0..d1.len() { + check_f36(&d1.get(i).unwrap(), &d2.get(i).expect("get d2").into()).expect("check 1 data"); + } +} +fn fuzz_f46(data: &[u8], cursor: Cursor) { + if types_api::StructJVecReader::verify(data, true).is_err() { + return; + } + let d1 = types_api::StructJVec::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let d2: types_api2::StructJVec = cursor.clone().into(); + + for i in 0..d1.len() { + check_f37(&d1.get(i).unwrap(), &d2.get(i).expect("get d2").into()).expect("check 1 data"); + } +} +fn fuzz_f47(data: &[u8], cursor: Cursor) { + if types_api::StructPVecReader::verify(data, true).is_err() { + return; + } + let d1 = types_api::StructPVec::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let d2: types_api2::StructPVec = cursor.clone().into(); + + for i in 0..d1.len() { + check_f40(&d1.get(i).unwrap(), &d2.get(i).expect("get d2").into()).expect("check 1 data"); + } +} +fn fuzz_f48(data: &[u8], cursor: Cursor) { + if types_api::BytesVecReader::verify(data, true).is_err() { + return; + } + let d1 = types_api::BytesVec::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let d2: types_api2::BytesVec = cursor.clone().into(); + + for i in 0..d1.len() { + let dd1 = d1.get(i).unwrap(); + let dd2: Vec = d2.get(i).expect("get d2").try_into().unwrap(); + for j in 0..dd1.len() { + TypesCheckErr::check_1_data(&dd1.get(j).unwrap(), &dd2.get(j).unwrap().clone().into()) + .expect("check 1 data"); + } + } +} +fn fuzz_f49(data: &[u8], cursor: Cursor) { + if types_api::WordsVecReader::verify(data, true).is_err() { + return; + } + let d1 = types_api::WordsVec::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let d2: types_api2::WordsVec = cursor.clone().into(); + + for i in 0..d1.len() { + let dd1 = d1.get(i).unwrap(); + let dd2 = d2.get(i).expect("get d2"); + for j in 0..dd1.len() { + check_f16(&dd1.get(j).unwrap(), &dd2.get(j).unwrap().clone().into()) + .expect("check 1 data"); + } + } +} +fn fuzz_f50(data: &[u8], cursor: Cursor) { + let d2: types_api2::Table0 = cursor.into(); + + if types_api::Table0Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Table0::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f50(&d1, &d2).expect("f50"); +} +fn fuzz_f51(data: &[u8], cursor: Cursor) { + let d2: types_api2::Table1 = cursor.into(); + + if types_api::Table1Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Table1::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f51(&d1, &d2).expect("f51"); +} +fn fuzz_f52(data: &[u8], cursor: Cursor) { + let d2: types_api2::Table2 = cursor.into(); + + if types_api::Table2Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Table2::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f52(&d1, &d2).expect("f52"); +} +fn fuzz_f53(data: &[u8], cursor: Cursor) { + let d2: types_api2::Table3 = cursor.into(); + + if types_api::Table3Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Table3::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f53(&d1, &d2).expect("f53"); +} +fn fuzz_f54(data: &[u8], cursor: Cursor) { + let d2: types_api2::Table4 = cursor.into(); + + if types_api::Table4Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Table4::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f54(&d1, &d2).expect("f54"); +} +fn fuzz_f55(data: &[u8], cursor: Cursor) { + let d2: types_api2::Table5 = cursor.into(); + + if types_api::Table5Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Table5::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f55(&d1, &d2).expect("f55"); +} +fn fuzz_f56(data: &[u8], cursor: Cursor) { + let d2: types_api2::Table6 = cursor.into(); + + if types_api::Table6Reader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::Table6::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + check_f56(&d1, &d2).expect("f56"); +} +fn fuzz_f57(data: &[u8], cursor: Cursor) { + if types_api::BytesOptReader::verify(data, true).is_err() { + return; + } + + let _d1 = types_api::BytesOpt::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let _d2: types_api2::BytesOpt = cursor.into(); + // check_f57(&d1.try_into(), &d2).expect("f57"); +} +fn fuzz_f74(data: &[u8], cursor: Cursor) { + if types_api::TableBReader::verify(data, true).is_err() { + return; + } + + let d1 = types_api::TableB::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let d2: types_api2::TableB = cursor.into(); + check_f74(&d1, &d2).expect("f74"); +} + +fn fuzz_all(data: &[u8], cursor: Cursor) { + if types_api::AllInOneReader::verify(&data, true).is_err() { + return; + } + + let all1 = types_api::AllInOne::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())); + let all2: types_api2::AllInOne = cursor.into(); + + check_mol(&all1, &all2).expect("check mol"); +} + +fuzz_target!(|data: &[u8]| { + let cursor = Cursor::new(data.len(), Box::new(data.to_vec())); + fuzz_f0(data, cursor.clone()); + fuzz_f1(data, cursor.clone()); + fuzz_f2(data, cursor.clone()); + fuzz_f3(data, cursor.clone()); + fuzz_f4(data, cursor.clone()); + fuzz_f5(data, cursor.clone()); + fuzz_f6(data, cursor.clone()); + fuzz_f7(data, cursor.clone()); + fuzz_f8(data, cursor.clone()); + fuzz_f9(data, cursor.clone()); + fuzz_f10(data, cursor.clone()); + fuzz_f11(data, cursor.clone()); + fuzz_f12(data, cursor.clone()); + fuzz_f13(data, cursor.clone()); + fuzz_f14(data, cursor.clone()); + fuzz_f15(data, cursor.clone()); + fuzz_f16(data, cursor.clone()); + fuzz_f17(data, cursor.clone()); + fuzz_f18(data, cursor.clone()); + fuzz_f19(data, cursor.clone()); + fuzz_f20(data, cursor.clone()); + fuzz_f21(data, cursor.clone()); + fuzz_f22(data, cursor.clone()); + fuzz_f23(data, cursor.clone()); + fuzz_f24(data, cursor.clone()); + fuzz_f25(data, cursor.clone()); + fuzz_f26(data, cursor.clone()); + fuzz_f27(data, cursor.clone()); + fuzz_f28(data, cursor.clone()); + fuzz_f29(data, cursor.clone()); + fuzz_f30(data, cursor.clone()); + fuzz_f31(data, cursor.clone()); + fuzz_f32(data, cursor.clone()); + fuzz_f33(data, cursor.clone()); + fuzz_f34(data, cursor.clone()); + fuzz_f35(data, cursor.clone()); + fuzz_f36(data, cursor.clone()); + fuzz_f37(data, cursor.clone()); + fuzz_f38(data, cursor.clone()); + fuzz_f39(data, cursor.clone()); + fuzz_f40(data, cursor.clone()); + fuzz_f41(data, cursor.clone()); + fuzz_f42(data, cursor.clone()); + fuzz_f43(data, cursor.clone()); + fuzz_f44(data, cursor.clone()); + fuzz_f45(data, cursor.clone()); + fuzz_f46(data, cursor.clone()); + fuzz_f47(data, cursor.clone()); + fuzz_f48(data, cursor.clone()); + fuzz_f49(data, cursor.clone()); + fuzz_f50(data, cursor.clone()); + fuzz_f51(data, cursor.clone()); + fuzz_f52(data, cursor.clone()); + fuzz_f53(data, cursor.clone()); + fuzz_f54(data, cursor.clone()); + fuzz_f55(data, cursor.clone()); + fuzz_f56(data, cursor.clone()); + fuzz_f57(data, cursor.clone()); + fuzz_f74(data, cursor.clone()); + + fuzz_all(data, cursor.clone()); +}); diff --git a/examples/lazy-reader-tests/fuzz/rust-toolchain b/examples/lazy-reader-tests/fuzz/rust-toolchain new file mode 100644 index 0000000..70e4fd0 --- /dev/null +++ b/examples/lazy-reader-tests/fuzz/rust-toolchain @@ -0,0 +1 @@ +nightly-2023-07-26 \ No newline at end of file diff --git a/examples/lazy-reader-tests/src/lib.rs b/examples/lazy-reader-tests/src/lib.rs new file mode 100644 index 0000000..b36ae9b --- /dev/null +++ b/examples/lazy-reader-tests/src/lib.rs @@ -0,0 +1,354 @@ +pub mod types_api; +pub mod types_api2; + +pub mod types_all_data; +pub mod types_api2_mol2; +pub mod types_array; +pub mod types_moleculec_check; +pub mod types_option; +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; + +pub use types_api2_mol2::*; +pub use types_array::*; +pub use types_moleculec_check::*; +pub use types_option::*; +pub use types_struct::*; +pub use types_table::*; +pub use types_vec::*; + +pub trait BaseTypes { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self; +} +impl BaseTypes for u8 { + fn new_rng(rng: &mut ThreadRng, _config: &TypesConfig) -> Self { + rng.gen() + } +} + +pub enum OptionFillType { + FillRand, + FillSome, + FillNone, +} +pub struct TypesConfig { + pub option_fill: OptionFillType, + pub large_vec: bool, + pub min_size: bool, +} + +impl Default for TypesConfig { + fn default() -> Self { + Self { + option_fill: OptionFillType::FillRand, + large_vec: false, + min_size: false, + } + } +} + +#[derive(Debug)] +pub enum TypesCheckErr { + Lenght(String), + Data(String), + Opt(String), + Mol2Err(String), +} +pub type ResCheckErr = Result<(), TypesCheckErr>; + +impl TypesCheckErr { + pub fn to(&self, des: String) -> Self { + match self { + Self::Lenght(_) => Self::Lenght(des), + Self::Data(_) => Self::Data(des), + Self::Opt(_) => Self::Opt(des), + Self::Mol2Err(_) => Self::Mol2Err(des), + } + } + pub fn as_str(&self) -> &str { + match self { + Self::Lenght(v) => v, + Self::Data(v) => v, + Self::Opt(v) => v, + Self::Mol2Err(v) => v, + } + } + pub fn check_length(l1: usize, l2: usize) -> Result<(), Self> { + if l1 == l2 { + Ok(()) + } else { + Err(Self::Lenght(format!("different length : {} {}", l1, l2))) + } + } + + pub fn check_1_data(d1: &T, d2: &T) -> Result<(), Self> { + if d1 == d2 { + Ok(()) + } else { + Err(Self::Data(format!( + "different data: {:02x?} {:02x?}", + d1, d2 + ))) + } + } + + pub fn check_data>(d1: &T, d2: &[T1]) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + + for i in 0..d1.mol_len()? { + TypesCheckErr::check_1_data(&d1.mol_get(i)?, &d2[i])?; + } + + Ok(()) + } + + pub fn check_mol_data, T2: Mol2Vec>( + d1: &T1, + d2: &T2, + ) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.mol_len()?)?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_1_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) + } + + pub fn check_option(d1: &Option, d2: &Option) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + Ok(()) + } +} +impl From for TypesCheckErr { + fn from(value: molecule::lazy_reader::Error) -> Self { + use molecule::lazy_reader::Error::*; + match value { + Common => Self::Mol2Err(format!("Common")), + TotalSize(s1, s2) => Self::Mol2Err(format!( + "TotalSize (validate: size({}) > total_size({}))", + s1, s2 + )), + Header(s1, s2) => Self::Mol2Err(format!( + "Header(verify_fixed: self.size({}) != size({}))", + s1, s2 + )), + Offset => Self::Mol2Err(format!("Offset")), + UnknownItem => Self::Mol2Err(format!("UnknownItem")), + OutOfBound(s1, s2) => Self::Mol2Err(format!("OutOfBound({}, {})", s1, s2)), + FieldCount(s) => Self::Mol2Err(format!("FieldCount({})", s)), + Data => Self::Mol2Err(format!("Data")), + Overflow => Self::Mol2Err(format!("Overflow")), + Read(s1, s2) => Self::Mol2Err(format!( + "Read(TryFrom: size({}) != buf.len()({}))", + s1, s2 + )), + Verify => Self::Mol2Err(format!("Verify")), + Unknown => Self::Mol2Err(format!("Unknown")), + } + } +} +impl From for TypesCheckErr { + fn from(value: std::convert::Infallible) -> Self { + Self::Mol2Err(format!("conver failed: {:?}", value)) + } +} + +pub enum TypesUnionA { + Byte(TypesArray), + Word(TypesArrayWord), + StructA(TypesStructA), + Bytes(TypesVec), + Words(TypesVec), + Table0(TypesTable0), + Table6(TypesTable6), + Table6Opt(TypesOption), +} +impl BaseTypes for TypesUnionA { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + let v = if config.min_size { + 0 // Self::Byte + } else { + rng.gen_range(0..8) + }; + match v { + 0 => Self::Byte(TypesArray::new_rng(rng, config)), + 1 => Self::Word(TypesArrayWord::new_rng(rng, config)), + 2 => Self::StructA(TypesStructA::new_rng(rng, config)), + 3 => Self::Bytes(TypesVec::new_rng(rng, config)), + 4 => Self::Words(TypesVec::new_rng(rng, config)), + 5 => Self::Table0(TypesTable0::new_rng(rng, config)), + 6 => Self::Table6(TypesTable6::new_rng(rng, config)), + 7 => Self::Table6Opt(TypesOption::new_rng(rng, config)), + + _ => panic!("unknow error"), + } + } +} +impl Default for TypesUnionA { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} +impl TypesUnionA { + pub fn to_mol(&self) -> types_api::UnionA { + let t = match self { + Self::Byte(v) => types_api::UnionAUnion::Byte(v.to_mol()), + Self::Word(v) => types_api::UnionAUnion::Word(v.to_mol2()), + Self::StructA(v) => types_api::UnionAUnion::StructA(v.to_mol()), + Self::Bytes(v) => types_api::UnionAUnion::Bytes(v.to_mol()), + Self::Words(v) => types_api::UnionAUnion::Words(v.to_mol()), + Self::Table0(v) => types_api::UnionAUnion::Table0(v.to_mol()), + Self::Table6(v) => types_api::UnionAUnion::Table6(v.to_mol()), + Self::Table6Opt(v) => types_api::UnionAUnion::Table6Opt(v.to_mol()), + }; + types_api::UnionA::new_builder().set(t).build() + } + + pub fn check(&self, d: &types_api2::UnionA) -> ResCheckErr { + // let item_id = d.item_id(); + + match self { + 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), // 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), // 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"))), + }, + } + } +} diff --git a/examples/lazy-reader-tests/src/types_all_data.rs b/examples/lazy-reader-tests/src/types_all_data.rs new file mode 100644 index 0000000..0b3c8d4 --- /dev/null +++ b/examples/lazy-reader-tests/src/types_all_data.rs @@ -0,0 +1,1142 @@ +#![allow(unused_imports)] +// #![allow(dead_code)] + +use crate::types_api; +use crate::types_api2; + +use core::convert::TryInto; +use lazy_static::lazy_static; +use molecule::lazy_reader::Cursor; +use molecule::prelude::{Builder, Entity, Reader}; +use molecule::{bytes::Bytes, prelude::Byte}; +use rand::{random, rngs::ThreadRng, thread_rng, Rng, RngCore}; + +use super::*; + +fn new_cursor(d: &[u8]) -> Cursor { + Cursor::new(d.len(), Box::new(d.to_vec())) +} + +#[derive(Default)] +pub struct TypesAll { + f0: TypesArray, + f1: TypesArray, + f2: TypesArray, + f3: TypesArray, + f4: TypesArray, + f5: TypesArray, + f6: TypesArray, + f7: TypesArray, + f8: TypesArray, + f9: TypesArray, + f10: TypesArray, + f11: TypesArray, + f12: TypesArray, + f13: TypesArray, + f14: TypesArray, + f15: TypesArray, + + f16: TypesArrayWord, + f17: TypesArray, + f18: TypesArray, + f19: TypesArray, + f20: TypesArray, + f21: TypesArray, + f22: TypesArray, + f23: TypesArray, + + f24: TypesArray, 3>, + f25: TypesArray, 3>, + f26: TypesArray, 3>, + f27: TypesArray, 3>, + + f28: TypesStructA, + f29: TypesStructB, + f30: TypesStructC, + f31: TypesStructD, + f32: TypesStructE, + f33: TypesStructF, + f34: TypesStructG, + f35: TypesStructH, + f36: TypesStructI, + f37: TypesStructJ, + f38: TypesStructIx3, + f39: TypesStructO, + f40: TypesStructP, + + f41: TypesVec, + f42: TypesVec, + f43: TypesVec>, + f44: TypesVec>, + f45: TypesVec, + f46: TypesVec, + f47: TypesVec, + f48: TypesVec>, + f49: TypesVec>, + + f50: TypesTable0, + f51: TypesTable1, + f52: TypesTable2, + f53: TypesTable3, + f54: TypesTable4, + f55: TypesTable5, + f56: TypesTable6, + + f57: TypesOption, + f58: TypesOption, + f59: TypesOption, + f60: TypesOption, + f61: TypesOption>, + f62: TypesOption>, + f63: TypesOption>>, + f64: TypesOption>>, + f65: TypesOption, + f66: TypesOption, + f67: TypesOption>, + + f68: TypesVec>, + f69: TypesVec>, + f70: TypesVec>>, + f71: TypesVec>>, + + f72: TypesUnionA, + f73: TypesTableA, + f74: TypesTableB, + + f75: TypesUnionB, + f76: TypesUnionD, +} + +impl TypesAll { + pub fn new_by_config(config: &TypesConfig) -> Self { + let mut rng = thread_rng(); + Self { + f0: TypesArray::new_rng(&mut rng, config), + f1: TypesArray::new_rng(&mut rng, config), + f2: TypesArray::new_rng(&mut rng, config), + f3: TypesArray::new_rng(&mut rng, config), + f4: TypesArray::new_rng(&mut rng, config), + f5: TypesArray::new_rng(&mut rng, config), + f6: TypesArray::new_rng(&mut rng, config), + f7: TypesArray::new_rng(&mut rng, config), + f8: TypesArray::new_rng(&mut rng, config), + f9: TypesArray::new_rng(&mut rng, config), + f10: TypesArray::new_rng(&mut rng, config), + f11: TypesArray::new_rng(&mut rng, config), + f12: TypesArray::new_rng(&mut rng, config), + f13: TypesArray::new_rng(&mut rng, config), + f14: TypesArray::new_rng(&mut rng, config), + f15: TypesArray::new_rng(&mut rng, config), + f16: TypesArray::new_rng(&mut rng, config), + f17: TypesArray::new_rng(&mut rng, config), + f18: TypesArray::new_rng(&mut rng, config), + f19: TypesArray::new_rng(&mut rng, config), + f20: TypesArray::new_rng(&mut rng, config), + f21: TypesArray::new_rng(&mut rng, config), + f22: TypesArray::new_rng(&mut rng, config), + f23: TypesArray::new_rng(&mut rng, config), + f24: TypesArray::new_rng(&mut rng, config), + f25: TypesArray::new_rng(&mut rng, config), + f26: TypesArray::new_rng(&mut rng, config), + f27: TypesArray::new_rng(&mut rng, config), + f28: TypesStructA::new_rng(&mut rng, config), + f29: TypesStructB::new_rng(&mut rng, config), + f30: TypesStructC::new_rng(&mut rng, config), + f31: TypesStructD::new_rng(&mut rng, config), + f32: TypesStructE::new_rng(&mut rng, config), + f33: TypesStructF::new_rng(&mut rng, config), + f34: TypesStructG::new_rng(&mut rng, config), + f35: TypesStructH::new_rng(&mut rng, config), + f36: TypesStructI::new_rng(&mut rng, config), + f37: TypesStructJ::new_rng(&mut rng, config), + f38: TypesStructIx3::new_rng(&mut rng, config), + f39: TypesStructO::new_rng(&mut rng, config), + f40: TypesStructP::new_rng(&mut rng, config), + f41: TypesVec::new_rng(&mut rng, config), + f42: TypesVec::new_rng(&mut rng, config), + f43: TypesVec::new_rng(&mut rng, config), + f44: TypesVec::new_rng(&mut rng, config), + f45: TypesVec::new_rng(&mut rng, config), + f46: TypesVec::new_rng(&mut rng, config), + f47: TypesVec::new_rng(&mut rng, config), + f48: TypesVec::new_rng(&mut rng, config), + f49: TypesVec::new_rng(&mut rng, config), + f50: TypesTable0::new_rng(&mut rng, config), + f51: TypesTable1::new_rng(&mut rng, config), + f52: TypesTable2::new_rng(&mut rng, config), + f53: TypesTable3::new_rng(&mut rng, config), + f54: TypesTable4::new_rng(&mut rng, config), + f55: TypesTable5::new_rng(&mut rng, config), + f56: TypesTable6::new_rng(&mut rng, config), + f57: TypesOption::new_rng(&mut rng, config), + f58: TypesOption::new_rng(&mut rng, config), + f59: TypesOption::new_rng(&mut rng, config), + f60: TypesOption::new_rng(&mut rng, config), + f61: TypesOption::new_rng(&mut rng, config), + f62: TypesOption::new_rng(&mut rng, config), + f63: TypesOption::new_rng(&mut rng, config), + f64: TypesOption::new_rng(&mut rng, config), + f65: TypesOption::new_rng(&mut rng, config), + f66: TypesOption::new_rng(&mut rng, config), + f67: TypesOption::new_rng(&mut rng, config), + f68: TypesVec::new_rng(&mut rng, config), + f69: TypesVec::new_rng(&mut rng, config), + f70: TypesVec::new_rng(&mut rng, config), + f71: TypesVec::new_rng(&mut rng, config), + f72: TypesUnionA::new_rng(&mut rng, config), + f73: TypesTableA::new_rng(&mut rng, config), + f74: TypesTableB::new_rng(&mut rng, config), + f75: TypesUnionB::new_rng(&mut rng, config), + f76: TypesUnionD::new_rng(&mut rng, config), + } + } + pub fn to_bytes(&self) -> Vec { + use crate::types_api::*; + + let builder = types_api::AllInOneBuilder::default() + .f0(self.f0.to_mol()) + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .f5(self.f5.to_mol()) + .f6(self.f6.to_mol()) + .f7(self.f7.to_mol()) + .f8(self.f8.to_mol()) + .f9(self.f9.to_mol()) + .f10(self.f10.to_mol()) + .f11(self.f11.to_mol()) + .f12(self.f12.to_mol()) + .f13(self.f13.to_mol()) + .f14(self.f14.to_mol()) + .f15(self.f15.to_mol()) + .f16( + types_api::Word::new_builder() + .set(self.f16.d.map(|f| f.into())) + .build(), + ) + .f17(self.f17.to_mol()) + .f18(self.f18.to_mol()) + .f19(self.f19.to_mol()) + .f20(self.f20.to_mol()) + .f21(self.f21.to_mol()) + .f22(self.f22.to_mol()) + .f23(self.f23.to_mol()) + .f24(self.f24.to_mol()) + .f25(self.f25.to_mol()) + .f26(self.f26.to_mol()) + .f27(self.f27.to_mol()) + .f28(self.f28.to_mol()) + .f29(self.f29.to_mol()) + .f30(self.f30.to_mol()) + .f31(self.f31.to_mol()) + .f32(self.f32.to_mol()) + .f33(self.f33.to_mol()) + .f34(self.f34.to_mol()) + .f35(self.f35.to_mol()) + .f36(self.f36.to_mol()) + .f37(self.f37.to_mol()) + .f38(self.f38.to_mol()) + .f39(self.f39.to_mol()) + .f40(self.f40.to_mol()) + .f41(self.f41.to_mol()) + .f42(self.f42.to_mol()) + .f43(self.f43.to_mol()) + .f44(self.f44.to_mol()) + .f45(self.f45.to_mol()) + .f46(self.f46.to_mol()) + .f47(self.f47.to_mol()) + .f48(self.f48.to_mol()) + .f49(self.f49.to_mol()) + .f50(self.f50.to_mol()) + .f51(self.f51.to_mol()) + .f52(self.f52.to_mol()) + .f53(self.f53.to_mol()) + .f54(self.f54.to_mol()) + .f55(self.f55.to_mol()) + .f56(self.f56.to_mol()) + .f57(self.f57.to_mol()) + .f58(self.f58.to_mol()) + .f59(self.f59.to_mol()) + .f60(self.f60.to_mol()) + .f61(self.f61.to_mol()) + .f62(self.f62.to_mol()) + .f63(self.f63.to_mol()) + .f64(self.f64.to_mol()) + .f65(self.f65.to_mol()) + .f66(self.f66.to_mol()) + .f67(self.f67.to_mol()) + .f68(self.f68.to_mol()) + .f69(self.f69.to_mol()) + .f70(self.f70.to_mol()) + .f71(self.f71.to_mol()) + .f72(self.f72.to_mol()) + .f73(self.f73.to_mol()) + .f74(self.f74.to_mol()) + .f75(self.f75.to_mol()) + .f76(self.f76.to_mol()) + .build(); + + builder.as_reader().as_slice().to_vec() + } + + pub fn check(&self, data: &[u8]) -> ResCheckErr { + use crate::types_api2_mol2::Mol2Vec; + use types_api2::*; + + let cursor = new_cursor(data); + let all_in_one = AllInOne { cursor }; + all_in_one.verify(true)?; + all_in_one.verify(false)?; + + self.f0 + .check(&all_in_one.f0()?) + .map_err(|f| f.to(format!("f0:{}", f.as_str())))?; + self.f1 + .check(&Cursor::try_from(all_in_one.f1()?)?.into()) + .map_err(|f| f.to(format!("f1:{}", f.as_str())))?; + self.f2 + .check(&Cursor::try_from(all_in_one.f2()?)?.into()) + .map_err(|f| f.to(format!("f2:{}", f.as_str())))?; + self.f3 + .check(&Cursor::try_from(all_in_one.f3()?)?.into()) + .map_err(|f| f.to(format!("f3:{}", f.as_str())))?; + self.f4 + .check(&Cursor::try_from(all_in_one.f4()?)?.into()) + .map_err(|f| f.to(format!("f74:{}", f.as_str())))?; + self.f5 + .check(&Cursor::try_from(all_in_one.f5()?)?.into()) + .map_err(|f| f.to(format!("f5:{}", f.as_str())))?; + self.f6 + .check(&Cursor::try_from(all_in_one.f6()?)?.into()) + .map_err(|f| f.to(format!("f6:{}", f.as_str())))?; + self.f7 + .check(&Cursor::try_from(all_in_one.f7()?)?.into()) + .map_err(|f| f.to(format!("f7:{}", f.as_str())))?; + self.f8 + .check(&Cursor::try_from(all_in_one.f8()?)?.into()) + .map_err(|f| f.to(format!("f8:{}", f.as_str())))?; + self.f9 + .check(&Cursor::try_from(all_in_one.f9()?)?.into()) + .map_err(|f| f.to(format!("f9:{}", f.as_str())))?; + self.f10 + .check(&Cursor::try_from(all_in_one.f10()?)?.into()) + .map_err(|f| f.to(format!("f10:{}", f.as_str())))?; + self.f11 + .check(&Cursor::try_from(all_in_one.f11()?)?.into()) + .map_err(|f| f.to(format!("f11:{}", f.as_str())))?; + self.f12 + .check(&Cursor::try_from(all_in_one.f12()?)?.into()) + .map_err(|f| f.to(format!("f12:{}", f.as_str())))?; + self.f13 + .check(&Cursor::try_from(all_in_one.f13()?)?.into()) + .map_err(|f| f.to(format!("f13:{}", f.as_str())))?; + self.f14 + .check(&Cursor::try_from(all_in_one.f14()?)?.into()) + .map_err(|f| f.to(format!("f14:{}", f.as_str())))?; + self.f15 + .check(&Cursor::try_from(all_in_one.f15()?)?.into()) + .map_err(|f| f.to(format!("f15:{}", f.as_str())))?; + + self.f16 + .check2(&Cursor::try_from(all_in_one.f16()?)?.into()) + .map_err(|f| f.to(format!("f16:{}", f.as_str())))?; + self.f17 + .check(&all_in_one.f17()?.into()) + .map_err(|f| f.to(format!("f17:{}", f.as_str())))?; + self.f18 + .check(&all_in_one.f18()?.into()) + .map_err(|f| f.to(format!("f18:{}", f.as_str())))?; + self.f19 + .check(&all_in_one.f19()?.into()) + .map_err(|f| f.to(format!("f19:{}", f.as_str())))?; + self.f20 + .check(&all_in_one.f20()?.into()) + .map_err(|f| f.to(format!("f20:{}", f.as_str())))?; + self.f21 + .check(&all_in_one.f21()?.into()) + .map_err(|f| f.to(format!("f21:{}", f.as_str())))?; + self.f22 + .check(&all_in_one.f22()?.into()) + .map_err(|f| f.to(format!("f22:{}", f.as_str())))?; + self.f23 + .check(&all_in_one.f23()?.into()) + .map_err(|f| f.to(format!("f23:{}", f.as_str())))?; + + self.f24 + .check(&all_in_one.f24()?.into()) + .map_err(|f| f.to(format!("f24:{}", f.as_str())))?; + self.f25 + .check(&all_in_one.f25()?.into()) + .map_err(|f| f.to(format!("f25:{}", f.as_str())))?; + self.f26 + .check(&all_in_one.f26()?.into()) + .map_err(|f| f.to(format!("f26:{}", f.as_str())))?; + self.f27 + .check(&all_in_one.f27()?.into()) + .map_err(|f| f.to(format!("f27:{}", f.as_str())))?; + + self.f28 + .check(&all_in_one.f28()?.into()) + .map_err(|f| f.to(format!("f28:{}", f.as_str())))?; + self.f29 + .check(&all_in_one.f29()?.into()) + .map_err(|f| f.to(format!("f29:{}", f.as_str())))?; + self.f30 + .check(&all_in_one.f30()?.into()) + .map_err(|f| f.to(format!("f30:{}", f.as_str())))?; + self.f31 + .check(&all_in_one.f31()?.into()) + .map_err(|f| f.to(format!("f31:{}", f.as_str())))?; + self.f32 + .check(&all_in_one.f32()?.into()) + .map_err(|f| f.to(format!("f32:{}", f.as_str())))?; + self.f33 + .check(&all_in_one.f33()?.into()) + .map_err(|f| f.to(format!("f33:{}", f.as_str())))?; + self.f34 + .check(&all_in_one.f34()?.into()) + .map_err(|f| f.to(format!("f34:{}", f.as_str())))?; + self.f35 + .check(&all_in_one.f35()?.into()) + .map_err(|f| f.to(format!("f35:{}", f.as_str())))?; + self.f36 + .check(&all_in_one.f36()?.into()) + .map_err(|f| f.to(format!("f36:{}", f.as_str())))?; + self.f37 + .check(&all_in_one.f37()?.into()) + .map_err(|f| f.to(format!("f37:{}", f.as_str())))?; + self.f38 + .check(&all_in_one.f38()?.into()) + .map_err(|f| f.to(format!("f38:{}", f.as_str())))?; + self.f39 + .check(&all_in_one.f39()?.into()) + .map_err(|f| f.to(format!("f39:{}", f.as_str())))?; + self.f40 + .check(&all_in_one.f40()?.into()) + .map_err(|f| f.to(format!("f40:{}", f.as_str())))?; + + self.f41 + .check(&all_in_one.f41()?.try_into().unwrap()) + .map_err(|f| f.to(format!("f41:{}", f.as_str())))?; + self.f42 + .check(&all_in_one.f42()?.into()) + .map_err(|f| f.to(format!("f42:{}", f.as_str())))?; + self.f43 + .check(&all_in_one.f43()?.into()) + .map_err(|f| f.to(format!("f43:{}", f.as_str())))?; + self.f44 + .check(&all_in_one.f44()?.into()) + .map_err(|f| f.to(format!("f44:{}", f.as_str())))?; + self.f45 + .check(&all_in_one.f45()?.into()) + .map_err(|f| f.to(format!("f45:{}", f.as_str())))?; + self.f46 + .check(&all_in_one.f46()?.into()) + .map_err(|f| f.to(format!("f46:{}", f.as_str())))?; + self.f47 + .check(&all_in_one.f47()?.into()) + .map_err(|f| f.to(format!("f47:{}", f.as_str())))?; + self.f48 + .check(&all_in_one.f48()?.into()) + .map_err(|f| f.to(format!("f48:{}", f.as_str())))?; + self.f49 + .check(&all_in_one.f49()?.into()) + .map_err(|f| f.to(format!("f49:{}", f.as_str())))?; + + self.f50 + .check(&all_in_one.f50()?.into()) + .map_err(|f| f.to(format!("f50:{}", f.as_str())))?; + self.f51 + .check(&all_in_one.f51()?.into()) + .map_err(|f| f.to(format!("f51:{}", f.as_str())))?; + self.f52 + .check(&all_in_one.f52()?.into()) + .map_err(|f| f.to(format!("f52:{}", f.as_str())))?; + self.f53 + .check(&all_in_one.f53()?.into()) + .map_err(|f| f.to(format!("f53:{}", f.as_str())))?; + self.f54 + .check(&all_in_one.f54()?.into()) + .map_err(|f| f.to(format!("f54:{}", f.as_str())))?; + self.f55 + .check(&all_in_one.f55()?.into()) + .map_err(|f| f.to(format!("f55:{}", f.as_str())))?; + self.f56 + .check(&all_in_one.f56()?.into()) + .map_err(|f| f.to(format!("f56:{}", f.as_str())))?; + self.f57 + .check(&all_in_one.f57()?.into()) + .map_err(|f| f.to(format!("f57:{}", f.as_str())))?; + self.f58 + .check(&all_in_one.f58()?.map(|f| f.into())) + .map_err(|f| f.to(format!("f58:{}", f.as_str())))?; + self.f59 + .check(&all_in_one.f59()?) + .map_err(|f| f.to(format!("f59:{}", f.as_str())))?; + self.f60 + .check(&all_in_one.f60()?) + .map_err(|f| f.to(format!("f60:{}", f.as_str())))?; + self.f61 + .check(&all_in_one.f61()?) + .map_err(|f| f.to(format!("f61:{}", f.as_str())))?; + self.f62 + .check(&all_in_one.f62()?) + .map_err(|f| f.to(format!("f62:{}", f.as_str())))?; + self.f63 + .check(&all_in_one.f63()?) + .map_err(|f| f.to(format!("f63:{}", f.as_str())))?; + self.f64 + .check(&all_in_one.f64()?) + .map_err(|f| f.to(format!("f64:{}", f.as_str())))?; + self.f65 + .check(&all_in_one.f65()?) + .map_err(|f| f.to(format!("f65:{}", f.as_str())))?; + self.f66 + .check(&all_in_one.f66()?) + .map_err(|f| f.to(format!("f66:{}", f.as_str())))?; + self.f67 + .check(&all_in_one.f67()?) + .map_err(|f| f.to(format!("f67:{}", f.as_str())))?; + self.f68 + .check(&all_in_one.f68()?) + .map_err(|f| f.to(format!("f68:{}", f.as_str())))?; + self.f69 + .check(&all_in_one.f69()?) + .map_err(|f| f.to(format!("f69:{}", f.as_str())))?; + self.f70 + .check(&all_in_one.f70()?) + .map_err(|f| f.to(format!("f70:{}", f.as_str())))?; + self.f71 + .check(&all_in_one.f71()?) + .map_err(|f| f.to(format!("f71:{}", f.as_str())))?; + self.f72 + .check(&all_in_one.f72()?) + .map_err(|f| f.to(format!("f72:{}", f.as_str())))?; + self.f73 + .check(&all_in_one.f73()?) + .map_err(|f| f.to(format!("f73:{}", f.as_str())))?; + self.f74 + .check(&all_in_one.f74()?) + .map_err(|f| f.to(format!("f74:{}", f.as_str())))?; + self.f75 + .check(&all_in_one.f75()?) + .map_err(|f| f.to(format!("f75:{}", f.as_str())))?; + self.f76 + .check(&all_in_one.f76()?) + .map_err(|f| f.to(format!("f76:{}", f.as_str())))?; + types_api::AllInOneReader::verify(&data, true).expect("check data"); + + check_mol( + &types_api::AllInOne::new_unchecked(molecule::bytes::Bytes::from(data.to_vec())), + &all_in_one, + ) + .map_err(|f| f.to(format!("check mol and mol2 failed: {:?}", f.as_str())))?; + + Ok(()) + } +} + +#[test] +fn test_base() { + let test_data = TypesAll::default(); + let data = test_data.to_bytes(); + test_data.check(&data).expect("test base"); +} + +#[test] +fn test_opt_all_none() { + let mut config: TypesConfig = TypesConfig::default(); + config.option_fill = OptionFillType::FillNone; + let test_data = TypesAll::new_by_config(&config); + let data = test_data.to_bytes(); + test_data.check(&data).expect("test base"); + + config.option_fill = OptionFillType::FillSome; + let test_data = TypesAll::new_by_config(&config); + let data = test_data.to_bytes(); + test_data.check(&data).expect("test base"); +} + +#[test] +fn test_min_bytes() { + let mut config: TypesConfig = TypesConfig::default(); + config.min_size = true; + let test_data = TypesAll::new_by_config(&config); + let data = test_data.to_bytes(); + test_data.check(&data).expect("test base"); + + config.option_fill = OptionFillType::FillSome; + let test_data = TypesAll::new_by_config(&config); + let data = test_data.to_bytes(); + test_data.check(&data).expect("test base"); + + // Min size is 1106 +} + +#[test] +fn test_large_buf() { + let mut config = TypesConfig::default(); + config.large_vec = true; + let test_data = TypesAll::new_by_config(&config); + let data = test_data.to_bytes(); + test_data.check(&data).expect("test base"); +} + +#[test] +fn test_iterator() { + use types_api2::*; + + let test_data = TypesAll::default(); + let data = test_data.to_bytes(); + let cursor = new_cursor(&data); + let all_in_one = AllInOne { cursor }; + let f48 = all_in_one.f48().unwrap(); + + let mut count: usize = 0; + for _ in f48.iter() { + count += 1; + } + assert_eq!(count, f48.len().unwrap()); + + let mut count: usize = 0; + let len = f48.len().unwrap(); + for _ in f48 { + count += 1; + } + assert_eq!(count, len); +} + +#[test] +fn test_verify() { + use types_api2::*; + + let test_data = TypesAll::default(); + let data = test_data.to_bytes(); + let cursor = new_cursor(&data); + let all_in_one = AllInOne { cursor }; + all_in_one.verify(false).unwrap(); + all_in_one.verify(true).unwrap(); +} + +#[test] +fn test_err_rng_len() { + let mut rng = thread_rng(); + + fn generate_vec(len: usize, rng: &mut ThreadRng) -> Vec { + let mut len = len; + if len == 0 { + len = rng.gen::() % 1024; + } + let mut r = Vec::new(); + r.resize(len, 0); + rng.fill_bytes(&mut r); + r + } + + let data = generate_vec(0, &mut rng); + let compatible = true; + + assert_eq!( + types_api::Byte2Reader::verify(&data, compatible).is_err(), + types_api2::Byte2 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Byte7Reader::verify(&data, compatible).is_err(), + types_api2::Byte7 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Byte11Reader::verify(&data, compatible).is_err(), + types_api2::Byte11 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Byte16Reader::verify(&data, compatible).is_err(), + types_api2::Byte16 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Word2Reader::verify(&data, compatible).is_err(), + types_api2::Word2 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Word5Reader::verify(&data, compatible).is_err(), + types_api2::Word5 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Word8Reader::verify(&data, compatible).is_err(), + types_api2::Word8 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Byte3x3Reader::verify(&data, compatible).is_err(), + types_api2::Byte3x3 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Byte7x3Reader::verify(&data, compatible).is_err(), + types_api2::Byte7x3 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::StructAReader::verify(&data, compatible).is_err(), + types_api2::StructA { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::StructBReader::verify(&data, compatible).is_err(), + types_api2::StructB { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::StructCReader::verify(&data, compatible).is_err(), + types_api2::StructC { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::StructDReader::verify(&data, compatible).is_err(), + types_api2::StructD { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::StructFReader::verify(&data, compatible).is_err(), + types_api2::StructF { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::StructJReader::verify(&data, compatible).is_err(), + types_api2::StructJ { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::StructIx3Reader::verify(&data, compatible).is_err(), + types_api2::StructIx3 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::StructPReader::verify(&data, compatible).is_err(), + types_api2::StructP { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::BytesReader::verify(&data, compatible).is_err(), + types_api2::Bytes { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::WordsReader::verify(&data, compatible).is_err(), + types_api2::Words { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Byte3VecReader::verify(&data, compatible).is_err(), + types_api2::Byte3Vec { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Byte7VecReader::verify(&data, compatible).is_err(), + types_api2::Byte7Vec { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::StructIVecReader::verify(&data, compatible).is_err(), + types_api2::StructIVec { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::StructJVecReader::verify(&data, compatible).is_err(), + types_api2::StructJVec { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::StructPVecReader::verify(&data, compatible).is_err(), + types_api2::StructPVec { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::BytesVecReader::verify(&data, compatible).is_err(), + types_api2::BytesVec { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::WordsVecReader::verify(&data, compatible).is_err(), + types_api2::WordsVec { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Table0Reader::verify(&data, compatible).is_err(), + types_api2::Table0 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Table1Reader::verify(&data, compatible).is_err(), + types_api2::Table1 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Table2Reader::verify(&data, compatible).is_err(), + types_api2::Table2 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Table4Reader::verify(&data, compatible).is_err(), + types_api2::Table4 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::Table6Reader::verify(&data, compatible).is_err(), + types_api2::Table6 { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::ByteOptVecReader::verify(&data, compatible).is_err(), + types_api2::ByteOptVec { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::WordOptVecReader::verify(&data, compatible).is_err(), + types_api2::WordOptVec { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::WordsOptVecReader::verify(&data, compatible).is_err(), + types_api2::WordsOptVec { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::TableAReader::verify(&data, compatible).is_err(), + types_api2::TableA { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); + assert_eq!( + types_api::TableBReader::verify(&data, compatible).is_err(), + types_api2::TableB { + cursor: new_cursor(&data), + } + .verify(compatible) + .is_err() + ); +} + +#[test] +fn test_empty_union() { + let cursor = new_cursor(&[]); + let result = types_api2::UnionA::try_from(cursor); + assert!(result.is_err()); +} + +#[test] +fn test_union() { + fn test_union_item(base: TypesUnionA) { + let mut rng = thread_rng(); + + let data = base.to_mol(); + let item_id = data.item_id(); + + // success + let buf = data.as_bytes().to_vec(); + + types_api2::UnionA::try_from(new_cursor(&buf)) + .expect("new UnionA failed") + .verify(true) + .expect("verify unionA failed"); + + // Error item + let mut buf = data.as_bytes().to_vec(); + buf[0..4].copy_from_slice(&rng.gen_range(8u32..0xFFFFFFFEu32).to_le_bytes()); + + let union_a = types_api2::UnionA::try_from(new_cursor(&buf)); + if union_a.is_ok() && union_a.unwrap().verify(true).is_ok() { + panic!("verify failedunionA failed"); + } + + if item_id != 11 { + // exclude Bytes + // Error length + let mut buf = data.as_bytes().to_vec(); + if item_id != 0xFF000001 { + buf.extend_from_slice(&rng.gen::().to_le_bytes()); + } else { + buf.extend_from_slice({ + let mut d = rng.gen::(); + if d % 2 == 0 { + d += 1; + } + &d.to_le_bytes() + }) + } + + let union_a = types_api2::UnionA::try_from(new_cursor(&buf)); + if union_a.is_ok() && union_a.unwrap().verify(true).is_ok() { + panic!("verify failedunionA failed"); + } + } + } + + test_union_item(TypesUnionA::Byte(TypesArray::default())); + test_union_item(TypesUnionA::Word(TypesArrayWord::default())); + test_union_item(TypesUnionA::StructA(TypesStructA::default())); + test_union_item(TypesUnionA::Bytes(TypesVec::default())); + test_union_item(TypesUnionA::Words(TypesVec::default())); + test_union_item(TypesUnionA::Table0(TypesTable0::default())); + test_union_item(TypesUnionA::Table6(TypesTable6::default())); + test_union_item(TypesUnionA::Table6Opt(TypesOption::default())); + test_union_item(TypesUnionA::Table6Opt(TypesOption::new_none())); +} + +#[test] +fn test_table6() { + let base = TypesTable6::default(); + let data = base.to_mol(); + let mut rng = thread_rng(); + + let buf = data.as_bytes().to_vec(); + types_api2::Table6 { + cursor: new_cursor(&buf), + } + .verify(true) + .expect("table6"); + + // rng item + let mut buf = data.as_bytes().to_vec(); + buf[0..4].copy_from_slice(&rng.gen_range(7u32..0xFFFFFFFEu32).to_le_bytes()); + types_api2::Table6 { + cursor: new_cursor(&buf), + } + .verify(true) + .expect_err("verify table6"); + + // subitem + let data_builder = data.as_builder(); + let mut buf = data_builder.f6.as_bytes().to_vec(); + buf[0..4].copy_from_slice(&rng.gen_range(7u32..0xFFFFFFFEu32).to_le_bytes()); + let data_builder = data_builder.f6(types_api::Table5::new_unchecked( + molecule::bytes::Bytes::from(buf), + )); + + let buf = data_builder.build().as_bytes().to_vec(); + types_api2::Table6 { + cursor: new_cursor(&buf), + } + .verify(true) + .expect_err("verify table6"); +} + +#[test] +fn test_table_a() { + let base = TypesTableA::default(); + let data = base.to_mol(); + let mut rng = thread_rng(); + + // success + let buf = data.as_bytes().to_vec(); + types_api2::TableA { + cursor: new_cursor(&buf), + } + .verify(true) + .expect("verify TableA"); + + // rng item + let mut buf = data.as_bytes().to_vec(); + buf[0..4].copy_from_slice(&rng.gen_range(7u32..0xFFFFFFFEu32).to_le_bytes()); + types_api2::TableA { + cursor: new_cursor(&buf), + } + .verify(true) + .expect_err("verify TableA"); + + // subitem table1 + let data_builder = data.clone().as_builder(); + let mut buf = data_builder.f5.as_bytes().to_vec(); + buf[0..4].copy_from_slice(&rng.gen_range(7u32..0xFFFFFFFEu32).to_le_bytes()); + let data_builder = data_builder.f5(types_api::Table1::new_unchecked( + molecule::bytes::Bytes::from(buf), + )); + + let buf = data_builder.build().as_bytes().to_vec(); + types_api2::TableA { + cursor: new_cursor(&buf), + } + .verify(true) + .expect_err("verify TableA"); + + // subitem union + let data_builder = data.clone().as_builder(); + let mut buf = data_builder.f7.as_bytes().to_vec(); + buf[0..4].copy_from_slice(&rng.gen_range(7u32..0xFFFFFFFEu32).to_le_bytes()); + let data_builder = data_builder.f7(types_api::UnionA::new_unchecked( + molecule::bytes::Bytes::from(buf), + )); + + let buf = data_builder.build().as_bytes().to_vec(); + types_api2::TableA { + cursor: new_cursor(&buf), + } + .verify(true) + .expect_err("verify TableA"); +} + +#[test] +fn test_table_b() { + let base = TypesTableB::default(); + let data = base.to_mol(); + let mut rng = thread_rng(); + + // success + let buf = data.as_bytes().to_vec(); + types_api2::TableB { + cursor: new_cursor(&buf), + } + .verify(true) + .expect("verify TableB"); + + // rng item + let mut buf = data.as_bytes().to_vec(); + buf[0..4].copy_from_slice(&rng.gen_range(7u32..0xFFFFFFFEu32).to_le_bytes()); + types_api2::TableB { + cursor: new_cursor(&buf), + } + .verify(true) + .expect_err("verify TableA"); +} + +#[test] +fn test_struct_verify() { + let base = TypesStructP::default(); + let data = base.to_mol(); + + let mut buf = data.as_bytes().to_vec(); + let mut rng = thread_rng(); + rng.fill_bytes(buf.as_mut()); + + types_api2::StructP { + cursor: new_cursor(&buf), + } + .verify(false) + .expect("verify StructP"); + + let mut buf = data.as_bytes().to_vec(); + buf.extend_from_slice(&rng.gen::().to_le_bytes()); + types_api2::StructP { + cursor: new_cursor(&buf), + } + .verify(false) + .expect_err(""); + + let mut buf = data.as_bytes().to_vec(); + buf = buf[..buf.len() - 3].to_vec(); + types_api2::StructP { + cursor: new_cursor(&buf), + } + .verify(false) + .expect_err(""); +} diff --git a/examples/lazy-reader-tests/src/types_api.rs b/examples/lazy-reader-tests/src/types_api.rs new file mode 100644 index 0000000..c0a5580 --- /dev/null +++ b/examples/lazy-reader-tests/src/types_api.rs @@ -0,0 +1 @@ +include!(concat!(env!("OUT_DIR"), "/", "types", ".rs")); diff --git a/examples/lazy-reader-tests/src/types_api2.rs b/examples/lazy-reader-tests/src/types_api2.rs new file mode 100644 index 0000000..174e7d7 --- /dev/null +++ b/examples/lazy-reader-tests/src/types_api2.rs @@ -0,0 +1,11 @@ +// #![allow(unused_imports)] +// #![allow(dead_code)] + +include!(concat!( + env!("OUT_DIR"), + "/", + "lazy_reader", + "/", + "types", + ".rs" +)); diff --git a/examples/lazy-reader-tests/src/types_api2_mol2.rs b/examples/lazy-reader-tests/src/types_api2_mol2.rs new file mode 100644 index 0000000..a0f4ae2 --- /dev/null +++ b/examples/lazy-reader-tests/src/types_api2_mol2.rs @@ -0,0 +1,796 @@ +use super::TypesCheckErr; +use crate::types_api; +use crate::types_api2::*; +use molecule::lazy_reader::Cursor; + +pub trait Mol2Vec { + type RetType; + fn mol_len(&self) -> Result; + fn mol_get(&self, index: usize) -> Result; +} +impl Mol2Vec for Vec { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self[index]) + } +} +impl Mol2Vec for Byte2 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte3 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte4 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte5 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte6 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte7 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte8 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte9 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte10 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte11 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte12 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte13 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte14 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte15 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Byte16 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Word { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for StructIx3 { + type RetType = StructI; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Bytes { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()?) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for StructIVec { + type RetType = StructI; + fn mol_len(&self) -> Result { + Ok(self.len()?) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for StructJVec { + type RetType = StructJ; + fn mol_len(&self) -> Result { + Ok(self.len()?) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for StructPVec { + type RetType = StructP; + fn mol_len(&self) -> Result { + Ok(self.len()?) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for Word2 { + type RetType = Word; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Word3 { + type RetType = Word; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Word4 { + type RetType = Word; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Word5 { + type RetType = Word; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Word6 { + type RetType = Word; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Word7 { + type RetType = Word; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Word8 { + type RetType = Word; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Byte3x3 { + type RetType = Byte3; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Byte5x3 { + type RetType = Byte5; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Byte7x3 { + type RetType = Byte7; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Byte9x3 { + type RetType = Byte9; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Words { + type RetType = Word; + fn mol_len(&self) -> Result { + Ok(self.len()?) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Byte3Vec { + type RetType = Byte3; + fn mol_len(&self) -> Result { + Ok(self.len()?) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for Byte7Vec { + type RetType = Byte7; + fn mol_len(&self) -> Result { + Ok(self.len()?) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(Cursor::try_from(self.get(index)?)?)) + } +} +impl Mol2Vec for BytesVec { + type RetType = Cursor; + fn mol_len(&self) -> Result { + Ok(self.len()?) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index)?) + } +} +impl Mol2Vec for WordsVec { + type RetType = Words; + fn mol_len(&self) -> Result { + Ok(self.len()?) + } + fn mol_get(&self, index: usize) -> Result { + Ok(Self::RetType::from(self.get(index)?)) + } +} + +impl Mol2Vec for types_api::Byte2 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte3 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte4 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte5 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte6 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte7 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte8 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte9 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte10 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte11 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte12 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte13 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte14 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte15 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Byte16 { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Word { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.raw_data().len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.raw_data().get(index).unwrap().clone()) + } +} +impl Mol2Vec for types_api::Word2 { + type RetType = types_api::Word; + fn mol_len(&self) -> Result { + Ok(2) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::Word3 { + type RetType = types_api::Word; + fn mol_len(&self) -> Result { + Ok(3) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + 2 => self.nth2(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::Word4 { + type RetType = types_api::Word; + fn mol_len(&self) -> Result { + Ok(4) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + 2 => self.nth2(), + 3 => self.nth3(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::Word5 { + type RetType = types_api::Word; + fn mol_len(&self) -> Result { + Ok(5) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + 2 => self.nth2(), + 3 => self.nth3(), + 4 => self.nth4(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::Word6 { + type RetType = types_api::Word; + fn mol_len(&self) -> Result { + Ok(6) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + 2 => self.nth2(), + 3 => self.nth3(), + 4 => self.nth4(), + 5 => self.nth5(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::Word7 { + type RetType = types_api::Word; + fn mol_len(&self) -> Result { + Ok(7) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + 2 => self.nth2(), + 3 => self.nth3(), + 4 => self.nth4(), + 5 => self.nth5(), + 6 => self.nth6(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::Word8 { + type RetType = types_api::Word; + fn mol_len(&self) -> Result { + Ok(8) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + 2 => self.nth2(), + 3 => self.nth3(), + 4 => self.nth4(), + 5 => self.nth5(), + 6 => self.nth6(), + 7 => self.nth7(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::Byte3x3 { + type RetType = types_api::Byte3; + fn mol_len(&self) -> Result { + Ok(3) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + 2 => self.nth2(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::Byte5x3 { + type RetType = types_api::Byte5; + fn mol_len(&self) -> Result { + Ok(3) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + 2 => self.nth2(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::Byte7x3 { + type RetType = types_api::Byte7; + fn mol_len(&self) -> Result { + Ok(3) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + 2 => self.nth2(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::Byte9x3 { + type RetType = types_api::Byte9; + fn mol_len(&self) -> Result { + Ok(3) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + 2 => self.nth2(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::StructIx3 { + type RetType = types_api::StructI; + fn mol_len(&self) -> Result { + Ok(3) + } + fn mol_get(&self, index: usize) -> Result { + Ok(match index { + 0 => self.nth0(), + 1 => self.nth1(), + 2 => self.nth2(), + _ => panic!("out of bound"), + }) + } +} +impl Mol2Vec for types_api::Bytes { + type RetType = u8; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap().into()) + } +} +impl Mol2Vec for types_api::Words { + type RetType = types_api::Word; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} +impl Mol2Vec for types_api::Byte3Vec { + type RetType = types_api::Byte3; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} +impl Mol2Vec for types_api::Byte7Vec { + type RetType = types_api::Byte7; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} +impl Mol2Vec for types_api::StructIVec { + type RetType = types_api::StructI; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} +impl Mol2Vec for types_api::StructJVec { + type RetType = types_api::StructJ; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} +impl Mol2Vec for types_api::StructPVec { + type RetType = types_api::StructP; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} +impl Mol2Vec for types_api::BytesVec { + type RetType = types_api::Bytes; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} +impl Mol2Vec for types_api::WordsVec { + type RetType = types_api::Words; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} +impl Mol2Vec for types_api::ByteOptVec { + type RetType = types_api::ByteOpt; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} +impl Mol2Vec for types_api::WordOptVec { + type RetType = types_api::WordOpt; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} +impl Mol2Vec for types_api::WordsOptVec { + type RetType = types_api::WordsOpt; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} +impl Mol2Vec for types_api::BytesOptVec { + type RetType = types_api::BytesOpt; + fn mol_len(&self) -> Result { + Ok(self.len()) + } + fn mol_get(&self, index: usize) -> Result { + Ok(self.get(index).unwrap()) + } +} diff --git a/examples/lazy-reader-tests/src/types_array.rs b/examples/lazy-reader-tests/src/types_array.rs new file mode 100644 index 0000000..e4fb37f --- /dev/null +++ b/examples/lazy-reader-tests/src/types_array.rs @@ -0,0 +1,368 @@ +use super::{BaseTypes, ResCheckErr, TypesCheckErr, TypesConfig}; +use crate::{types_api, types_api2}; +use molecule::lazy_reader::Cursor; +use molecule::prelude::{Builder, Byte, Entity}; +use rand::{rngs::ThreadRng, thread_rng}; + +#[derive(Clone, Copy)] +pub struct TypesArray { + pub d: [T; N], +} + +impl BaseTypes for TypesArray { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + let mut buf = [T::new_rng(rng, config); N]; + + for i in 0..N { + buf[i] = T::new_rng(rng, config); + } + + Self { d: buf } + } +} +impl TypesArray { + pub fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + let mut d = Vec::new(); + for _ in 0..N { + d.push(T::new_rng(rng, config)); + } + + Self { + d: d.try_into().ok().unwrap(), + } + } +} + +impl Default for TypesArray { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} + +impl TypesArray { + pub fn to_mol(&self) -> Byte { + self.d[0].into() + } + + pub fn check(&self, d: &u8) -> ResCheckErr { + TypesCheckErr::check_1_data(d, &self.d[0]) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte2 { + types_api::Byte2::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + pub fn to_mol2(&self) -> types_api::Word { + types_api::Word::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + + pub fn check(&self, d: &types_api2::Byte2) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } + pub fn check2(&self, d: &types_api2::Word) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte3 { + types_api::Byte3::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + + pub fn check(&self, d: &types_api2::Byte3) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte4 { + types_api::Byte4::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + + pub fn check(&self, d: &types_api2::Byte4) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte5 { + types_api::Byte5::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + + pub fn check(&self, d: &types_api2::Byte5) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte6 { + types_api::Byte6::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + + pub fn check(&self, d: &types_api2::Byte6) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte7 { + types_api::Byte7::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + pub fn check(&self, d: &types_api2::Byte7) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte8 { + types_api::Byte8::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + pub fn check(&self, d: &types_api2::Byte8) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte9 { + types_api::Byte9::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + pub fn check(&self, d: &types_api2::Byte9) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte10 { + types_api::Byte10::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + pub fn check(&self, d: &types_api2::Byte10) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte11 { + types_api::Byte11::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + pub fn check(&self, d: &types_api2::Byte11) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte12 { + types_api::Byte12::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + pub fn check(&self, d: &types_api2::Byte12) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte13 { + types_api::Byte13::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + pub fn check(&self, d: &types_api2::Byte13) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte14 { + types_api::Byte14::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + pub fn check(&self, d: &types_api2::Byte14) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte15 { + types_api::Byte15::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + pub fn check(&self, d: &types_api2::Byte15) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Byte16 { + types_api::Byte16::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + pub fn check(&self, d: &types_api2::Byte16) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +pub type TypesArrayWord = TypesArray; +impl TypesArray { + pub fn to_mol(&self) -> types_api::Word2 { + types_api::Word2::new_builder() + .set(self.d.clone().map(|f| f.to_mol2())) + .build() + } + pub fn check(&self, d: &types_api2::Word2) -> ResCheckErr { + for i in 0..d.len() { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Word3 { + types_api::Word3::new_builder() + .set(self.d.clone().map(|f| f.to_mol2())) + .build() + } + pub fn check(&self, d: &types_api2::Word3) -> ResCheckErr { + TypesCheckErr::check_length(d.len(), self.d.len())?; + for i in 0..d.len() { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Word4 { + types_api::Word4::new_builder() + .set(self.d.clone().map(|f| f.to_mol2())) + .build() + } + pub fn check(&self, d: &types_api2::Word4) -> ResCheckErr { + TypesCheckErr::check_length(d.len(), self.d.len())?; + for i in 0..d.len() { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Word5 { + types_api::Word5::new_builder() + .set(self.d.clone().map(|f| f.to_mol2())) + .build() + } + pub fn check(&self, d: &types_api2::Word5) -> ResCheckErr { + TypesCheckErr::check_length(d.len(), self.d.len())?; + for i in 0..d.len() { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Word6 { + types_api::Word6::new_builder() + .set(self.d.clone().map(|f| f.to_mol2())) + .build() + } + pub fn check(&self, d: &types_api2::Word6) -> ResCheckErr { + TypesCheckErr::check_length(d.len(), self.d.len())?; + for i in 0..d.len() { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Word7 { + types_api::Word7::new_builder() + .set(self.d.clone().map(|f| f.to_mol2())) + .build() + } + pub fn check(&self, d: &types_api2::Word7) -> ResCheckErr { + TypesCheckErr::check_length(d.len(), self.d.len())?; + for i in 0..d.len() { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesArray { + pub fn to_mol(&self) -> types_api::Word8 { + types_api::Word8::new_builder() + .set(self.d.clone().map(|f| f.to_mol2())) + .build() + } + pub fn check(&self, d: &types_api2::Word8) -> ResCheckErr { + TypesCheckErr::check_length(d.len(), self.d.len())?; + for i in 0..d.len() { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesArray, 3> { + pub fn to_mol(&self) -> types_api::Byte3x3 { + types_api::Byte3x3::new_builder() + .set(self.d.clone().map(|f| f.to_mol())) + .build() + } + pub fn check(&self, d: &types_api2::Byte3x3) -> ResCheckErr { + TypesCheckErr::check_length(d.len(), self.d.len())?; + for i in 0..d.len() { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesArray, 3> { + pub fn to_mol(&self) -> types_api::Byte5x3 { + types_api::Byte5x3::new_builder() + .set(self.d.clone().map(|f| f.to_mol())) + .build() + } + + pub fn check(&self, d: &types_api2::Byte5x3) -> ResCheckErr { + TypesCheckErr::check_length(d.len(), self.d.len())?; + for i in 0..d.len() { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesArray, 3> { + pub fn to_mol(&self) -> types_api::Byte7x3 { + types_api::Byte7x3::new_builder() + .set(self.d.clone().map(|f| f.to_mol())) + .build() + } + pub fn check(&self, d: &types_api2::Byte7x3) -> ResCheckErr { + TypesCheckErr::check_length(d.len(), self.d.len())?; + for i in 0..d.len() { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesArray, 3> { + pub fn to_mol(&self) -> types_api::Byte9x3 { + types_api::Byte9x3::new_builder() + .set(self.d.clone().map(|f| f.to_mol())) + .build() + } + pub fn check(&self, d: &types_api2::Byte9x3) -> ResCheckErr { + TypesCheckErr::check_length(d.len(), self.d.len())?; + for i in 0..d.len() { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} diff --git a/examples/lazy-reader-tests/src/types_moleculec_check.rs b/examples/lazy-reader-tests/src/types_moleculec_check.rs new file mode 100644 index 0000000..78146e4 --- /dev/null +++ b/examples/lazy-reader-tests/src/types_moleculec_check.rs @@ -0,0 +1,742 @@ +use crate::{types_api, types_api2, Mol2Vec, ResCheckErr, TypesCheckErr}; +use molecule::lazy_reader::Cursor; +use molecule::prelude::Byte; + +pub fn check_mol(d1: &types_api::AllInOne, d2: &types_api2::AllInOne) -> ResCheckErr { + check_f0(&d1.f0(), &d2.f0()?.into())?; + check_f1(&d1.f1(), &Cursor::try_from(d2.f1()?)?.into())?; + check_f2(&d1.f2(), &Cursor::try_from(d2.f2()?)?.into())?; + check_f3(&d1.f3(), &Cursor::try_from(d2.f3()?)?.into())?; + check_f4(&d1.f4(), &Cursor::try_from(d2.f4()?)?.into())?; + check_f5(&d1.f5(), &Cursor::try_from(d2.f5()?)?.into())?; + check_f6(&d1.f6(), &Cursor::try_from(d2.f6()?)?.into())?; + check_f7(&d1.f7(), &Cursor::try_from(d2.f7()?)?.into())?; + check_f8(&d1.f8(), &Cursor::try_from(d2.f8()?)?.into())?; + check_f9(&d1.f9(), &Cursor::try_from(d2.f9()?)?.into())?; + check_f10(&d1.f10(), &Cursor::try_from(d2.f10()?)?.into())?; + check_f11(&d1.f11(), &Cursor::try_from(d2.f11()?)?.into())?; + check_f12(&d1.f12(), &Cursor::try_from(d2.f12()?)?.into())?; + check_f13(&d1.f13(), &Cursor::try_from(d2.f13()?)?.into())?; + check_f14(&d1.f14(), &Cursor::try_from(d2.f14()?)?.into())?; + check_f15(&d1.f15(), &Cursor::try_from(d2.f15()?)?.into())?; + + check_f16(&d1.f16(), &Cursor::try_from(d2.f16()?)?.into())?; + check_f17(&d1.f17(), &d2.f17()?.into())?; + check_f18(&d1.f18(), &d2.f18()?.into())?; + check_f19(&d1.f19(), &d2.f19()?.into())?; + check_f20(&d1.f20(), &d2.f20()?.into())?; + check_f21(&d1.f21(), &d2.f21()?.into())?; + check_f22(&d1.f22(), &d2.f22()?.into())?; + check_f23(&d1.f23(), &d2.f23()?.into())?; + + check_f24(&d1.f24(), &d2.f24()?.into())?; + check_f25(&d1.f25(), &d2.f25()?.into())?; + check_f26(&d1.f26(), &d2.f26()?.into())?; + check_f27(&d1.f27(), &d2.f27()?.into())?; + + check_f28(&d1.f28(), &d2.f28()?.into())?; + check_f29(&d1.f29(), &d2.f29()?.into())?; + check_f30(&d1.f30(), &d2.f30()?.into())?; + check_f31(&d1.f31(), &d2.f31()?.into())?; + check_f32(&d1.f32(), &d2.f32()?.into())?; + check_f33(&d1.f33(), &d2.f33()?.into())?; + check_f34(&d1.f34(), &d2.f34()?.into())?; + check_f35(&d1.f35(), &d2.f35()?.into())?; + check_f36(&d1.f36(), &d2.f36()?.into())?; + check_f37(&d1.f37(), &d2.f37()?.into())?; + check_f38(&d1.f38(), &d2.f38()?.into())?; + check_f39(&d1.f39(), &d2.f39()?.into())?; + check_f40(&d1.f40(), &d2.f40()?.into())?; + + check_f41(&d1.f41(), &d2.f41()?)?; + check_f42(&d1.f42(), &d2.f42()?.into())?; + check_f43(&d1.f43(), &d2.f43()?.into())?; + check_f44(&d1.f44(), &d2.f44()?.into())?; + check_f45(&d1.f45(), &d2.f45()?.into())?; + check_f46(&d1.f46(), &d2.f46()?.into())?; + check_f47(&d1.f47(), &d2.f47()?.into())?; + check_f48(&d1.f48(), &d2.f48()?.into())?; + check_f49(&d1.f49(), &d2.f49()?.into())?; + + check_f50(&d1.f50(), &d2.f50()?.into())?; + check_f51(&d1.f51(), &d2.f51()?.into())?; + check_f52(&d1.f52(), &d2.f52()?.into())?; + check_f53(&d1.f53(), &d2.f53()?.into())?; + check_f54(&d1.f54(), &d2.f54()?.into())?; + check_f55(&d1.f55(), &d2.f55()?.into())?; + check_f56(&d1.f56(), &d2.f56()?.into())?; + + check_f57(&d1.f57().to_opt(), &d2.f57()?)?; + check_f58( + &d1.f58().to_opt(), + &d2.f58()?.map(|f| Cursor::try_from(f).unwrap().into()), + )?; + check_f59(&d1.f59().to_opt(), &d2.f59()?)?; + check_f60(&d1.f60().to_opt(), &d2.f60()?)?; + check_f61( + &d1.f61().to_opt(), + &d2.f61()?.map(|f| f.try_into().unwrap()), + )?; + check_f62(&d1.f62().to_opt(), &d2.f62()?)?; + check_f63(&d1.f63().to_opt(), &d2.f63()?)?; + check_f64(&d1.f64().to_opt(), &d2.f64()?)?; + check_f65(&d1.f65().to_opt(), &d2.f65()?)?; + check_f66(&d1.f66().to_opt(), &d2.f66()?)?; + check_f67(&d1.f67().to_opt().map(|f| f.to_opt()), &d2.f67()?)?; + + check_f68(&d1.f68(), &d2.f68()?)?; + check_f69(&d1.f69(), &d2.f69()?)?; + check_f70(&d1.f70(), &d2.f70()?)?; + check_f71(&d1.f71(), &d2.f71()?)?; + + check_f72(&d1.f72(), &d2.f72()?)?; + check_f73(&d1.f73(), &d2.f73()?)?; + check_f74(&d1.f74(), &d2.f74()?)?; + + Ok(()) +} + +pub fn try_get_vec(t: &T) -> ResCheckErr { + for i in 0..t.mol_len()? { + t.mol_get(i)?; + } + Ok(()) +} + +pub fn check_f0(d1: &Byte, d2: &Byte) -> ResCheckErr { + TypesCheckErr::check_1_data(d1, d2) +} +pub fn check_f1(d1: &types_api::Byte2, d2: &types_api2::Byte2) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f2(d1: &types_api::Byte3, d2: &types_api2::Byte3) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f3(d1: &types_api::Byte4, d2: &types_api2::Byte4) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f4(d1: &types_api::Byte5, d2: &types_api2::Byte5) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f5(d1: &types_api::Byte6, d2: &types_api2::Byte6) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f6(d1: &types_api::Byte7, d2: &types_api2::Byte7) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f7(d1: &types_api::Byte8, d2: &types_api2::Byte8) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f8(d1: &types_api::Byte9, d2: &types_api2::Byte9) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f9(d1: &types_api::Byte10, d2: &types_api2::Byte10) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f10(d1: &types_api::Byte11, d2: &types_api2::Byte11) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f11(d1: &types_api::Byte12, d2: &types_api2::Byte12) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f12(d1: &types_api::Byte13, d2: &types_api2::Byte13) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f13(d1: &types_api::Byte14, d2: &types_api2::Byte14) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f14(d1: &types_api::Byte15, d2: &types_api2::Byte15) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f15(d1: &types_api::Byte16, d2: &types_api2::Byte16) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f16(d1: &types_api::Word, d2: &types_api2::Word) -> ResCheckErr { + TypesCheckErr::check_mol_data(d1, d2) +} +pub fn check_f17(d1: &types_api::Word2, d2: &types_api2::Word2) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f18(d1: &types_api::Word3, d2: &types_api2::Word3) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f19(d1: &types_api::Word4, d2: &types_api2::Word4) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f20(d1: &types_api::Word5, d2: &types_api2::Word5) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f21(d1: &types_api::Word6, d2: &types_api2::Word6) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f22(d1: &types_api::Word7, d2: &types_api2::Word7) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f23(d1: &types_api::Word8, d2: &types_api2::Word8) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f24(d1: &types_api::Byte3x3, d2: &types_api2::Byte3x3) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f25(d1: &types_api::Byte5x3, d2: &types_api2::Byte5x3) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f26(d1: &types_api::Byte7x3, d2: &types_api2::Byte7x3) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f27(d1: &types_api::Byte9x3, d2: &types_api2::Byte9x3) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f28(d1: &types_api::StructA, d2: &types_api2::StructA) -> ResCheckErr { + check_f0(&d1.f1(), &d2.f1()?.into())?; + check_f0(&d1.f2(), &d2.f2()?.into())?; + check_f1(&d1.f3(), &Cursor::try_from(d2.f3()?)?.into())?; + check_f1(&d1.f4(), &Cursor::try_from(d2.f4()?)?.into())?; + + Ok(()) +} +pub fn check_f29(d1: &types_api::StructB, d2: &types_api2::StructB) -> ResCheckErr { + check_f0(&d1.f1(), &d2.f1()?.into())?; + check_f0(&d1.f2(), &d2.f2()?.into())?; + check_f1(&d1.f3(), &Cursor::try_from(d2.f3()?)?.into())?; + check_f2(&d1.f4(), &Cursor::try_from(d2.f4()?)?.into())?; + + Ok(()) +} +pub fn check_f30(d1: &types_api::StructC, d2: &types_api2::StructC) -> ResCheckErr { + check_f0(&d1.f1(), &d2.f1()?.into())?; + check_f0(&d1.f2(), &d2.f2()?.into())?; + check_f1(&d1.f3(), &Cursor::try_from(d2.f3()?)?.into())?; + check_f3(&d1.f4(), &Cursor::try_from(d2.f4()?)?.into())?; + + Ok(()) +} +pub fn check_f31(d1: &types_api::StructD, d2: &types_api2::StructD) -> ResCheckErr { + check_f0(&d1.f1(), &d2.f1()?.into())?; + check_f0(&d1.f2(), &d2.f2()?.into())?; + check_f1(&d1.f3(), &Cursor::try_from(d2.f3()?)?.into())?; + check_f4(&d1.f4(), &Cursor::try_from(d2.f4()?)?.into())?; + + Ok(()) +} +pub fn check_f32(d1: &types_api::StructE, d2: &types_api2::StructE) -> ResCheckErr { + check_f0(&d1.f1(), &d2.f1()?.into())?; + check_f1(&d1.f2(), &Cursor::try_from(d2.f2()?)?.into())?; + check_f0(&d1.f3(), &d2.f3()?.into())?; + check_f1(&d1.f4(), &Cursor::try_from(d2.f4()?)?.into())?; + + Ok(()) +} +pub fn check_f33(d1: &types_api::StructF, d2: &types_api2::StructF) -> ResCheckErr { + check_f0(&d1.f1(), &d2.f1()?.into())?; + check_f2(&d1.f2(), &Cursor::try_from(d2.f2()?)?.into())?; + check_f0(&d1.f3(), &d2.f3()?.into())?; + + Ok(()) +} +pub fn check_f34(d1: &types_api::StructG, d2: &types_api2::StructG) -> ResCheckErr { + check_f2(&d1.f1(), &Cursor::try_from(d2.f1()?)?.into())?; + check_f0(&d1.f2(), &d2.f2()?.into())?; + check_f1(&d1.f3(), &Cursor::try_from(d2.f3()?)?.into())?; + check_f17(&d1.f4(), &d2.f4()?.into())?; + + Ok(()) +} +pub fn check_f35(d1: &types_api::StructH, d2: &types_api2::StructH) -> ResCheckErr { + check_f2(&d1.f1(), &Cursor::try_from(d2.f1()?)?.into())?; + check_f0(&d1.f2(), &d2.f2()?.into())?; + check_f1(&d1.f3(), &Cursor::try_from(d2.f3()?)?.into())?; + check_f3(&d1.f4(), &Cursor::try_from(d2.f4()?)?.into())?; + + Ok(()) +} +pub fn check_f36(d1: &types_api::StructI, d2: &types_api2::StructI) -> ResCheckErr { + check_f2(&d1.f1(), &Cursor::try_from(d2.f1()?)?.into())?; + check_f0(&d1.f2(), &d2.f2()?.into())?; + + Ok(()) +} +pub fn check_f37(d1: &types_api::StructJ, d2: &types_api2::StructJ) -> ResCheckErr { + check_f5(&d1.f1(), &Cursor::try_from(d2.f1()?)?.into())?; + check_f0(&d1.f2(), &d2.f2()?.into())?; + + Ok(()) +} +pub fn check_f38(d1: &types_api::StructIx3, d2: &types_api2::StructIx3) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len())?; + for i in 0..d1.mol_len()? { + check_f36(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + + Ok(()) +} +pub fn check_f39(d1: &types_api::StructO, d2: &types_api2::StructO) -> ResCheckErr { + check_f38(&d1.f1(), &d2.f1()?.into())?; + check_f0(&d1.f2(), &d2.f2()?.into())?; + + Ok(()) +} +pub fn check_f40(d1: &types_api::StructP, d2: &types_api2::StructP) -> ResCheckErr { + check_f37(&d1.f1(), &d2.f1()?.into())?; + check_f0(&d1.f2(), &d2.f2()?.into())?; + + Ok(()) +} +pub fn check_f41(d1: &types_api::Bytes, d2: &Cursor) -> ResCheckErr { + d2.verify_fixed_size(d1.len())?; + let d2: Vec = d2.clone().try_into().unwrap(); + TypesCheckErr::check_mol_data(d1, &d2) +} +pub fn check_f42(d1: &types_api::Words, d2: &types_api2::Words) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f43(d1: &types_api::Byte3Vec, d2: &types_api2::Byte3Vec) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f44(d1: &types_api::Byte7Vec, d2: &types_api2::Byte7Vec) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + TypesCheckErr::check_mol_data(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f45(d1: &types_api::StructIVec, d2: &types_api2::StructIVec) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + check_f36(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f46(d1: &types_api::StructJVec, d2: &types_api2::StructJVec) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + check_f37(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f47(d1: &types_api::StructPVec, d2: &types_api2::StructPVec) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + check_f40(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f48(d1: &types_api::BytesVec, d2: &types_api2::BytesVec) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + check_f41(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f49(d1: &types_api::WordsVec, d2: &types_api2::WordsVec) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + check_f42(&d1.mol_get(i)?, &d2.mol_get(i)?)?; + } + Ok(()) +} +pub fn check_f50(_d1: &types_api::Table0, _d2: &types_api2::Table0) -> ResCheckErr { + // assert!(!d2.cursor.table_has_extra_fields(0)?); + Ok(()) +} +pub fn check_f51(d1: &types_api::Table1, d2: &types_api2::Table1) -> ResCheckErr { + assert!(d2.cursor.table_has_extra_fields(0)?); + check_f0(&d1.f1(), &d2.f1()?.into())?; + Ok(()) +} +pub fn check_f52(d1: &types_api::Table2, d2: &types_api2::Table2) -> ResCheckErr { + assert!(d2.cursor.table_has_extra_fields(1)?); + check_f0(&d1.f1(), &d2.f1()?.into())?; + check_f17(&d1.f2(), &d2.f2()?.into())?; + Ok(()) +} +pub fn check_f53(d1: &types_api::Table3, d2: &types_api2::Table3) -> ResCheckErr { + assert!(d2.cursor.table_has_extra_fields(2)?); + check_f0(&d1.f1(), &d2.f1()?.into())?; + check_f17(&d1.f2(), &d2.f2()?.into())?; + check_f28(&d1.f3(), &d2.f3()?.into())?; + Ok(()) +} +pub fn check_f54(d1: &types_api::Table4, d2: &types_api2::Table4) -> ResCheckErr { + assert!(d2.cursor.table_has_extra_fields(3)?); + check_f0(&d1.f1(), &d2.f1()?.into())?; + check_f17(&d1.f2(), &d2.f2()?.into())?; + check_f28(&d1.f3(), &d2.f3()?.into())?; + check_f41(&d1.f4(), &d2.f4()?.try_into().unwrap())?; + Ok(()) +} +pub fn check_f55(d1: &types_api::Table5, d2: &types_api2::Table5) -> ResCheckErr { + assert!(d2.cursor.table_has_extra_fields(4)?); + check_f0(&d1.f1(), &d2.f1()?.into())?; + check_f17(&d1.f2(), &d2.f2()?.into())?; + check_f28(&d1.f3(), &d2.f3()?.into())?; + check_f41(&d1.f4(), &d2.f4()?.try_into().unwrap())?; + check_f48(&d1.f5(), &d2.f5()?.into())?; + Ok(()) +} +pub fn check_f56(d1: &types_api::Table6, d2: &types_api2::Table6) -> ResCheckErr { + assert!(d2.cursor.table_has_extra_fields(5)?); + check_f0(&d1.f1(), &d2.f1()?.into())?; + check_f17(&d1.f2(), &d2.f2()?.into())?; + check_f28(&d1.f3(), &d2.f3()?.into())?; + check_f41(&d1.f4(), &d2.f4()?.try_into().unwrap())?; + check_f48(&d1.f5(), &d2.f5()?.into())?; + check_f55(&d1.f6(), &d2.f6()?.into())?; + Ok(()) +} +pub fn check_f57(d1: &Option, d2: &Option) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + if d1.is_none() { + return Ok(()); + } + + TypesCheckErr::check_1_data(d1.as_ref().unwrap(), &d2.as_ref().unwrap().clone().into())?; + + Ok(()) +} +pub fn check_f58(d1: &Option, d2: &Option) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + if d1.is_none() { + return Ok(()); + } + + check_f16(d1.as_ref().unwrap(), d2.as_ref().unwrap())?; + + Ok(()) +} +pub fn check_f59(d1: &Option, d2: &Option) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + if d1.is_none() { + return Ok(()); + } + + check_f28(d1.as_ref().unwrap(), d2.as_ref().unwrap())?; + + Ok(()) +} +pub fn check_f60(d1: &Option, d2: &Option) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + if d1.is_none() { + return Ok(()); + } + + check_f40(d1.as_ref().unwrap(), d2.as_ref().unwrap())?; + + Ok(()) +} +pub fn check_f61(d1: &Option, d2: &Option) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + if d1.is_none() { + return Ok(()); + } + + check_f41(d1.as_ref().unwrap(), d2.as_ref().unwrap())?; + + Ok(()) +} +pub fn check_f62(d1: &Option, d2: &Option) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + if d1.is_none() { + return Ok(()); + } + + check_f42(d1.as_ref().unwrap(), d2.as_ref().unwrap())?; + + Ok(()) +} +pub fn check_f63( + d1: &Option, + d2: &Option, +) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + if d1.is_none() { + return Ok(()); + } + + check_f48(d1.as_ref().unwrap(), d2.as_ref().unwrap())?; + + Ok(()) +} +pub fn check_f64( + d1: &Option, + d2: &Option, +) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + if d1.is_none() { + return Ok(()); + } + + check_f49(d1.as_ref().unwrap(), d2.as_ref().unwrap())?; + + Ok(()) +} +pub fn check_f65(d1: &Option, d2: &Option) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + if d1.is_none() { + return Ok(()); + } + + check_f50(d1.as_ref().unwrap(), d2.as_ref().unwrap())?; + + Ok(()) +} +pub fn check_f66(d1: &Option, d2: &Option) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + if d1.is_none() { + return Ok(()); + } + + check_f56(d1.as_ref().unwrap(), d2.as_ref().unwrap())?; + + Ok(()) +} +pub fn check_f67( + d1: &Option>, + d2: &Option>, +) -> ResCheckErr { + if d1.is_some() != d2.is_some() { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + d1.is_some(), + d2.is_some() + ))); + } + if d1.is_none() { + return Ok(()); + } + + check_f66(d1.as_ref().unwrap(), d2.as_ref().unwrap())?; + + Ok(()) +} +pub fn check_f68(d1: &types_api::ByteOptVec, d2: &types_api2::ByteOptVec) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + let dd1 = d1.mol_get(i)?.to_opt(); + let dd2 = d2.get(i)?; + check_f57(&dd1, &dd2)?; + } + Ok(()) +} +pub fn check_f69(d1: &types_api::WordOptVec, d2: &types_api2::WordOptVec) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + let dd1 = d1.mol_get(i)?.to_opt(); + let dd2 = d2.get(i)?.map(|f| Cursor::try_from(f).unwrap().into()); + check_f58(&dd1, &dd2)?; + } + Ok(()) +} +pub fn check_f70(d1: &types_api::WordsOptVec, d2: &types_api2::WordsOptVec) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + let dd1 = d1.mol_get(i)?.to_opt(); + let dd2 = d2.get(i)?.map(|f| f.into()); + check_f62(&dd1, &dd2)?; + } + Ok(()) +} +pub fn check_f71(d1: &types_api::BytesOptVec, d2: &types_api2::BytesOptVec) -> ResCheckErr { + TypesCheckErr::check_length(d1.mol_len()?, d2.len()?)?; + for i in 0..d1.mol_len()? { + let dd1 = d1.mol_get(i)?.to_opt(); + let dd2 = d2.get(i)?.map(|f| f.try_into().unwrap()); + check_f61(&dd1, &dd2)?; + } + Ok(()) +} +pub fn check_f72(d1: &types_api::UnionA, d2: &types_api2::UnionA) -> ResCheckErr { + match d1.to_enum() { + types_api::UnionAUnion::Byte(v) => match d2 { + types_api2::UnionA::Byte(v2) => TypesCheckErr::check_1_data(&v, &v2.clone().into())?, + _ => return Err(TypesCheckErr::Data(format!("check union type is failed"))), + }, + types_api::UnionAUnion::Word(v) => match d2 { + types_api2::UnionA::Word(v2) => check_f16(&v, v2)?, + _ => return Err(TypesCheckErr::Data(format!("check union type is failed"))), + }, + types_api::UnionAUnion::StructA(v) => match d2 { + types_api2::UnionA::StructA(v2) => check_f28(&v, &v2)?, + _ => return Err(TypesCheckErr::Data(format!("check union type is failed"))), + }, + types_api::UnionAUnion::Bytes(v) => match d2 { + types_api2::UnionA::Bytes(v2) => check_f41(&v, &v2)?, + _ => return Err(TypesCheckErr::Data(format!("check union type is failed"))), + }, + types_api::UnionAUnion::Words(v) => match d2 { + types_api2::UnionA::Words(v2) => check_f42(&v, &v2)?, + _ => return Err(TypesCheckErr::Data(format!("check union type is failed"))), + }, + types_api::UnionAUnion::Table0(v) => match d2 { + types_api2::UnionA::Table0(v2) => check_f50(&v, v2)?, + _ => return Err(TypesCheckErr::Data(format!("check union type is failed"))), + }, + types_api::UnionAUnion::Table6(v) => match d2 { + types_api2::UnionA::Table6(v2) => check_f56(&v, v2)?, + _ => return Err(TypesCheckErr::Data(format!("check union type is failed"))), + }, + types_api::UnionAUnion::Table6Opt(v) => match d2 { + types_api2::UnionA::Table6Opt(v2) => check_f66(&v.to_opt(), v2)?, + _ => return Err(TypesCheckErr::Data(format!("check union type is failed"))), + }, + }; + + Ok(()) +} +pub fn check_f73(d1: &types_api::TableA, d2: &types_api2::TableA) -> ResCheckErr { + check_f17(&d1.f1(), &d2.f1()?.into())?; + check_f28(&d1.f2(), &d2.f2()?.into())?; + check_f41(&d1.f3(), &d2.f3()?.try_into().unwrap())?; + check_f48(&d1.f4(), &d2.f4()?)?; + check_f51(&d1.f5(), &d2.f5()?)?; + check_f61(&d1.f6().to_opt(), &d2.f6()?.map(|f| f.try_into().unwrap()))?; + check_f72(&d1.f7(), &d2.f7()?)?; + Ok(()) +} +pub fn check_f74(d1: &types_api::TableB, d2: &types_api2::TableB) -> ResCheckErr { + check_f0(&d1.f1().nth0(), &d2.f1()?.into())?; + check_f0(&d1.f2().nth0(), &(d2.f2()? as u8).into())?; + + TypesCheckErr::check_1_data( + &u16::from_le_bytes(d1.f3().raw_data().to_vec().try_into().unwrap()), + &d2.f3()?, + )?; + TypesCheckErr::check_1_data( + &i16::from_le_bytes(d1.f4().raw_data().to_vec().try_into().unwrap()), + &d2.f4()?, + )?; + + TypesCheckErr::check_1_data( + &u32::from_le_bytes(d1.f5().raw_data().to_vec().try_into().unwrap()), + &d2.f5()?, + )?; + + TypesCheckErr::check_1_data( + &i32::from_le_bytes(d1.f6().raw_data().to_vec().try_into().unwrap()), + &d2.f6()?, + )?; + + TypesCheckErr::check_1_data( + &u64::from_le_bytes(d1.f7().raw_data().to_vec().try_into().unwrap()), + &d2.f7()?, + )?; + + TypesCheckErr::check_1_data( + &i64::from_le_bytes(d1.f8().raw_data().to_vec().try_into().unwrap()), + &d2.f8()?, + )?; + + Ok(()) +} diff --git a/examples/lazy-reader-tests/src/types_option.rs b/examples/lazy-reader-tests/src/types_option.rs new file mode 100644 index 0000000..c715c3b --- /dev/null +++ b/examples/lazy-reader-tests/src/types_option.rs @@ -0,0 +1,227 @@ +use super::{ + BaseTypes, ResCheckErr, TypesArrayWord, TypesCheckErr, TypesConfig, TypesStructA, TypesStructP, + TypesTable0, TypesTable6, TypesVec, +}; +use crate::{types_api, types_api2}; +use molecule::lazy_reader::Cursor; +use molecule::prelude::{Builder, Entity}; +use rand::{rngs::ThreadRng, thread_rng, Rng}; + +pub struct TypesOption { + d: Option, +} +impl BaseTypes for TypesOption { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + let fill = if config.min_size { + false + } else { + match config.option_fill { + super::OptionFillType::FillRand => rng.gen(), + super::OptionFillType::FillSome => true, + super::OptionFillType::FillNone => false, + } + }; + if fill { + Self { + d: Some(T::new_rng(rng, config)), + } + } else { + Self { d: None } + } + } +} +impl Default for TypesOption { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} + +impl TypesOption { + pub fn new_none() -> Self { + Self { d: None } + } +} + +impl TypesOption { + pub fn to_mol(&self) -> types_api::ByteOpt { + types_api::ByteOpt::new_builder() + .set(self.d.map(|f| f.into())) + .build() + } + + pub fn check(&self, d: &Option) -> ResCheckErr { + TypesCheckErr::check_option(d, &self.d)?; + if d.is_none() { + return Ok(()); + } + TypesCheckErr::check_1_data(d.as_ref().unwrap(), self.d.as_ref().unwrap()) + } +} +impl TypesOption { + pub fn to_mol(&self) -> types_api::WordOpt { + types_api::WordOpt::new_builder() + .set(self.d.map(|f| f.to_mol2())) + .build() + } + + pub fn check(&self, d: &Option) -> ResCheckErr { + TypesCheckErr::check_option(d, &self.d)?; + if d.is_none() { + return Ok(()); + } + self.d + .as_ref() + .unwrap() + .check2(&d.as_ref().unwrap().clone().into()) + } +} +impl TypesOption { + pub fn to_mol(&self) -> types_api::StructAOpt { + types_api::StructAOpt::new_builder() + .set(self.d.map(|f| f.to_mol())) + .build() + } + + pub fn check(&self, d: &Option) -> ResCheckErr { + TypesCheckErr::check_option(d, &self.d)?; + if d.is_none() { + return Ok(()); + } + self.d.as_ref().unwrap().check(d.as_ref().unwrap()) + } +} +impl TypesOption { + pub fn to_mol(&self) -> types_api::StructPOpt { + types_api::StructPOpt::new_builder() + .set(self.d.map(|f| f.to_mol())) + .build() + } + + pub fn check(&self, d: &Option) -> ResCheckErr { + TypesCheckErr::check_option(d, &self.d)?; + if d.is_none() { + return Ok(()); + } + self.d.as_ref().unwrap().check(d.as_ref().unwrap()) + } +} +impl TypesOption> { + pub fn to_mol(&self) -> types_api::BytesOpt { + types_api::BytesOpt::new_builder() + .set(self.d.as_ref().map(|f| f.to_mol())) + .build() + } + + pub fn check(&self, d: &Option) -> ResCheckErr { + TypesCheckErr::check_option(d, &self.d)?; + if d.is_none() { + return Ok(()); + } + self.d + .as_ref() + .unwrap() + .check(&d.as_ref().unwrap().clone().try_into().unwrap()) + } +} +impl TypesOption> { + pub fn to_mol(&self) -> types_api::WordsOpt { + types_api::WordsOpt::new_builder() + .set(self.d.as_ref().map(|f| f.to_mol())) + .build() + } + + pub fn check(&self, d: &Option) -> ResCheckErr { + TypesCheckErr::check_option(d, &self.d)?; + if d.is_none() { + return Ok(()); + } + self.d.as_ref().unwrap().check(&d.as_ref().unwrap()) + } +} +impl TypesOption>> { + pub fn to_mol(&self) -> types_api::BytesVecOpt { + types_api::BytesVecOpt::new_builder() + .set(self.d.as_ref().map(|f| f.to_mol())) + .build() + } + + pub fn check(&self, d: &Option) -> ResCheckErr { + TypesCheckErr::check_option(d, &self.d)?; + if d.is_none() { + return Ok(()); + } + self.d.as_ref().unwrap().check(d.as_ref().unwrap()) + } +} +impl TypesOption>> { + pub fn to_mol(&self) -> types_api::WordsVecOpt { + types_api::WordsVecOpt::new_builder() + .set(self.d.as_ref().map(|f| f.to_mol())) + .build() + } + + pub fn check(&self, d: &Option) -> ResCheckErr { + TypesCheckErr::check_option(d, &self.d)?; + if d.is_none() { + return Ok(()); + } + self.d.as_ref().unwrap().check(d.as_ref().unwrap()) + } +} +impl TypesOption { + pub fn to_mol(&self) -> types_api::Table0Opt { + types_api::Table0Opt::new_builder() + .set(self.d.as_ref().map(|f| f.to_mol())) + .build() + } + + pub fn check(&self, d: &Option) -> ResCheckErr { + TypesCheckErr::check_option(d, &self.d)?; + if d.is_none() { + return Ok(()); + } + self.d.as_ref().unwrap().check(d.as_ref().unwrap()) + } +} +impl TypesOption { + pub fn to_mol(&self) -> types_api::Table6Opt { + types_api::Table6Opt::new_builder() + .set(self.d.as_ref().map(|f| f.to_mol())) + .build() + } + + pub fn check(&self, d: &Option) -> ResCheckErr { + TypesCheckErr::check_option(d, &self.d)?; + if d.is_none() { + return Ok(()); + } + self.d.as_ref().unwrap().check(d.as_ref().unwrap()) + } +} +impl TypesOption> { + pub fn to_mol(&self) -> types_api::Table6OptOpt { + types_api::Table6OptOpt::new_builder() + .set(self.d.as_ref().map(|f| f.to_mol())) + .build() + } + + pub fn check(&self, d: &Option>) -> ResCheckErr { + let f1_flag = d.is_some() && d.as_ref().is_none(); + let f2_flag = self.d.is_some() && self.d.as_ref().is_none(); + if f1_flag != f2_flag { + return Err(TypesCheckErr::Opt(format!( + "different option: {:?} {:?}", + f1_flag, f2_flag + ))); + } + if !f1_flag { + return Ok(()); + } + + TypesCheckErr::check_option(d, &self.d)?; + if d.is_none() { + return Ok(()); + } + self.d.as_ref().unwrap().check(d.as_ref().unwrap()) + } +} diff --git a/examples/lazy-reader-tests/src/types_struct.rs b/examples/lazy-reader-tests/src/types_struct.rs new file mode 100644 index 0000000..16efa2a --- /dev/null +++ b/examples/lazy-reader-tests/src/types_struct.rs @@ -0,0 +1,282 @@ +use super::*; +use crate::{types_api, types_api2}; +use molecule::prelude::{Builder, Entity}; +use rand::rngs::ThreadRng; + +#[derive(Clone, Copy)] +pub struct TypesStructBytes { + pub f1: T1, + pub f2: T2, + pub f3: T3, + pub f4: T4, +} + +impl BaseTypes + for TypesStructBytes +{ + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + Self { + f1: T1::new_rng(rng, config), + f2: T2::new_rng(rng, config), + f3: T3::new_rng(rng, config), + f4: T4::new_rng(rng, config), + } + } +} + +impl Default + for TypesStructBytes +{ + fn default() -> Self { + let mut rng = rand::thread_rng(); + let config = TypesConfig::default(); + Self { + f1: T1::new_rng(&mut rng, &config), + f2: T2::new_rng(&mut rng, &config), + f3: T3::new_rng(&mut rng, &config), + f4: T4::new_rng(&mut rng, &config), + } + } +} + +pub type TypesStructA = + TypesStructBytes, TypesArray, TypesArray, TypesArray>; +impl TypesStructA { + pub fn to_mol(&self) -> types_api::StructA { + types_api::StructA::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructA) -> ResCheckErr { + self.f1.check(&d.f1()?.into())?; + self.f2.check(&d.f2()?.into())?; + self.f3.check(&Cursor::try_from(d.f3()?)?.into())?; + self.f4.check(&Cursor::try_from(d.f4()?)?.into())?; + Ok(()) + } +} +pub type TypesStructB = + TypesStructBytes, TypesArray, TypesArray, TypesArray>; +impl TypesStructB { + pub fn to_mol(&self) -> types_api::StructB { + types_api::StructB::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructB) -> ResCheckErr { + self.f1.check(&d.f1()?.into())?; + self.f2.check(&d.f2()?.into())?; + self.f3.check(&Cursor::try_from(d.f3()?)?.into())?; + self.f4.check(&Cursor::try_from(d.f4()?)?.into())?; + Ok(()) + } +} + +pub type TypesStructC = + TypesStructBytes, TypesArray, TypesArray, TypesArray>; +impl TypesStructC { + pub fn to_mol(&self) -> types_api::StructC { + types_api::StructC::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructC) -> ResCheckErr { + self.f1.check(&d.f1()?.into())?; + self.f2.check(&d.f2()?.into())?; + self.f3.check(&Cursor::try_from(d.f3()?)?.into())?; + self.f4.check(&Cursor::try_from(d.f4()?)?.into())?; + Ok(()) + } +} + +pub type TypesStructD = + TypesStructBytes, TypesArray, TypesArray, TypesArray>; +impl TypesStructD { + pub fn to_mol(&self) -> types_api::StructD { + types_api::StructD::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructD) -> ResCheckErr { + self.f1.check(&d.f1()?.into())?; + self.f2.check(&d.f2()?.into())?; + self.f3.check(&Cursor::try_from(d.f3()?)?.into())?; + self.f4.check(&Cursor::try_from(d.f4()?)?.into())?; + Ok(()) + } +} + +pub type TypesStructE = + TypesStructBytes, TypesArray, TypesArray, TypesArray>; +impl TypesStructE { + pub fn to_mol(&self) -> types_api::StructE { + types_api::StructE::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructE) -> ResCheckErr { + self.f1.check(&d.f1()?.into())?; + self.f2.check(&Cursor::try_from(d.f2()?)?.into())?; + self.f3.check(&d.f3()?.into())?; + self.f4.check(&Cursor::try_from(d.f4()?)?.into())?; + Ok(()) + } +} + +pub type TypesStructF = + TypesStructBytes, TypesArray, TypesArray, TypesArray>; +impl TypesStructF { + pub fn to_mol(&self) -> types_api::StructF { + types_api::StructF::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructF) -> ResCheckErr { + self.f1.check(&d.f1()?.into())?; + self.f2.check(&Cursor::try_from(d.f2()?)?.into())?; + self.f3.check(&d.f3()?.into())?; + Ok(()) + } +} + +pub type TypesStructG = TypesStructBytes< + TypesArray, + TypesArray, + TypesArray, + TypesArray, +>; +impl TypesStructG { + pub fn to_mol(&self) -> types_api::StructG { + types_api::StructG::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructG) -> ResCheckErr { + self.f1.check(&Cursor::try_from(d.f1()?)?.into())?; + self.f2.check(&d.f2()?.into())?; + self.f3.check(&Cursor::try_from(d.f3()?)?.into())?; + self.f4.check(&d.f4()?.into())?; + Ok(()) + } +} + +pub type TypesStructH = + TypesStructBytes, TypesArray, TypesArray, TypesArray>; +impl TypesStructH { + pub fn to_mol(&self) -> types_api::StructH { + types_api::StructH::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructH) -> ResCheckErr { + self.f1.check(&Cursor::try_from(d.f1()?)?.into())?; + self.f2.check(&d.f2()?.into())?; + self.f3.check(&Cursor::try_from(d.f3()?)?.into())?; + self.f4.check(&Cursor::try_from(d.f4()?)?.into())?; + Ok(()) + } +} + +pub type TypesStructI = + TypesStructBytes, TypesArray, TypesArray, TypesArray>; +impl TypesStructI { + pub fn to_mol(&self) -> types_api::StructI { + types_api::StructI::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructI) -> ResCheckErr { + self.f1.check(&Cursor::try_from(d.f1()?)?.into())?; + self.f2.check(&d.f2()?.into())?; + Ok(()) + } +} + +pub type TypesStructJ = + TypesStructBytes, TypesArray, TypesArray, TypesArray>; +impl TypesStructJ { + pub fn to_mol(&self) -> types_api::StructJ { + types_api::StructJ::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructJ) -> ResCheckErr { + self.f1.check(&Cursor::try_from(d.f1()?)?.into())?; + self.f2.check(&d.f2()?.into())?; + Ok(()) + } +} + +pub type TypesStructIx3 = TypesArray; +impl TypesStructIx3 { + pub fn to_mol(&self) -> types_api::StructIx3 { + types_api::StructIx3::new_builder() + .set(self.d.clone().map(|f| f.to_mol())) + .build() + } + pub fn check(&self, d: &types_api2::StructIx3) -> ResCheckErr { + TypesCheckErr::check_length(d.len(), self.d.len())?; + for i in 0..d.len() { + let dd = d.get(i)?; + self.d[i].check(&dd)?; + } + Ok(()) + } +} + +pub type TypesStructO = + TypesStructBytes, TypesArray, TypesArray>; +impl TypesStructO { + pub fn to_mol(&self) -> types_api::StructO { + types_api::StructO::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructO) -> ResCheckErr { + self.f1.check(&d.f1()?.into())?; + self.f2.check(&d.f2()?.into())?; + Ok(()) + } +} + +pub type TypesStructP = + TypesStructBytes, TypesArray, TypesArray>; +impl TypesStructP { + pub fn to_mol(&self) -> types_api::StructP { + types_api::StructP::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::StructP) -> ResCheckErr { + self.f1.check(&d.f1()?.into())?; + self.f2.check(&d.f2()?.into())?; + Ok(()) + } +} diff --git a/examples/lazy-reader-tests/src/types_table.rs b/examples/lazy-reader-tests/src/types_table.rs new file mode 100644 index 0000000..27aaea8 --- /dev/null +++ b/examples/lazy-reader-tests/src/types_table.rs @@ -0,0 +1,374 @@ +use super::{ + BaseTypes, ResCheckErr, TypesArray, TypesArrayWord, TypesCheckErr, TypesConfig, TypesOption, + TypesStructA, TypesUnionA, TypesVec, +}; +use crate::{types_api, types_api2}; +use molecule::prelude::{Builder, Entity}; +use rand::{prelude::*, rngs::ThreadRng, thread_rng}; + +pub struct TypesTable0 {} +impl BaseTypes for TypesTable0 { + fn new_rng(_rng: &mut ThreadRng, _config: &TypesConfig) -> Self { + Self {} + } +} +impl Default for TypesTable0 { + fn default() -> Self { + Self {} + } +} +impl TypesTable0 { + pub fn to_mol(&self) -> types_api::Table0 { + types_api::Table0::new_builder().build() + } + pub fn check(&self, _d: &types_api2::Table0) -> ResCheckErr { + // TODO + Ok(()) + } +} + +pub struct TypesTable1 { + f1: TypesArray, +} +impl BaseTypes for TypesTable1 { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + Self { + f1: TypesArray::new_rng(rng, config), + } + } +} +impl Default for TypesTable1 { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} +impl TypesTable1 { + pub fn to_mol(&self) -> types_api::Table1 { + types_api::Table1::new_builder() + .f1(self.f1.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::Table1) -> ResCheckErr { + self.f1.check(&d.f1()?)?; + Ok(()) + } +} + +pub struct TypesTable2 { + f1: TypesArray, + f2: TypesArray, +} +impl BaseTypes for TypesTable2 { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + Self { + f1: TypesArray::new_rng(rng, config), + f2: TypesArray::new_rng(rng, config), + } + } +} +impl Default for TypesTable2 { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} +impl TypesTable2 { + pub fn to_mol(&self) -> types_api::Table2 { + types_api::Table2::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::Table2) -> ResCheckErr { + self.f1.check(&d.f1()?)?; + self.f2.check(&d.f2()?)?; + Ok(()) + } +} + +pub struct TypesTable3 { + f1: TypesArray, + f2: TypesArray, + f3: TypesStructA, +} +impl BaseTypes for TypesTable3 { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + Self { + f1: TypesArray::new_rng(rng, config), + f2: TypesArray::new_rng(rng, config), + f3: TypesStructA::new_rng(rng, config), + } + } +} +impl Default for TypesTable3 { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} +impl TypesTable3 { + pub fn to_mol(&self) -> types_api::Table3 { + types_api::Table3::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::Table3) -> ResCheckErr { + self.f1.check(&d.f1()?)?; + self.f2.check(&d.f2()?)?; + self.f3.check(&d.f3()?)?; + Ok(()) + } +} + +pub struct TypesTable4 { + f1: TypesArray, + f2: TypesArray, + f3: TypesStructA, + f4: TypesVec, +} +impl BaseTypes for TypesTable4 { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + Self { + f1: TypesArray::new_rng(rng, config), + f2: TypesArray::new_rng(rng, config), + f3: TypesStructA::new_rng(rng, config), + f4: TypesVec::new_rng(rng, config), + } + } +} +impl Default for TypesTable4 { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} +impl TypesTable4 { + pub fn to_mol(&self) -> types_api::Table4 { + types_api::Table4::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::Table4) -> ResCheckErr { + self.f1.check(&d.f1()?)?; + self.f2.check(&d.f2()?)?; + self.f3.check(&d.f3()?)?; + self.f4.check(&d.f4()?.try_into().unwrap())?; + Ok(()) + } +} + +pub struct TypesTable5 { + f1: TypesArray, + f2: TypesArray, + f3: TypesStructA, + f4: TypesVec, + f5: TypesVec>, +} +impl BaseTypes for TypesTable5 { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + Self { + f1: TypesArray::new_rng(rng, config), + f2: TypesArray::new_rng(rng, config), + f3: TypesStructA::new_rng(rng, config), + f4: TypesVec::new_rng(rng, config), + f5: TypesVec::new_rng(rng, config), + } + } +} +impl Default for TypesTable5 { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} +impl TypesTable5 { + pub fn to_mol(&self) -> types_api::Table5 { + types_api::Table5::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .f5(self.f5.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::Table5) -> ResCheckErr { + self.f1.check(&d.f1()?)?; + self.f2.check(&d.f2()?)?; + self.f3.check(&d.f3()?)?; + self.f4.check(&d.f4()?.try_into().unwrap())?; + self.f5.check(&d.f5()?.try_into().unwrap())?; + Ok(()) + } +} + +pub struct TypesTable6 { + f1: TypesArray, + f2: TypesArray, + f3: TypesStructA, + f4: TypesVec, + f5: TypesVec>, + f6: TypesTable5, +} +impl BaseTypes for TypesTable6 { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + Self { + f1: TypesArray::new_rng(rng, config), + f2: TypesArray::new_rng(rng, config), + f3: TypesStructA::new_rng(rng, config), + f4: TypesVec::new_rng(rng, config), + f5: TypesVec::new_rng(rng, config), + f6: TypesTable5::new_rng(rng, config), + } + } +} +impl Default for TypesTable6 { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} +impl TypesTable6 { + pub fn to_mol(&self) -> types_api::Table6 { + types_api::Table6::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .f5(self.f5.to_mol()) + .f6(self.f6.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::Table6) -> ResCheckErr { + self.f1.check(&d.f1()?)?; + self.f2.check(&d.f2()?)?; + self.f3.check(&d.f3()?)?; + self.f4.check(&d.f4()?.try_into().unwrap())?; + self.f5.check(&d.f5()?.try_into().unwrap())?; + self.f6.check(&d.f6()?.try_into().unwrap())?; + Ok(()) + } +} +pub struct TypesTableA { + f1: TypesArray, + f2: TypesStructA, + f3: TypesVec, + f4: TypesVec>, + f5: TypesTable1, + f6: TypesOption>, + f7: TypesUnionA, + f8: TypesArray, +} +impl BaseTypes for TypesTableA { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + Self { + f1: TypesArray::new_rng(rng, config), + f2: TypesStructA::new_rng(rng, config), + f3: TypesVec::new_rng(rng, config), + f4: TypesVec::new_rng(rng, config), + f5: TypesTable1::new_rng(rng, config), + f6: TypesOption::new_rng(rng, config), + f7: TypesUnionA::new_rng(rng, config), + f8: TypesArray::new_rng(rng, config), + } + } +} +impl Default for TypesTableA { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} +impl TypesTableA { + pub fn to_mol(&self) -> types_api::TableA { + types_api::TableA::new_builder() + .f1(self.f1.to_mol()) + .f2(self.f2.to_mol()) + .f3(self.f3.to_mol()) + .f4(self.f4.to_mol()) + .f5(self.f5.to_mol()) + .f6(self.f6.to_mol()) + .f7(self.f7.to_mol()) + .f8(self.f8.to_mol()) + .build() + } + pub fn check(&self, d: &types_api2::TableA) -> ResCheckErr { + self.f1.check(&d.f1()?)?; + self.f2.check(&d.f2()?)?; + self.f3.check(&d.f3()?.try_into().unwrap())?; + self.f4.check(&d.f4()?.try_into().unwrap())?; + self.f5.check(&d.f5()?.try_into().unwrap())?; + self.f6.check(&d.f6()?.try_into().unwrap())?; + Ok(()) + } +} + +pub struct TypesTableB { + f1: u8, + f2: i8, + f3: u16, + f4: i16, + f5: u32, + f6: i32, + f7: u64, + f8: i64, +} +impl BaseTypes for TypesTableB { + fn new_rng(rng: &mut ThreadRng, _config: &TypesConfig) -> Self { + Self { + f1: rng.gen(), + f2: rng.gen(), + f3: rng.gen(), + f4: rng.gen(), + f5: rng.gen(), + f6: rng.gen(), + f7: rng.gen(), + f8: rng.gen(), + } + } +} +impl Default for TypesTableB { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} +impl TypesTableB { + pub fn to_mol(&self) -> types_api::TableB { + types_api::TableB::new_builder() + .f1(types_api::Uint8::new_builder() + .set([self.f1.into()]) + .build()) + .f2(types_api::Int8::new_builder() + .set([(self.f2 as u8).into()]) + .build()) + .f3(types_api::Uint16::new_builder() + .set(self.f3.to_le_bytes().map(|f| f.into())) + .build()) + .f4(types_api::Int16::new_builder() + .set(self.f4.to_le_bytes().map(|f| f.into())) + .build()) + .f5(types_api::Uint32::new_builder() + .set(self.f5.to_le_bytes().map(|f| f.into())) + .build()) + .f6(types_api::Int32::new_builder() + .set(self.f6.to_le_bytes().map(|f| f.into())) + .build()) + .f7(types_api::Uint64::new_builder() + .set(self.f7.to_le_bytes().map(|f| f.into())) + .build()) + .f8(types_api::Int64::new_builder() + .set(self.f8.to_le_bytes().map(|f| f.into())) + .build()) + .build() + } + pub fn check(&self, d: &types_api2::TableB) -> ResCheckErr { + TypesCheckErr::check_1_data(&self.f1, &d.f1()?)?; + TypesCheckErr::check_1_data(&self.f2, &d.f2()?)?; + TypesCheckErr::check_1_data(&self.f3, &d.f3()?)?; + TypesCheckErr::check_1_data(&self.f4, &d.f4()?)?; + TypesCheckErr::check_1_data(&self.f5, &d.f5()?)?; + TypesCheckErr::check_1_data(&self.f6, &d.f6()?)?; + TypesCheckErr::check_1_data(&self.f7, &d.f7()?)?; + TypesCheckErr::check_1_data(&self.f8, &d.f8()?)?; + + Ok(()) + } +} diff --git a/examples/lazy-reader-tests/src/types_vec.rs b/examples/lazy-reader-tests/src/types_vec.rs new file mode 100644 index 0000000..8fec5b0 --- /dev/null +++ b/examples/lazy-reader-tests/src/types_vec.rs @@ -0,0 +1,227 @@ +use super::*; +use crate::{types_api, types_api2}; +use molecule::lazy_reader::Cursor; +use molecule::prelude::{Builder, Entity}; +use rand::{rngs::ThreadRng, thread_rng, Rng}; + +pub struct TypesVec { + pub d: Vec, +} + +impl BaseTypes for TypesVec { + fn new_rng(rng: &mut ThreadRng, config: &TypesConfig) -> Self { + let mut d = Vec::new(); + + let size = if config.large_vec { + rng.gen_range(128..1024) + } else if config.min_size { + 0 + } else { + rng.gen_range(1..128) + }; + for _i in 0..size { + d.push(T::new_rng(rng, config)); + } + + Self { d } + } +} +impl Default for TypesVec { + fn default() -> Self { + Self::new_rng(&mut thread_rng(), &TypesConfig::default()) + } +} + +impl TypesVec { + pub fn to_mol(&self) -> types_api::Bytes { + types_api::Bytes::new_builder() + .set(self.d.iter().map(|f| f.clone().into()).collect()) + .build() + } + pub fn check(&self, d: &Vec) -> ResCheckErr { + TypesCheckErr::check_data(d, &self.d) + } +} +impl TypesVec { + pub fn to_mol(&self) -> types_api::Words { + types_api::Words::new_builder() + .set(self.d.iter().map(|f| f.to_mol2()).collect()) + .build() + } + pub fn check(&self, d: &types_api2::Words) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesVec> { + pub fn to_mol(&self) -> types_api::Byte3Vec { + types_api::Byte3Vec::new_builder() + .set(self.d.iter().map(|f| f.to_mol()).collect()) + .build() + } + pub fn check(&self, d: &types_api2::Byte3Vec) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesVec> { + pub fn to_mol(&self) -> types_api::Byte7Vec { + types_api::Byte7Vec::new_builder() + .set(self.d.iter().map(|f| f.to_mol()).collect()) + .build() + } + pub fn check(&self, d: &types_api2::Byte7Vec) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check(&Cursor::try_from(d.get(i)?)?.into())?; + } + Ok(()) + } +} +impl TypesVec { + pub fn to_mol(&self) -> types_api::StructIVec { + types_api::StructIVec::new_builder() + .set(self.d.iter().map(|f| f.to_mol()).collect()) + .build() + } + pub fn check(&self, d: &types_api2::StructIVec) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check(&d.get(i)?)?; + } + Ok(()) + } +} +impl TypesVec { + pub fn to_mol(&self) -> types_api::StructJVec { + types_api::StructJVec::new_builder() + .set(self.d.iter().map(|f| f.to_mol()).collect()) + .build() + } + pub fn check(&self, d: &types_api2::StructJVec) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check(&d.get(i)?)?; + } + Ok(()) + } +} +impl TypesVec { + pub fn to_mol(&self) -> types_api::StructPVec { + types_api::StructPVec::new_builder() + .set(self.d.iter().map(|f| f.to_mol()).collect()) + .build() + } + pub fn check(&self, d: &types_api2::StructPVec) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check(&d.get(i)?)?; + } + Ok(()) + } +} +impl TypesVec> { + pub fn to_mol(&self) -> types_api::BytesVec { + types_api::BytesVec::new_builder() + .set(self.d.iter().map(|f| f.to_mol()).collect()) + .build() + } + pub fn check(&self, d: &types_api2::BytesVec) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check(&d.get(i)?.try_into().unwrap())?; + } + Ok(()) + } +} +impl TypesVec> { + pub fn to_mol(&self) -> types_api::WordsVec { + types_api::WordsVec::new_builder() + .set( + self.d + .iter() + .map(|f| { + types_api::Words::new_builder() + .set(f.d.iter().map(|ff| ff.to_mol2()).collect()) + .build() + }) + .collect(), + ) + .build() + } + pub fn check(&self, d: &types_api2::WordsVec) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check(&d.get(i)?.into())?; + } + Ok(()) + } +} +impl TypesVec> { + pub fn to_mol(&self) -> types_api::ByteOptVec { + types_api::ByteOptVec::new_builder() + .set(self.d.iter().map(|f| f.to_mol()).collect()) + .build() + } + pub fn check(&self, d: &types_api2::ByteOptVec) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check(&d.get(i)?.into())?; + } + Ok(()) + } +} +impl TypesVec> { + pub fn to_mol(&self) -> types_api::WordOptVec { + types_api::WordOptVec::new_builder() + .set(self.d.iter().map(|f| f.to_mol()).collect()) + .build() + } + pub fn check(&self, d: &types_api2::WordOptVec) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check( + &match d.get(i)? { + Some(v) => Some(Cursor::try_from(v)?), + None => None, + } + .into(), + )?; + } + Ok(()) + } +} +impl TypesVec>> { + pub fn to_mol(&self) -> types_api::WordsOptVec { + types_api::WordsOptVec::new_builder() + .set(self.d.iter().map(|f| f.to_mol()).collect()) + .build() + } + pub fn check(&self, d: &types_api2::WordsOptVec) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check(&d.get(i)?.into())?; + } + Ok(()) + } +} +impl TypesVec>> { + pub fn to_mol(&self) -> types_api::BytesOptVec { + types_api::BytesOptVec::new_builder() + .set(self.d.iter().map(|f| f.to_mol()).collect()) + .build() + } + pub fn check(&self, d: &types_api2::BytesOptVec) -> ResCheckErr { + TypesCheckErr::check_length(d.len()?, self.d.len())?; + for i in 0..d.len()? { + self.d[i].check(&d.get(i)?.into())?; + } + Ok(()) + } +} diff --git a/test/schemas/types.mol b/test/schemas/types.mol index aefb284..ed568b2 100644 --- a/test/schemas/types.mol +++ b/test/schemas/types.mol @@ -167,14 +167,14 @@ vector WordsOptVec ; vector BytesOptVec ; union UnionA { - byte, - Word, - StructA, - Bytes, - Words, - Table0, - Table6, - Table6Opt, + byte : 2, + Word : 3, + StructA : 7, + Bytes : 11, + Words : 4278190081, + Table0 : 4278190082, + Table6 : 4278190083, + Table6Opt : 4278190084, } union UnionB { @@ -203,6 +203,26 @@ table TableA { f8: byte, } +array Uint8 [byte; 1]; +array Int8 [byte; 1]; +array Uint16 [byte; 2]; +array Int16 [byte; 2]; +array Uint32 [byte; 4]; +array Int32 [byte; 4]; +array Uint64 [byte; 8]; +array Int64 [byte; 8]; + +table TableB { + f1: Uint8, + f2: Int8, + f3: Uint16, + f4: Int16, + f5: Uint32, + f6: Int32, + f7: Uint64, + f8: Int64, +} + table AllInOne { f0: byte, f1: Byte2, @@ -278,4 +298,7 @@ table AllInOne { f71: BytesOptVec, f72: UnionA, f73: TableA, + f74: TableB, + f75: UnionB, + f76: UnionD, } diff --git a/test/vectors/default.yaml b/test/vectors/default.yaml index 3e3435b..5266376 100644 --- a/test/vectors/default.yaml +++ b/test/vectors/default.yaml @@ -218,7 +218,7 @@ 08000000\ 00\ \ - 00000000\ + 02000000\ 00\ \ 00" @@ -263,7 +263,7 @@ # - name: UnionA - expected: "0x00000000//00" + expected: "0x02000000//00" - name: UnionB expected: "0x02000000//00" diff --git a/test/vectors/simple.yaml b/test/vectors/simple.yaml index 6dca236..0cc441f 100644 --- a/test/vectors/simple.yaml +++ b/test/vectors/simple.yaml @@ -316,7 +316,7 @@ 01000000//00\ 02000000//00/11" f6: "0x00000000" - f7: "0x03000000//00000000" + f7: "0x0b000000//00000000" f8: "0x99" expected: "0x67000000//\ 24000000_28000000_2e000000_32000000_\ @@ -336,7 +336,7 @@ \ 00000000\ \ - 03000000\ + 0b000000\ 00000000\ \ 99" @@ -436,37 +436,37 @@ item: type: byte data: "0x00" - expected: "0x00000000//00" + expected: "0x02000000//00" - name: UnionA item: type: Word data: "0x0000" - expected: "0x01000000//0000" + expected: "0x03000000//0000" - name: UnionA item: type: StructA data: "0x00/00/0000/0000" - expected: "0x02000000//00/00/0000/0000" + expected: "0x07000000//00/00/0000/0000" - name: UnionA item: type: Bytes data: "0x00000000" - expected: "0x03000000//00000000" + expected: "0x0b000000//00000000" - name: UnionA item: type: Words data: "0x00000000" - expected: "0x04000000//00000000" + expected: "0x010000ff//00000000" - name: UnionA item: type: Table0 data: "0x04000000" - expected: "0x05000000//04000000" + expected: "0x020000ff//04000000" - name: UnionA item: @@ -482,7 +482,7 @@ 00000000_0000\ 00000000\ 04000000" - expected: "0x06000000//\ + expected: "0x030000ff//\ 5a000000//\ 1c000000_1d000000_21000000_27000000_2b000000_2f000000//\ 00/00000000/00000000_0000/00000000/04000000/\ @@ -499,7 +499,7 @@ item: type: Table6Opt data: "0x" - expected: "0x07000000" + expected: "0x040000ff" - name: UnionA item: @@ -515,7 +515,7 @@ 00000000_0000\ 00000000\ 04000000" - expected: "0x07000000//\ + expected: "0x040000ff//\ 5a000000//\ 1c000000_1d000000_21000000_27000000_2b000000_2f000000//\ 00/00000000/00000000_0000/00000000/04000000/\ diff --git a/tools/codegen/src/generator/languages/mod.rs b/tools/codegen/src/generator/languages/mod.rs index 6b15a44..877aa1b 100644 --- a/tools/codegen/src/generator/languages/mod.rs +++ b/tools/codegen/src/generator/languages/mod.rs @@ -4,11 +4,13 @@ use crate::ast; mod c; mod rust; +mod rust_lazy_reader; #[derive(Debug, Clone, Copy)] pub enum Language { C, Rust, + RustLazyReader, } pub(super) trait LanguageGenerator { @@ -20,6 +22,7 @@ impl fmt::Display for Language { match *self { Self::C => write!(f, "C"), Self::Rust => write!(f, "Rust"), + Self::RustLazyReader => write!(f, "Rust(Lazy Reader)"), } } } @@ -30,6 +33,7 @@ impl TryFrom<&str> for Language { match value.to_lowercase().as_str() { "c" => Ok(Self::C), "rust" => Ok(Self::Rust), + "rust-lazy-reader" => Ok(Self::RustLazyReader), lang => Err(format!("unsupport language: [{}]", lang)), } } @@ -40,6 +44,7 @@ impl Language { match self { Self::C => "h", Self::Rust => "rs", + Self::RustLazyReader => "rs", } } @@ -47,6 +52,7 @@ impl Language { match self { Self::C => c::Generator::generate(writer, ast), Self::Rust => rust::Generator::generate(writer, ast), + Self::RustLazyReader => rust_lazy_reader::Generator::generate(writer, ast), } } } diff --git a/tools/codegen/src/generator/languages/rust_lazy_reader/generator.rs b/tools/codegen/src/generator/languages/rust_lazy_reader/generator.rs new file mode 100644 index 0000000..5f39b8a --- /dev/null +++ b/tools/codegen/src/generator/languages/rust_lazy_reader/generator.rs @@ -0,0 +1,847 @@ +use super::{ident_new, ident_new_camel, LazyReaderGenerator}; +use crate::ast::{self, HasName, *}; +use proc_macro2::{Literal, TokenStream}; +use quote::quote; +use std::io; + +impl ast::Union { + fn get_item_name(typ: &TopDecl) -> TokenStream { + let item_name = ident_new_camel(typ.name()); + let item_type_name = Self::get_type_name(typ); + + quote! { + #item_name(#item_type_name), + } + } + + fn get_type_name(typ: &TopDecl) -> TokenStream { + match typ { + TopDecl::Primitive(v) => { + let name = ident_new(match v.name().to_lowercase().as_str() { + "byte" => "u8", + "uint8" => "u8", + "int8" => "i8", + "uint16" => "u16", + "int16" => "i16", + "uint32" => "u32", + "int32" => "i32", + "uint64" => "u64", + "int64" => "i64", + _ => { + panic!("unknow type: {}", v.name()) + } + }); + quote!(#name) + } + TopDecl::Option_(o) => { + let name = Self::get_type_name(o.item().typ()); + quote!(Option<#name>) + } + TopDecl::FixVec(v) => { + if let TopDecl::Primitive(_) = v.item().typ().as_ref() { + quote!(Cursor) + } else { + let name = ident_new_camel(typ.name()); + quote!(#name) + } + } + _ => { + let name = ident_new_camel(typ.name()); + quote!(#name) + } + } + } +} + +impl LazyReaderGenerator for ast::Union { + fn gen_rust(&self, output: &mut W) -> io::Result<()> { + let name = ident_new(self.name()); + + // generate enum: + let q = self.items().iter().map(|item| { + let item_name = Self::get_item_name(item.typ().as_ref()); + quote! { + #item_name + } + }); + writeln!( + output, + "{}", + quote! { + pub enum #name { + #( #q )* + } + } + )?; + + // generate enum try_from + let q = self.items().iter().map(|item| { + let item_id = item.id(); + let item_name_str = item.typ().name(); + let item_name = ident_new_camel(item_name_str); + let item_type = Self::get_type_name(item.typ()); + + let q = match item.typ().as_ref() { + TopDecl::Primitive(a) => match a.name().to_lowercase().as_str() { + "byte" | "uint8" | "int8" | "uint16" | "int16" | "uint32" | "int32" + | "uint64" | "int64" => { + quote! {{ + cur.verify_fixed_size(core::mem::size_of::<#item_type>())?; + cur.try_into()? + }} + } + _ => { + quote!(cur.into()) + } + }, + TopDecl::Option_(o) => { + let item_name = ident_new_camel(o.item().typ().name()); + quote! {{ + if cur.option_is_none() { + None + } else { + Some(#item_name::from(cur)) + } + }} + } + TopDecl::FixVec(v) => { + if let TopDecl::Primitive(_) = v.item().typ().as_ref() { + quote! {{ + if cur.fixvec_length()? != cur.size - NUMBER_SIZE { + return Err(Error::TotalSize( + cur.fixvec_length()?, + cur.size + )); + } + + cur.add_offset(NUMBER_SIZE)?; + cur.sub_size(NUMBER_SIZE)?; + cur + }} + } else { + quote! { + cur.into() + } + } + } + _ => { + quote! { + cur.into() + } + } + }; + + quote! { + #item_id => { + Ok(Self::#item_name(#q)) + } + } + }); + let q = quote! { + impl TryFrom for #name { + type Error = Error; + fn try_from(cur: Cursor) -> Result { + let item = cur.union_unpack()?; + + let mut cur = cur; + cur.add_offset(NUMBER_SIZE)?; + cur.sub_size(NUMBER_SIZE)?; + + match item.item_id { + #( #q )* + _ => Err(Error::UnknownItem) + } + } + } + }; + writeln!(output, "{}", q)?; + + // generate verify + let verify_items = self.items().iter().enumerate().map(|(_i, item)| { + let item_name = ident_new_camel(item.typ().name()); + match item.typ().as_ref() { + TopDecl::Primitive(_) => { + quote!( Self::#item_name(_v) => Ok(()), ) + } + TopDecl::Option_(_) => { + quote! { + Self::#item_name(v) => { + if v.is_some() { + v.as_ref().unwrap().verify(compatible)?; + } + Ok(()) + }, + } + } + TopDecl::FixVec(v) => { + if let TopDecl::Primitive(_) = v.item().typ().as_ref() { + quote! { + Self::#item_name(_v) => Ok(()), + } + } else { + quote! { + Self::#item_name(v) => { + v.verify(compatible)?; + Ok(()) + }, + } + } + } + _ => quote! { + Self::#item_name(v) => { + v.verify(compatible)?; + Ok(()) + }, + }, + } + }); + + let q = quote! { + impl #name { + pub fn verify(&self, compatible: bool) -> Result<(), Error> { + match self { + #( #verify_items )* + } + } + } + }; + writeln!(output, "{}", q)?; + Ok(()) + } +} + +impl LazyReaderGenerator for ast::Array { + fn gen_rust(&self, output: &mut W) -> io::Result<()> { + let (transformed_name, tc) = get_rust_type_category(self.item().typ()); + generate_rust_common_array( + output, + self.name(), + transformed_name, + tc, + Some(self), + None, + None, + )?; + let total_size = self.item_count() * self.item_size(); + let name = ident_new(self.name()); + + let verify_sub = { + let func = verify_typ(self.item().typ().as_ref(), quote!(self.get(i)?)); + if func.is_empty() { + quote!() + } else { + quote!(for i in 0..self.len() { + #func + }) + } + }; + + let val_compatible = if verify_sub.is_empty() { + quote!(_compatible) + } else { + quote!(compatible) + }; + let q = quote! { + impl #name { + pub fn verify(&self, #val_compatible: bool) -> Result<(), Error> { + self.cursor.verify_fixed_size(#total_size)?; + #verify_sub; + Ok(()) + } + } + }; + writeln!(output, "{}", q)?; + Ok(()) + } +} +impl LazyReaderGenerator for ast::Option_ {} + +impl LazyReaderGenerator for ast::Struct { + fn gen_rust(&self, output: &mut W) -> io::Result<()> { + generate_rust_common_table(output, self.name(), self.fields(), Some(self.field_sizes()))?; + let name = ident_new(self.name()); + let total_size: usize = self.field_sizes().iter().sum(); + + let verify_fields = self + .fields() + .iter() + .enumerate() + .map(|(_i, f)| verify_filed(f)); + + let q = quote! { + impl #name { + pub fn verify(&self, compatible: bool) -> Result<(), Error> { + self.cursor.verify_fixed_size(#total_size)?; + #( #verify_fields )* + Ok(()) + } + } + }; + writeln!(output, "{}", q)?; + Ok(()) + } +} + +// in FixVec, all item size is same and known already, the count is unknown. +impl LazyReaderGenerator for ast::FixVec { + fn gen_rust(&self, output: &mut W) -> io::Result<()> { + let (transformed_name, tc) = get_rust_type_category(self.item().typ()); + generate_rust_common_array( + output, + self.name(), + transformed_name, + tc, + None, + Some(self), + None, + )?; + + let name = ident_new(self.name()); + let item_size = self.item_size(); + + let q = quote! { + impl #name { + pub fn verify(&self, _compatible: bool) -> Result<(), Error> { + self.cursor.verify_fixvec(#item_size)?; + Ok(()) + } + } + }; + writeln!(output, "{}", q)?; + Ok(()) + } +} + +impl LazyReaderGenerator for ast::DynVec { + fn gen_rust(&self, output: &mut W) -> io::Result<()> { + let (transformed_name, tc) = get_rust_type_category(self.item().typ()); + generate_rust_common_array( + output, + self.name(), + transformed_name, + tc, + None, + None, + Some(self), + )?; + + let verify_sub = { + let func = verify_typ(self.item().typ().as_ref(), quote!(self.get(i)?)); + if func.is_empty() { + quote!() + } else { + quote!(for i in 0..self.len()? { + #func + }) + } + }; + let val_compatible = if verify_sub.is_empty() { + quote!(_compatible) + } else { + quote!(compatible) + }; + + let name = ident_new(self.name()); + let q = quote! { + impl #name { + pub fn verify(&self, #val_compatible: bool) -> Result<(), Error> { + self.cursor.verify_dynvec()?; + #verify_sub; + Ok(()) + } + } + }; + writeln!(output, "{}", q)?; + Ok(()) + } +} + +impl LazyReaderGenerator for ast::Table { + fn gen_rust(&self, output: &mut W) -> io::Result<()> { + generate_rust_common_table(output, self.name(), self.fields(), None)?; + let field_count = self.fields().len(); + let name = ident_new(self.name()); + + let verify_fields = self + .fields() + .iter() + .enumerate() + .map(|(_i, f)| verify_filed(f)); + + let q = quote! { + impl #name { + pub fn verify(&self, compatible: bool) -> Result<(), Error> { + self.cursor.verify_table(#field_count, compatible)?; + #( #verify_fields )* + Ok(()) + } + } + }; + writeln!(output, "{}", q)?; + Ok(()) + } +} + +fn generate_rust_common_array( + output: &mut W, + plain_name: &str, + type_name: TokenStream, + tc: TypeCategory, + array: Option<&ast::Array>, + fixvec: Option<&ast::FixVec>, + _dynvec: Option<&ast::DynVec>, +) -> io::Result<()> { + let name = ident_new(plain_name); + let q = quote! { + #[derive(Clone)] + pub struct #name { + pub cursor: Cursor, + } + + impl From for #name { + fn from(cursor: Cursor) -> Self { + Self { cursor } + } + } + }; + + writeln!(output, "{}", q)?; + + // len + if let Some(arr) = array { + let item_count = Literal::usize_unsuffixed(arr.item_count()); + let q = quote! { + impl #name { + pub fn len(&self) -> usize { #item_count } + } + }; + writeln!(output, "{}", q)?; + } else if fixvec.is_some() { + let q = quote! { + impl #name { + pub fn len(&self) -> Result { self.cursor.fixvec_length() } + } + }; + writeln!(output, "{}", q)?; + } else { + let q = quote! { + impl #name { + pub fn len(&self) -> Result { self.cursor.dynvec_length() } + } + }; + writeln!(output, "{}", q)?; + } + generate_rust_common_array_impl(output, plain_name, type_name, tc, array, fixvec)?; + Ok(()) +} + +fn generate_rust_common_array_impl( + output: &mut W, + plain_name: &str, + item_name: TokenStream, + tc: TypeCategory, + array: Option<&Array>, + fixvec: Option<&FixVec>, +) -> io::Result<()> { + let slice_by = if let Some(fv) = fixvec { + let size = fv.item_size(); + quote! { fixvec_slice_by_index(#size, index) } + } else if let Some(arr) = array { + let index = arr.item_size(); + quote! { slice_by_offset(#index*index, #index) } + } else { + quote! { dynvec_slice_by_index(index) } + }; + let convert_code = tc.gen_convert_code(); + let name = ident_new(plain_name); + let iterator_name = ident_new(&format!("{}Iterator", name)); + let iterator_ref_name = ident_new(&format!("{}IteratorRef", name)); + let q = quote! { + impl #name { + pub fn get(&self, index: usize) -> Result<#item_name, Error> { + let cur = self.cursor.#slice_by?; + #convert_code + } + } + }; + writeln!(output, "{}", q)?; + + if array.is_some() { + return Ok(()); + } + let q = quote! { + pub struct #iterator_name { + cur: #name, + index: usize, + len: usize, + } + impl core::iter::Iterator for #iterator_name { + type Item = #item_name; + fn next(&mut self) -> Option { + if self.index >= self.len { + None + } else { + let res = self.cur.get(self.index).unwrap(); + self.index += 1; + Some(res) + } + } + } + impl core::iter::IntoIterator for #name { + type Item = #item_name; + type IntoIter = #iterator_name; + fn into_iter(self) -> Self::IntoIter { + let len = self.len().unwrap(); + Self::IntoIter { + cur: self, + index: 0, + len + } + } + } + pub struct #iterator_ref_name<'a> { + cur: &'a #name, + index: usize, + len: usize + } + impl<'a> core::iter::Iterator for #iterator_ref_name<'a> { + type Item = #item_name; + fn next(&mut self) -> Option { + if self.index >= self.len { + None + } else { + let res = self.cur.get(self.index).unwrap(); + self.index += 1; + Some(res) + } + } + } + impl #name { + pub fn iter(&self) -> #iterator_ref_name { + let len = self.len().unwrap(); + #iterator_ref_name { + cur: &self, + index: 0, + len + } + } + } + }; + writeln!(output, "{}", q)?; + Ok(()) +} + +fn generate_rust_common_table( + output: &mut W, + plain_name: &str, + fields: &[FieldDecl], + field_sizes: Option<&[usize]>, +) -> io::Result<()> { + let name = ident_new(plain_name); + let q = quote! { + #[derive(Clone)] + pub struct #name { + pub cursor: Cursor, + } + + impl From for #name { + fn from(cursor: Cursor) -> Self { + #name { cursor } + } + } + }; + writeln!(output, "{}", q)?; + for (index, field) in fields.iter().enumerate() { + generate_rust_common_table_impl(output, plain_name, field, index, field_sizes)?; + } + Ok(()) +} + +fn generate_rust_common_table_impl( + output: &mut W, + plain_name: &str, + field: &FieldDecl, + index: usize, + field_sizes: Option<&[usize]>, +) -> io::Result<()> { + let field_name = field.name(); + let (transformed_name, tc) = get_rust_type_category(field.typ()); + let slice_by = generate_rust_slice_by(index, &field_sizes); + let convert_code = tc.gen_convert_code(); + let name = ident_new(plain_name); + let field_name = ident_new(field_name); + let q = quote! { + impl #name { + pub fn #field_name(&self) -> Result<#transformed_name, Error> { + let cur = self.cursor.#slice_by?; + #convert_code + } + } + }; + writeln!(output, "{}", q)?; + Ok(()) +} + +// 1. category 1, primitive +// uint8, int8 +// uint16, int16 +// uint32, int32 +// uint64, int64 + +// 2. category 2, array/fixvec +// +// array + +// 3. category 3, normal type + +// 4. category 4, Option +enum TypeCategory { + Primitive, + Array, + FixVec, + Type, + // 1st: nested level + // 2nd: is nested type is FixVec or not + // 3rd: has From + Option(u32, bool, bool), + Union, +} + +impl TypeCategory { + pub fn is_fixvec(&self) -> bool { + matches!(self, Self::FixVec) + } + pub fn has_from(&self) -> bool { + matches!(self, Self::Type | Self::Array) + } + pub fn gen_convert_code(&self) -> TokenStream { + match self { + &TypeCategory::Option(level, flag, _has_from) => { + if level == 1 { + if flag { + quote! { + if cur.option_is_none() { + Ok(None) + } else { + let cur = cur.convert_to_rawbytes()?; + Ok(Some(cur.into())) + } + } + // Here is a warning: this `if` has identical blocks + // } else if has_from { + // quote! { + // if cur.option_is_none() { + // Ok(None) + // } else { + // Ok(Some(cur.try_into()?)) + // } + // } + } else { + quote! { + if cur.option_is_none() { + Ok(None) + } else { + Ok(Some(cur.try_into()?)) + } + } + } + } else if level == 2 { + if flag { + quote! { + if cur.option_is_none() { + Ok(None) + } else { + let cur = cur.convert_to_rawbytes()?; + Ok(Some(Some(cur.try_into()))) + } + } + } else { + quote! { + if cur.option_is_none() { + Ok(None) + } else { + Ok(Some(Some(cur.into()))) + } + } + } + } else { + panic!("can't support") + } + } + TypeCategory::Type => quote! { Ok(cur.into()) }, + TypeCategory::Primitive => quote! { cur.try_into() }, + TypeCategory::Array => quote! { cur.try_into() }, + TypeCategory::FixVec => { + quote! { + cur.convert_to_rawbytes() + } + } + TypeCategory::Union => { + quote!(cur.try_into()) + } + } + } +} + +// see TypeCategory +fn get_rust_type_category(typ: &TopDecl) -> (TokenStream, TypeCategory) { + let name = typ.name(); + let mut tc = TypeCategory::Primitive; + let token_name = ident_new(name); + let mut transformed_name = quote! { #token_name }; + match typ { + // if the field type is array and the field type name is "uint8", "int8" ... + // then it's primitive + TopDecl::Array(a) => { + let field_type_name = name.to_lowercase(); + let new_name = match field_type_name.as_ref() { + // see https://github.com/XuJiandong/moleculec-c2#extra-support-for-known-types + "uint8" => quote! { u8 }, + "int8" => quote! { i8 }, + "uint16" => quote! { u16 }, + "int16" => quote! { i16 }, + "uint32" => quote! { u32 }, + "int32" => quote! { i32 }, + "uint64" => quote! { u64 }, + "int64" => quote! { i64 }, + _ => { + if let TopDecl::Primitive(_) = a.item().typ().as_ref() { + // array of byte + tc = TypeCategory::Array; + let len = a.item_count(); + quote! { [u8; #len] } + } else { + // array of Types + tc = TypeCategory::Type; + transformed_name + } + } + }; + transformed_name = new_name; + } + TopDecl::Primitive(_) => { + transformed_name = quote! { u8 }; + } + TopDecl::FixVec(v) => { + // FixVec is different than Array: it has a header. + if let TopDecl::Primitive(_) = v.item().typ().as_ref() { + // array of byte + transformed_name = quote! { Cursor }; + tc = TypeCategory::FixVec; + } else { + tc = TypeCategory::Type; + } + } + TopDecl::Option_(o) => { + // Option