use alloc::string::String;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
use crate::hash::Hash;
use crate::seal::SealRef;
pub type StateTypeId = u16;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct GlobalState {
pub type_id: StateTypeId,
pub data: Vec<u8>,
}
impl GlobalState {
pub fn new(type_id: StateTypeId, data: Vec<u8>) -> Self {
Self { type_id, data }
}
pub fn from_hash(type_id: StateTypeId, value: Hash) -> Self {
Self {
type_id,
data: value.to_vec(),
}
}
pub fn as_hash(&self) -> Option<Hash> {
if self.data.len() == 32 {
let mut bytes = [0u8; 32];
bytes.copy_from_slice(&self.data);
Some(Hash::new(bytes))
} else {
None
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct OwnedState {
pub type_id: StateTypeId,
pub seal: SealRef,
pub data: Vec<u8>,
}
impl OwnedState {
pub fn new(type_id: StateTypeId, seal: SealRef, data: Vec<u8>) -> Self {
Self {
type_id,
seal,
data,
}
}
pub fn from_hash(type_id: StateTypeId, seal: SealRef, value: Hash) -> Self {
Self {
type_id,
seal,
data: value.to_vec(),
}
}
pub fn as_hash(&self) -> Option<Hash> {
if self.data.len() == 32 {
let mut bytes = [0u8; 32];
bytes.copy_from_slice(&self.data);
Some(Hash::new(bytes))
} else {
None
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Metadata {
pub key: String,
pub value: Vec<u8>,
}
impl Metadata {
pub fn new(key: impl Into<String>, value: Vec<u8>) -> Self {
Self {
key: key.into(),
value,
}
}
pub fn from_string(key: impl Into<String>, value: impl Into<String>) -> Self {
Self {
key: key.into(),
value: value.into().into_bytes(),
}
}
pub fn as_string(&self) -> Option<String> {
String::from_utf8(self.value.clone()).ok()
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct StateAssignment {
pub type_id: StateTypeId,
pub seal: SealRef,
pub data: Vec<u8>,
}
impl StateAssignment {
pub fn new(type_id: StateTypeId, seal: SealRef, data: Vec<u8>) -> Self {
Self {
type_id,
seal,
data,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct StateRef {
pub type_id: StateTypeId,
pub commitment: Hash,
pub output_index: u32,
}
impl StateRef {
pub fn new(type_id: StateTypeId, commitment: Hash, output_index: u32) -> Self {
Self {
type_id,
commitment,
output_index,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_global_state_creation() {
let state = GlobalState::new(1, vec![1, 2, 3]);
assert_eq!(state.type_id, 1);
assert_eq!(state.data, vec![1, 2, 3]);
}
#[test]
fn test_global_state_from_hash() {
let hash = Hash::new([42u8; 32]);
let state = GlobalState::from_hash(1, hash);
assert_eq!(state.type_id, 1);
assert_eq!(state.as_hash(), Some(hash));
}
#[test]
fn test_global_state_wrong_size() {
let state = GlobalState::new(1, vec![1, 2]); assert!(state.as_hash().is_none());
}
#[test]
fn test_owned_state_creation() {
let seal = SealRef::new(vec![1, 2, 3], Some(42)).unwrap();
let state = OwnedState::new(2, seal.clone(), vec![4, 5, 6]);
assert_eq!(state.type_id, 2);
assert_eq!(state.seal, seal);
assert_eq!(state.data, vec![4, 5, 6]);
}
#[test]
fn test_owned_state_from_hash() {
let seal = SealRef::new(vec![1, 2, 3], Some(42)).unwrap();
let hash = Hash::new([99u8; 32]);
let state = OwnedState::from_hash(2, seal.clone(), hash);
assert_eq!(state.seal, seal);
assert_eq!(state.as_hash(), Some(hash));
}
#[test]
fn test_metadata_creation() {
let meta = Metadata::new("timestamp", 1700000000u64.to_le_bytes().to_vec());
assert_eq!(meta.key, "timestamp");
}
#[test]
fn test_metadata_from_string() {
let meta = Metadata::from_string("note", "hello world");
assert_eq!(meta.as_string(), Some("hello world".to_string()));
}
#[test]
fn test_metadata_binary() {
let meta = Metadata::new("binary", vec![0x00, 0xFF, 0x80]);
assert!(meta.as_string().is_none()); }
#[test]
fn test_state_assignment() {
let seal = SealRef::new(vec![1, 2, 3], Some(42)).unwrap();
let assignment = StateAssignment::new(3, seal.clone(), vec![7, 8, 9]);
assert_eq!(assignment.type_id, 3);
assert_eq!(assignment.seal, seal);
}
#[test]
fn test_state_ref() {
let state_ref = StateRef::new(1, Hash::new([5u8; 32]), 0);
assert_eq!(state_ref.type_id, 1);
assert_eq!(state_ref.output_index, 0);
}
#[test]
fn test_state_serialization_roundtrip() {
let seal = SealRef::new(vec![1, 2, 3], Some(42)).unwrap();
let state = OwnedState::new(2, seal, vec![4, 5, 6]);
let bytes = bincode::serialize(&state).unwrap();
let restored: OwnedState = bincode::deserialize(&bytes).unwrap();
assert_eq!(state, restored);
}
#[test]
fn test_global_state_serialization_roundtrip() {
let state = GlobalState::new(1, vec![1, 2, 3]);
let bytes = bincode::serialize(&state).unwrap();
let restored: GlobalState = bincode::deserialize(&bytes).unwrap();
assert_eq!(state, restored);
}
#[test]
fn test_metadata_serialization_roundtrip() {
let meta = Metadata::from_string("note", "test value");
let bytes = bincode::serialize(&meta).unwrap();
let restored: Metadata = bincode::deserialize(&bytes).unwrap();
assert_eq!(meta, restored);
}
}