-
Notifications
You must be signed in to change notification settings - Fork 207
feat(schema): support legacy & non legacy ser #3356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,8 +21,8 @@ pub struct Member { | |
| } | ||
|
|
||
| impl Member { | ||
| pub fn serialize(&self) -> Result<Vec<Felt>, PrimitiveError> { | ||
| self.ty.serialize() | ||
| pub fn serialize(&self, legacy_storage: bool) -> Result<Vec<Felt>, PrimitiveError> { | ||
| self.ty.serialize(legacy_storage) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -139,52 +139,63 @@ impl Ty { | |
| } | ||
| } | ||
|
|
||
| pub fn serialize(&self) -> Result<Vec<Felt>, PrimitiveError> { | ||
| pub fn serialize(&self, legacy_storage: bool) -> Result<Vec<Felt>, PrimitiveError> { | ||
| let mut felts = vec![]; | ||
|
|
||
| fn serialize_inner(ty: &Ty, felts: &mut Vec<Felt>) -> Result<(), PrimitiveError> { | ||
| fn serialize_inner( | ||
| ty: &Ty, | ||
| felts: &mut Vec<Felt>, | ||
| legacy_storage: bool, | ||
| ) -> Result<(), PrimitiveError> { | ||
| match ty { | ||
| Ty::Primitive(c) => { | ||
| felts.extend(c.serialize()?); | ||
| } | ||
| Ty::Struct(s) => { | ||
| for child in &s.children { | ||
| serialize_inner(&child.ty, felts)?; | ||
| serialize_inner(&child.ty, felts, child.key || legacy_storage)?; | ||
| } | ||
| } | ||
| Ty::Enum(e) => { | ||
| let option = e | ||
| .option | ||
| .map(|v| Ok(vec![Felt::from(v)])) | ||
| .unwrap_or(Err(PrimitiveError::MissingFieldElement))?; | ||
| felts.extend(option); | ||
|
|
||
| // TODO: we should increment `option` is the model does not use the legacy | ||
| // storage system. But is this `serialize` function still | ||
| // used ? | ||
|
|
||
| for EnumOption { ty, .. } in &e.options { | ||
| serialize_inner(ty, felts)?; | ||
| if let Some(option) = e.option { | ||
| // For new storage system, enum variant indices start from 1 | ||
| let mut serialized_option = Felt::from(option); | ||
| if !legacy_storage { | ||
| serialized_option += Felt::ONE; | ||
| } | ||
| felts.push(serialized_option); | ||
|
|
||
| // Only serialize the selected option | ||
| if let Some(selected_option) = e.options.get(option as usize) { | ||
| serialize_inner(&selected_option.ty, felts, legacy_storage)?; | ||
| } | ||
| } else { | ||
| // For uninitialized enum in new storage system, use 0 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure about that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But doesn't the new storage system actually allow enums to be None, hence the whole goal of bringing this new layout change? So that, in the case of an uninitialized enum, the option set is correctly None. Because here we're just mimicking the exact same behaviour as the deserialize, but in the other way. So if someone deserializes a new layout Enum with a selector of 0, then tries to serialize it again, it will raise an error and lead to inconsistency across the two functions. We need to either not allow enum options to be None, or allow them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In fact, the real behaviour at dojo-core level, for a DojoStore model (so non legacy one) is:
Unfortunately, the schema (Ty) provided by the So, at sozo level, when we deserialize an uninitialized enum (because we may read uninitialized storage when calling At torii level, I don't know why you may have to serialize some model data. I thought only the deserialize() function was used. Could you tell me more about that ? But, for me, it doesn't make sense to serialize an uninitialized enum. A possible use case would be to override an existing enum in the world storage to erase it but there is already So, yes, if you could tell me the usecases you see in Torii for that, it could help me to understand the needs. |
||
| if !legacy_storage { | ||
| felts.push(Felt::ZERO); | ||
| } else { | ||
| return Err(PrimitiveError::MissingFieldElement); | ||
| } | ||
| } | ||
| } | ||
| Ty::Tuple(tys) => { | ||
| for ty in tys { | ||
| serialize_inner(ty, felts)?; | ||
| serialize_inner(ty, felts, legacy_storage)?; | ||
| } | ||
| } | ||
| Ty::Array(items_ty) => { | ||
| let _ = serialize_inner( | ||
| &Ty::Primitive(Primitive::U32(Some(items_ty.len().try_into().unwrap()))), | ||
| felts, | ||
| legacy_storage, | ||
| ); | ||
| for item_ty in items_ty { | ||
| serialize_inner(item_ty, felts)?; | ||
| serialize_inner(item_ty, felts, legacy_storage)?; | ||
| } | ||
| } | ||
| Ty::FixedSizeArray((items_ty, size)) => { | ||
| let item_ty = &items_ty[0]; | ||
| for _ in 0..*size { | ||
| serialize_inner(item_ty, felts)?; | ||
| Ty::FixedSizeArray((items_ty, _size)) => { | ||
| for elem in items_ty { | ||
| serialize_inner(elem, felts, legacy_storage)?; | ||
| } | ||
| } | ||
| Ty::ByteArray(bytes) => { | ||
|
|
@@ -196,7 +207,7 @@ impl Ty { | |
| Ok(()) | ||
| } | ||
|
|
||
| serialize_inner(self, &mut felts)?; | ||
| serialize_inner(self, &mut felts, legacy_storage)?; | ||
|
|
||
| Ok(felts) | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Respect key semantics in Member::serialize
ohayo sensei,
Member::serializenow exposes thelegacy_storageflag but ignoresself.key. Callers that passlegacy_storage = falsewhen serializing key members will emit the new 1-based encoding, whiledeserializeon Line 231 still forces legacy semantics viachild.key || legacy_storage, breaking round-trips for key enums/structs. Please mirror that predicate here.self.ty.serialize(legacy_storage) + self.ty.serialize(self.key || legacy_storage)🤖 Prompt for AI Agents