Skip to content

Commit 1963da1

Browse files
authored
Merge pull request #102 from XuJiandong/refactor-lazy-reader
Refactor lazy reader
2 parents e0f6d76 + 52ae5fe commit 1963da1

File tree

9 files changed

+90
-91
lines changed

9 files changed

+90
-91
lines changed

.github/workflows/ci.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- name: Setup
2121
uses: actions-rust-lang/setup-rust-toolchain@v1
2222
with:
23-
toolchain: 1.75.0
23+
toolchain: 1.85.1
2424
components: rustfmt
2525
- name: Run
2626
run: make fmt
@@ -32,7 +32,7 @@ jobs:
3232
- name: Setup
3333
uses: actions-rust-lang/setup-rust-toolchain@v1
3434
with:
35-
toolchain: 1.75.0
35+
toolchain: 1.85.1
3636
components: clippy
3737
- name: Run
3838
run: make clippy
@@ -45,7 +45,7 @@ jobs:
4545
- name: Setup
4646
uses: actions-rust-lang/setup-rust-toolchain@v1
4747
with:
48-
toolchain: 1.75.0 # MSRV
48+
toolchain: 1.85.1 # MSRV
4949
- name: Run
5050
run: make ci-msrv
5151
test-crates:
@@ -57,7 +57,7 @@ jobs:
5757
- name: Setup
5858
uses: actions-rust-lang/setup-rust-toolchain@v1
5959
with:
60-
toolchain: 1.75.0
60+
toolchain: 1.85.1
6161
- name: Run
6262
run: make ci-crates
6363
test-examples:
@@ -69,7 +69,7 @@ jobs:
6969
- name: Setup
7070
uses: actions-rust-lang/setup-rust-toolchain@v1
7171
with:
72-
toolchain: 1.75.0
72+
toolchain: 1.85.1
7373
- name: Run
7474
run: make ci-examples
7575
success:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Implementations in other languages are maintained by respective authors.
8484

8585
## Supported Rust Versions
8686

87-
The minimum supported version is 1.75.0.
87+
The minimum supported version is 1.85.1.
8888
The current Molecule version is not guaranteed to build on Rust versions earlier than the
8989
minimum supported version.
9090

bindings/rust/src/lazy_reader.rs

Lines changed: 35 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,7 @@
2121
//! load_func: F,
2222
//! buf: &mut [u8],
2323
//! offset: usize,
24-
//! total_size: usize,
2524
//!) -> Result<usize, Error> {
26-
//! if offset >= total_size {
27-
//! return Err(Error::OutOfBound(offset, total_size));
28-
//! }
29-
//! let remaining_len = total_size - offset;
30-
//! let min_len = min(remaining_len, buf.len());
31-
//! if (offset + min_len) > total_size {
32-
//! return Err(Error::OutOfBound(offset + min_len, total_size));
33-
//! }
3425
//! let actual_len = match load_func(buf, offset) {
3526
//! Ok(l) => l,
3627
//! Err(err) => match err {
@@ -52,27 +43,26 @@
5243
//! }
5344
//!}
5445
//!pub struct TransactionReader {
55-
//! pub total_size: usize,
46+
//! pub size: usize,
5647
//!}
5748
//!impl TransactionReader {
5849
//! pub fn new() -> Self {
59-
//! let total_size = read_size(|buf| syscalls::load_transaction(buf, 0)).unwrap();
60-
//! Self { total_size }
50+
//! let size = read_size(|buf| syscalls::load_transaction(buf, 0)).unwrap();
51+
//! Self { size }
6152
//! }
6253
//!}
6354
//!impl Read for TransactionReader {
6455
//! fn read(&self, buf: &mut [u8], offset: usize) -> Result<usize, Error> {
6556
//! read_data(
6657
//! |buf, offset| syscalls::load_transaction(buf, offset),
6758
//! buf,
68-
//! offset,
69-
//! self.total_size,
59+
//! offset
7060
//! )
7161
//! }
7262
//!}
7363
//!impl From<TransactionReader> for Cursor {
7464
//! fn from(data: TransactionReader) -> Self {
75-
//! Cursor::new(data.total_size, Box::new(data))
65+
//! Cursor::new(data.size, Box::new(data))
7666
//! }
7767
//!}
7868
//!pub fn new_transaction() -> blockchain::Transaction {
@@ -133,7 +123,6 @@ pub const NUMBER_SIZE: usize = 4;
133123
///
134124
pub struct DataSource {
135125
reader: Box<dyn Read>,
136-
total_size: usize,
137126
cache_start_point: usize,
138127
// cache actual size may be smaller than cache.len()
139128
cache_actual_size: usize,
@@ -142,12 +131,11 @@ pub struct DataSource {
142131

143132
impl DataSource {
144133
///
145-
/// Create a data source from `reader` and corresponding `total_size`
134+
/// Create a data source from `reader`
146135
///
147-
pub fn new(total_size: usize, reader: Box<dyn Read>) -> Self {
136+
pub fn new(reader: Box<dyn Read>) -> Self {
148137
DataSource {
149138
reader,
150-
total_size,
151139
cache_start_point: 0,
152140
cache_actual_size: 0,
153141
cache: vec![0u8; MAX_CACHE_SIZE],
@@ -208,13 +196,13 @@ pub struct Union {
208196

209197
impl Cursor {
210198
///
211-
/// Create a cursor from `reader` and its corresponding total size
199+
/// Create a cursor from `reader` and its corresponding size
212200
///
213-
pub fn new(total_size: usize, reader: Box<dyn Read>) -> Self {
214-
let data_source = DataSource::new(total_size, reader);
201+
pub fn new(size: usize, reader: Box<dyn Read>) -> Self {
202+
let data_source = DataSource::new(reader);
215203
Cursor {
216204
offset: 0,
217-
size: total_size,
205+
size,
218206
data_source: Rc::new(RefCell::new(data_source)),
219207
}
220208
}
@@ -241,22 +229,6 @@ impl Cursor {
241229
self.size = self.size.checked_sub(shrink_size).ok_or(Error::Overflow)?;
242230
Ok(())
243231
}
244-
245-
///
246-
/// Validate a cursor to ensure that size and offset are not out of bounds.
247-
///
248-
pub fn validate(&self) -> Result<(), Error> {
249-
if let Some(size) = self.offset.checked_add(self.size) {
250-
if size > self.data_source.borrow().total_size {
251-
Err(Error::TotalSize(size, self.data_source.borrow().total_size))
252-
} else {
253-
Ok(())
254-
}
255-
} else {
256-
Err(Error::Overflow)
257-
}
258-
}
259-
260232
///
261233
/// Read the first 4 bytes and unpack them into a u32 in little endian format.
262234
///
@@ -283,15 +255,22 @@ impl Cursor {
283255
/// Verify that a cursor is a valid molecule `table` with
284256
/// `expected_field_count` fields. if `compatible` is true, actual fields
285257
/// count can be larger than `expected_field_count`.
286-
///
258+
///
287259
pub fn verify_table(&self, expected_field_count: usize, compatible: bool) -> Result<(), Error> {
288260
self.verify_dynvec()?;
261+
let total_size = self.unpack_number()?;
262+
// Handle empty table case
263+
if total_size == NUMBER_SIZE {
264+
// An empty table (only header) can only be valid if expected_field_count is 0
265+
// This applies regardless of the compatible flag
266+
if expected_field_count == 0 {
267+
return Ok(());
268+
} else {
269+
return Err(Error::Verify);
270+
}
271+
}
289272
let mut cur = self.clone();
290273
cur.add_offset(NUMBER_SIZE)?;
291-
if self.size == cur.size {
292-
// empty table
293-
return Ok(());
294-
}
295274
let first_offset = cur.unpack_number()?;
296275
let field_count = first_offset / NUMBER_SIZE - 1;
297276
if field_count < expected_field_count || !compatible && field_count > expected_field_count {
@@ -379,10 +358,7 @@ impl Cursor {
379358
if self.size == NUMBER_SIZE {
380359
Ok(0)
381360
} else {
382-
let mut cur2 = self.clone();
383-
cur2.add_offset(NUMBER_SIZE)?;
384-
cur2.sub_size(NUMBER_SIZE)?;
385-
cur2.validate()?;
361+
let cur2 = self.slice_by_start(NUMBER_SIZE)?;
386362
cur2.get_item_count()
387363
}
388364
}
@@ -419,14 +395,16 @@ impl Cursor {
419395

420396
///
421397
/// Create a new cursor by adding an `offset` and setting the `size` to that
422-
/// of the original cursor.
398+
/// of the original cursor.
423399
///
424400
pub fn slice_by_offset(&self, offset: usize, size: usize) -> Result<Cursor, Error> {
425-
let mut cur2 = self.clone();
426-
cur2.add_offset(offset)?;
427-
cur2.size = size;
428-
cur2.validate()?;
429-
Ok(cur2)
401+
if (offset + size) > self.size {
402+
return Err(Error::TotalSize(offset, size));
403+
}
404+
let mut cur = self.clone();
405+
cur.add_offset(offset)?;
406+
cur.size = size;
407+
Ok(cur)
430408
}
431409
///
432410
/// Create a new cursor by adding an offset and shrinking the size to that
@@ -436,7 +414,6 @@ impl Cursor {
436414
let mut cur2 = self.clone();
437415
cur2.add_offset(delta)?;
438416
cur2.sub_size(delta)?;
439-
cur2.validate()?;
440417
Ok(cur2)
441418
}
442419

@@ -449,16 +426,12 @@ impl Cursor {
449426
item_size: usize,
450427
item_index: usize,
451428
) -> Result<Cursor, Error> {
452-
let mut cur2 = self.clone();
453429
let item_count = self.unpack_number()?;
454430
if item_index >= item_count {
455431
Err(Error::OutOfBound(item_index, item_count))
456432
} else {
457433
let offset = calculate_offset(item_size, item_index, NUMBER_SIZE)?;
458-
cur2.add_offset(offset)?;
459-
cur2.size = item_size;
460-
cur2.validate()?;
461-
Ok(cur2)
434+
Ok(self.slice_by_offset(offset, item_size)?)
462435
}
463436
}
464437
///
@@ -493,7 +466,6 @@ impl Cursor {
493466
res.size = item_end;
494467
res.sub_size(item_start)?;
495468
}
496-
res.validate()?;
497469
Ok(res)
498470
}
499471

@@ -504,11 +476,7 @@ impl Cursor {
504476

505477
/// Assuming a cursor is `fixvec`, return raw data without header.
506478
pub fn fixvec_slice_raw_bytes(&self) -> Result<Cursor, Error> {
507-
let mut res = self.clone();
508-
res.add_offset(NUMBER_SIZE)?;
509-
res.size = self.unpack_number()?;
510-
res.validate()?;
511-
Ok(res)
479+
self.slice_by_offset(NUMBER_SIZE, self.unpack_number()?)
512480
}
513481

514482
/// helper function for generated code
@@ -523,10 +491,7 @@ impl Cursor {
523491
/// Assuming a cursor is `union`. Return a `union`.
524492
pub fn union_unpack(&self) -> Result<Union, Error> {
525493
let item_id = self.unpack_number()?;
526-
let mut cursor = self.clone();
527-
cursor.add_offset(NUMBER_SIZE)?;
528-
cursor.sub_size(NUMBER_SIZE)?;
529-
cursor.validate()?;
494+
let cursor = self.slice_by_start(NUMBER_SIZE)?;
530495
Ok(Union { item_id, cursor })
531496
}
532497
}

bindings/rust/src/primitive.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ impl fmt::Debug for Byte {
1616
}
1717
}
1818

19-
impl<'r> fmt::Debug for ByteReader<'r> {
19+
impl fmt::Debug for ByteReader<'_> {
2020
#[inline]
2121
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2222
write!(f, "{}(0x{:02x})", Self::NAME, self.0[0])
@@ -30,7 +30,7 @@ impl fmt::Display for Byte {
3030
}
3131
}
3232

33-
impl<'r> fmt::Display for ByteReader<'r> {
33+
impl fmt::Display for ByteReader<'_> {
3434
#[inline]
3535
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3636
write!(f, "{}(0x{:02x})", Self::NAME, self.0[0])

examples/lazy-reader-tests/src/types_all_data.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,3 +1140,43 @@ fn test_struct_verify() {
11401140
.verify(false)
11411141
.expect_err("");
11421142
}
1143+
1144+
#[test]
1145+
fn test_verify_table() {
1146+
// table with 2 fields
1147+
let data = vec![14, 0, 0, 0, 12, 0, 0, 0, 13, 0, 0, 0, 100, 200];
1148+
types_api2::Table1 {
1149+
cursor: new_cursor(&data),
1150+
}
1151+
.verify(false)
1152+
.expect_err("");
1153+
types_api2::Table1 {
1154+
cursor: new_cursor(&data),
1155+
}
1156+
.verify(true)
1157+
.expect("");
1158+
// table with 0 field
1159+
let data = vec![4, 0, 0, 0];
1160+
types_api2::Table1 {
1161+
cursor: new_cursor(&data),
1162+
}
1163+
.verify(false)
1164+
.expect_err("");
1165+
types_api2::Table1 {
1166+
cursor: new_cursor(&data),
1167+
}
1168+
.verify(true)
1169+
.expect_err("");
1170+
1171+
// empty table can accept it
1172+
types_api2::Table0 {
1173+
cursor: new_cursor(&data),
1174+
}
1175+
.verify(true)
1176+
.expect("");
1177+
types_api2::Table0 {
1178+
cursor: new_cursor(&data),
1179+
}
1180+
.verify(false)
1181+
.expect("");
1182+
}

rust-toolchain.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[toolchain]
2+
channel = "1.85.1"

tools/codegen/src/ast/raw/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
utils::{self, PairsUtils as _},
1313
};
1414

15-
impl<'i> utils::PairsUtils for Pairs<'i, parser::Rule> {
15+
impl utils::PairsUtils for Pairs<'_, parser::Rule> {
1616
fn next_string(&mut self) -> String {
1717
self.next().unwrap().as_str().to_owned()
1818
}

tools/codegen/src/ast/verified/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl TopDecl {
164164

165165
fn imported_depth(&self) -> usize {
166166
match self {
167-
Self::Primitive(_) => usize::max_value(),
167+
Self::Primitive(_) => usize::MAX,
168168
Self::Option_(inner) => inner.imported_depth,
169169
Self::Union(inner) => inner.imported_depth,
170170
Self::Array(inner) => inner.imported_depth,

0 commit comments

Comments
 (0)