1+ use borsh:: { BorshDeserialize , BorshSerialize } ;
12use num_derive:: { FromPrimitive , ToPrimitive } ;
23
4+ /// Discriminant indicating which keyspace is being accessed.
35#[ repr( u64 ) ]
46#[ derive( Debug , Clone , Copy , PartialEq , Eq , FromPrimitive , ToPrimitive ) ]
57pub enum KeyspaceTag {
6- /// Used for a state based storage which usually involves single dimensional data i.e.
7- /// key-value pairs, etc.
8- ///
9- /// See also [`Keyspace::State`].
10- State = 0 ,
11- /// Used for a context based storage which usually involves multi dimensional data i.e. maps,
12- /// efficient vectors, etc.
13- Context = 1 ,
14- /// Used for a named key based storage which usually involves named keys.
15- NamedKey = 2 ,
16- /// Used for getting all named keys
17- AllNamedKeys = 4 ,
8+ /// Context-based storage addressing using a structured address.
9+ Context = 0 ,
10+ /// Named key based storage which usually involves human-readable names.
11+ NamedKey = 1 ,
12+ }
13+
14+ /// Discriminant indicating which collection type is being used.
15+ #[ repr( u8 ) ]
16+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , FromPrimitive , ToPrimitive ) ]
17+ pub enum CollectionTypeTag {
18+ /// A key-value mapping collection.
19+ Map = 0 ,
20+ /// A set collection for unique elements.
21+ Set = 1 ,
22+ /// A vector collection.
23+ Vector = 2 ,
24+ /// An iterable map collection.
25+ IterableMap = 3 ,
26+ }
27+
28+ #[ derive( Debug , Clone , PartialEq , Eq , BorshSerialize , BorshDeserialize ) ]
29+ pub enum ContextAddr {
30+ /// Address of a state field for a given entity.
31+ StateAddr ( StateAddrInner ) ,
32+ /// Address of a collection element for a given entity.
33+ CollectionAddr ( CollectionAddrInner ) ,
34+ }
35+
36+ /// Address for a specific state field owned by `entity_addr`.
37+ #[ derive( Debug , Clone , PartialEq , Eq , BorshSerialize , BorshDeserialize ) ]
38+ pub struct StateAddrInner {
39+ pub field_addr : String ,
40+ }
41+
42+ impl StateAddrInner {
43+ #[ inline]
44+ pub fn new < T : Into < String > > ( field_addr : T ) -> Self {
45+ Self {
46+ field_addr : field_addr. into ( ) ,
47+ }
48+ }
49+ }
50+
51+ /// Address for a collection element owned by `entity_addr`.
52+ ///
53+ /// The `collection_type_tag` identifies the collection kind (e.g., map, set, vector).
54+ /// The `collection_prefix` is an 8-byte collection-level namespace derived from the collection
55+ /// name. The `tail` is a 32-byte element-level discriminator (e.g., hashed key or index).
56+ #[ derive( Debug , Clone , PartialEq , Eq , BorshSerialize , BorshDeserialize ) ]
57+ pub struct CollectionAddrInner {
58+ pub entity_addr : [ u8 ; 32 ] ,
59+ pub collection_type_tag : u8 ,
60+ pub collection_prefix : [ u8 ; 8 ] ,
61+ pub tail : [ u8 ; 32 ] ,
62+ }
63+
64+ impl CollectionAddrInner {
65+ pub fn new (
66+ entity_addr : [ u8 ; 32 ] ,
67+ collection_type_tag : CollectionTypeTag ,
68+ collection_prefix : [ u8 ; 8 ] ,
69+ tail : [ u8 ; 32 ] ,
70+ ) -> Self {
71+ Self {
72+ entity_addr,
73+ collection_type_tag : collection_type_tag as u8 ,
74+ collection_prefix,
75+ tail,
76+ }
77+ }
78+ }
79+
80+ impl From < StateAddrInner > for ContextAddr {
81+ fn from ( value : StateAddrInner ) -> Self {
82+ ContextAddr :: StateAddr ( value)
83+ }
84+ }
85+
86+ impl From < CollectionAddrInner > for ContextAddr {
87+ fn from ( value : CollectionAddrInner ) -> Self {
88+ ContextAddr :: CollectionAddr ( value)
89+ }
1890}
1991
2092#[ repr( u64 ) ]
21- #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
93+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
2294pub enum Keyspace < ' a > {
23- /// Stores contract's context.
24- ///
25- /// There's no additional payload for this variant as the host implies the contract's address.
26- State ,
27- /// Stores contract's context data. Bytes can be any value as long as it uniquely identifies a
28- /// value.
29- Context ( & ' a [ u8 ] ) ,
30- /// Stores contract's named keys.
95+ /// Structured context address.
96+ Context ( ContextAddr ) ,
97+ /// Human-readable named key.
3198 NamedKey ( & ' a str ) ,
32- /// All the named keys for the given contract
33- ///
34- /// No additional info as the contracts address will be used as the base.
35- AllNamedKeys ,
3699}
37100
38101impl Keyspace < ' _ > {
39102 #[ must_use]
40103 pub fn as_tag ( & self ) -> KeyspaceTag {
41104 match self {
42- Keyspace :: State => KeyspaceTag :: State ,
43105 Keyspace :: Context ( _) => KeyspaceTag :: Context ,
44106 Keyspace :: NamedKey ( _) => KeyspaceTag :: NamedKey ,
45- Keyspace :: AllNamedKeys => KeyspaceTag :: AllNamedKeys ,
46107 }
47108 }
48109
@@ -51,48 +112,3 @@ impl Keyspace<'_> {
51112 self . as_tag ( ) as u64
52113 }
53114}
54-
55- #[ cfg( test) ]
56- mod tests {
57- use super :: * ;
58-
59- #[ test]
60- fn test_as_tag_state ( ) {
61- let keyspace = Keyspace :: State ;
62- assert_eq ! ( keyspace. as_tag( ) , KeyspaceTag :: State ) ;
63- }
64-
65- #[ test]
66- fn test_as_tag_context ( ) {
67- let data = [ 1 , 2 , 3 ] ;
68- let keyspace = Keyspace :: Context ( & data) ;
69- assert_eq ! ( keyspace. as_tag( ) , KeyspaceTag :: Context ) ;
70- }
71-
72- #[ test]
73- fn test_as_tag_named_key ( ) {
74- let name = "my_key" ;
75- let keyspace = Keyspace :: NamedKey ( name) ;
76- assert_eq ! ( keyspace. as_tag( ) , KeyspaceTag :: NamedKey ) ;
77- }
78-
79- #[ test]
80- fn test_as_u64_state ( ) {
81- let keyspace = Keyspace :: State ;
82- assert_eq ! ( keyspace. as_u64( ) , 0 ) ;
83- }
84-
85- #[ test]
86- fn test_as_u64_context ( ) {
87- let data = [ 1 , 2 , 3 ] ;
88- let keyspace = Keyspace :: Context ( & data) ;
89- assert_eq ! ( keyspace. as_u64( ) , 1 ) ;
90- }
91-
92- #[ test]
93- fn test_as_u64_named_key ( ) {
94- let name = "my_key" ;
95- let keyspace = Keyspace :: NamedKey ( name) ;
96- assert_eq ! ( keyspace. as_u64( ) , 2 ) ;
97- }
98- }
0 commit comments