@@ -8,9 +8,8 @@ This simple examples defines a zero-copy type with its discriminator.
8
8
9
9
``` rust
10
10
use {
11
- borsh :: {BorshSerialize , BorshDeserialize },
12
11
bytemuck :: {Pod , Zeroable },
13
- spl_discriminator :: {ArrayDiscriminator , SplDiscriminate }
12
+ spl_discriminator :: {ArrayDiscriminator , SplDiscriminate },
14
13
spl_type_length_value :: {
15
14
state :: {TlvState , TlvStateBorrowed , TlvStateMut }
16
15
},
@@ -45,57 +44,63 @@ impl SplDiscriminate for MyOtherPodValue {
45
44
46
45
// Account will have two sets of `get_base_len()` (8-byte discriminator and 4-byte length),
47
46
// and enough room for a `MyPodValue` and a `MyOtherPodValue`
48
- let account_size = TlvState :: get_base_len () + std :: mem :: size_of :: <MyPodValue >() + \
49
- TlvState :: get_base_len () + std :: mem :: size_of :: <MyOtherPodValue >();
47
+ let account_size = TlvStateMut :: get_base_len ()
48
+ + std :: mem :: size_of :: <MyPodValue >()
49
+ + TlvStateMut :: get_base_len ()
50
+ + std :: mem :: size_of :: <MyOtherPodValue >()
51
+ + TlvStateMut :: get_base_len ()
52
+ + std :: mem :: size_of :: <MyOtherPodValue >()
50
53
51
54
// Buffer likely comes from a Solana `solana_program::account_info::AccountInfo`,
52
55
// but this example just uses a vector.
53
56
let mut buffer = vec! [0 ; account_size ];
54
57
55
- // Unpack the base buffer as a TLV structure
56
- let mut state = TlvStateMut :: unpack (& mut buffer ). unwrap ();
57
-
58
- // Init and write default value
59
- // Note: you'll need to provide a boolean whether or not to allow repeating
60
- // values with the same TLV discriminator.
61
- // If set to false, this function will error when an existing entry is detected.
62
- let value = state . init_value :: <MyPodValue >(false ). unwrap ();
63
- // Update it in-place
64
- value . data[0 ] = 1 ;
65
-
66
- // Init and write another default value
67
- // This time, we're going to allow repeating values.
68
- let other_value1 = state . init_value :: <MyOtherPodValue >(true ). unwrap ();
69
- assert_eq! (other_value1 . data, 10 );
70
- // Update it in-place
71
- other_value1 . data = 2 ;
72
-
73
- // Let's do it again, since we can now have repeating values!
74
- let other_value2 = state . init_value :: <MyOtherPodValue >(true ). unwrap ();
75
- assert_eq! (other_value2 . data, 10 );
76
- // Update it in-place
77
- other_value2 . data = 4 ;
78
-
79
- // Later on, to work with it again, since we did _not_ allow repeating entries,
80
- // we can just get the first value we encounter.
81
- let value = state . get_first_value_mut :: <MyPodValue >(). unwrap ();
58
+ {
59
+ // Unpack the base buffer as a TLV structure
60
+ let mut state = TlvStateMut :: unpack (& mut buffer ). unwrap ();
61
+
62
+ // Init and write default value
63
+ // Note: you'll need to provide a boolean whether or not to allow repeating
64
+ // values with the same TLV discriminator.
65
+ // If set to false, this function will error when an existing entry is detected.
66
+ let (value , _ ) = state . init_value :: <MyPodValue >(false ). unwrap ();
67
+ // Update it in-place
68
+ value . data[0 ] = 1 ;
69
+
70
+ // Init and write another default value
71
+ // This time, we're going to allow repeating values.
72
+ let (other_value1 , _ ) = state . init_value :: <MyOtherPodValue >(true ). unwrap ();
73
+ assert_eq! (other_value1 . data, 10 );
74
+ // Update it in-place
75
+ other_value1 . data = 2 ;
76
+
77
+ // Let's do it again, since we can now have repeating values!
78
+ let (other_value2 , _ ) = state . init_value :: <MyOtherPodValue >(true ). unwrap ();
79
+ assert_eq! (other_value2 . data, 10 );
80
+ // Update it in-place
81
+ other_value2 . data = 4 ;
82
+
83
+ // Later on, to work with it again, we can just get the first value we
84
+ // encounter, because we did _not_ allow repeating entries for `MyPodValue`.
85
+ let value = state . get_first_value_mut :: <MyPodValue >(). unwrap ();
86
+ }
82
87
83
88
// Or fetch it from an immutable buffer
84
89
let state = TlvStateBorrowed :: unpack (& buffer ). unwrap ();
85
90
let value1 = state . get_first_value :: <MyOtherPodValue >(). unwrap ();
86
91
87
92
// Since we used repeating entries for `MyOtherPodValue`, we can grab either one by
88
93
// its entry number
89
- let value1 = state . get_value_with_repetition :: <MyOtherPodValue >(1 ). unwrap ();
90
- let value2 = state . get_value_with_repetition :: <MyOtherPodValue >(2 ). unwrap ();
94
+ let value1 = state . get_value_with_repetition :: <MyOtherPodValue >(0 ). unwrap ();
95
+ let value2 = state . get_value_with_repetition :: <MyOtherPodValue >(1 ). unwrap ();
91
96
92
97
```
93
98
94
99
## Motivation
95
100
96
101
The Solana blockchain exposes slabs of bytes to on-chain programs, allowing program
97
102
writers to interpret these bytes and change them however they wish. Currently,
98
- programs interpret account bytes as being only of one type. For example, an token
103
+ programs interpret account bytes as being only of one type. For example, a token
99
104
mint account is only ever a token mint, an AMM pool account is only ever an AMM pool,
100
105
a token metadata account can only hold token metadata, etc.
101
106
@@ -135,7 +140,11 @@ trait on your type.
135
140
``` rust
136
141
use {
137
142
borsh :: {BorshDeserialize , BorshSerialize },
138
- solana_program :: borsh :: {get_instance_packed_len, try_from_slice_unchecked},
143
+ solana_program :: {
144
+ borsh1 :: {get_instance_packed_len, try_from_slice_unchecked},
145
+ program_error :: ProgramError ,
146
+ },
147
+ spl_discriminator :: {ArrayDiscriminator , SplDiscriminate },
139
148
spl_type_length_value :: {
140
149
state :: {TlvState , TlvStateMut },
141
150
variable_len_pack :: VariableLenPack
@@ -164,7 +173,7 @@ impl VariableLenPack for MyVariableLenType {
164
173
let initial_data = " This is a pretty cool test!" ;
165
174
// Allocate exactly the right size for the string, can go bigger if desired
166
175
let tlv_size = 4 + initial_data . len ();
167
- let account_size = TlvState :: get_base_len () + tlv_size ;
176
+ let account_size = TlvStateMut :: get_base_len () + tlv_size ;
168
177
169
178
// Buffer likely comes from a Solana `solana_program::account_info::AccountInfo`,
170
179
// but this example just uses a vector.
@@ -177,7 +186,7 @@ let _ = state.alloc::<MyVariableLenType>(tlv_size, false).unwrap();
177
186
let my_variable_len = MyVariableLenType {
178
187
data : initial_data . to_string ()
179
188
};
180
- state . pack_variable_len_value (& my_variable_len ). unwrap ();
189
+ state . pack_first_variable_len_value (& my_variable_len ). unwrap ();
181
190
let deser = state . get_first_variable_len_value :: <MyVariableLenType >(). unwrap ();
182
191
assert_eq! (deser , my_variable_len );
183
192
```
0 commit comments