Skip to main content

miden_protocol/account/component/storage/schema/
slot.rs

1use alloc::collections::BTreeMap;
2use alloc::string::String;
3
4use super::super::type_registry::{SchemaRequirement, SchemaType};
5use super::super::{InitStorageData, StorageValueName};
6use super::{MapSlotSchema, ValueSlotSchema, WordSchema};
7use crate::account::{StorageSlot, StorageSlotName};
8use crate::errors::ComponentMetadataError;
9use crate::utils::serde::{
10    ByteReader,
11    ByteWriter,
12    Deserializable,
13    DeserializationError,
14    Serializable,
15};
16
17// STORAGE SLOT SCHEMA
18// ================================================================================================
19
20/// Describes the schema for a storage slot.
21/// Can describe either a value slot, or a map slot.
22#[allow(clippy::large_enum_variant)]
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum StorageSlotSchema {
25    Value(ValueSlotSchema),
26    Map(MapSlotSchema),
27}
28
29impl StorageSlotSchema {
30    /// Creates a value slot schema with the given description and word schema.
31    ///
32    /// Accepts anything convertible to [`WordSchema`]: a [`SchemaType`] for simple typed slots,
33    /// a `[FeltSchema; 4]` for composite slots, or a [`WordSchema`] directly.
34    pub fn value(description: impl Into<String>, word: impl Into<WordSchema>) -> Self {
35        Self::Value(ValueSlotSchema::new(Some(description.into()), word.into()))
36    }
37
38    /// Creates a map slot schema with the given description and simple key/value types.
39    pub fn map(
40        description: impl Into<String>,
41        key_type: SchemaType,
42        value_type: SchemaType,
43    ) -> Self {
44        Self::Map(MapSlotSchema::new(
45            Some(description.into()),
46            None,
47            WordSchema::new_simple(key_type),
48            WordSchema::new_simple(value_type),
49        ))
50    }
51
52    pub(super) fn collect_init_value_requirements(
53        &self,
54        slot_name: &StorageSlotName,
55        requirements: &mut BTreeMap<StorageValueName, SchemaRequirement>,
56    ) -> Result<(), ComponentMetadataError> {
57        let slot_name = StorageValueName::from_slot_name(slot_name);
58        match self {
59            StorageSlotSchema::Value(slot) => {
60                slot.collect_init_value_requirements(slot_name, requirements)
61            },
62            StorageSlotSchema::Map(_) => Ok(()),
63        }
64    }
65
66    /// Builds a [`StorageSlot`] for the specified `slot_name` using the provided initialization
67    /// data.
68    pub fn try_build_storage_slot(
69        &self,
70        slot_name: &StorageSlotName,
71        init_storage_data: &InitStorageData,
72    ) -> Result<StorageSlot, ComponentMetadataError> {
73        match self {
74            StorageSlotSchema::Value(slot) => {
75                let word = slot.try_build_word(init_storage_data, slot_name)?;
76                Ok(StorageSlot::with_value(slot_name.clone(), word))
77            },
78            StorageSlotSchema::Map(slot) => {
79                let storage_map = slot.try_build_map(init_storage_data, slot_name)?;
80                Ok(StorageSlot::with_map(slot_name.clone(), storage_map))
81            },
82        }
83    }
84
85    pub(super) fn validate(&self) -> Result<(), ComponentMetadataError> {
86        match self {
87            StorageSlotSchema::Value(slot) => slot.validate()?,
88            StorageSlotSchema::Map(slot) => slot.validate()?,
89        }
90
91        Ok(())
92    }
93
94    pub(super) fn write_into_with_optional_defaults<W: ByteWriter>(
95        &self,
96        target: &mut W,
97        include_defaults: bool,
98    ) {
99        match self {
100            StorageSlotSchema::Value(slot) => {
101                target.write_u8(0u8);
102                slot.write_into_with_optional_defaults(target, include_defaults);
103            },
104            StorageSlotSchema::Map(slot) => {
105                target.write_u8(1u8);
106                slot.write_into_with_optional_defaults(target, include_defaults);
107            },
108        }
109    }
110}
111
112impl Serializable for StorageSlotSchema {
113    fn write_into<W: ByteWriter>(&self, target: &mut W) {
114        self.write_into_with_optional_defaults(target, true);
115    }
116}
117
118impl Deserializable for StorageSlotSchema {
119    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
120        let variant_tag = source.read_u8()?;
121        match variant_tag {
122            0 => Ok(StorageSlotSchema::Value(ValueSlotSchema::read_from(source)?)),
123            1 => Ok(StorageSlotSchema::Map(MapSlotSchema::read_from(source)?)),
124            _ => Err(DeserializationError::InvalidValue(format!(
125                "unknown variant tag '{variant_tag}' for StorageSlotSchema"
126            ))),
127        }
128    }
129}