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 {
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///
134124pub 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
143132impl 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
209197impl 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}
0 commit comments