From d5e28cb3650fb7dd0fd63d4e2bde1134a497d39b Mon Sep 17 00:00:00 2001 From: EjembiEmmanuel Date: Sun, 7 Jul 2024 20:34:13 +0100 Subject: [PATCH 01/13] feat: add support for signed integers --- .../dojo-core/src/database/introspect.cairo | 60 +++++++ crates/dojo-types/src/primitive.rs | 146 +++++++++++++++--- crates/dojo-types/src/schema.rs | 25 +++ crates/sozo/ops/src/model.rs | 23 ++- crates/torii/core/src/model.rs | 38 ++++- crates/torii/grpc/src/types/schema.rs | 11 +- 6 files changed, 269 insertions(+), 34 deletions(-) diff --git a/crates/dojo-core/src/database/introspect.cairo b/crates/dojo-core/src/database/introspect.cairo index 1eb1e2a1ad..8cd2332b17 100644 --- a/crates/dojo-core/src/database/introspect.cairo +++ b/crates/dojo-core/src/database/introspect.cairo @@ -156,6 +156,66 @@ impl Introspect_u256 of Introspect { } } +impl Introspect_i8 of Introspect { + fn size() -> Option { + Option::Some(1) + } + fn layout() -> Layout { + Layout::Fixed(array![251].span()) + } + fn ty() -> Ty { + Ty::Primitive('i8') + } +} + +impl Introspect_i16 of Introspect { + fn size() -> Option { + Option::Some(1) + } + fn layout() -> Layout { + Layout::Fixed(array![251].span()) + } + fn ty() -> Ty { + Ty::Primitive('i16') + } +} + +impl Introspect_i32 of Introspect { + fn size() -> Option { + Option::Some(1) + } + fn layout() -> Layout { + Layout::Fixed(array![251].span()) + } + fn ty() -> Ty { + Ty::Primitive('i32') + } +} + +impl Introspect_i64 of Introspect { + fn size() -> Option { + Option::Some(1) + } + fn layout() -> Layout { + Layout::Fixed(array![251].span()) + } + fn ty() -> Ty { + Ty::Primitive('i64') + } +} + +impl Introspect_i128 of Introspect { + fn size() -> Option { + Option::Some(1) + } + fn layout() -> Layout { + Layout::Fixed(array![251].span()) + } + fn ty() -> Ty { + Ty::Primitive('i128') + } +} + impl Introspect_address of Introspect { fn size() -> Option { Option::Some(1) diff --git a/crates/dojo-types/src/primitive.rs b/crates/dojo-types/src/primitive.rs index 6192c107e3..5b367f3bbd 100644 --- a/crates/dojo-types/src/primitive.rs +++ b/crates/dojo-types/src/primitive.rs @@ -25,6 +25,11 @@ use strum_macros::{AsRefStr, Display, EnumIter, EnumString}; #[strum(serialize_all = "lowercase")] #[serde(rename_all = "lowercase")] pub enum Primitive { + I8(Option), + I16(Option), + I32(Option), + I64(Option), + I128(Option), U8(Option), U16(Option), U32(Option), @@ -96,26 +101,36 @@ macro_rules! as_primitive { } impl Primitive { + as_primitive!(as_i8, I8, i8); + as_primitive!(as_i16, I16, i16); + as_primitive!(as_i32, I32, i32); + as_primitive!(as_i64, I64, i64); + as_primitive!(as_i128, I128, i128); as_primitive!(as_u8, U8, u8); as_primitive!(as_u16, U16, u16); as_primitive!(as_u32, U32, u32); as_primitive!(as_u64, U64, u64); as_primitive!(as_u128, U128, u128); as_primitive!(as_u256, U256, U256); - as_primitive!(as_bool, Bool, bool); as_primitive!(as_usize, USize, u32); + as_primitive!(as_bool, Bool, bool); as_primitive!(as_felt252, Felt252, Felt); as_primitive!(as_class_hash, ClassHash, Felt); as_primitive!(as_contract_address, ContractAddress, Felt); + set_primitive!(set_i8, I8, i8); + set_primitive!(set_i16, I16, i16); + set_primitive!(set_i32, I32, i32); + set_primitive!(set_i64, I64, i64); + set_primitive!(set_i128, I128, i128); set_primitive!(set_u8, U8, u8); set_primitive!(set_u16, U16, u16); set_primitive!(set_u32, U32, u32); set_primitive!(set_u64, U64, u64); set_primitive!(set_u128, U128, u128); set_primitive!(set_u256, U256, U256); - set_primitive!(set_bool, Bool, bool); set_primitive!(set_usize, USize, u32); + set_primitive!(set_bool, Bool, bool); set_primitive!(set_felt252, Felt252, Felt); set_primitive!(set_class_hash, ClassHash, Felt); set_primitive!(set_contract_address, ContractAddress, Felt); @@ -133,6 +148,11 @@ impl Primitive { Primitive::Felt252(_) => 8, Primitive::ClassHash(_) => 9, Primitive::ContractAddress(_) => 10, + Primitive::I8(_) => 11, + Primitive::I16(_) => 12, + Primitive::I32(_) => 13, + Primitive::I64(_) => 14, + Primitive::I128(_) => 15, } } @@ -142,7 +162,12 @@ impl Primitive { pub fn to_sql_type(&self) -> SqlType { match self { - Primitive::U8(_) + Primitive::I8(_) + | Primitive::I16(_) + | Primitive::I32(_) + | Primitive::I64(_) + | Primitive::I128(_) + | Primitive::U8(_) | Primitive::U16(_) | Primitive::U32(_) | Primitive::USize(_) @@ -165,7 +190,12 @@ impl Primitive { } match self { - Primitive::U8(_) + Primitive::I8(_) + | Primitive::I16(_) + | Primitive::I32(_) + | Primitive::I64(_) + | Primitive::I128(_) + | Primitive::U8(_) | Primitive::U16(_) | Primitive::U32(_) | Primitive::USize(_) @@ -198,6 +228,46 @@ impl Primitive { } match self { + Primitive::I8(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_i8().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + + Primitive::I16(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_i16().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + + Primitive::I32(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_i32().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + + Primitive::I64(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_i64().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + + Primitive::I128(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_i128().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + Primitive::U8(ref mut value) => { let felt = felts.remove(0); *value = Some(felt.to_u8().ok_or_else(|| PrimitiveError::ValueOutOfRange { @@ -230,19 +300,6 @@ impl Primitive { })?); } - Primitive::USize(ref mut value) => { - let felt = felts.remove(0); - *value = Some(felt.to_u32().ok_or_else(|| PrimitiveError::ValueOutOfRange { - r#type: type_name::(), - value: felt, - })?); - } - - Primitive::Bool(ref mut value) => { - let raw = felts.remove(0); - *value = Some(raw == Felt::ONE); - } - Primitive::U128(ref mut value) => { let felt = felts.remove(0); *value = Some(felt.to_u128().ok_or_else(|| PrimitiveError::ValueOutOfRange { @@ -265,6 +322,19 @@ impl Primitive { *value = Some(U256::from_be_bytes(bytes)); } + Primitive::USize(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_u32().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + + Primitive::Bool(ref mut value) => { + let raw = felts.remove(0); + *value = Some(raw == Felt::ONE); + } + Primitive::ContractAddress(ref mut value) => { *value = Some(felts.remove(0)); } @@ -283,6 +353,21 @@ impl Primitive { pub fn serialize(&self) -> Result, PrimitiveError> { match self { + Primitive::I8(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::I16(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::I32(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::I64(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::I128(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), Primitive::U8(value) => value .map(|v| Ok(vec![Felt::from(v)])) .unwrap_or(Err(PrimitiveError::MissingFieldElement)), @@ -295,12 +380,6 @@ impl Primitive { Primitive::U64(value) => value .map(|v| Ok(vec![Felt::from(v)])) .unwrap_or(Err(PrimitiveError::MissingFieldElement)), - Primitive::USize(value) => value - .map(|v| Ok(vec![Felt::from(v)])) - .unwrap_or(Err(PrimitiveError::MissingFieldElement)), - Primitive::Bool(value) => value - .map(|v| Ok(vec![if v { Felt::ONE } else { Felt::ZERO }])) - .unwrap_or(Err(PrimitiveError::MissingFieldElement)), Primitive::U128(value) => value .map(|v| Ok(vec![Felt::from(v)])) .unwrap_or(Err(PrimitiveError::MissingFieldElement)), @@ -318,6 +397,12 @@ impl Primitive { Ok(vec![value0, value1]) }) .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::USize(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::Bool(value) => value + .map(|v| Ok(vec![if v { Felt::ONE } else { Felt::ZERO }])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), Primitive::ContractAddress(value) => { value.map(|v| Ok(vec![v])).unwrap_or(Err(PrimitiveError::MissingFieldElement)) } @@ -364,6 +449,21 @@ mod tests { #[test] fn inner_value_getter_setter() { + let mut primitive = Primitive::I8(None); + primitive.set_i8(Some(-1i8)).unwrap(); + assert_eq!(primitive.as_i8(), Some(-1i8)); + let mut primitive = Primitive::I16(None); + primitive.set_i16(Some(-1i16)).unwrap(); + assert_eq!(primitive.as_i16(), Some(-1i16)); + let mut primitive = Primitive::I32(None); + primitive.set_i32(Some(-1i32)).unwrap(); + assert_eq!(primitive.as_i32(), Some(-1i32)); + let mut primitive = Primitive::I64(None); + primitive.set_i64(Some(-1i64)).unwrap(); + assert_eq!(primitive.as_i64(), Some(-1i64)); + let mut primitive = Primitive::I128(None); + primitive.set_i128(Some(-1i128)).unwrap(); + assert_eq!(primitive.as_i128(), Some(-1i128)); let mut primitive = Primitive::U8(None); primitive.set_u8(Some(1u8)).unwrap(); assert_eq!(primitive.as_u8(), Some(1u8)); diff --git a/crates/dojo-types/src/schema.rs b/crates/dojo-types/src/schema.rs index 162ce295c1..8be03760fb 100644 --- a/crates/dojo-types/src/schema.rs +++ b/crates/dojo-types/src/schema.rs @@ -360,6 +360,31 @@ fn format_member(m: &Member) -> String { if let Ty::Primitive(ty) = &m.ty { match ty { + Primitive::I8(value) => { + if let Some(value) = value { + str.push_str(&format!(" = {}", value)); + } + } + Primitive::I16(value) => { + if let Some(value) = value { + str.push_str(&format!(" = {}", value)); + } + } + Primitive::I32(value) => { + if let Some(value) = value { + str.push_str(&format!(" = {}", value)); + } + } + Primitive::I64(value) => { + if let Some(value) = value { + str.push_str(&format!(" = {}", value)); + } + } + Primitive::I128(value) => { + if let Some(value) = value { + str.push_str(&format!(" = {}", value)); + } + } Primitive::U8(value) => { if let Some(value) = value { str.push_str(&format!(" = {}", value)); diff --git a/crates/sozo/ops/src/model.rs b/crates/sozo/ops/src/model.rs index 8bf245c3ea..7842ba7efa 100644 --- a/crates/sozo/ops/src/model.rs +++ b/crates/sozo/ops/src/model.rs @@ -138,11 +138,19 @@ fn format_layout_ref(type_name: &str) -> String { } fn format_selector(selector: String) -> String { - if selector.starts_with("0x") { format!("[{}]", selector) } else { selector } + if selector.starts_with("0x") { + format!("[{}]", selector) + } else { + selector + } } fn format_name(name: String) -> String { - if !name.is_empty() { format!(" {} ", name) } else { name } + if !name.is_empty() { + format!(" {} ", name) + } else { + name + } } fn format_field(selector: String, name: String, layout: String) -> String { @@ -173,6 +181,11 @@ fn get_name_from_schema(schema: &dojo_types::schema::Ty) -> String { dojo_types::schema::Ty::Struct(s) => s.name.clone(), dojo_types::schema::Ty::Enum(e) => e.name.clone(), dojo_types::schema::Ty::Primitive(p) => match p { + dojo_types::primitive::Primitive::I8(_) => "i8".to_string(), + dojo_types::primitive::Primitive::I16(_) => "i16".to_string(), + dojo_types::primitive::Primitive::I32(_) => "i32".to_string(), + dojo_types::primitive::Primitive::I64(_) => "i64".to_string(), + dojo_types::primitive::Primitive::I128(_) => "i128".to_string(), dojo_types::primitive::Primitive::U8(_) => "u8".to_string(), dojo_types::primitive::Primitive::U16(_) => "u16".to_string(), dojo_types::primitive::Primitive::U32(_) => "u32".to_string(), @@ -395,7 +408,11 @@ fn deep_print_layout( } fn _start_indent(level: usize, start_indent: bool) -> String { - if start_indent { INDENT.repeat(level) } else { "".to_string() } + if start_indent { + INDENT.repeat(level) + } else { + "".to_string() + } } fn format_primitive( diff --git a/crates/torii/core/src/model.rs b/crates/torii/core/src/model.rs index e9d21749fd..53ea9ad370 100644 --- a/crates/torii/core/src/model.rs +++ b/crates/torii/core/src/model.rs @@ -410,13 +410,31 @@ pub fn map_row_to_ty( match ty { Ty::Primitive(primitive) => { match &primitive { - Primitive::Bool(_) => { - let value = row.try_get::(&column_name)?; - primitive.set_bool(Some(value))?; + Primitive::I8(_) => { + let value = row.try_get::(&column_name)?; + primitive.set_i8(Some(value))?; } - Primitive::USize(_) => { - let value = row.try_get::(&column_name)?; - primitive.set_usize(Some(value))?; + Primitive::I16(_) => { + let value = row.try_get::(&column_name)?; + primitive.set_i16(Some(value))?; + } + Primitive::I32(_) => { + let value = row.try_get::(&column_name)?; + primitive.set_i32(Some(value))?; + } + Primitive::I64(_) => { + let value = row.try_get::(&column_name)?; + let hex_str = value.trim_start_matches("0x"); + primitive.set_i64(Some( + i64::from_str_radix(hex_str, 16).map_err(ParseError::ParseIntError)?, + ))?; + } + Primitive::I128(_) => { + let value = row.try_get::(&column_name)?; + let hex_str = value.trim_start_matches("0x"); + primitive.set_i128(Some( + i128::from_str_radix(hex_str, 16).map_err(ParseError::ParseIntError)?, + ))?; } Primitive::U8(_) => { let value = row.try_get::(&column_name)?; @@ -449,6 +467,14 @@ pub fn map_row_to_ty( let hex_str = value.trim_start_matches("0x"); primitive.set_u256(Some(U256::from_be_hex(hex_str)))?; } + Primitive::USize(_) => { + let value = row.try_get::(&column_name)?; + primitive.set_usize(Some(value))?; + } + Primitive::Bool(_) => { + let value = row.try_get::(&column_name)?; + primitive.set_bool(Some(value))?; + } Primitive::Felt252(_) => { let value = row.try_get::(&column_name)?; primitive diff --git a/crates/torii/grpc/src/types/schema.rs b/crates/torii/grpc/src/types/schema.rs index 728a5da5f6..263be28edb 100644 --- a/crates/torii/grpc/src/types/schema.rs +++ b/crates/torii/grpc/src/types/schema.rs @@ -250,18 +250,25 @@ impl TryFrom for proto::types::Primitive { use proto::types::value::ValueType; let value_type = match primitive { - Primitive::Bool(bool) => bool.map(ValueType::BoolValue), + Primitive::I8(i8) => i8.map(|val| ValueType::IntValue(val as i64)), + Primitive::I16(i16) => i16.map(|val| ValueType::IntValue(val as i64)), + Primitive::I32(i32) => i32.map(|val| ValueType::IntValue(val as i64)), + Primitive::I64(i64) => i64.map(ValueType::IntValue), + Primitive::I128(i128) => { + i128.map(|val| ValueType::ByteValue(val.to_be_bytes().to_vec())) + } Primitive::U8(u8) => u8.map(|val| ValueType::UintValue(val as u64)), Primitive::U16(u16) => u16.map(|val| ValueType::UintValue(val as u64)), Primitive::U32(u32) => u32.map(|val| ValueType::UintValue(val as u64)), Primitive::U64(u64) => u64.map(ValueType::UintValue), - Primitive::USize(usize) => usize.map(|val| ValueType::UintValue(val as u64)), Primitive::U128(u128) => { u128.map(|val| ValueType::ByteValue(val.to_be_bytes().to_vec())) } Primitive::U256(u256) => { u256.map(|val| ValueType::ByteValue(val.to_be_bytes().to_vec())) } + Primitive::USize(usize) => usize.map(|val| ValueType::UintValue(val as u64)), + Primitive::Bool(bool) => bool.map(ValueType::BoolValue), Primitive::Felt252(felt) => { felt.map(|val| ValueType::ByteValue(val.to_bytes_be().to_vec())) } From 06c556527a0a64d18849cd78c260c15cb43daf78 Mon Sep 17 00:00:00 2001 From: EjembiEmmanuel Date: Sun, 7 Jul 2024 20:40:18 +0100 Subject: [PATCH 02/13] chore: run scripts/rust_fmt.sh --- scripts/prettier.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/prettier.sh diff --git a/scripts/prettier.sh b/scripts/prettier.sh old mode 100644 new mode 100755 From f5f10c63ebcf9400eac9766d58568743e403f211 Mon Sep 17 00:00:00 2001 From: EjembiEmmanuel Date: Sun, 7 Jul 2024 20:34:13 +0100 Subject: [PATCH 03/13] feat: add support for signed integers --- .../dojo-core/src/database/introspect.cairo | 60 +++++++ crates/dojo-types/src/primitive.rs | 146 +++++++++++++++--- crates/dojo-types/src/schema.rs | 25 +++ crates/sozo/ops/src/model.rs | 23 ++- crates/torii/core/src/model.rs | 38 ++++- crates/torii/grpc/src/types/schema.rs | 11 +- 6 files changed, 269 insertions(+), 34 deletions(-) diff --git a/crates/dojo-core/src/database/introspect.cairo b/crates/dojo-core/src/database/introspect.cairo index 1eb1e2a1ad..8cd2332b17 100644 --- a/crates/dojo-core/src/database/introspect.cairo +++ b/crates/dojo-core/src/database/introspect.cairo @@ -156,6 +156,66 @@ impl Introspect_u256 of Introspect { } } +impl Introspect_i8 of Introspect { + fn size() -> Option { + Option::Some(1) + } + fn layout() -> Layout { + Layout::Fixed(array![251].span()) + } + fn ty() -> Ty { + Ty::Primitive('i8') + } +} + +impl Introspect_i16 of Introspect { + fn size() -> Option { + Option::Some(1) + } + fn layout() -> Layout { + Layout::Fixed(array![251].span()) + } + fn ty() -> Ty { + Ty::Primitive('i16') + } +} + +impl Introspect_i32 of Introspect { + fn size() -> Option { + Option::Some(1) + } + fn layout() -> Layout { + Layout::Fixed(array![251].span()) + } + fn ty() -> Ty { + Ty::Primitive('i32') + } +} + +impl Introspect_i64 of Introspect { + fn size() -> Option { + Option::Some(1) + } + fn layout() -> Layout { + Layout::Fixed(array![251].span()) + } + fn ty() -> Ty { + Ty::Primitive('i64') + } +} + +impl Introspect_i128 of Introspect { + fn size() -> Option { + Option::Some(1) + } + fn layout() -> Layout { + Layout::Fixed(array![251].span()) + } + fn ty() -> Ty { + Ty::Primitive('i128') + } +} + impl Introspect_address of Introspect { fn size() -> Option { Option::Some(1) diff --git a/crates/dojo-types/src/primitive.rs b/crates/dojo-types/src/primitive.rs index 6192c107e3..5b367f3bbd 100644 --- a/crates/dojo-types/src/primitive.rs +++ b/crates/dojo-types/src/primitive.rs @@ -25,6 +25,11 @@ use strum_macros::{AsRefStr, Display, EnumIter, EnumString}; #[strum(serialize_all = "lowercase")] #[serde(rename_all = "lowercase")] pub enum Primitive { + I8(Option), + I16(Option), + I32(Option), + I64(Option), + I128(Option), U8(Option), U16(Option), U32(Option), @@ -96,26 +101,36 @@ macro_rules! as_primitive { } impl Primitive { + as_primitive!(as_i8, I8, i8); + as_primitive!(as_i16, I16, i16); + as_primitive!(as_i32, I32, i32); + as_primitive!(as_i64, I64, i64); + as_primitive!(as_i128, I128, i128); as_primitive!(as_u8, U8, u8); as_primitive!(as_u16, U16, u16); as_primitive!(as_u32, U32, u32); as_primitive!(as_u64, U64, u64); as_primitive!(as_u128, U128, u128); as_primitive!(as_u256, U256, U256); - as_primitive!(as_bool, Bool, bool); as_primitive!(as_usize, USize, u32); + as_primitive!(as_bool, Bool, bool); as_primitive!(as_felt252, Felt252, Felt); as_primitive!(as_class_hash, ClassHash, Felt); as_primitive!(as_contract_address, ContractAddress, Felt); + set_primitive!(set_i8, I8, i8); + set_primitive!(set_i16, I16, i16); + set_primitive!(set_i32, I32, i32); + set_primitive!(set_i64, I64, i64); + set_primitive!(set_i128, I128, i128); set_primitive!(set_u8, U8, u8); set_primitive!(set_u16, U16, u16); set_primitive!(set_u32, U32, u32); set_primitive!(set_u64, U64, u64); set_primitive!(set_u128, U128, u128); set_primitive!(set_u256, U256, U256); - set_primitive!(set_bool, Bool, bool); set_primitive!(set_usize, USize, u32); + set_primitive!(set_bool, Bool, bool); set_primitive!(set_felt252, Felt252, Felt); set_primitive!(set_class_hash, ClassHash, Felt); set_primitive!(set_contract_address, ContractAddress, Felt); @@ -133,6 +148,11 @@ impl Primitive { Primitive::Felt252(_) => 8, Primitive::ClassHash(_) => 9, Primitive::ContractAddress(_) => 10, + Primitive::I8(_) => 11, + Primitive::I16(_) => 12, + Primitive::I32(_) => 13, + Primitive::I64(_) => 14, + Primitive::I128(_) => 15, } } @@ -142,7 +162,12 @@ impl Primitive { pub fn to_sql_type(&self) -> SqlType { match self { - Primitive::U8(_) + Primitive::I8(_) + | Primitive::I16(_) + | Primitive::I32(_) + | Primitive::I64(_) + | Primitive::I128(_) + | Primitive::U8(_) | Primitive::U16(_) | Primitive::U32(_) | Primitive::USize(_) @@ -165,7 +190,12 @@ impl Primitive { } match self { - Primitive::U8(_) + Primitive::I8(_) + | Primitive::I16(_) + | Primitive::I32(_) + | Primitive::I64(_) + | Primitive::I128(_) + | Primitive::U8(_) | Primitive::U16(_) | Primitive::U32(_) | Primitive::USize(_) @@ -198,6 +228,46 @@ impl Primitive { } match self { + Primitive::I8(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_i8().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + + Primitive::I16(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_i16().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + + Primitive::I32(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_i32().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + + Primitive::I64(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_i64().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + + Primitive::I128(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_i128().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + Primitive::U8(ref mut value) => { let felt = felts.remove(0); *value = Some(felt.to_u8().ok_or_else(|| PrimitiveError::ValueOutOfRange { @@ -230,19 +300,6 @@ impl Primitive { })?); } - Primitive::USize(ref mut value) => { - let felt = felts.remove(0); - *value = Some(felt.to_u32().ok_or_else(|| PrimitiveError::ValueOutOfRange { - r#type: type_name::(), - value: felt, - })?); - } - - Primitive::Bool(ref mut value) => { - let raw = felts.remove(0); - *value = Some(raw == Felt::ONE); - } - Primitive::U128(ref mut value) => { let felt = felts.remove(0); *value = Some(felt.to_u128().ok_or_else(|| PrimitiveError::ValueOutOfRange { @@ -265,6 +322,19 @@ impl Primitive { *value = Some(U256::from_be_bytes(bytes)); } + Primitive::USize(ref mut value) => { + let felt = felts.remove(0); + *value = Some(felt.to_u32().ok_or_else(|| PrimitiveError::ValueOutOfRange { + r#type: type_name::(), + value: felt, + })?); + } + + Primitive::Bool(ref mut value) => { + let raw = felts.remove(0); + *value = Some(raw == Felt::ONE); + } + Primitive::ContractAddress(ref mut value) => { *value = Some(felts.remove(0)); } @@ -283,6 +353,21 @@ impl Primitive { pub fn serialize(&self) -> Result, PrimitiveError> { match self { + Primitive::I8(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::I16(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::I32(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::I64(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::I128(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), Primitive::U8(value) => value .map(|v| Ok(vec![Felt::from(v)])) .unwrap_or(Err(PrimitiveError::MissingFieldElement)), @@ -295,12 +380,6 @@ impl Primitive { Primitive::U64(value) => value .map(|v| Ok(vec![Felt::from(v)])) .unwrap_or(Err(PrimitiveError::MissingFieldElement)), - Primitive::USize(value) => value - .map(|v| Ok(vec![Felt::from(v)])) - .unwrap_or(Err(PrimitiveError::MissingFieldElement)), - Primitive::Bool(value) => value - .map(|v| Ok(vec![if v { Felt::ONE } else { Felt::ZERO }])) - .unwrap_or(Err(PrimitiveError::MissingFieldElement)), Primitive::U128(value) => value .map(|v| Ok(vec![Felt::from(v)])) .unwrap_or(Err(PrimitiveError::MissingFieldElement)), @@ -318,6 +397,12 @@ impl Primitive { Ok(vec![value0, value1]) }) .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::USize(value) => value + .map(|v| Ok(vec![Felt::from(v)])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), + Primitive::Bool(value) => value + .map(|v| Ok(vec![if v { Felt::ONE } else { Felt::ZERO }])) + .unwrap_or(Err(PrimitiveError::MissingFieldElement)), Primitive::ContractAddress(value) => { value.map(|v| Ok(vec![v])).unwrap_or(Err(PrimitiveError::MissingFieldElement)) } @@ -364,6 +449,21 @@ mod tests { #[test] fn inner_value_getter_setter() { + let mut primitive = Primitive::I8(None); + primitive.set_i8(Some(-1i8)).unwrap(); + assert_eq!(primitive.as_i8(), Some(-1i8)); + let mut primitive = Primitive::I16(None); + primitive.set_i16(Some(-1i16)).unwrap(); + assert_eq!(primitive.as_i16(), Some(-1i16)); + let mut primitive = Primitive::I32(None); + primitive.set_i32(Some(-1i32)).unwrap(); + assert_eq!(primitive.as_i32(), Some(-1i32)); + let mut primitive = Primitive::I64(None); + primitive.set_i64(Some(-1i64)).unwrap(); + assert_eq!(primitive.as_i64(), Some(-1i64)); + let mut primitive = Primitive::I128(None); + primitive.set_i128(Some(-1i128)).unwrap(); + assert_eq!(primitive.as_i128(), Some(-1i128)); let mut primitive = Primitive::U8(None); primitive.set_u8(Some(1u8)).unwrap(); assert_eq!(primitive.as_u8(), Some(1u8)); diff --git a/crates/dojo-types/src/schema.rs b/crates/dojo-types/src/schema.rs index a9a15b5969..0e41467ba9 100644 --- a/crates/dojo-types/src/schema.rs +++ b/crates/dojo-types/src/schema.rs @@ -361,6 +361,31 @@ fn format_member(m: &Member) -> String { if let Ty::Primitive(ty) = &m.ty { match ty { + Primitive::I8(value) => { + if let Some(value) = value { + str.push_str(&format!(" = {}", value)); + } + } + Primitive::I16(value) => { + if let Some(value) = value { + str.push_str(&format!(" = {}", value)); + } + } + Primitive::I32(value) => { + if let Some(value) = value { + str.push_str(&format!(" = {}", value)); + } + } + Primitive::I64(value) => { + if let Some(value) = value { + str.push_str(&format!(" = {}", value)); + } + } + Primitive::I128(value) => { + if let Some(value) = value { + str.push_str(&format!(" = {}", value)); + } + } Primitive::U8(value) => { if let Some(value) = value { str.push_str(&format!(" = {}", value)); diff --git a/crates/sozo/ops/src/model.rs b/crates/sozo/ops/src/model.rs index ed3a235234..1cab823d96 100644 --- a/crates/sozo/ops/src/model.rs +++ b/crates/sozo/ops/src/model.rs @@ -138,11 +138,19 @@ fn format_layout_ref(type_name: &str) -> String { } fn format_selector(selector: String) -> String { - if selector.starts_with("0x") { format!("[{}]", selector) } else { selector } + if selector.starts_with("0x") { + format!("[{}]", selector) + } else { + selector + } } fn format_name(name: String) -> String { - if !name.is_empty() { format!(" {} ", name) } else { name } + if !name.is_empty() { + format!(" {} ", name) + } else { + name + } } fn format_field(selector: String, name: String, layout: String) -> String { @@ -173,6 +181,11 @@ fn get_name_from_schema(schema: &dojo_types::schema::Ty) -> String { dojo_types::schema::Ty::Struct(s) => s.name.clone(), dojo_types::schema::Ty::Enum(e) => e.name.clone(), dojo_types::schema::Ty::Primitive(p) => match p { + dojo_types::primitive::Primitive::I8(_) => "i8".to_string(), + dojo_types::primitive::Primitive::I16(_) => "i16".to_string(), + dojo_types::primitive::Primitive::I32(_) => "i32".to_string(), + dojo_types::primitive::Primitive::I64(_) => "i64".to_string(), + dojo_types::primitive::Primitive::I128(_) => "i128".to_string(), dojo_types::primitive::Primitive::U8(_) => "u8".to_string(), dojo_types::primitive::Primitive::U16(_) => "u16".to_string(), dojo_types::primitive::Primitive::U32(_) => "u32".to_string(), @@ -395,7 +408,11 @@ fn deep_print_layout( } fn _start_indent(level: usize, start_indent: bool) -> String { - if start_indent { INDENT.repeat(level) } else { "".to_string() } + if start_indent { + INDENT.repeat(level) + } else { + "".to_string() + } } fn format_primitive( diff --git a/crates/torii/core/src/model.rs b/crates/torii/core/src/model.rs index cc449674d6..66090ee660 100644 --- a/crates/torii/core/src/model.rs +++ b/crates/torii/core/src/model.rs @@ -427,13 +427,31 @@ pub fn map_row_to_ty( match ty { Ty::Primitive(primitive) => { match &primitive { - Primitive::Bool(_) => { - let value = row.try_get::(&column_name)?; - primitive.set_bool(Some(value))?; + Primitive::I8(_) => { + let value = row.try_get::(&column_name)?; + primitive.set_i8(Some(value))?; } - Primitive::USize(_) => { - let value = row.try_get::(&column_name)?; - primitive.set_usize(Some(value))?; + Primitive::I16(_) => { + let value = row.try_get::(&column_name)?; + primitive.set_i16(Some(value))?; + } + Primitive::I32(_) => { + let value = row.try_get::(&column_name)?; + primitive.set_i32(Some(value))?; + } + Primitive::I64(_) => { + let value = row.try_get::(&column_name)?; + let hex_str = value.trim_start_matches("0x"); + primitive.set_i64(Some( + i64::from_str_radix(hex_str, 16).map_err(ParseError::ParseIntError)?, + ))?; + } + Primitive::I128(_) => { + let value = row.try_get::(&column_name)?; + let hex_str = value.trim_start_matches("0x"); + primitive.set_i128(Some( + i128::from_str_radix(hex_str, 16).map_err(ParseError::ParseIntError)?, + ))?; } Primitive::U8(_) => { let value = row.try_get::(&column_name)?; @@ -466,6 +484,14 @@ pub fn map_row_to_ty( let hex_str = value.trim_start_matches("0x"); primitive.set_u256(Some(U256::from_be_hex(hex_str)))?; } + Primitive::USize(_) => { + let value = row.try_get::(&column_name)?; + primitive.set_usize(Some(value))?; + } + Primitive::Bool(_) => { + let value = row.try_get::(&column_name)?; + primitive.set_bool(Some(value))?; + } Primitive::Felt252(_) => { let value = row.try_get::(&column_name)?; primitive diff --git a/crates/torii/grpc/src/types/schema.rs b/crates/torii/grpc/src/types/schema.rs index 086fbdf530..8f63d746d0 100644 --- a/crates/torii/grpc/src/types/schema.rs +++ b/crates/torii/grpc/src/types/schema.rs @@ -189,18 +189,25 @@ impl From for proto::types::Primitive { use proto::types::value::ValueType; let value_type = match primitive { - Primitive::Bool(bool) => bool.map(ValueType::BoolValue), + Primitive::I8(i8) => i8.map(|val| ValueType::IntValue(val as i64)), + Primitive::I16(i16) => i16.map(|val| ValueType::IntValue(val as i64)), + Primitive::I32(i32) => i32.map(|val| ValueType::IntValue(val as i64)), + Primitive::I64(i64) => i64.map(ValueType::IntValue), + Primitive::I128(i128) => { + i128.map(|val| ValueType::ByteValue(val.to_be_bytes().to_vec())) + } Primitive::U8(u8) => u8.map(|val| ValueType::UintValue(val as u64)), Primitive::U16(u16) => u16.map(|val| ValueType::UintValue(val as u64)), Primitive::U32(u32) => u32.map(|val| ValueType::UintValue(val as u64)), Primitive::U64(u64) => u64.map(ValueType::UintValue), - Primitive::USize(usize) => usize.map(|val| ValueType::UintValue(val as u64)), Primitive::U128(u128) => { u128.map(|val| ValueType::ByteValue(val.to_be_bytes().to_vec())) } Primitive::U256(u256) => { u256.map(|val| ValueType::ByteValue(val.to_be_bytes().to_vec())) } + Primitive::USize(usize) => usize.map(|val| ValueType::UintValue(val as u64)), + Primitive::Bool(bool) => bool.map(ValueType::BoolValue), Primitive::Felt252(felt) => { felt.map(|val| ValueType::ByteValue(val.to_bytes_be().to_vec())) } From 0ad393c0a9873facad740d80356bf52a5dce96a5 Mon Sep 17 00:00:00 2001 From: EjembiEmmanuel Date: Sun, 7 Jul 2024 20:40:18 +0100 Subject: [PATCH 04/13] chore: run scripts/rust_fmt.sh --- scripts/prettier.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/prettier.sh diff --git a/scripts/prettier.sh b/scripts/prettier.sh old mode 100644 new mode 100755 From 0404110e8b573a0be2cc812eacf988bd8af3c27f Mon Sep 17 00:00:00 2001 From: EjembiEmmanuel Date: Mon, 8 Jul 2024 18:05:35 +0100 Subject: [PATCH 05/13] feat: decode signed integer --- bin/sozo/src/commands/calldata_decoder.rs | 34 ++++++++++++++++++++- crates/torii/types-test/src/contracts.cairo | 5 +++ crates/torii/types-test/src/models.cairo | 7 ++++- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/bin/sozo/src/commands/calldata_decoder.rs b/bin/sozo/src/commands/calldata_decoder.rs index 082f50d7cd..e7bdba3968 100644 --- a/bin/sozo/src/commands/calldata_decoder.rs +++ b/bin/sozo/src/commands/calldata_decoder.rs @@ -1,6 +1,7 @@ use anyhow::{self, Result}; +use bigdecimal::FromPrimitive; use cainome::cairo_serde::{ByteArray, CairoSerde}; -use num_bigint::BigUint; +use num_bigint::{BigInt, BigUint}; use starknet::core::types::{Felt, FromStrError}; use starknet::core::utils::cairo_short_string_to_felt; @@ -93,6 +94,28 @@ impl CalldataDecoder for ShortStrCalldataDecoder { } } +struct SignedIntegerCalldataDecoder; +impl CalldataDecoder for SignedIntegerCalldataDecoder { + fn decode(&self, input: &str) -> DecoderResult> { + match input.parse::() { + Ok(value) if value <= i8::MAX as i128 && value >= i8::MIN as i128 => { + Ok(vec![Felt::from_i8(value as i8).expect("Invalid numeric string")]) + } + Ok(value) if value <= i16::MAX as i128 && value >= i16::MIN as i128 => { + Ok(vec![Felt::from_i16(value as i16).expect("Invalid numeric string")]) + } + Ok(value) if value <= i32::MAX as i128 && value >= i32::MIN as i128 => { + Ok(vec![Felt::from_i32(value as i32).expect("Invalid numeric string")]) + } + Ok(value) if value <= i64::MAX as i128 && value >= i64::MIN as i128 => { + Ok(vec![Felt::from_i64(value as i64).expect("Invalid numeric string")]) + } + Ok(value) => Ok(vec![Felt::from_i128(value as i128).expect("Invalid numeric string")]), + Err(_) => Err(CalldataDecoderError::ParseError("Invalid numeric string".to_string())), + } + } +} + /// Decodes a string into a [`Felt`], either from hexadecimal or decimal string. struct DefaultCalldataDecoder; impl CalldataDecoder for DefaultCalldataDecoder { @@ -150,6 +173,7 @@ fn decode_inner(item: &str) -> DecoderResult> { "u256" => U256CalldataDecoder.decode(value)?, "str" => StrCalldataDecoder.decode(value)?, "sstr" => ShortStrCalldataDecoder.decode(value)?, + "-" => SignedIntegerCalldataDecoder.decode(value)?, _ => DefaultCalldataDecoder.decode(item)?, } } else { @@ -236,6 +260,14 @@ mod tests { assert_eq!(result, expected); } + #[test] + fn test_signed_integer_decoder() { + let input = "64"; + let expected = vec![64_i128.into()]; + let result = decode_calldata(input).unwrap(); + assert_eq!(result, expected); + } + #[test] fn test_combined_decoders() { let input = "u256:0x64,str:world,987654,0x123"; diff --git a/crates/torii/types-test/src/contracts.cairo b/crates/torii/types-test/src/contracts.cairo index df0ef8be39..3fcc40c8f2 100644 --- a/crates/torii/types-test/src/contracts.cairo +++ b/crates/torii/types-test/src/contracts.cairo @@ -61,6 +61,11 @@ mod records { Record { record_id, depth: Depth::Zero, + type_i8: record_idx.into(), + type_i16: record_idx.into(), + type_i32: record_idx.into(), + type_i64: record_idx.into(), + type_i128: record_idx.into(), type_u8: record_idx.into(), type_u16: record_idx.into(), type_u32: record_idx.into(), diff --git a/crates/torii/types-test/src/models.cairo b/crates/torii/types-test/src/models.cairo index 17f6fb91a2..489cefd6b1 100644 --- a/crates/torii/types-test/src/models.cairo +++ b/crates/torii/types-test/src/models.cairo @@ -7,6 +7,11 @@ struct Record { #[key] record_id: u32, depth: Depth, + type_i8: i8, + type_i16: i16, + type_i32: i32, + type_i64: i64, + type_i128: i128, type_u8: u8, type_u16: u16, type_u32: u32, @@ -85,7 +90,6 @@ impl DepthIntoFelt252 of Into { } } } - // takes a long time to deploy, uncomment for now // #[derive(Introspect, Copy, Drop, Serde)] // #[dojo::model] @@ -349,3 +353,4 @@ impl DepthIntoFelt252 of Into { // a254: u256, // a255: u256, // } + From 3bb9810441b00eb25e26136d3a20aa18091469b1 Mon Sep 17 00:00:00 2001 From: EjembiEmmanuel Date: Mon, 8 Jul 2024 22:45:32 +0100 Subject: [PATCH 06/13] test: test signed integers decoder --- bin/sozo/src/commands/calldata_decoder.rs | 46 +++++++++++++++++++++-- bin/sozo/src/commands/execute.rs | 1 + 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/bin/sozo/src/commands/calldata_decoder.rs b/bin/sozo/src/commands/calldata_decoder.rs index e7bdba3968..753deed828 100644 --- a/bin/sozo/src/commands/calldata_decoder.rs +++ b/bin/sozo/src/commands/calldata_decoder.rs @@ -1,7 +1,7 @@ use anyhow::{self, Result}; use bigdecimal::FromPrimitive; use cainome::cairo_serde::{ByteArray, CairoSerde}; -use num_bigint::{BigInt, BigUint}; +use num_bigint::BigUint; use starknet::core::types::{Felt, FromStrError}; use starknet::core::utils::cairo_short_string_to_felt; @@ -94,6 +94,7 @@ impl CalldataDecoder for ShortStrCalldataDecoder { } } +/// Decodes a signed integer into a [`Felt`] struct SignedIntegerCalldataDecoder; impl CalldataDecoder for SignedIntegerCalldataDecoder { fn decode(&self, input: &str) -> DecoderResult> { @@ -261,9 +262,46 @@ mod tests { } #[test] - fn test_signed_integer_decoder() { - let input = "64"; - let expected = vec![64_i128.into()]; + fn test_signed_integer_decoder_i8() { + let input = "-64"; + let signed_i8: i8 = -64; + let expected = vec![signed_i8.into()]; + let result = decode_calldata(input).unwrap(); + assert_eq!(result, expected); + } + + #[test] + fn test_signed_integer_decoder_i16() { + let input = "-12345"; + let signed_i16: i16 = -12345; + let expected = vec![signed_i16.into()]; + let result = decode_calldata(input).unwrap(); + assert_eq!(result, expected); + } + + #[test] + fn test_signed_integer_decoder_i32() { + let input = "-987654321"; + let signed_i32: i32 = -987654321; + let expected = vec![signed_i32.into()]; + let result = decode_calldata(input).unwrap(); + assert_eq!(result, expected); + } + + #[test] + fn test_signed_integer_decoder_i64() { + let input = "-1234567890123456789"; + let signed_i64: i64 = -1234567890123456789; + let expected = vec![signed_i64.into()]; + let result = decode_calldata(input).unwrap(); + assert_eq!(result, expected); + } + + #[test] + fn test_signed_integer_decoder_i128() { + let input = "-123456789012345678901234567890123456"; + let signed_i128: i128 = -123456789012345678901234567890123456; + let expected = vec![signed_i128.into()]; let result = decode_calldata(input).unwrap(); assert_eq!(result, expected); } diff --git a/bin/sozo/src/commands/execute.rs b/bin/sozo/src/commands/execute.rs index 9d2dcf4faa..89e7e5fb6d 100644 --- a/bin/sozo/src/commands/execute.rs +++ b/bin/sozo/src/commands/execute.rs @@ -31,6 +31,7 @@ pub struct ExecuteArgs { - u256: A 256-bit unsigned integer. - sstr: A cairo short string. - str: A cairo string (ByteArray). + - -: A signed integer. - no prefix: A cairo felt or any type that fit into one felt.")] pub calldata: Option, From c6ac6fc16c2e543f12e6e0494690d897e40de7ba Mon Sep 17 00:00:00 2001 From: EjembiEmmanuel Date: Tue, 9 Jul 2024 01:24:03 +0100 Subject: [PATCH 07/13] refac: remove redundant type casting --- bin/sozo/src/commands/calldata_decoder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/sozo/src/commands/calldata_decoder.rs b/bin/sozo/src/commands/calldata_decoder.rs index 753deed828..021572b4e8 100644 --- a/bin/sozo/src/commands/calldata_decoder.rs +++ b/bin/sozo/src/commands/calldata_decoder.rs @@ -111,7 +111,7 @@ impl CalldataDecoder for SignedIntegerCalldataDecoder { Ok(value) if value <= i64::MAX as i128 && value >= i64::MIN as i128 => { Ok(vec![Felt::from_i64(value as i64).expect("Invalid numeric string")]) } - Ok(value) => Ok(vec![Felt::from_i128(value as i128).expect("Invalid numeric string")]), + Ok(value) => Ok(vec![Felt::from_i128(value).expect("Invalid numeric string")]), Err(_) => Err(CalldataDecoderError::ParseError("Invalid numeric string".to_string())), } } From 40dc003403b051bff3720e235614a19a2000fdeb Mon Sep 17 00:00:00 2001 From: EjembiEmmanuel Date: Tue, 9 Jul 2024 12:59:08 +0100 Subject: [PATCH 08/13] refac: modify signed integer decoder --- bin/sozo/src/commands/calldata_decoder.rs | 22 +++++----------------- bin/sozo/src/commands/execute.rs | 2 +- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/bin/sozo/src/commands/calldata_decoder.rs b/bin/sozo/src/commands/calldata_decoder.rs index 021572b4e8..b8c3bedff5 100644 --- a/bin/sozo/src/commands/calldata_decoder.rs +++ b/bin/sozo/src/commands/calldata_decoder.rs @@ -1,5 +1,4 @@ use anyhow::{self, Result}; -use bigdecimal::FromPrimitive; use cainome::cairo_serde::{ByteArray, CairoSerde}; use num_bigint::BigUint; use starknet::core::types::{Felt, FromStrError}; @@ -98,21 +97,10 @@ impl CalldataDecoder for ShortStrCalldataDecoder { struct SignedIntegerCalldataDecoder; impl CalldataDecoder for SignedIntegerCalldataDecoder { fn decode(&self, input: &str) -> DecoderResult> { - match input.parse::() { - Ok(value) if value <= i8::MAX as i128 && value >= i8::MIN as i128 => { - Ok(vec![Felt::from_i8(value as i8).expect("Invalid numeric string")]) - } - Ok(value) if value <= i16::MAX as i128 && value >= i16::MIN as i128 => { - Ok(vec![Felt::from_i16(value as i16).expect("Invalid numeric string")]) - } - Ok(value) if value <= i32::MAX as i128 && value >= i32::MIN as i128 => { - Ok(vec![Felt::from_i32(value as i32).expect("Invalid numeric string")]) - } - Ok(value) if value <= i64::MAX as i128 && value >= i64::MIN as i128 => { - Ok(vec![Felt::from_i64(value as i64).expect("Invalid numeric string")]) - } - Ok(value) => Ok(vec![Felt::from_i128(value).expect("Invalid numeric string")]), - Err(_) => Err(CalldataDecoderError::ParseError("Invalid numeric string".to_string())), + if let Ok(value) = input.parse::() { + Ok(vec![value.into()]) + } else { + Err(CalldataDecoderError::ParseError("Invalid numeric string".to_string())) } } } @@ -174,7 +162,7 @@ fn decode_inner(item: &str) -> DecoderResult> { "u256" => U256CalldataDecoder.decode(value)?, "str" => StrCalldataDecoder.decode(value)?, "sstr" => ShortStrCalldataDecoder.decode(value)?, - "-" => SignedIntegerCalldataDecoder.decode(value)?, + "int" => SignedIntegerCalldataDecoder.decode(value)?, _ => DefaultCalldataDecoder.decode(item)?, } } else { diff --git a/bin/sozo/src/commands/execute.rs b/bin/sozo/src/commands/execute.rs index 89e7e5fb6d..145b0b81e0 100644 --- a/bin/sozo/src/commands/execute.rs +++ b/bin/sozo/src/commands/execute.rs @@ -31,7 +31,7 @@ pub struct ExecuteArgs { - u256: A 256-bit unsigned integer. - sstr: A cairo short string. - str: A cairo string (ByteArray). - - -: A signed integer. + - int: A signed integer. - no prefix: A cairo felt or any type that fit into one felt.")] pub calldata: Option, From 4d0f5f370bc3009d94bfbc9a2b87a97f401c7e10 Mon Sep 17 00:00:00 2001 From: EjembiEmmanuel Date: Sun, 14 Jul 2024 17:32:23 +0100 Subject: [PATCH 09/13] feat: implement try from felt for signed integers --- crates/dojo-types/src/lib.rs | 1 + crates/dojo-types/src/primitive.rs | 57 +++++++++++++----- crates/dojo-types/src/primitive_conversion.rs | 58 +++++++++++++++++++ crates/torii/types-test/src/contracts.cairo | 10 ++-- examples/spawn-and-move/src/actions.cairo | 3 +- examples/spawn-and-move/src/models.cairo | 1 + 6 files changed, 109 insertions(+), 21 deletions(-) create mode 100644 crates/dojo-types/src/primitive_conversion.rs diff --git a/crates/dojo-types/src/lib.rs b/crates/dojo-types/src/lib.rs index 3ced1a5883..4a3636f980 100644 --- a/crates/dojo-types/src/lib.rs +++ b/crates/dojo-types/src/lib.rs @@ -7,6 +7,7 @@ use starknet::core::types::Felt; pub mod event; pub mod packing; pub mod primitive; +pub mod primitive_conversion; pub mod schema; pub mod storage; pub mod system; diff --git a/crates/dojo-types/src/primitive.rs b/crates/dojo-types/src/primitive.rs index 5b367f3bbd..b305513f27 100644 --- a/crates/dojo-types/src/primitive.rs +++ b/crates/dojo-types/src/primitive.rs @@ -7,6 +7,8 @@ use starknet::core::types::Felt; use strum::IntoEnumIterator; use strum_macros::{AsRefStr, Display, EnumIter, EnumString}; +use super::primitive_conversion::try_from_felt; + #[derive( AsRefStr, Display, @@ -230,41 +232,36 @@ impl Primitive { match self { Primitive::I8(ref mut value) => { let felt = felts.remove(0); - *value = Some(felt.to_i8().ok_or_else(|| PrimitiveError::ValueOutOfRange { - r#type: type_name::(), - value: felt, + *value = Some(try_from_felt::(felt).map_err(|_| { + PrimitiveError::ValueOutOfRange { r#type: type_name::(), value: felt } })?); } Primitive::I16(ref mut value) => { let felt = felts.remove(0); - *value = Some(felt.to_i16().ok_or_else(|| PrimitiveError::ValueOutOfRange { - r#type: type_name::(), - value: felt, + *value = Some(try_from_felt::(felt).map_err(|_| { + PrimitiveError::ValueOutOfRange { r#type: type_name::(), value: felt } })?); } Primitive::I32(ref mut value) => { let felt = felts.remove(0); - *value = Some(felt.to_i32().ok_or_else(|| PrimitiveError::ValueOutOfRange { - r#type: type_name::(), - value: felt, + *value = Some(try_from_felt::(felt).map_err(|_| { + PrimitiveError::ValueOutOfRange { r#type: type_name::(), value: felt } })?); } Primitive::I64(ref mut value) => { let felt = felts.remove(0); - *value = Some(felt.to_i64().ok_or_else(|| PrimitiveError::ValueOutOfRange { - r#type: type_name::(), - value: felt, + *value = Some(try_from_felt::(felt).map_err(|_| { + PrimitiveError::ValueOutOfRange { r#type: type_name::(), value: felt } })?); } Primitive::I128(ref mut value) => { let felt = felts.remove(0); - *value = Some(felt.to_i128().ok_or_else(|| PrimitiveError::ValueOutOfRange { - r#type: type_name::(), - value: felt, + *value = Some(try_from_felt::(felt).map_err(|_| { + PrimitiveError::ValueOutOfRange { r#type: type_name::(), value: felt } })?); } @@ -425,6 +422,8 @@ mod tests { use super::Primitive; + use super::try_from_felt; + #[test] fn test_u256() { let primitive = Primitive::U256(Some(U256::from_be_hex( @@ -498,4 +497,32 @@ mod tests { primitive.set_contract_address(Some(Felt::from(1u128))).unwrap(); assert_eq!(primitive.as_contract_address(), Some(Felt::from(1u128))); } + + #[test] + fn test_try_from_felt() { + let i_8: i8 = -64; + let felt = Felt::from(i_8); + let signed_integer = try_from_felt::(felt).unwrap(); + assert_eq!(i_8, signed_integer); + + let i_16: i16 = -14293; + let felt = Felt::from(i_16); + let signed_integer = try_from_felt::(felt).unwrap(); + assert_eq!(i_16, signed_integer); + + let i_32: i32 = -194875; + let felt = Felt::from(i_32); + let signed_integer = try_from_felt::(felt).unwrap(); + assert_eq!(i_32, signed_integer); + + let i_64: i64 = -3147483648; + let felt = Felt::from(i_64); + let signed_integer = try_from_felt::(felt).unwrap(); + assert_eq!(i_64, signed_integer); + + let i_128: i128 = -170141183460469231731687303715884105728; + let felt = Felt::from(i_128); + let signed_integer = try_from_felt::(felt).unwrap(); + assert_eq!(i_128, signed_integer); + } } diff --git a/crates/dojo-types/src/primitive_conversion.rs b/crates/dojo-types/src/primitive_conversion.rs new file mode 100644 index 0000000000..38d5ad9b16 --- /dev/null +++ b/crates/dojo-types/src/primitive_conversion.rs @@ -0,0 +1,58 @@ +use core::convert::TryInto; +use starknet::core::types::Felt; + +#[derive(Debug, Copy, Clone)] +pub struct PrimitiveFromFeltError; + +impl core::fmt::Display for PrimitiveFromFeltError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Failed to convert `Felt` into primitive type") + } +} + +const MINUS_TWO_BYTES_REPR: [u8; 32] = [ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 16, 0, 0, 0, 0, 0, 0, 8, +]; + +pub trait FromFelt: Sized { + fn try_from_felt(value: Felt) -> Result; +} + +macro_rules! impl_from_felt { + ($into:ty) => { + impl FromFelt for $into { + fn try_from_felt(value: Felt) -> Result { + let size_of_type = core::mem::size_of::<$into>(); + let bytes_le = value.to_bytes_le(); + + if bytes_le[size_of_type..].iter().all(|&v| v == 0) + && bytes_le[size_of_type - 1] <= 0b01111111 + { + Ok(<$into>::from_le_bytes(bytes_le[..size_of_type].try_into().unwrap())) + } else if bytes_le[size_of_type..] == MINUS_TWO_BYTES_REPR[size_of_type..] + && bytes_le[size_of_type - 1] >= 0b10000000 + { + let offsetted_value = + <$into>::from_le_bytes(bytes_le[..size_of_type].try_into().unwrap()); + + offsetted_value.checked_sub(1).ok_or(PrimitiveFromFeltError) + } else if bytes_le[24..] == [17, 0, 0, 0, 0, 0, 0, 8] { + return Ok(-1); + } else { + Err(PrimitiveFromFeltError) + } + } + } + }; +} + +impl_from_felt!(i8); +impl_from_felt!(i16); +impl_from_felt!(i32); +impl_from_felt!(i64); +impl_from_felt!(i128); + +pub fn try_from_felt(value: Felt) -> Result { + T::try_from_felt(value) +} diff --git a/crates/torii/types-test/src/contracts.cairo b/crates/torii/types-test/src/contracts.cairo index 3fcc40c8f2..d56fc419c6 100644 --- a/crates/torii/types-test/src/contracts.cairo +++ b/crates/torii/types-test/src/contracts.cairo @@ -61,11 +61,11 @@ mod records { Record { record_id, depth: Depth::Zero, - type_i8: record_idx.into(), - type_i16: record_idx.into(), - type_i32: record_idx.into(), - type_i64: record_idx.into(), - type_i128: record_idx.into(), + type_i8: type_felt.try_into().unwrap(), + type_i16: type_felt.try_into().unwrap(), + type_i32: type_felt.try_into().unwrap(), + type_i64: type_felt.try_into().unwrap(), + type_i128: type_felt.try_into().unwrap(), type_u8: record_idx.into(), type_u16: record_idx.into(), type_u32: record_idx.into(), diff --git a/examples/spawn-and-move/src/actions.cairo b/examples/spawn-and-move/src/actions.cairo index a0d7753e0f..c0074cc091 100644 --- a/examples/spawn-and-move/src/actions.cairo +++ b/examples/spawn-and-move/src/actions.cairo @@ -85,7 +85,8 @@ mod actions { let player = get_caller_address(); let items = array![ - PlayerItem { item_id: 1, quantity: 100 }, PlayerItem { item_id: 2, quantity: 50 } + PlayerItem { item_id: 1, quantity: 100, score: 10 }, + PlayerItem { item_id: 2, quantity: 50, score: -32 } ]; let config = PlayerConfig { player, name, items, favorite_item: Option::Some(1), }; diff --git a/examples/spawn-and-move/src/models.cairo b/examples/spawn-and-move/src/models.cairo index 50da9c93f9..4882eb9ddf 100644 --- a/examples/spawn-and-move/src/models.cairo +++ b/examples/spawn-and-move/src/models.cairo @@ -74,6 +74,7 @@ struct Position { struct PlayerItem { item_id: u32, quantity: u32, + score: i32, } #[derive(Drop, Serde)] From aa2ea322eda43845f22e5804cad30f2abc4229cc Mon Sep 17 00:00:00 2001 From: Oche Date: Mon, 15 Jul 2024 10:15:21 +0100 Subject: [PATCH 10/13] Delete scripts/prettier.sh --- scripts/prettier.sh | 6 ------ 1 file changed, 6 deletions(-) delete mode 100755 scripts/prettier.sh diff --git a/scripts/prettier.sh b/scripts/prettier.sh deleted file mode 100755 index adada3aabd..0000000000 --- a/scripts/prettier.sh +++ /dev/null @@ -1,6 +0,0 @@ -#/bin/bash - -# Formats all the markdown and yaml files in the repository. - -prettier --check "**/*.md" -prettier --check "**/*.{yaml,yml}" From 8ca937ecc5d9ac68b1bb0d83ae5b17edbb5d675c Mon Sep 17 00:00:00 2001 From: EjembiEmmanuel Date: Mon, 15 Jul 2024 11:25:48 +0100 Subject: [PATCH 11/13] chore: add comments --- crates/dojo-types/src/primitive.rs | 30 -------------- crates/dojo-types/src/primitive_conversion.rs | 39 +++++++++++++++++++ 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/crates/dojo-types/src/primitive.rs b/crates/dojo-types/src/primitive.rs index b305513f27..24c55c6b40 100644 --- a/crates/dojo-types/src/primitive.rs +++ b/crates/dojo-types/src/primitive.rs @@ -422,8 +422,6 @@ mod tests { use super::Primitive; - use super::try_from_felt; - #[test] fn test_u256() { let primitive = Primitive::U256(Some(U256::from_be_hex( @@ -497,32 +495,4 @@ mod tests { primitive.set_contract_address(Some(Felt::from(1u128))).unwrap(); assert_eq!(primitive.as_contract_address(), Some(Felt::from(1u128))); } - - #[test] - fn test_try_from_felt() { - let i_8: i8 = -64; - let felt = Felt::from(i_8); - let signed_integer = try_from_felt::(felt).unwrap(); - assert_eq!(i_8, signed_integer); - - let i_16: i16 = -14293; - let felt = Felt::from(i_16); - let signed_integer = try_from_felt::(felt).unwrap(); - assert_eq!(i_16, signed_integer); - - let i_32: i32 = -194875; - let felt = Felt::from(i_32); - let signed_integer = try_from_felt::(felt).unwrap(); - assert_eq!(i_32, signed_integer); - - let i_64: i64 = -3147483648; - let felt = Felt::from(i_64); - let signed_integer = try_from_felt::(felt).unwrap(); - assert_eq!(i_64, signed_integer); - - let i_128: i128 = -170141183460469231731687303715884105728; - let felt = Felt::from(i_128); - let signed_integer = try_from_felt::(felt).unwrap(); - assert_eq!(i_128, signed_integer); - } } diff --git a/crates/dojo-types/src/primitive_conversion.rs b/crates/dojo-types/src/primitive_conversion.rs index 38d5ad9b16..373ffcfa74 100644 --- a/crates/dojo-types/src/primitive_conversion.rs +++ b/crates/dojo-types/src/primitive_conversion.rs @@ -1,3 +1,8 @@ +// This is a partial implementation of https://github.com/starknet-io/types-rs/pull/74 +// and is required because signed integers are not coverted from Felt correctly with the +// current implementation +// TODO: remove when https://github.com/starknet-io/types-rs/pull/74 is merged. + use core::convert::TryInto; use starknet::core::types::Felt; @@ -56,3 +61,37 @@ impl_from_felt!(i128); pub fn try_from_felt(value: Felt) -> Result { T::try_from_felt(value) } + +#[cfg(test)] +mod tests { + use super::try_from_felt; + use starknet::core::types::Felt; + + #[test] + fn test_try_from_felt() { + let i_8: i8 = -64; + let felt = Felt::from(i_8); + let signed_integer = try_from_felt::(felt).unwrap(); + assert_eq!(i_8, signed_integer); + + let i_16: i16 = -14293; + let felt = Felt::from(i_16); + let signed_integer = try_from_felt::(felt).unwrap(); + assert_eq!(i_16, signed_integer); + + let i_32: i32 = -194875; + let felt = Felt::from(i_32); + let signed_integer = try_from_felt::(felt).unwrap(); + assert_eq!(i_32, signed_integer); + + let i_64: i64 = -3147483648; + let felt = Felt::from(i_64); + let signed_integer = try_from_felt::(felt).unwrap(); + assert_eq!(i_64, signed_integer); + + let i_128: i128 = -170141183460469231731687303715884105728; + let felt = Felt::from(i_128); + let signed_integer = try_from_felt::(felt).unwrap(); + assert_eq!(i_128, signed_integer); + } +} From 936ba3c1cd6044eee65b7e4d8af4f8709d0612a6 Mon Sep 17 00:00:00 2001 From: glihm Date: Mon, 15 Jul 2024 21:32:25 -0600 Subject: [PATCH 12/13] fix: ensure signed integers are correctly printed --- crates/dojo-types/src/primitive.rs | 15 +++++++++------ crates/dojo-types/src/primitive_conversion.rs | 10 +++++++++- crates/sozo/ops/src/model.rs | 18 +++--------------- .../dojo_examples-PlayerConfig-3adad785.json | 4 ++++ .../dojo_examples-actions-40b6994c.toml | 4 ++-- .../dojo_examples-PlayerConfig-3adad785.toml | 4 ++-- .../dojo_examples-PlayerConfig-3adad785.json | 4 ++++ .../manifests/dev/deployment/manifest.json | 12 ++++++++---- .../manifests/dev/deployment/manifest.toml | 8 ++++---- .../dojo_examples-PlayerConfig-3adad785.json | 4 ++++ .../dojo_examples-actions-40b6994c.toml | 4 ++-- .../dojo_examples-PlayerConfig-3adad785.toml | 4 ++-- 12 files changed, 53 insertions(+), 38 deletions(-) diff --git a/crates/dojo-types/src/primitive.rs b/crates/dojo-types/src/primitive.rs index 24c55c6b40..cfbf241c39 100644 --- a/crates/dojo-types/src/primitive.rs +++ b/crates/dojo-types/src/primitive.rs @@ -63,6 +63,8 @@ pub enum PrimitiveError { CairoSerde(#[from] cainome::cairo_serde::Error), #[error(transparent)] FromUtf8Error(#[from] std::string::FromUtf8Error), + #[error(transparent)] + FeltFromFeltError(#[from] crate::primitive_conversion::PrimitiveFromFeltError), } #[derive(AsRefStr, Debug, Display, EnumString, PartialEq)] @@ -192,12 +194,13 @@ impl Primitive { } match self { - Primitive::I8(_) - | Primitive::I16(_) - | Primitive::I32(_) - | Primitive::I64(_) - | Primitive::I128(_) - | Primitive::U8(_) + Primitive::I8(_) => Ok(format!("{}", try_from_felt::(value[0])?)), + Primitive::I16(_) => Ok(format!("{}", try_from_felt::(value[0])?)), + Primitive::I32(_) => Ok(format!("{}", try_from_felt::(value[0])?)), + Primitive::I64(_) => Ok(format!("{}", try_from_felt::(value[0])?)), + Primitive::I128(_) => Ok(format!("{}", try_from_felt::(value[0])?)), + + Primitive::U8(_) | Primitive::U16(_) | Primitive::U32(_) | Primitive::USize(_) diff --git a/crates/dojo-types/src/primitive_conversion.rs b/crates/dojo-types/src/primitive_conversion.rs index 373ffcfa74..f93be2962e 100644 --- a/crates/dojo-types/src/primitive_conversion.rs +++ b/crates/dojo-types/src/primitive_conversion.rs @@ -4,6 +4,7 @@ // TODO: remove when https://github.com/starknet-io/types-rs/pull/74 is merged. use core::convert::TryInto; + use starknet::core::types::Felt; #[derive(Debug, Copy, Clone)] @@ -15,6 +16,12 @@ impl core::fmt::Display for PrimitiveFromFeltError { } } +impl std::error::Error for PrimitiveFromFeltError { + fn description(&self) -> &str { + "Failed to convert `Felt` into primitive type" + } +} + const MINUS_TWO_BYTES_REPR: [u8; 32] = [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 16, 0, 0, 0, 0, 0, 0, 8, @@ -64,9 +71,10 @@ pub fn try_from_felt(value: Felt) -> Result String { } fn format_selector(selector: String) -> String { - if selector.starts_with("0x") { - format!("[{}]", selector) - } else { - selector - } + if selector.starts_with("0x") { format!("[{}]", selector) } else { selector } } fn format_name(name: String) -> String { - if !name.is_empty() { - format!(" {} ", name) - } else { - name - } + if !name.is_empty() { format!(" {} ", name) } else { name } } fn format_field(selector: String, name: String, layout: String) -> String { @@ -408,11 +400,7 @@ fn deep_print_layout( } fn _start_indent(level: usize, start_indent: bool) -> String { - if start_indent { - INDENT.repeat(level) - } else { - "".to_string() - } + if start_indent { INDENT.repeat(level) } else { "".to_string() } } fn format_primitive( diff --git a/examples/spawn-and-move/manifests/dev/base/abis/models/dojo_examples-PlayerConfig-3adad785.json b/examples/spawn-and-move/manifests/dev/base/abis/models/dojo_examples-PlayerConfig-3adad785.json index 0185cc11f9..8549c6cad8 100644 --- a/examples/spawn-and-move/manifests/dev/base/abis/models/dojo_examples-PlayerConfig-3adad785.json +++ b/examples/spawn-and-move/manifests/dev/base/abis/models/dojo_examples-PlayerConfig-3adad785.json @@ -377,6 +377,10 @@ { "name": "quantity", "type": "core::integer::u32" + }, + { + "name": "score", + "type": "core::integer::i32" } ] }, diff --git a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-actions-40b6994c.toml b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-actions-40b6994c.toml index d570cea3bc..fb28175143 100644 --- a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-actions-40b6994c.toml +++ b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-actions-40b6994c.toml @@ -1,6 +1,6 @@ kind = "DojoContract" -class_hash = "0x19d49d8d67dd2e6f73c93eb886105d445ac6983a49950831a325872f8c662be" -original_class_hash = "0x19d49d8d67dd2e6f73c93eb886105d445ac6983a49950831a325872f8c662be" +class_hash = "0x676eed1c5c6c5f1ddf488914d137e07761d1a320df8a50fbf75ecf209624a33" +original_class_hash = "0x676eed1c5c6c5f1ddf488914d137e07761d1a320df8a50fbf75ecf209624a33" base_class_hash = "0x0" abi = "manifests/dev/base/abis/contracts/dojo_examples-actions-40b6994c.json" reads = [] diff --git a/examples/spawn-and-move/manifests/dev/base/models/dojo_examples-PlayerConfig-3adad785.toml b/examples/spawn-and-move/manifests/dev/base/models/dojo_examples-PlayerConfig-3adad785.toml index 6bfcf12738..b631214a2e 100644 --- a/examples/spawn-and-move/manifests/dev/base/models/dojo_examples-PlayerConfig-3adad785.toml +++ b/examples/spawn-and-move/manifests/dev/base/models/dojo_examples-PlayerConfig-3adad785.toml @@ -1,6 +1,6 @@ kind = "DojoModel" -class_hash = "0x13f8294fde1c2605e9825782ae293b3bae2291e6cbd20d4ef8878ff044d4b82" -original_class_hash = "0x13f8294fde1c2605e9825782ae293b3bae2291e6cbd20d4ef8878ff044d4b82" +class_hash = "0x16141fdae16b43c612d705795e8993ebacd06edb4ec582041b15b6878d65de7" +original_class_hash = "0x16141fdae16b43c612d705795e8993ebacd06edb4ec582041b15b6878d65de7" abi = "manifests/dev/base/abis/models/dojo_examples-PlayerConfig-3adad785.json" tag = "dojo_examples-PlayerConfig" manifest_name = "dojo_examples-PlayerConfig-3adad785" diff --git a/examples/spawn-and-move/manifests/dev/deployment/abis/models/dojo_examples-PlayerConfig-3adad785.json b/examples/spawn-and-move/manifests/dev/deployment/abis/models/dojo_examples-PlayerConfig-3adad785.json index 0185cc11f9..8549c6cad8 100644 --- a/examples/spawn-and-move/manifests/dev/deployment/abis/models/dojo_examples-PlayerConfig-3adad785.json +++ b/examples/spawn-and-move/manifests/dev/deployment/abis/models/dojo_examples-PlayerConfig-3adad785.json @@ -377,6 +377,10 @@ { "name": "quantity", "type": "core::integer::u32" + }, + { + "name": "score", + "type": "core::integer::i32" } ] }, diff --git a/examples/spawn-and-move/manifests/dev/deployment/manifest.json b/examples/spawn-and-move/manifests/dev/deployment/manifest.json index 1fd7c0ef24..ce9072be7e 100644 --- a/examples/spawn-and-move/manifests/dev/deployment/manifest.json +++ b/examples/spawn-and-move/manifests/dev/deployment/manifest.json @@ -1211,8 +1211,8 @@ { "kind": "DojoContract", "address": "0x5c92c8995272a6ae073392c6878fe80cd71ae0be4931bce75f3dbfe24c208a8", - "class_hash": "0x19d49d8d67dd2e6f73c93eb886105d445ac6983a49950831a325872f8c662be", - "original_class_hash": "0x19d49d8d67dd2e6f73c93eb886105d445ac6983a49950831a325872f8c662be", + "class_hash": "0x676eed1c5c6c5f1ddf488914d137e07761d1a320df8a50fbf75ecf209624a33", + "original_class_hash": "0x676eed1c5c6c5f1ddf488914d137e07761d1a320df8a50fbf75ecf209624a33", "base_class_hash": "0x26a4f5d2d9638877a2648297339275df5eaab0adb3cdf0010887c2dbf2be4", "abi": [ { @@ -4575,8 +4575,8 @@ "key": false } ], - "class_hash": "0x13f8294fde1c2605e9825782ae293b3bae2291e6cbd20d4ef8878ff044d4b82", - "original_class_hash": "0x13f8294fde1c2605e9825782ae293b3bae2291e6cbd20d4ef8878ff044d4b82", + "class_hash": "0x16141fdae16b43c612d705795e8993ebacd06edb4ec582041b15b6878d65de7", + "original_class_hash": "0x16141fdae16b43c612d705795e8993ebacd06edb4ec582041b15b6878d65de7", "abi": [ { "type": "impl", @@ -4956,6 +4956,10 @@ { "name": "quantity", "type": "core::integer::u32" + }, + { + "name": "score", + "type": "core::integer::i32" } ] }, diff --git a/examples/spawn-and-move/manifests/dev/deployment/manifest.toml b/examples/spawn-and-move/manifests/dev/deployment/manifest.toml index 513b453b78..f6bacb4b73 100644 --- a/examples/spawn-and-move/manifests/dev/deployment/manifest.toml +++ b/examples/spawn-and-move/manifests/dev/deployment/manifest.toml @@ -24,8 +24,8 @@ manifest_name = "dojo-base" [[contracts]] kind = "DojoContract" address = "0x5c92c8995272a6ae073392c6878fe80cd71ae0be4931bce75f3dbfe24c208a8" -class_hash = "0x19d49d8d67dd2e6f73c93eb886105d445ac6983a49950831a325872f8c662be" -original_class_hash = "0x19d49d8d67dd2e6f73c93eb886105d445ac6983a49950831a325872f8c662be" +class_hash = "0x676eed1c5c6c5f1ddf488914d137e07761d1a320df8a50fbf75ecf209624a33" +original_class_hash = "0x676eed1c5c6c5f1ddf488914d137e07761d1a320df8a50fbf75ecf209624a33" base_class_hash = "0x26a4f5d2d9638877a2648297339275df5eaab0adb3cdf0010887c2dbf2be4" abi = "manifests/dev/deployment/abis/contracts/dojo_examples-actions-40b6994c.json" reads = [] @@ -196,8 +196,8 @@ key = false [[models]] kind = "DojoModel" -class_hash = "0x13f8294fde1c2605e9825782ae293b3bae2291e6cbd20d4ef8878ff044d4b82" -original_class_hash = "0x13f8294fde1c2605e9825782ae293b3bae2291e6cbd20d4ef8878ff044d4b82" +class_hash = "0x16141fdae16b43c612d705795e8993ebacd06edb4ec582041b15b6878d65de7" +original_class_hash = "0x16141fdae16b43c612d705795e8993ebacd06edb4ec582041b15b6878d65de7" abi = "manifests/dev/deployment/abis/models/dojo_examples-PlayerConfig-3adad785.json" tag = "dojo_examples-PlayerConfig" manifest_name = "dojo_examples-PlayerConfig-3adad785" diff --git a/examples/spawn-and-move/manifests/release/base/abis/models/dojo_examples-PlayerConfig-3adad785.json b/examples/spawn-and-move/manifests/release/base/abis/models/dojo_examples-PlayerConfig-3adad785.json index 0185cc11f9..8549c6cad8 100644 --- a/examples/spawn-and-move/manifests/release/base/abis/models/dojo_examples-PlayerConfig-3adad785.json +++ b/examples/spawn-and-move/manifests/release/base/abis/models/dojo_examples-PlayerConfig-3adad785.json @@ -377,6 +377,10 @@ { "name": "quantity", "type": "core::integer::u32" + }, + { + "name": "score", + "type": "core::integer::i32" } ] }, diff --git a/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-actions-40b6994c.toml b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-actions-40b6994c.toml index 0a2661f564..445640874c 100644 --- a/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-actions-40b6994c.toml +++ b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-actions-40b6994c.toml @@ -1,6 +1,6 @@ kind = "DojoContract" -class_hash = "0x19d49d8d67dd2e6f73c93eb886105d445ac6983a49950831a325872f8c662be" -original_class_hash = "0x19d49d8d67dd2e6f73c93eb886105d445ac6983a49950831a325872f8c662be" +class_hash = "0x676eed1c5c6c5f1ddf488914d137e07761d1a320df8a50fbf75ecf209624a33" +original_class_hash = "0x676eed1c5c6c5f1ddf488914d137e07761d1a320df8a50fbf75ecf209624a33" base_class_hash = "0x0" abi = "manifests/release/base/abis/contracts/dojo_examples-actions-40b6994c.json" reads = [] diff --git a/examples/spawn-and-move/manifests/release/base/models/dojo_examples-PlayerConfig-3adad785.toml b/examples/spawn-and-move/manifests/release/base/models/dojo_examples-PlayerConfig-3adad785.toml index 6fd10ebb99..b19e2f2b73 100644 --- a/examples/spawn-and-move/manifests/release/base/models/dojo_examples-PlayerConfig-3adad785.toml +++ b/examples/spawn-and-move/manifests/release/base/models/dojo_examples-PlayerConfig-3adad785.toml @@ -1,6 +1,6 @@ kind = "DojoModel" -class_hash = "0x13f8294fde1c2605e9825782ae293b3bae2291e6cbd20d4ef8878ff044d4b82" -original_class_hash = "0x13f8294fde1c2605e9825782ae293b3bae2291e6cbd20d4ef8878ff044d4b82" +class_hash = "0x16141fdae16b43c612d705795e8993ebacd06edb4ec582041b15b6878d65de7" +original_class_hash = "0x16141fdae16b43c612d705795e8993ebacd06edb4ec582041b15b6878d65de7" abi = "manifests/release/base/abis/models/dojo_examples-PlayerConfig-3adad785.json" tag = "dojo_examples-PlayerConfig" manifest_name = "dojo_examples-PlayerConfig-3adad785" From 2adfda3fef4052184ae1bdb6e021f823ee46de89 Mon Sep 17 00:00:00 2001 From: glihm Date: Tue, 16 Jul 2024 09:29:07 -0600 Subject: [PATCH 13/13] fix: add more tests --- bin/sozo/src/commands/calldata_decoder.rs | 8 ++ crates/dojo-types/src/primitive.rs | 33 +++++ crates/dojo-types/src/schema.rs | 154 +++++++++++++++++++++- 3 files changed, 193 insertions(+), 2 deletions(-) diff --git a/bin/sozo/src/commands/calldata_decoder.rs b/bin/sozo/src/commands/calldata_decoder.rs index b8c3bedff5..fd74e0aa46 100644 --- a/bin/sozo/src/commands/calldata_decoder.rs +++ b/bin/sozo/src/commands/calldata_decoder.rs @@ -317,4 +317,12 @@ mod tests { let result = decode_calldata(input).unwrap(); assert_eq!(result, expected); } + + #[test] + fn test_invalid_signed_integer_decoder() { + let input = "-12345abc"; + let decoder = SignedIntegerCalldataDecoder; + let result = decoder.decode(input); + assert!(result.is_err()); + } } diff --git a/crates/dojo-types/src/primitive.rs b/crates/dojo-types/src/primitive.rs index cfbf241c39..334a4728b0 100644 --- a/crates/dojo-types/src/primitive.rs +++ b/crates/dojo-types/src/primitive.rs @@ -498,4 +498,37 @@ mod tests { primitive.set_contract_address(Some(Felt::from(1u128))).unwrap(); assert_eq!(primitive.as_contract_address(), Some(Felt::from(1u128))); } + + #[test] + fn test_primitive_deserialization() { + let test_cases = vec![ + (vec![Felt::from(-42i8)], Primitive::I8(Some(-42))), + (vec![Felt::from(-1000i16)], Primitive::I16(Some(-1000))), + (vec![Felt::from(-100000i32)], Primitive::I32(Some(-100000))), + (vec![Felt::from(-1000000000i64)], Primitive::I64(Some(-1000000000))), + ( + vec![Felt::from(-1000000000000000000i128)], + Primitive::I128(Some(-1000000000000000000)), + ), + (vec![Felt::from(42u8)], Primitive::U8(Some(42))), + (vec![Felt::from(1000u16)], Primitive::U16(Some(1000))), + (vec![Felt::from(100000u32)], Primitive::U32(Some(100000))), + (vec![Felt::from(1000000000u64)], Primitive::U64(Some(1000000000))), + (vec![Felt::from(1000000000000000000u128)], Primitive::U128(Some(1000000000000000000))), + (vec![Felt::from(42u32)], Primitive::USize(Some(42))), + (vec![Felt::from(1u8)], Primitive::Bool(Some(true))), + (vec![Felt::from(123456789u128)], Primitive::Felt252(Some(Felt::from(123456789)))), + (vec![Felt::from(987654321u128)], Primitive::ClassHash(Some(Felt::from(987654321)))), + ( + vec![Felt::from(123456789u128)], + Primitive::ContractAddress(Some(Felt::from(123456789))), + ), + ]; + + for (serialized, expected) in test_cases { + let mut to_deser = expected; + to_deser.deserialize(&mut serialized.clone()).unwrap(); + assert_eq!(to_deser, expected); + } + } } diff --git a/crates/dojo-types/src/schema.rs b/crates/dojo-types/src/schema.rs index 31f24d4b39..f5497c06bf 100644 --- a/crates/dojo-types/src/schema.rs +++ b/crates/dojo-types/src/schema.rs @@ -55,8 +55,15 @@ impl Ty { Ty::Primitive(c) => c.to_string(), Ty::Struct(s) => s.name.clone(), Ty::Enum(e) => e.name.replace( - 'T', - &e.options.iter().map(|o| o.ty.name().replace("()", "")).unique().join(""), + "", + &e.options + .iter() + .map(|o| { + let t = o.ty.name().replace("()", ""); + format!("<{}>", t) + }) + .unique() + .join(""), ), Ty::Tuple(tys) => format!("({})", tys.iter().map(|ty| ty.name()).join(", ")), Ty::Array(ty) => format!("Array<{}>", ty[0].name()), @@ -452,3 +459,146 @@ fn format_member(m: &Member) -> String { str } + +#[cfg(test)] +mod tests { + use crypto_bigint::U256; + use starknet::core::types::Felt; + + use super::*; + use crate::primitive::Primitive; + + #[test] + fn test_format_member() { + let test_cases = vec![ + ( + Member { + name: "i8_field".to_string(), + ty: Ty::Primitive(Primitive::I8(Some(-42))), + key: false, + }, + " i8_field: i8 = -42", + ), + ( + Member { + name: "i16_field".to_string(), + ty: Ty::Primitive(Primitive::I16(Some(-1000))), + key: false, + }, + " i16_field: i16 = -1000", + ), + ( + Member { + name: "i32_field".to_string(), + ty: Ty::Primitive(Primitive::I32(Some(-100000))), + key: false, + }, + " i32_field: i32 = -100000", + ), + ( + Member { + name: "i64_field".to_string(), + ty: Ty::Primitive(Primitive::I64(Some(-1000000000))), + key: false, + }, + " i64_field: i64 = -1000000000", + ), + ( + Member { + name: "i128_field".to_string(), + ty: Ty::Primitive(Primitive::I128(Some(-1000000000000000000))), + key: false, + }, + " i128_field: i128 = -1000000000000000000", + ), + ( + Member { + name: "u8_field".to_string(), + ty: Ty::Primitive(Primitive::U8(Some(255))), + key: false, + }, + " u8_field: u8 = 255", + ), + ( + Member { + name: "u16_field".to_string(), + ty: Ty::Primitive(Primitive::U16(Some(65535))), + key: false, + }, + " u16_field: u16 = 65535", + ), + ( + Member { + name: "u32_field".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(4294967295))), + key: false, + }, + " u32_field: u32 = 4294967295", + ), + ( + Member { + name: "u64_field".to_string(), + ty: Ty::Primitive(Primitive::U64(Some(18446744073709551615))), + key: false, + }, + " u64_field: u64 = 18446744073709551615", + ), + ( + Member { + name: "u128_field".to_string(), + ty: Ty::Primitive(Primitive::U128(Some( + 340282366920938463463374607431768211455, + ))), + key: false, + }, + " u128_field: u128 = 340282366920938463463374607431768211455", + ), + ( + Member { + name: "u256_field".to_string(), + ty: Ty::Primitive(Primitive::U256(Some(U256::from_u128(123456789_u128)))), + key: false, + }, + " u256_field: u256 = \ + 00000000000000000000000000000000000000000000000000000000075BCD15", + ), + ( + Member { + name: "bool_field".to_string(), + ty: Ty::Primitive(Primitive::Bool(Some(true))), + key: false, + }, + " bool_field: bool = true", + ), + ( + Member { + name: "felt252_field".to_string(), + ty: Ty::Primitive(Primitive::Felt252(Some( + Felt::from_hex("0x123abc").unwrap(), + ))), + key: false, + }, + " felt252_field: felt252 = 0x123abc", + ), + ( + Member { + name: "enum_field".to_string(), + ty: Ty::Enum(Enum { + name: "TestEnum".to_string(), + option: Some(1), + options: vec![ + EnumOption { name: "OptionA".to_string(), ty: Ty::Tuple(vec![]) }, + EnumOption { name: "OptionB".to_string(), ty: Ty::Tuple(vec![]) }, + ], + }), + key: false, + }, + " enum_field: TestEnum = OptionB", + ), + ]; + + for (member, expected) in test_cases { + assert_eq!(format_member(&member), expected); + } + } +}