-
Notifications
You must be signed in to change notification settings - Fork 182
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: update to new dojo-bindgen version & handle enums
- Loading branch information
Showing
1 changed file
with
170 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,189 @@ | ||
use async_trait::async_trait; | ||
use cainome::parser::tokens::{Composite, Token}; | ||
|
||
use crate::error::BindgenResult; | ||
use crate::error::{BindgenResult, Error}; | ||
use crate::plugins::BuiltinPlugin; | ||
use crate::DojoData; | ||
use crate::{DojoData, DojoModel}; | ||
|
||
pub struct UnityPlugin; | ||
|
||
#[derive(Debug)] | ||
pub enum UnityPluginError { | ||
InvalidType(String), | ||
} | ||
|
||
impl std::fmt::Display for UnityPluginError { | ||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
match self { | ||
UnityPluginError::InvalidType(type_path) => write!(f, "Invalid type: {}", type_path), | ||
} | ||
} | ||
} | ||
|
||
impl std::error::Error for UnityPluginError {} | ||
|
||
pub struct UnityPlugin { | ||
} | ||
|
||
impl UnityPlugin { | ||
pub fn new() -> Self { | ||
Self {} | ||
Self { | ||
} | ||
} | ||
|
||
// Maps cairo types to C#/Unity SDK defined types | ||
fn map_type(type_name: &str) -> Result<String, UnityPluginError> { | ||
match type_name { | ||
"u8" => Ok("byte".to_string()), | ||
"u16" => Ok("ushort".to_string()), | ||
"u32" => Ok("uint".to_string()), | ||
"u64" => Ok("ulong".to_string()), | ||
"u128" => Ok("Span<byte>".to_string()), | ||
"u256" => Ok("Span<ulong>".to_string()), | ||
"usize" => Ok("uint".to_string()), | ||
"felt252" => Ok("FieldElement".to_string()), | ||
"ClassHash" => Ok("FieldElement".to_string()), | ||
"ContractAddress" => Ok("FieldElement".to_string()), | ||
|
||
_ => Ok(type_name.to_string()), | ||
} | ||
} | ||
|
||
// Token should be a struct | ||
// This will be formatted into a C# struct | ||
// using C# and unity SDK types | ||
fn format_struct(token: &Composite) -> Result<String, UnityPluginError> { | ||
let fields = token.inners.iter().map(|field| { | ||
format!( | ||
"public {} {};", | ||
UnityPlugin::map_type(field.token.clone().type_name().as_str()).unwrap(), | ||
field.name | ||
) | ||
}).collect::<Vec<String>>().join("\n "); | ||
|
||
return Ok(format!( | ||
" | ||
[Serializable] | ||
public struct {} {{ | ||
{} | ||
}} | ||
", | ||
token.type_name(), fields | ||
)); | ||
} | ||
|
||
// Token should be an enum | ||
// This will be formatted into a C# enum | ||
// Enum is mapped using index of cairo enum | ||
fn format_enum(token: &Composite) -> Result<String, UnityPluginError> { | ||
let fields = token.inners.iter().map(|field| { | ||
format!( | ||
"{},", | ||
field.name, | ||
) | ||
}).collect::<Vec<String>>().join("\n "); | ||
|
||
return Ok(format!( | ||
" | ||
public enum {} {{ | ||
{} | ||
}} | ||
", | ||
token.type_name(), fields | ||
)); | ||
} | ||
|
||
fn format_model(model: &Composite) -> Result<String, UnityPluginError> { | ||
let fields = model.inners.iter().map(|field| {format!( | ||
"[ModelField(\"{}\")]\n public {} {};", | ||
field.name, | ||
UnityPlugin::map_type(field.token.type_name().as_str()).unwrap(), | ||
field.name, | ||
)}).collect::<Vec<String>>().join("\n\n "); | ||
|
||
return Ok(format!( | ||
" | ||
public class {} : ModelInstance {{ | ||
{} | ||
// Start is called before the first frame update | ||
void Start() {{ | ||
}} | ||
// Update is called once per frame | ||
void Update() {{ | ||
}} | ||
}} | ||
", | ||
model.type_name(), fields | ||
)); | ||
} | ||
|
||
fn handle_model(&self, model: &DojoModel) -> Result<String, UnityPluginError> { | ||
let mut out = String::new(); | ||
out += "using System;\n"; | ||
out += "using Dojo;\n"; | ||
out += "using Dojo.Starknet;\n"; | ||
|
||
if model.tokens.get("structs").is_none() { | ||
return Err(UnityPluginError::InvalidType("structs".to_string())); | ||
} | ||
|
||
let mut model_struct: Option<&Composite> = None; | ||
let tokens = &model.tokens; | ||
for (token_type, tokens) in tokens { | ||
match token_type.as_str() { | ||
"structs" => { | ||
for token in tokens { | ||
// first index is our model struct | ||
if token.type_name() == model.name { | ||
model_struct = Some(token.to_composite().unwrap()); | ||
continue; | ||
} | ||
|
||
out += UnityPlugin::format_struct(token.to_composite().unwrap())?.as_str(); | ||
} | ||
}, | ||
"enums" => { | ||
for token in tokens { | ||
out += UnityPlugin::format_enum(token.to_composite().unwrap())?.as_str(); | ||
} | ||
}, | ||
"functions" => {}, | ||
_ => { | ||
return Err(UnityPluginError::InvalidType(token_type.to_string())); | ||
} | ||
} | ||
} | ||
|
||
out += "\n"; | ||
|
||
out += UnityPlugin::format_model(model_struct.expect("model struct not found"))?.as_str(); | ||
|
||
Ok(out) | ||
} | ||
} | ||
|
||
#[async_trait] | ||
impl BuiltinPlugin for UnityPlugin { | ||
async fn generate_code(&self, data: &DojoData) -> BindgenResult<()> { | ||
println!("-> Unity models bindings\n"); | ||
|
||
async fn generate_code( | ||
&self, | ||
data: &DojoData | ||
) -> BindgenResult<()> { | ||
// Handle codegen for models | ||
for (name, model) in &data.models { | ||
println!("## Model: {}", name); | ||
println!("{:?}\n", model); | ||
println!("Generating model: {}", name); | ||
let code = self.handle_model(model).map_err(|e| { | ||
Error::Format(format!("Failed to generate code for model: {}", e)) | ||
})?; | ||
// println!("{}", code); | ||
} | ||
|
||
for (file_name, contract) in &data.contracts { | ||
println!("## Contract: {}", file_name); | ||
println!("{:?}\n", contract); | ||
// Handle codegen for systems | ||
for (name, system) in &data.contracts { | ||
println!("Generating system: {}", name); | ||
println!("{:?}", system); | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
} |