Skip to main content

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

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