miden_protocol/account/patch/storage/
value_patch.rs1use super::slot_patch::MergeOutcome;
2use crate::Word;
3use crate::account::{StoragePatchOperation, StorageSlotName};
4use crate::errors::AccountPatchError;
5use crate::utils::serde::{
6 ByteReader,
7 ByteWriter,
8 Deserializable,
9 DeserializationError,
10 Serializable,
11};
12
13#[derive(Debug, Clone, PartialEq, Eq)]
18pub enum StorageValuePatch {
19 Create { value: Word },
21
22 Update { value: Word },
24
25 Remove,
27}
28
29impl StorageValuePatch {
30 const CREATE: u8 = 0;
34 const UPDATE: u8 = 1;
35 const REMOVE: u8 = 2;
36
37 pub fn value(&self) -> Option<Word> {
43 match self {
44 StorageValuePatch::Create { value } | StorageValuePatch::Update { value } => {
45 Some(*value)
46 },
47 StorageValuePatch::Remove => None,
48 }
49 }
50
51 pub fn patch_op(&self) -> StoragePatchOperation {
53 match self {
54 StorageValuePatch::Create { .. } => StoragePatchOperation::Create,
55 StorageValuePatch::Update { .. } => StoragePatchOperation::Update,
56 StorageValuePatch::Remove => StoragePatchOperation::Remove,
57 }
58 }
59
60 pub(super) fn committed_value(&self) -> Word {
67 self.value().unwrap_or_default()
68 }
69
70 fn compact_value(value: &Word) -> Option<&Word> {
73 (!value.is_empty()).then_some(value)
74 }
75
76 pub(super) fn merge(
81 &mut self,
82 slot_name: &StorageSlotName,
83 other: Self,
84 ) -> Result<MergeOutcome, AccountPatchError> {
85 match (self, other) {
86 (StorageValuePatch::Create { .. }, StorageValuePatch::Create { .. }) => {
89 return Err(AccountPatchError::StoragePatchMergeDoubleCreate(slot_name.clone()));
90 },
91 (
92 StorageValuePatch::Create { value: current },
93 StorageValuePatch::Update { value: incoming },
94 ) => *current = incoming,
95 (StorageValuePatch::Create { .. }, StorageValuePatch::Remove) => {
96 return Ok(MergeOutcome::Remove);
97 },
98
99 (StorageValuePatch::Update { .. }, StorageValuePatch::Create { .. }) => {
102 return Err(AccountPatchError::StoragePatchMergeCreateAfterUpdate(
103 slot_name.clone(),
104 ));
105 },
106 (
107 StorageValuePatch::Update { value: current },
108 StorageValuePatch::Update { value: incoming },
109 ) => *current = incoming,
110 (current @ StorageValuePatch::Update { .. }, StorageValuePatch::Remove) => {
111 *current = StorageValuePatch::Remove
112 },
113
114 (current @ StorageValuePatch::Remove, incoming @ StorageValuePatch::Create { .. }) => {
117 *current = incoming;
118 },
119 (StorageValuePatch::Remove, StorageValuePatch::Update { .. }) => {
120 return Err(AccountPatchError::StoragePatchMergeUpdateAfterRemove(
121 slot_name.clone(),
122 ));
123 },
124 (StorageValuePatch::Remove, StorageValuePatch::Remove) => {
125 return Err(AccountPatchError::StoragePatchMergeDoubleRemove(slot_name.clone()));
126 },
127 }
128
129 Ok(MergeOutcome::Keep)
130 }
131}
132
133impl Serializable for StorageValuePatch {
134 fn write_into<W: ByteWriter>(&self, target: &mut W) {
135 match self {
136 StorageValuePatch::Create { value } => {
137 target.write_u8(Self::CREATE);
138 target.write(Self::compact_value(value));
139 },
140 StorageValuePatch::Update { value } => {
141 target.write_u8(Self::UPDATE);
142 target.write(Self::compact_value(value));
143 },
144 StorageValuePatch::Remove => {
145 target.write_u8(Self::REMOVE);
146 },
147 }
148 }
149
150 fn get_size_hint(&self) -> usize {
151 let tag_size = 0u8.get_size_hint();
152 match self {
153 StorageValuePatch::Create { value } | StorageValuePatch::Update { value } => {
154 tag_size + Self::compact_value(value).get_size_hint()
155 },
156 StorageValuePatch::Remove => tag_size,
157 }
158 }
159}
160
161impl Deserializable for StorageValuePatch {
162 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
163 match source.read_u8()? {
164 Self::CREATE => Ok(Self::Create {
165 value: source.read::<Option<Word>>()?.unwrap_or_default(),
166 }),
167 Self::UPDATE => Ok(Self::Update {
168 value: source.read::<Option<Word>>()?.unwrap_or_default(),
169 }),
170 Self::REMOVE => Ok(Self::Remove),
171 other => Err(DeserializationError::InvalidValue(format!(
172 "unknown storage value patch variant {other}"
173 ))),
174 }
175 }
176}