11use std:: convert:: TryInto ;
22
3- use cid :: Cid ;
3+ use fvm_ipld_encoding :: DAG_CBOR ;
44use thiserror:: Error ;
55
6+ use super :: { ExecutionError , SyscallError } ;
7+ use crate :: syscall_error;
8+
69#[ derive( Default ) ]
710pub ( crate ) struct BlockRegistry {
811 blocks : Vec < Block > ,
@@ -14,6 +17,7 @@ pub(crate) struct BlockRegistry {
1417pub type BlockId = u32 ;
1518
1619const FIRST_ID : BlockId = 1 ;
20+ const MAX_BLOCKS : u32 = i32:: MAX as u32 ; // TODO: Limit
1721
1822#[ derive( Copy , Clone ) ]
1923pub struct BlockStat {
@@ -61,19 +65,42 @@ impl Block {
6165}
6266
6367#[ derive( Error , Debug ) ]
64- pub enum BlockError {
65- #[ error( "block {0} is unreachable" ) ]
66- Unreachable ( Box < Cid > ) ,
68+ pub enum BlockPutError {
6769 #[ error( "too many blocks have been written" ) ]
6870 TooManyBlocks ,
69- #[ error( "block handle {0} does not exist, or is illegal" ) ]
70- InvalidHandle ( BlockId ) ,
71- #[ error( "invalid multihash length or code" ) ]
72- InvalidMultihashSpec { length : u32 , code : u64 } ,
7371 #[ error( "invalid or forbidden ipld codec" ) ]
7472 InvalidCodec ( u64 ) ,
75- #[ error( "state {0} is missing from the local datastore" ) ]
76- MissingState ( Box < Cid > ) , // boxed because CIDs are potentially large.
73+ }
74+
75+ impl From < BlockPutError > for super :: SyscallError {
76+ fn from ( e : BlockPutError ) -> Self {
77+ match e {
78+ BlockPutError :: TooManyBlocks => syscall_error ! ( LimitExceeded ; "{}" , e) ,
79+ BlockPutError :: InvalidCodec ( _) => syscall_error ! ( IllegalCodec ; "{}" , e) ,
80+ }
81+ }
82+ }
83+
84+ impl From < BlockPutError > for ExecutionError {
85+ fn from ( e : BlockPutError ) -> Self {
86+ ExecutionError :: Syscall ( e. into ( ) )
87+ }
88+ }
89+
90+ #[ derive( Error , Debug ) ]
91+ #[ error( "block handle {0} does not exist, or is illegal" ) ]
92+ pub struct InvalidHandleError ( BlockId ) ;
93+
94+ impl From < InvalidHandleError > for SyscallError {
95+ fn from ( e : InvalidHandleError ) -> Self {
96+ syscall_error ! ( InvalidHandle ; "{}" , e)
97+ }
98+ }
99+
100+ impl From < InvalidHandleError > for ExecutionError {
101+ fn from ( e : InvalidHandleError ) -> Self {
102+ ExecutionError :: Syscall ( e. into ( ) )
103+ }
77104}
78105
79106impl BlockRegistry {
@@ -84,41 +111,46 @@ impl BlockRegistry {
84111
85112impl BlockRegistry {
86113 /// Adds a new block to the registry, and returns a handle to refer to it.
87- pub fn put ( & mut self , block : Block ) -> Result < BlockId , BlockError > {
88- // TODO: limit the code types we allow.
89- let mut id: u32 = self
90- . blocks
91- . len ( )
92- . try_into ( )
93- . map_err ( |_| BlockError :: TooManyBlocks ) ?;
94- id += FIRST_ID ;
114+ pub fn put ( & mut self , block : Block ) -> Result < BlockId , BlockPutError > {
115+ if self . is_full ( ) {
116+ return Err ( BlockPutError :: TooManyBlocks ) ;
117+ }
118+ if block. codec != DAG_CBOR {
119+ return Err ( BlockPutError :: InvalidCodec ( block. codec ) ) ;
120+ }
121+
122+ let id = FIRST_ID + self . blocks . len ( ) as u32 ;
95123 self . blocks . push ( block) ;
96124 Ok ( id)
97125 }
98126
99127 /// Gets the block associated with a block handle.
100- pub fn get ( & self , id : BlockId ) -> Result < & Block , BlockError > {
128+ pub fn get ( & self , id : BlockId ) -> Result < & Block , InvalidHandleError > {
101129 if id < FIRST_ID {
102- return Err ( BlockError :: InvalidHandle ( id) ) ;
130+ return Err ( InvalidHandleError ( id) ) ;
103131 }
104132 id. try_into ( )
105133 . ok ( )
106134 . and_then ( |idx : usize | self . blocks . get ( idx - FIRST_ID as usize ) )
107- . ok_or ( BlockError :: InvalidHandle ( id) )
135+ . ok_or ( InvalidHandleError ( id) )
108136 }
109137
110138 /// Returns the size & codec of the specified block.
111- pub fn stat ( & self , id : BlockId ) -> Result < BlockStat , BlockError > {
139+ pub fn stat ( & self , id : BlockId ) -> Result < BlockStat , InvalidHandleError > {
112140 if id < FIRST_ID {
113- return Err ( BlockError :: InvalidHandle ( id) ) ;
141+ return Err ( InvalidHandleError ( id) ) ;
114142 }
115143 id. try_into ( )
116144 . ok ( )
117145 . and_then ( |idx : usize | self . blocks . get ( idx - FIRST_ID as usize ) )
118- . ok_or ( BlockError :: InvalidHandle ( id) )
146+ . ok_or ( InvalidHandleError ( id) )
119147 . map ( |b| BlockStat {
120148 codec : b. codec ( ) ,
121149 size : b. size ( ) ,
122150 } )
123151 }
152+
153+ pub fn is_full ( & self ) -> bool {
154+ self . blocks . len ( ) as u32 == MAX_BLOCKS
155+ }
124156}
0 commit comments