miden_objects/account/component/template/storage/
entry_content.rs

1use alloc::boxed::Box;
2use alloc::collections::BTreeSet;
3use alloc::string::{String, ToString};
4use alloc::vec::Vec;
5use core::iter;
6
7use super::placeholder::{PlaceholderTypeRequirement, TEMPLATE_REGISTRY, TemplateType};
8use super::{
9    FieldIdentifier,
10    InitStorageData,
11    MapEntry,
12    StorageValueName,
13    TemplateRequirementsIter,
14};
15use crate::account::StorageMap;
16use crate::account::component::template::AccountComponentTemplateError;
17use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
18use crate::{Felt, FieldElement, Word};
19
20// WORDS
21// ================================================================================================
22
23/// Defines how a word is represented within the component's storage description.
24///
25/// Each word representation can be:
26/// - A template that defines a type but does not carry a value.
27/// - A predefined value that may contain a hardcoded word or a mix of fixed and templated felts.
28#[derive(Debug, Clone, PartialEq, Eq)]
29#[allow(clippy::large_enum_variant)]
30pub enum WordRepresentation {
31    /// A templated value that serves as a placeholder for instantiation.
32    ///
33    /// This variant defines a type but does not store a value. The actual value is provided at the
34    /// time of instantiation. The name is required to identify this template externally.
35    Template {
36        /// The type associated with this templated word.
37        r#type: TemplateType,
38        identifier: FieldIdentifier,
39    },
40
41    /// A predefined value that can be used directly within storage.
42    ///
43    /// This variant may contain either a fully hardcoded word or a structured set of felts, some
44    /// of which may themselves be templates.
45    Value {
46        identifier: Option<FieldIdentifier>,
47        /// The 4-felt representation of the stored word.
48        value: [FeltRepresentation; 4],
49    },
50}
51
52impl WordRepresentation {
53    /// Constructs a new `Template` variant.
54    pub fn new_template(r#type: TemplateType, identifier: FieldIdentifier) -> Self {
55        WordRepresentation::Template { r#type, identifier }
56    }
57
58    /// Constructs a new `Value` variant.
59    pub fn new_value(
60        value: impl Into<[FeltRepresentation; 4]>,
61        identifier: Option<FieldIdentifier>,
62    ) -> Self {
63        WordRepresentation::Value { identifier, value: value.into() }
64    }
65
66    /// Sets the description of the [`WordRepresentation`] and returns `self`.
67    pub fn with_description(self, description: impl Into<String>) -> Self {
68        match self {
69            WordRepresentation::Template { r#type, identifier } => WordRepresentation::Template {
70                r#type,
71                identifier: FieldIdentifier {
72                    name: identifier.name,
73                    description: Some(description.into()),
74                },
75            },
76            WordRepresentation::Value { identifier, value } => WordRepresentation::Value {
77                identifier: identifier.map(|id| FieldIdentifier {
78                    name: id.name,
79                    description: Some(description.into()),
80                }),
81                value,
82            },
83        }
84    }
85
86    /// Returns the name associated with the word representation.
87    /// - For the `Template` variant, it always returns a reference to the name.
88    /// - For the `Value` variant, it returns `Some` if a name is present, or `None` otherwise.
89    pub fn name(&self) -> Option<&StorageValueName> {
90        match self {
91            WordRepresentation::Template { identifier, .. } => Some(&identifier.name),
92            WordRepresentation::Value { identifier, .. } => identifier.as_ref().map(|id| &id.name),
93        }
94    }
95
96    /// Returns the description associated with the word representation.
97    /// Both variants store an `Option<String>`, which is converted to an `Option<&str>`.
98    pub fn description(&self) -> Option<&str> {
99        match self {
100            WordRepresentation::Template { identifier, .. } => identifier.description.as_deref(),
101            WordRepresentation::Value { identifier, .. } => {
102                identifier.as_ref().and_then(|id| id.description.as_deref())
103            },
104        }
105    }
106
107    /// Returns the type name.
108    pub fn word_type(&self) -> TemplateType {
109        match self {
110            WordRepresentation::Template { r#type, .. } => r#type.clone(),
111            WordRepresentation::Value { .. } => TemplateType::native_word(),
112        }
113    }
114
115    /// Returns the value (an array of 4 `FeltRepresentation`s) if this is a `Value`
116    /// variant; otherwise, returns `None`.
117    pub fn value(&self) -> Option<&[FeltRepresentation; 4]> {
118        match self {
119            WordRepresentation::Value { value, .. } => Some(value),
120            WordRepresentation::Template { .. } => None,
121        }
122    }
123
124    /// Returns an iterator over the word's placeholders.
125    ///
126    /// For [`WordRepresentation::Value`], it corresponds to the inner iterators (since inner
127    /// elements can be templated as well).
128    /// For [`WordRepresentation::Template`] it returns the words's placeholder requirements
129    /// as defined.
130    pub fn template_requirements(
131        &self,
132        placeholder_prefix: StorageValueName,
133    ) -> TemplateRequirementsIter<'_> {
134        let placeholder_key =
135            placeholder_prefix.with_suffix(self.name().unwrap_or(&StorageValueName::empty()));
136        match self {
137            WordRepresentation::Template { identifier, r#type } => Box::new(iter::once((
138                placeholder_key,
139                PlaceholderTypeRequirement {
140                    description: identifier.description.clone(),
141                    r#type: r#type.clone(),
142                },
143            ))),
144            WordRepresentation::Value { value, .. } => Box::new(
145                value
146                    .iter()
147                    .flat_map(move |felt| felt.template_requirements(placeholder_key.clone())),
148            ),
149        }
150    }
151
152    /// Attempts to convert the [WordRepresentation] into a [Word].
153    ///
154    /// If the representation is a template, the value is retrieved from
155    /// `init_storage_data`, identified by its key. If any of the inner elements
156    /// within the value are a template, they are retrieved in the same way.
157    pub(crate) fn try_build_word(
158        &self,
159        init_storage_data: &InitStorageData,
160        placeholder_prefix: StorageValueName,
161    ) -> Result<Word, AccountComponentTemplateError> {
162        match self {
163            WordRepresentation::Template { identifier, r#type } => {
164                let placeholder_path = placeholder_prefix.with_suffix(&identifier.name);
165                let maybe_value = init_storage_data.get(&placeholder_path);
166                if let Some(value) = maybe_value {
167                    let parsed_value = TEMPLATE_REGISTRY
168                        .try_parse_word(r#type, value)
169                        .map_err(AccountComponentTemplateError::StorageValueParsingError)?;
170
171                    Ok(parsed_value)
172                } else {
173                    Err(AccountComponentTemplateError::PlaceholderValueNotProvided(
174                        placeholder_path,
175                    ))
176                }
177            },
178            WordRepresentation::Value { value, identifier } => {
179                let mut result = [Felt::ZERO; 4];
180
181                for (index, felt_repr) in value.iter().enumerate() {
182                    let placeholder = placeholder_prefix.clone().with_suffix(
183                        identifier
184                            .as_ref()
185                            .map(|id| &id.name)
186                            .unwrap_or(&StorageValueName::empty()),
187                    );
188                    result[index] = felt_repr.try_build_felt(init_storage_data, placeholder)?;
189                }
190                // SAFETY: result is guaranteed to have all its 4 indices rewritten
191                Ok(Word::from(result))
192            },
193        }
194    }
195
196    /// Validates that the defined type exists and all the inner felt types exist as well
197    pub(crate) fn validate(&self) -> Result<(), AccountComponentTemplateError> {
198        // Check that type exists in registry
199        let type_exists = TEMPLATE_REGISTRY.contains_word_type(&self.word_type());
200        if !type_exists {
201            return Err(AccountComponentTemplateError::InvalidType(
202                self.word_type().to_string(),
203                "Word".into(),
204            ));
205        }
206
207        if let Some(felts) = self.value() {
208            for felt in felts {
209                felt.validate()?;
210            }
211        }
212
213        Ok(())
214    }
215}
216
217impl Serializable for WordRepresentation {
218    fn write_into<W: ByteWriter>(&self, target: &mut W) {
219        match self {
220            WordRepresentation::Template { identifier, r#type } => {
221                target.write_u8(0);
222                target.write(identifier);
223                target.write(r#type);
224            },
225            WordRepresentation::Value { identifier, value } => {
226                target.write_u8(1);
227                target.write(identifier);
228                target.write(value);
229            },
230        }
231    }
232}
233
234impl Deserializable for WordRepresentation {
235    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
236        let tag = source.read_u8()?;
237        match tag {
238            0 => {
239                let identifier = FieldIdentifier::read_from(source)?;
240                let r#type = TemplateType::read_from(source)?;
241                Ok(WordRepresentation::Template { identifier, r#type })
242            },
243            1 => {
244                let identifier = Option::<FieldIdentifier>::read_from(source)?;
245                let value = <[FeltRepresentation; 4]>::read_from(source)?;
246                Ok(WordRepresentation::Value { identifier, value })
247            },
248            other => Err(DeserializationError::InvalidValue(format!(
249                "unknown tag '{other}' for WordRepresentation"
250            ))),
251        }
252    }
253}
254
255impl From<[FeltRepresentation; 4]> for WordRepresentation {
256    fn from(value: [FeltRepresentation; 4]) -> Self {
257        WordRepresentation::new_value(value, Option::<FieldIdentifier>::None)
258    }
259}
260
261impl From<[Felt; 4]> for WordRepresentation {
262    fn from(value: [Felt; 4]) -> Self {
263        WordRepresentation::new_value(
264            value.map(FeltRepresentation::from),
265            Option::<FieldIdentifier>::None,
266        )
267    }
268}
269
270// FELTS
271// ================================================================================================
272
273/// Supported element representations for a component's storage entries.
274///
275/// Each felt element in a storage entry can either be:
276/// - A concrete value that holds a predefined felt.
277/// - A template that specifies the type of felt expected, with the actual value to be provided
278///   later.
279#[derive(Debug, Clone, PartialEq, Eq)]
280pub enum FeltRepresentation {
281    /// A concrete felt value.
282    ///
283    /// This variant holds a felt that is part of the component's storage.
284    /// The optional name allows for identification, and the description offers additional context.
285    Value {
286        /// An optional identifier for this felt value.
287        /// An optional explanation of the felt's purpose.
288        identifier: Option<FieldIdentifier>,
289        /// The actual felt value.
290        value: Felt,
291    },
292
293    /// A templated felt element.
294    ///
295    /// This variant specifies the expected type of the felt without providing a concrete value.
296    /// The name is required to uniquely identify the template, and an optional description can
297    /// further clarify its intended use.
298    Template {
299        /// The expected type for this felt element.
300        r#type: TemplateType,
301        /// A unique name for the felt template.
302        /// An optional description that explains the purpose of this template.
303        identifier: FieldIdentifier,
304    },
305}
306
307impl FeltRepresentation {
308    /// Creates a new [`FeltRepresentation::Value`] variant.
309    pub fn new_value(value: impl Into<Felt>, name: Option<StorageValueName>) -> Self {
310        FeltRepresentation::Value {
311            value: value.into(),
312            identifier: name.map(FieldIdentifier::with_name),
313        }
314    }
315
316    /// Creates a new [`FeltRepresentation::Template`] variant.
317    ///
318    /// The name will be used for identification at the moment of instantiating the componentn.
319    pub fn new_template(r#type: TemplateType, name: StorageValueName) -> Self {
320        FeltRepresentation::Template {
321            r#type,
322            identifier: FieldIdentifier::with_name(name),
323        }
324    }
325
326    /// Sets the description of the [`FeltRepresentation`] and returns `self`.
327    pub fn with_description(self, description: impl Into<String>) -> Self {
328        match self {
329            FeltRepresentation::Template { r#type, identifier } => FeltRepresentation::Template {
330                r#type,
331                identifier: FieldIdentifier {
332                    name: identifier.name,
333                    description: Some(description.into()),
334                },
335            },
336            FeltRepresentation::Value { identifier, value } => FeltRepresentation::Value {
337                identifier: identifier.map(|id| FieldIdentifier {
338                    name: id.name,
339                    description: Some(description.into()),
340                }),
341                value,
342            },
343        }
344    }
345
346    /// Returns the felt type.
347    pub fn felt_type(&self) -> TemplateType {
348        match self {
349            FeltRepresentation::Template { r#type, .. } => r#type.clone(),
350            FeltRepresentation::Value { .. } => TemplateType::native_felt(),
351        }
352    }
353
354    /// Attempts to convert the [FeltRepresentation] into a [Felt].
355    ///
356    /// If the representation is a template, the value is retrieved from `init_storage_data`,
357    /// identified by its key. Otherwise, the returned value is just the inner element.
358    pub(crate) fn try_build_felt(
359        &self,
360        init_storage_data: &InitStorageData,
361        placeholder_prefix: StorageValueName,
362    ) -> Result<Felt, AccountComponentTemplateError> {
363        match self {
364            FeltRepresentation::Template { identifier, r#type } => {
365                let placeholder_key = placeholder_prefix.with_suffix(&identifier.name);
366                let raw_value = init_storage_data.get(&placeholder_key).ok_or(
367                    AccountComponentTemplateError::PlaceholderValueNotProvided(placeholder_key),
368                )?;
369
370                Ok(TEMPLATE_REGISTRY
371                    .try_parse_felt(r#type, raw_value)
372                    .map_err(AccountComponentTemplateError::StorageValueParsingError)?)
373            },
374            FeltRepresentation::Value { value, .. } => Ok(*value),
375        }
376    }
377
378    /// Returns an iterator over the felt's template.
379    ///
380    /// For [`FeltRepresentation::Value`], these is an empty set; for
381    /// [`FeltRepresentation::Template`] it returns the felt's placeholder key based on the
382    /// felt's name within the component description.
383    pub fn template_requirements(
384        &self,
385        placeholder_prefix: StorageValueName,
386    ) -> TemplateRequirementsIter<'_> {
387        match self {
388            FeltRepresentation::Template { identifier, r#type } => Box::new(iter::once((
389                placeholder_prefix.with_suffix(&identifier.name),
390                PlaceholderTypeRequirement {
391                    description: identifier.description.clone(),
392                    r#type: r#type.clone(),
393                },
394            ))),
395            _ => Box::new(iter::empty()),
396        }
397    }
398
399    /// Validates that the defined Felt type exists
400    pub(crate) fn validate(&self) -> Result<(), AccountComponentTemplateError> {
401        // Check that type exists in registry
402        let type_exists = TEMPLATE_REGISTRY.contains_felt_type(&self.felt_type());
403        if !type_exists {
404            return Err(AccountComponentTemplateError::InvalidType(
405                self.felt_type().to_string(),
406                "Felt".into(),
407            ));
408        }
409        Ok(())
410    }
411}
412
413impl From<Felt> for FeltRepresentation {
414    fn from(value: Felt) -> Self {
415        FeltRepresentation::new_value(value, Option::<StorageValueName>::None)
416    }
417}
418
419impl Default for FeltRepresentation {
420    fn default() -> Self {
421        FeltRepresentation::new_value(Felt::default(), Option::<StorageValueName>::None)
422    }
423}
424
425impl Serializable for FeltRepresentation {
426    fn write_into<W: ByteWriter>(&self, target: &mut W) {
427        match self {
428            FeltRepresentation::Value { identifier, value } => {
429                target.write_u8(0);
430                target.write(identifier);
431                target.write(value);
432            },
433            FeltRepresentation::Template { identifier, r#type } => {
434                target.write_u8(1);
435                target.write(identifier);
436                target.write(r#type);
437            },
438        }
439    }
440}
441
442impl Deserializable for FeltRepresentation {
443    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
444        let tag = source.read_u8()?;
445        match tag {
446            0 => {
447                let identifier = Option::<FieldIdentifier>::read_from(source)?;
448                let value = Felt::read_from(source)?;
449                Ok(FeltRepresentation::Value { value, identifier })
450            },
451            1 => {
452                let identifier = FieldIdentifier::read_from(source)?;
453                let r#type = TemplateType::read_from(source)?;
454                Ok(FeltRepresentation::Template { r#type, identifier })
455            },
456            other => Err(DeserializationError::InvalidValue(format!(
457                "unknown tag '{other}' for FeltRepresentation"
458            ))),
459        }
460    }
461}
462
463// MAP REPRESENTATION
464// ================================================================================================
465
466/// Supported map representations for a component's storage entries.
467#[derive(Debug, Clone, PartialEq, Eq)]
468#[cfg_attr(feature = "std", derive(::serde::Deserialize, ::serde::Serialize))]
469pub enum MapRepresentation {
470    /// A map whose contents are provided during instantiation via placeholders.
471    Template {
472        /// The human-readable identifier of the map slot.
473        identifier: FieldIdentifier,
474    },
475    /// A map with statically defined key/value pairs.
476    Value {
477        /// The human-readable identifier of the map slot.
478        identifier: FieldIdentifier,
479        /// Storage map entries, consisting of a list of keys associated with their values.
480        entries: Vec<MapEntry>,
481    },
482}
483
484impl MapRepresentation {
485    /// Creates a new `MapRepresentation` from a vector of map entries.
486    pub fn new_value(entries: Vec<MapEntry>, name: impl Into<StorageValueName>) -> Self {
487        MapRepresentation::Value {
488            entries,
489            identifier: FieldIdentifier::with_name(name.into()),
490        }
491    }
492
493    /// Creates a new templated map representation.
494    pub fn new_template(name: impl Into<StorageValueName>) -> Self {
495        MapRepresentation::Template {
496            identifier: FieldIdentifier::with_name(name.into()),
497        }
498    }
499
500    /// Sets the description of the [`MapRepresentation`] and returns `self`.
501    pub fn with_description(self, description: impl Into<String>) -> Self {
502        match self {
503            MapRepresentation::Template { identifier } => MapRepresentation::Template {
504                identifier: FieldIdentifier {
505                    name: identifier.name,
506                    description: Some(description.into()),
507                },
508            },
509            MapRepresentation::Value { identifier, entries } => MapRepresentation::Value {
510                entries,
511                identifier: FieldIdentifier {
512                    name: identifier.name,
513                    description: Some(description.into()),
514                },
515            },
516        }
517    }
518
519    /// Returns an iterator over all of the storage entries' placeholder keys, alongside their
520    /// expected type.
521    pub fn template_requirements(&self) -> TemplateRequirementsIter<'_> {
522        match self {
523            MapRepresentation::Template { identifier } => Box::new(iter::once((
524                identifier.name.clone(),
525                PlaceholderTypeRequirement {
526                    description: identifier.description.clone(),
527                    r#type: TemplateType::storage_map(),
528                },
529            ))),
530            MapRepresentation::Value { identifier, entries } => Box::new(
531                entries
532                    .iter()
533                    .flat_map(move |entry| entry.template_requirements(identifier.name.clone())),
534            ),
535        }
536    }
537
538    /// Returns a reference to map entries.
539    pub fn entries(&self) -> &[MapEntry] {
540        match self {
541            MapRepresentation::Value { entries, .. } => entries,
542            MapRepresentation::Template { .. } => &[],
543        }
544    }
545
546    /// Returns a reference to the map's name within the storage metadata.
547    pub fn name(&self) -> &StorageValueName {
548        match self {
549            MapRepresentation::Template { identifier }
550            | MapRepresentation::Value { identifier, .. } => &identifier.name,
551        }
552    }
553
554    /// Returns a reference to the field's description.
555    pub fn description(&self) -> Option<&String> {
556        match self {
557            MapRepresentation::Template { identifier }
558            | MapRepresentation::Value { identifier, .. } => identifier.description.as_ref(),
559        }
560    }
561
562    /// Returns the number of statically defined key-value pairs in the map.
563    pub fn len(&self) -> usize {
564        match self {
565            MapRepresentation::Value { entries, .. } => entries.len(),
566            MapRepresentation::Template { .. } => 0,
567        }
568    }
569
570    /// Returns `true` if there are no statically defined entries in the map.
571    pub fn is_empty(&self) -> bool {
572        match self {
573            MapRepresentation::Value { entries, .. } => entries.is_empty(),
574            MapRepresentation::Template { .. } => true,
575        }
576    }
577
578    /// Attempts to convert the [MapRepresentation] into a [StorageMap].
579    ///
580    /// If any of the inner elements are templates, their values are retrieved from
581    /// `init_storage_data`, identified by their key.
582    pub fn try_build_map(
583        &self,
584        init_storage_data: &InitStorageData,
585    ) -> Result<StorageMap, AccountComponentTemplateError> {
586        match self {
587            MapRepresentation::Value { identifier, entries } => {
588                let entries = entries
589                    .iter()
590                    .map(|map_entry| {
591                        let key = map_entry
592                            .key()
593                            .try_build_word(init_storage_data, identifier.name.clone())?;
594                        let value = map_entry
595                            .value()
596                            .try_build_word(init_storage_data, identifier.name.clone())?;
597                        Ok((key, value))
598                    })
599                    .collect::<Result<Vec<(Word, Word)>, _>>()?;
600
601                StorageMap::with_entries(entries).map_err(|err| {
602                    AccountComponentTemplateError::StorageMapHasDuplicateKeys(Box::new(err))
603                })
604            },
605            MapRepresentation::Template { identifier } => {
606                if let Some(entries) = init_storage_data.map_entries(&identifier.name) {
607                    return StorageMap::with_entries(entries.clone()).map_err(|err| {
608                        AccountComponentTemplateError::StorageMapHasDuplicateKeys(Box::new(err))
609                    });
610                }
611
612                Err(AccountComponentTemplateError::PlaceholderValueNotProvided(
613                    identifier.name.clone(),
614                ))
615            },
616        }
617    }
618
619    /// Validates the map representation by checking for duplicate keys and placeholder validity.
620    pub(crate) fn validate(&self) -> Result<(), AccountComponentTemplateError> {
621        match self {
622            MapRepresentation::Template { .. } => Ok(()),
623            MapRepresentation::Value { entries, .. } => {
624                let mut seen_keys = BTreeSet::new();
625                for entry in entries.iter() {
626                    entry.key().validate()?;
627                    entry.value().validate()?;
628                    if let Ok(key) = entry
629                        .key()
630                        .try_build_word(&InitStorageData::default(), StorageValueName::empty())
631                        && !seen_keys.insert(key)
632                    {
633                        return Err(AccountComponentTemplateError::StorageMapHasDuplicateKeys(
634                            Box::from(format!("key `{key}` is duplicated")),
635                        ));
636                    }
637                }
638
639                Ok(())
640            },
641        }
642    }
643}
644
645impl Serializable for MapRepresentation {
646    fn write_into<W: ByteWriter>(&self, target: &mut W) {
647        match self {
648            MapRepresentation::Value { identifier, entries } => {
649                target.write_u8(0u8);
650                target.write(identifier);
651                target.write(entries);
652            },
653            MapRepresentation::Template { identifier } => {
654                target.write_u8(1u8);
655                target.write(identifier);
656            },
657        }
658    }
659}
660
661impl Deserializable for MapRepresentation {
662    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
663        let tag = source.read_u8()?;
664        match tag {
665            0 => {
666                let identifier = FieldIdentifier::read_from(source)?;
667                let entries = Vec::<MapEntry>::read_from(source)?;
668                Ok(MapRepresentation::Value { entries, identifier })
669            },
670            1 => {
671                let identifier = FieldIdentifier::read_from(source)?;
672                Ok(MapRepresentation::Template { identifier })
673            },
674            other => Err(DeserializationError::InvalidValue(format!(
675                "unknown tag '{other}' for MapRepresentation"
676            ))),
677        }
678    }
679}
680
681// MULTI-WORD VALUE
682// ================================================================================================
683
684/// Defines how multi-slot values are represented within the component's storage description.
685///
686/// Each multi-word value representation can be:
687/// - A predefined value that may contain a hardcoded word or a mix of fixed and templated felts.
688#[derive(Debug, Clone, PartialEq, Eq)]
689pub enum MultiWordRepresentation {
690    // TODO: Once there are multi-slot template types, add a MultiWordRepresentation::Template
691    // here
692    Value {
693        /// The human-readable name of this multi-slot entry.
694        identifier: FieldIdentifier,
695        /// A list of values to fill the logical slot, with a length equal to the number of slots.
696        values: Vec<[FeltRepresentation; 4]>,
697    },
698}
699
700impl MultiWordRepresentation {
701    /// Returns the number of words in this representation.
702    pub fn num_words(&self) -> usize {
703        match self {
704            MultiWordRepresentation::Value { values, .. } => values.len(),
705        }
706    }
707
708    /// Validates the multi-slot value.
709    pub fn validate(&self) -> Result<(), AccountComponentTemplateError> {
710        match self {
711            MultiWordRepresentation::Value { values, .. } => {
712                for slot_word in values {
713                    for felt_in_slot in slot_word {
714                        felt_in_slot.validate()?;
715                    }
716                }
717            },
718        }
719        Ok(())
720    }
721}
722
723impl Serializable for MultiWordRepresentation {
724    fn write_into<W: ByteWriter>(&self, target: &mut W) {
725        match self {
726            MultiWordRepresentation::Value { identifier, values } => {
727                target.write_u8(0u8);
728                target.write(identifier);
729                target.write(values);
730            },
731        }
732    }
733}
734impl Deserializable for MultiWordRepresentation {
735    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
736        let variant_tag = source.read_u8()?;
737        match variant_tag {
738            0 => {
739                let identifier: FieldIdentifier = source.read()?;
740                let values: Vec<[FeltRepresentation; 4]> = source.read()?;
741                Ok(MultiWordRepresentation::Value { identifier, values })
742            },
743            _ => Err(DeserializationError::InvalidValue(format!(
744                "unknown variant tag '{variant_tag}' for MultiWordRepresentation"
745            ))),
746        }
747    }
748}