1use alloc::string::String;
8use alloc::vec::Vec;
9use serde::{Deserialize, Serialize};
10
11use crate::hash::Hash;
12use crate::seal::SealRef;
13
14pub type StateTypeId = u16;
16
17#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
22pub struct GlobalState {
23 pub type_id: StateTypeId,
25 pub data: Vec<u8>,
27}
28
29impl GlobalState {
30 pub fn new(type_id: StateTypeId, data: Vec<u8>) -> Self {
32 Self { type_id, data }
33 }
34
35 pub fn from_hash(type_id: StateTypeId, value: Hash) -> Self {
37 Self {
38 type_id,
39 data: value.to_vec(),
40 }
41 }
42
43 pub fn as_hash(&self) -> Option<Hash> {
45 if self.data.len() == 32 {
46 let mut bytes = [0u8; 32];
47 bytes.copy_from_slice(&self.data);
48 Some(Hash::new(bytes))
49 } else {
50 None
51 }
52 }
53}
54
55#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
60pub struct OwnedState {
61 pub type_id: StateTypeId,
63 pub seal: SealRef,
65 pub data: Vec<u8>,
67}
68
69impl OwnedState {
70 pub fn new(type_id: StateTypeId, seal: SealRef, data: Vec<u8>) -> Self {
72 Self {
73 type_id,
74 seal,
75 data,
76 }
77 }
78
79 pub fn from_hash(type_id: StateTypeId, seal: SealRef, value: Hash) -> Self {
81 Self {
82 type_id,
83 seal,
84 data: value.to_vec(),
85 }
86 }
87
88 pub fn as_hash(&self) -> Option<Hash> {
90 if self.data.len() == 32 {
91 let mut bytes = [0u8; 32];
92 bytes.copy_from_slice(&self.data);
93 Some(Hash::new(bytes))
94 } else {
95 None
96 }
97 }
98}
99
100#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
105pub struct Metadata {
106 pub key: String,
108 pub value: Vec<u8>,
110}
111
112impl Metadata {
113 pub fn new(key: impl Into<String>, value: Vec<u8>) -> Self {
115 Self {
116 key: key.into(),
117 value,
118 }
119 }
120
121 pub fn from_string(key: impl Into<String>, value: impl Into<String>) -> Self {
123 Self {
124 key: key.into(),
125 value: value.into().into_bytes(),
126 }
127 }
128
129 pub fn as_string(&self) -> Option<String> {
131 String::from_utf8(self.value.clone()).ok()
132 }
133}
134
135#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
139pub struct StateAssignment {
140 pub type_id: StateTypeId,
142 pub seal: SealRef,
144 pub data: Vec<u8>,
146}
147
148impl StateAssignment {
149 pub fn new(type_id: StateTypeId, seal: SealRef, data: Vec<u8>) -> Self {
151 Self {
152 type_id,
153 seal,
154 data,
155 }
156 }
157}
158
159#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
163pub struct StateRef {
164 pub type_id: StateTypeId,
166 pub commitment: Hash,
168 pub output_index: u32,
170}
171
172impl StateRef {
173 pub fn new(type_id: StateTypeId, commitment: Hash, output_index: u32) -> Self {
175 Self {
176 type_id,
177 commitment,
178 output_index,
179 }
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186
187 #[test]
188 fn test_global_state_creation() {
189 let state = GlobalState::new(1, vec![1, 2, 3]);
190 assert_eq!(state.type_id, 1);
191 assert_eq!(state.data, vec![1, 2, 3]);
192 }
193
194 #[test]
195 fn test_global_state_from_hash() {
196 let hash = Hash::new([42u8; 32]);
197 let state = GlobalState::from_hash(1, hash);
198 assert_eq!(state.type_id, 1);
199 assert_eq!(state.as_hash(), Some(hash));
200 }
201
202 #[test]
203 fn test_global_state_wrong_size() {
204 let state = GlobalState::new(1, vec![1, 2]); assert!(state.as_hash().is_none());
206 }
207
208 #[test]
209 fn test_owned_state_creation() {
210 let seal = SealRef::new(vec![1, 2, 3], Some(42)).unwrap();
211 let state = OwnedState::new(2, seal.clone(), vec![4, 5, 6]);
212 assert_eq!(state.type_id, 2);
213 assert_eq!(state.seal, seal);
214 assert_eq!(state.data, vec![4, 5, 6]);
215 }
216
217 #[test]
218 fn test_owned_state_from_hash() {
219 let seal = SealRef::new(vec![1, 2, 3], Some(42)).unwrap();
220 let hash = Hash::new([99u8; 32]);
221 let state = OwnedState::from_hash(2, seal.clone(), hash);
222 assert_eq!(state.seal, seal);
223 assert_eq!(state.as_hash(), Some(hash));
224 }
225
226 #[test]
227 fn test_metadata_creation() {
228 let meta = Metadata::new("timestamp", 1700000000u64.to_le_bytes().to_vec());
229 assert_eq!(meta.key, "timestamp");
230 }
231
232 #[test]
233 fn test_metadata_from_string() {
234 let meta = Metadata::from_string("note", "hello world");
235 assert_eq!(meta.as_string(), Some("hello world".to_string()));
236 }
237
238 #[test]
239 fn test_metadata_binary() {
240 let meta = Metadata::new("binary", vec![0x00, 0xFF, 0x80]);
241 assert!(meta.as_string().is_none()); }
243
244 #[test]
245 fn test_state_assignment() {
246 let seal = SealRef::new(vec![1, 2, 3], Some(42)).unwrap();
247 let assignment = StateAssignment::new(3, seal.clone(), vec![7, 8, 9]);
248 assert_eq!(assignment.type_id, 3);
249 assert_eq!(assignment.seal, seal);
250 }
251
252 #[test]
253 fn test_state_ref() {
254 let state_ref = StateRef::new(1, Hash::new([5u8; 32]), 0);
255 assert_eq!(state_ref.type_id, 1);
256 assert_eq!(state_ref.output_index, 0);
257 }
258
259 #[test]
260 fn test_state_serialization_roundtrip() {
261 let seal = SealRef::new(vec![1, 2, 3], Some(42)).unwrap();
262 let state = OwnedState::new(2, seal, vec![4, 5, 6]);
263 let bytes = bincode::serialize(&state).unwrap();
264 let restored: OwnedState = bincode::deserialize(&bytes).unwrap();
265 assert_eq!(state, restored);
266 }
267
268 #[test]
269 fn test_global_state_serialization_roundtrip() {
270 let state = GlobalState::new(1, vec![1, 2, 3]);
271 let bytes = bincode::serialize(&state).unwrap();
272 let restored: GlobalState = bincode::deserialize(&bytes).unwrap();
273 assert_eq!(state, restored);
274 }
275
276 #[test]
277 fn test_metadata_serialization_roundtrip() {
278 let meta = Metadata::from_string("note", "test value");
279 let bytes = bincode::serialize(&meta).unwrap();
280 let restored: Metadata = bincode::deserialize(&bytes).unwrap();
281 assert_eq!(meta, restored);
282 }
283}