Skip to content

Commit

Permalink
feat(torii-libp2p): support new layout types
Browse files Browse the repository at this point in the history
  • Loading branch information
Larkooo committed Jun 7, 2024
1 parent 9ea6574 commit 31780b0
Show file tree
Hide file tree
Showing 2 changed files with 190 additions and 172 deletions.
360 changes: 190 additions & 170 deletions crates/torii/libp2p/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{fs, io};
use chrono::Utc;
use crypto_bigint::U256;
use dojo_types::primitive::Primitive;
use dojo_types::schema::{Struct, Ty};
use dojo_types::schema::Ty;
use futures::StreamExt;
use indexmap::IndexMap;
use libp2p::core::multiaddr::Protocol;
Expand Down Expand Up @@ -443,175 +443,121 @@ fn ty_keys(ty: &Ty) -> Result<Vec<FieldElement>, Error> {
}
}

pub fn parse_ty_to_object(ty: &Ty) -> Result<IndexMap<String, PrimitiveType>, Error> {
match ty {
Ty::Struct(struct_ty) => {
let mut object = IndexMap::new();
for member in &struct_ty.children {
let mut member_object = IndexMap::new();
member_object.insert("key".to_string(), PrimitiveType::Bool(member.key));
member_object.insert(
"type".to_string(),
PrimitiveType::String(ty_to_string_type(&member.ty)),
);
member_object.insert("value".to_string(), parse_ty_to_primitive(&member.ty)?);
object.insert(member.name.clone(), PrimitiveType::Object(member_object));
pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error> {
match value {
PrimitiveType::Object(object) => {
let struct_ = if let Ty::Struct(struct_) = ty {
struct_

Check warning on line 450 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L446-L450

Added lines #L446 - L450 were not covered by tests
} else {
return Err(Error::InvalidMessageError("Expected Struct type".to_string()));

Check warning on line 452 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L452

Added line #L452 was not covered by tests
};

for (key, value) in object {
let member =
struct_.children.iter_mut().find(|member| member.name == *key).ok_or_else(
|| Error::InvalidMessageError(format!("Member {} not found", key)),
)?;

Check warning on line 459 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L455-L459

Added lines #L455 - L459 were not covered by tests

parse_value_to_ty(value, &mut member.ty)?;

Check warning on line 461 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L461

Added line #L461 was not covered by tests
}
Ok(object)
}
_ => Err(Error::InvalidMessageError("Expected Struct type".to_string())),
}
}

pub fn ty_to_string_type(ty: &Ty) -> String {
match ty {
Ty::Primitive(primitive) => match primitive {
Primitive::U8(_) => "u8".to_string(),
Primitive::U16(_) => "u16".to_string(),
Primitive::U32(_) => "u32".to_string(),
Primitive::USize(_) => "usize".to_string(),
Primitive::U64(_) => "u64".to_string(),
Primitive::U128(_) => "u128".to_string(),
Primitive::U256(_) => "u256".to_string(),
Primitive::Felt252(_) => "felt252".to_string(),
Primitive::ClassHash(_) => "class_hash".to_string(),
Primitive::ContractAddress(_) => "contract_address".to_string(),
Primitive::Bool(_) => "bool".to_string(),
},
Ty::Struct(_) => "struct".to_string(),
Ty::Tuple(_) => "tuple".to_string(),
Ty::Array(_) => "array".to_string(),
Ty::ByteArray(_) => "bytearray".to_string(),
Ty::Enum(_) => "enum".to_string(),
}
}

pub fn parse_ty_to_primitive(ty: &Ty) -> Result<PrimitiveType, Error> {
match ty {
Ty::Primitive(primitive) => match primitive {
Primitive::U8(value) => {
Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64))))
}
Primitive::U16(value) => {
Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64))))
}
Primitive::U32(value) => {
Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64))))
}
Primitive::USize(value) => {
Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64))))
}
Primitive::U64(value) => {
Ok(PrimitiveType::Number(Number::from(value.map(|v| v).unwrap_or(0u64))))
PrimitiveType::Array(values) => match ty {
Ty::Array(array) => {
let inner_type = array[0].clone();

// clear the array, which contains the inner type
array.clear();

Check warning on line 469 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L464-L469

Added lines #L464 - L469 were not covered by tests

// parse each value to the inner type
for value in values {
let mut ty = inner_type.clone();
parse_value_to_ty(value, &mut ty)?;
array.push(ty);

Check warning on line 475 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L472-L475

Added lines #L472 - L475 were not covered by tests
}
}
Primitive::U128(value) => Ok(PrimitiveType::String(
value.map(|v| v.to_string()).unwrap_or_else(|| "0".to_string()),
)),
Primitive::U256(value) => Ok(PrimitiveType::String(
value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()),
)),
Primitive::Felt252(value) => Ok(PrimitiveType::String(
value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()),
)),
Primitive::ClassHash(value) => Ok(PrimitiveType::String(
value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()),
)),
Primitive::ContractAddress(value) => Ok(PrimitiveType::String(
value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()),
)),
Primitive::Bool(value) => Ok(PrimitiveType::Bool(value.unwrap_or(false))),
},
_ => Err(Error::InvalidMessageError("Expected Primitive type".to_string())),
}
}

pub fn parse_object_to_ty(
model: &mut Struct,
object: &IndexMap<String, PrimitiveType>,
) -> Result<(), Error> {
for (field_name, value) in object {
let field = model.children.iter_mut().find(|m| m.name == *field_name).ok_or_else(|| {
Error::InvalidMessageError(format!("Field {} not found in model", field_name))
})?;
Ty::Tuple(tuple) => {
// our array values need to match the length of the tuple
if tuple.len() != values.len() {
return Err(Error::InvalidMessageError("Tuple length mismatch".to_string()));
}

Check warning on line 482 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L478-L482

Added lines #L478 - L482 were not covered by tests

match value {
PrimitiveType::Object(object) => {
parse_object_to_ty(model, object)?;
for (i, value) in tuple.iter_mut().enumerate() {
parse_value_to_ty(&values[i], value)?;

Check warning on line 485 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L484-L485

Added lines #L484 - L485 were not covered by tests
}
}
PrimitiveType::Array(_) => {
// tuples not supported yet
unimplemented!()
_ => {
return Err(Error::InvalidMessageError("Invalid array type".to_string()));

Check warning on line 489 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L489

Added line #L489 was not covered by tests
}
PrimitiveType::Number(number) => match &mut field.ty {
Ty::Primitive(primitive) => match *primitive {
Primitive::U8(ref mut u8) => {
*u8 = Some(number.as_u64().unwrap() as u8);
}
Primitive::U16(ref mut u16) => {
*u16 = Some(number.as_u64().unwrap() as u16);
}
Primitive::U32(ref mut u32) => {
*u32 = Some(number.as_u64().unwrap() as u32);
}
Primitive::USize(ref mut usize) => {
*usize = Some(number.as_u64().unwrap() as u32);
}
Primitive::U64(ref mut u64) => {
*u64 = Some(number.as_u64().unwrap());
}
_ => {
return Err(Error::InvalidMessageError("Invalid number type".to_string()));
}
},
Ty::Enum(enum_) => {
enum_.option = Some(number.as_u64().unwrap() as u8);
},
PrimitiveType::Number(number) => match ty {
Ty::Primitive(primitive) => match *primitive {
Primitive::U8(ref mut u8) => {
*u8 = Some(number.as_u64().unwrap() as u8);
}
Primitive::U16(ref mut u16) => {
*u16 = Some(number.as_u64().unwrap() as u16);
}
Primitive::U32(ref mut u32) => {
*u32 = Some(number.as_u64().unwrap() as u32);
}
Primitive::USize(ref mut usize) => {
*usize = Some(number.as_u64().unwrap() as u32);
}
Primitive::U64(ref mut u64) => {
*u64 = Some(number.as_u64().unwrap());

Check warning on line 507 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L492-L507

Added lines #L492 - L507 were not covered by tests
}
_ => return Err(Error::InvalidMessageError("Invalid number type".to_string())),
},
PrimitiveType::Bool(boolean) => {
field.ty = Ty::Primitive(Primitive::Bool(Some(*boolean)));
}
PrimitiveType::String(string) => match &mut field.ty {
Ty::Primitive(primitive) => match primitive {
Primitive::U8(v) => {
*v = Some(u8::from_str(string).unwrap());
}
Primitive::U16(v) => {
*v = Some(u16::from_str(string).unwrap());
}
Primitive::U32(v) => {
*v = Some(u32::from_str(string).unwrap());
}
Primitive::USize(v) => {
*v = Some(u32::from_str(string).unwrap());
}
Primitive::U64(v) => {
*v = Some(u64::from_str(string).unwrap());
}
Primitive::U128(v) => {
*v = Some(u128::from_str(string).unwrap());
}
Primitive::U256(v) => {
*v = Some(U256::from_be_hex(string));
}
Primitive::Felt252(v) => {
*v = Some(FieldElement::from_str(string).unwrap());
}
Primitive::ClassHash(v) => {
*v = Some(FieldElement::from_str(string).unwrap());
}
Primitive::ContractAddress(v) => {
*v = Some(FieldElement::from_str(string).unwrap());
}
Primitive::Bool(v) => {
*v = Some(bool::from_str(string).unwrap());
}
},
_ => {
return Err(Error::InvalidMessageError("Invalid string type".to_string()));
return Err(Error::InvalidMessageError("Invalid number type".to_string()));

Check warning on line 510 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L510

Added line #L510 was not covered by tests
}
},
Ty::Enum(enum_) => {
enum_.option = Some(number.as_u64().unwrap() as u8);
}
_ => return Err(Error::InvalidMessageError("Invalid number type".to_string())),

Check warning on line 516 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L513-L516

Added lines #L513 - L516 were not covered by tests
},
PrimitiveType::Bool(boolean) => {
*ty = Ty::Primitive(Primitive::Bool(Some(*boolean)));

Check warning on line 519 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L518-L519

Added lines #L518 - L519 were not covered by tests
}
PrimitiveType::String(string) => match ty {
Ty::Primitive(primitive) => match primitive {
Primitive::U8(v) => {
*v = Some(u8::from_str(string).unwrap());
}
Primitive::U16(v) => {
*v = Some(u16::from_str(string).unwrap());
}
Primitive::U32(v) => {
*v = Some(u32::from_str(string).unwrap());
}
Primitive::USize(v) => {
*v = Some(u32::from_str(string).unwrap());
}
Primitive::U64(v) => {
*v = Some(u64::from_str(string).unwrap());
}
Primitive::U128(v) => {
*v = Some(u128::from_str(string).unwrap());
}
Primitive::U256(v) => {
*v = Some(U256::from_be_hex(string));
}
Primitive::Felt252(v) => {
*v = Some(FieldElement::from_str(string).unwrap());
}
Primitive::ClassHash(v) => {
*v = Some(FieldElement::from_str(string).unwrap());
}
Primitive::ContractAddress(v) => {
*v = Some(FieldElement::from_str(string).unwrap());
}
Primitive::Bool(v) => {
*v = Some(bool::from_str(string).unwrap());
}

Check warning on line 555 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L521-L555

Added lines #L521 - L555 were not covered by tests
},
_ => {
return Err(Error::InvalidMessageError("Invalid string type".to_string()));

Check warning on line 558 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L558

Added line #L558 was not covered by tests
}
},
}

Ok(())
Expand Down Expand Up @@ -649,18 +595,8 @@ async fn validate_message(
))
})?;

let ty_struct = if let Ty::Struct(ty_struct) = &mut ty {
ty_struct
} else {
return Err(Error::InvalidMessageError("Model is not a struct".to_string()));
};

if let Some(object) = message.get(model_name) {
if let PrimitiveType::Object(object) = object {
parse_object_to_ty(ty_struct, object)?
} else {
return Err(Error::InvalidMessageError("Model is not a struct".to_string()));
}
parse_value_to_ty(object, &mut ty)?;

Check warning on line 599 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L599

Added line #L599 was not covered by tests
} else {
return Err(Error::InvalidMessageError("Model is missing".to_string()));
};
Expand Down Expand Up @@ -703,6 +639,90 @@ fn read_or_create_certificate(path: &Path) -> anyhow::Result<Certificate> {
Ok(cert)
}

// Deprecated. These should be potentially removed. As Ty -> TypedData is now done
// on the SDKs side
pub fn parse_ty_to_object(ty: &Ty) -> Result<IndexMap<String, PrimitiveType>, Error> {
match ty {
Ty::Struct(struct_ty) => {
let mut object = IndexMap::new();
for member in &struct_ty.children {
let mut member_object = IndexMap::new();
member_object.insert("key".to_string(), PrimitiveType::Bool(member.key));
member_object.insert(
"type".to_string(),
PrimitiveType::String(ty_to_string_type(&member.ty)),
);
member_object.insert("value".to_string(), parse_ty_to_primitive(&member.ty)?);
object.insert(member.name.clone(), PrimitiveType::Object(member_object));
}
Ok(object)
}
_ => Err(Error::InvalidMessageError("Expected Struct type".to_string())),

Check warning on line 660 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L660

Added line #L660 was not covered by tests
}
}

pub fn ty_to_string_type(ty: &Ty) -> String {
match ty {
Ty::Primitive(primitive) => match primitive {
Primitive::U8(_) => "u8".to_string(),
Primitive::U16(_) => "u16".to_string(),
Primitive::U32(_) => "u32".to_string(),
Primitive::USize(_) => "usize".to_string(),
Primitive::U64(_) => "u64".to_string(),
Primitive::U128(_) => "u128".to_string(),
Primitive::U256(_) => "u256".to_string(),
Primitive::Felt252(_) => "felt252".to_string(),
Primitive::ClassHash(_) => "class_hash".to_string(),

Check warning on line 675 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L668-L675

Added lines #L668 - L675 were not covered by tests
Primitive::ContractAddress(_) => "contract_address".to_string(),
Primitive::Bool(_) => "bool".to_string(),

Check warning on line 677 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L677

Added line #L677 was not covered by tests
},
Ty::Struct(_) => "struct".to_string(),
Ty::Tuple(_) => "tuple".to_string(),
Ty::Array(_) => "array".to_string(),
Ty::ByteArray(_) => "bytearray".to_string(),
Ty::Enum(_) => "enum".to_string(),

Check warning on line 683 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L679-L683

Added lines #L679 - L683 were not covered by tests
}
}

pub fn parse_ty_to_primitive(ty: &Ty) -> Result<PrimitiveType, Error> {
match ty {
Ty::Primitive(primitive) => match primitive {
Primitive::U8(value) => {
Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64))))
}
Primitive::U16(value) => {
Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64))))

Check warning on line 694 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L693-L694

Added lines #L693 - L694 were not covered by tests
}
Primitive::U32(value) => {
Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64))))

Check warning on line 697 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L696-L697

Added lines #L696 - L697 were not covered by tests
}
Primitive::USize(value) => {
Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64))))

Check warning on line 700 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L699-L700

Added lines #L699 - L700 were not covered by tests
}
Primitive::U64(value) => {
Ok(PrimitiveType::Number(Number::from(value.map(|v| v).unwrap_or(0u64))))

Check warning on line 703 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L702-L703

Added lines #L702 - L703 were not covered by tests
}
Primitive::U128(value) => Ok(PrimitiveType::String(
value.map(|v| v.to_string()).unwrap_or_else(|| "0".to_string()),
)),
Primitive::U256(value) => Ok(PrimitiveType::String(
value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()),
)),
Primitive::Felt252(value) => Ok(PrimitiveType::String(
value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()),
)),
Primitive::ClassHash(value) => Ok(PrimitiveType::String(
value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()),
)),

Check warning on line 716 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L705-L716

Added lines #L705 - L716 were not covered by tests
Primitive::ContractAddress(value) => Ok(PrimitiveType::String(
value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()),
)),
Primitive::Bool(value) => Ok(PrimitiveType::Bool(value.unwrap_or(false))),

Check warning on line 720 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L720

Added line #L720 was not covered by tests
},
_ => Err(Error::InvalidMessageError("Expected Primitive type".to_string())),

Check warning on line 722 in crates/torii/libp2p/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/libp2p/src/server/mod.rs#L722

Added line #L722 was not covered by tests
}
}

#[cfg(test)]
mod tests {
use tempfile::tempdir;
Expand Down
Loading

0 comments on commit 31780b0

Please sign in to comment.