From cfa2b7246048004040e07a7ab69c57007f670c14 Mon Sep 17 00:00:00 2001 From: Virx Date: Thu, 10 Oct 2024 17:49:02 -0400 Subject: [PATCH] Update to new spec --- Cargo.lock | 22 +++--- Cargo.toml | 2 +- README.md | 8 +- codegen/enums.rs | 49 +++++++++--- codegen/main.rs | 38 ++++++--- codegen/pyi.rs | 44 +++++++++-- codegen/structs.rs | 191 ++++++++++++++++++++++++++++++++++----------- codegen/unions.rs | 22 +++++- flatbuffers-schema | 2 +- pybench.py | 8 +- pytest.py | 3 +- rustfmt.toml | 3 +- src/lib.rs | 15 +++- 13 files changed, 302 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 37a9da8..4acaa68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,9 +34,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bitflags" @@ -153,15 +153,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "portable-atomic" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "proc-macro-utils" @@ -176,9 +176,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] @@ -279,7 +279,7 @@ dependencies = [ [[package]] name = "rlbot-flatbuffers-py" -version = "0.9.1" +version = "0.10.0" dependencies = [ "flatbuffers", "get-size", @@ -330,9 +330,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index d289d94..07bbd01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rlbot-flatbuffers-py" -version = "0.9.1" +version = "0.10.0" edition = "2021" description = "A Python module implemented in Rust for serializing and deserializing RLBot's flatbuffers" repository = "https://github.com/VirxEC/rlbot_flatbuffers_py" diff --git a/README.md b/README.md index e6fc3ed..b751015 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,10 @@ All values are optional when creating a class and have the proper defaults. ```python import rlbot_flatbuffers as flat -def handle_packet(packet: flat.GameTickPacket): - if packet.game_info.game_state_type not in { - flat.GameStateType.Active, - flat.GameStateType.Kickoff, +def handle_packet(packet: flat.GamePacket): + if packet.game_info.game_status not in { + flat.GameStatus.Active, + flat.GameStatus.Kickoff, }: # Return early if the game isn't active return diff --git a/codegen/enums.rs b/codegen/enums.rs index e6e0507..d43db2c 100644 --- a/codegen/enums.rs +++ b/codegen/enums.rs @@ -117,12 +117,17 @@ impl EnumBindGenerator { continue; } - let definition = line_trim.trim_start_matches("pub const ").trim_end_matches(';'); + let definition = line_trim + .trim_start_matches("pub const ") + .trim_end_matches(';'); let mut parts = definition.split(": Self = "); let variable_name = parts.next()?; - let variable_value = parts.next()?.trim_start_matches("Self(").trim_end_matches(')'); + let variable_value = parts + .next()? + .trim_start_matches("Self(") + .trim_end_matches(')'); types.push((variable_name, variable_value)); @@ -143,11 +148,14 @@ impl EnumBindGenerator { let union_end_definition = "}\n"; let union_end = contents[union_start..].find(union_end_definition).unwrap(); - let union_definition = - &contents[union_start + union_definition.len()..union_start + union_end - union_end_definition.len()]; + let union_definition = &contents[union_start + union_definition.len() + ..union_start + union_end - union_end_definition.len()]; for (line, variable) in union_definition.split('\n').zip(&mut custom_types) { - let line_trim = line.trim().trim_start_matches(&variable.name).trim_end_matches(','); + let line_trim = line + .trim() + .trim_start_matches(&variable.name) + .trim_end_matches(','); if line_trim.is_empty() { variable.value = None; @@ -156,7 +164,9 @@ impl EnumBindGenerator { variable.snake_case_name = camel_to_snake_case(variable.name.as_str()); - let new_type = line_trim.trim_start_matches("(Box<").trim_end_matches("T>)"); + let new_type = line_trim + .trim_start_matches("(Box<") + .trim_end_matches("T>)"); variable.value = Some(new_type.to_string()); } @@ -225,7 +235,10 @@ impl Generator for EnumBindGenerator { contents = contents.replace("\r\n", "\n"); } - contents = contents.replace("use self::flatbuffers", "use get_size::GetSize;\nuse self::flatbuffers"); + contents = contents.replace( + "use self::flatbuffers", + "use get_size::GetSize;\nuse self::flatbuffers", + ); contents = contents.replace( "#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]\n", @@ -241,7 +254,10 @@ impl Generator for EnumBindGenerator { self, "#[pyclass(module = \"rlbot_flatbuffers\", frozen, hash, eq, eq_int)]" ); - write_str!(self, "#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]"); + write_str!( + self, + "#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]" + ); write_fmt!(self, "pub enum {} {{", self.struct_name); write_str!(self, " #[default]"); @@ -261,7 +277,11 @@ impl Generator for EnumBindGenerator { self.struct_name, self.struct_name ); - write_fmt!(self, " fn from(flat_t: flat::{}) -> Self {{", self.struct_name); + write_fmt!( + self, + " fn from(flat_t: flat::{}) -> Self {{", + self.struct_name + ); write_str!(self, " match flat_t {"); for variable_info in &self.types { @@ -274,7 +294,10 @@ impl Generator for EnumBindGenerator { ); } - write_str!(self, " v => unreachable!(\"Unknown value: {v:?}\"),"); + write_str!( + self, + " v => unreachable!(\"Unknown value: {v:?}\")," + ); write_str!(self, " }"); write_str!(self, " }"); @@ -289,7 +312,11 @@ impl Generator for EnumBindGenerator { self.struct_name, self.struct_name ); - write_fmt!(self, " fn from(py_type: &{}) -> Self {{", self.struct_name); + write_fmt!( + self, + " fn from(py_type: &{}) -> Self {{", + self.struct_name + ); write_str!(self, " match *py_type {"); for variable_info in &self.types { diff --git a/codegen/main.rs b/codegen/main.rs index 16012e4..630045f 100644 --- a/codegen/main.rs +++ b/codegen/main.rs @@ -25,11 +25,11 @@ pub enum PythonBindType { impl PythonBindType { pub const BASE_TYPES: [&'static str; 6] = ["bool", "i32", "u32", "f32", "String", "u8"]; - pub const FROZEN_TYPES: [&'static str; 18] = [ + pub const FROZEN_TYPES: [&'static str; 21] = [ "FieldInfo", "BoostPad", "GoalInfo", - "GameTickPacket", + "GamePacket", "PlayerInfo", "ScoreInfo", "BallInfo", @@ -44,9 +44,17 @@ impl PythonBindType { "BallPrediction", "PredictionSlice", "Physics", + "Vector2", + "ControllableInfo", + "ControllableTeamInfo", + ]; + pub const FROZEN_NEEDS_PY: [&'static str; 3] = ["GamePacket", "BallInfo", "CollisionShape"]; + pub const UNIONS: [&'static str; 4] = [ + "PlayerClass", + "CollisionShape", + "RelativeAnchor", + "RenderType", ]; - pub const FROZEN_NEEDS_PY: [&'static str; 3] = ["GameTickPacket", "BallInfo", "CollisionShape"]; - pub const UNIONS: [&'static str; 4] = ["PlayerClass", "CollisionShape", "RelativeAnchor", "RenderType"]; fn new(path: &Path) -> Option { // get the filename without the extension @@ -84,11 +92,15 @@ impl PythonBindType { )?)); } - if let Some((types, enum_type)) = enums::EnumBindGenerator::get_types(&contents, &struct_name) { + if let Some((types, enum_type)) = + enums::EnumBindGenerator::get_types(&contents, &struct_name) + { return Some(match enum_type { - enums::EnumType::Enum => { - Self::Enum(enums::EnumBindGenerator::new(filename.to_string(), struct_name, types)?) - } + enums::EnumType::Enum => Self::Enum(enums::EnumBindGenerator::new( + filename.to_string(), + struct_name, + types, + )?), enums::EnumType::Union => Self::Union(unions::UnionBindGenerator::new( filename.to_string(), struct_name, @@ -138,7 +150,10 @@ fn mod_rs_generator(type_data: &[PythonBindType]) -> io::Result<()> { file_contents.push(Cow::Borrowed("")); - fs::write(format!("{PYTHON_OUT_FOLDER}/mod.rs"), file_contents.join("\n"))?; + fs::write( + format!("{PYTHON_OUT_FOLDER}/mod.rs"), + file_contents.join("\n"), + )?; Ok(()) } @@ -155,7 +170,10 @@ fn run_flatc() -> io::Result<()> { let mut schema_folder = Path::new(SCHEMA_FOLDER); if !schema_folder.exists() { schema_folder = Path::new(SCHEMA_FOLDER_BACKUP); - assert!(schema_folder.exists(), "Could not find flatbuffers schema folder"); + assert!( + schema_folder.exists(), + "Could not find flatbuffers schema folder" + ); } let schema_folder_str = schema_folder.display(); diff --git a/codegen/pyi.rs b/codegen/pyi.rs index caad0b8..f407c57 100644 --- a/codegen/pyi.rs +++ b/codegen/pyi.rs @@ -88,7 +88,10 @@ pub fn generator(type_data: &[PythonBindType]) -> io::Result<()> { ); write_str!(file, " \"\"\""); write_str!(file, " def __int__(self) -> int: ..."); - write_fmt!(file, " def __eq__(self, other: {type_name}) -> bool: ..."); + write_fmt!( + file, + " def __eq__(self, other: {type_name}) -> bool: ..." + ); write_str!(file, " def __hash__(self) -> str: ..."); } PythonBindType::Struct(gen) => { @@ -111,6 +114,20 @@ pub fn generator(type_data: &[PythonBindType]) -> io::Result<()> { python_types.push("bytes".to_string()); write_fmt!(file, " {variable_name}: bytes"); } + RustType::Vec(InnerVecType::Base(type_name)) => { + let python_type = if type_name == "bool" { + "bool" + } else if type_name == "i32" || type_name == "u32" { + "int" + } else if type_name == "f32" { + "float" + } else { + type_name + }; + + python_types.push(format!("Sequence[{python_type}]")); + write_fmt!(file, " {variable_name}: Sequence[{python_type}]"); + } RustType::Vec(InnerVecType::String) => { python_types.push("Sequence[str]".to_string()); write_fmt!(file, " {variable_name}: Sequence[str]"); @@ -166,8 +183,16 @@ pub fn generator(type_data: &[PythonBindType]) -> io::Result<()> { let union_types = type_data .iter() .find_map(|item| match item { - PythonBindType::Union(gen) if gen.struct_name() == type_name => { - Some(gen.types.iter().skip(1).map(|v| v.name.as_str()).collect::>()) + PythonBindType::Union(gen) + if gen.struct_name() == type_name => + { + Some( + gen.types + .iter() + .skip(1) + .map(|v| v.name.as_str()) + .collect::>(), + ) } _ => None, }) @@ -175,7 +200,9 @@ pub fn generator(type_data: &[PythonBindType]) -> io::Result<()> { let types = union_types.join(" | "); python_types.push(format!("Optional[{types}]")); } - RustType::Custom(type_name) | RustType::Other(type_name) | RustType::Base(type_name) => { + RustType::Custom(type_name) + | RustType::Other(type_name) + | RustType::Base(type_name) => { python_types.push(type_name.to_string()); write_fmt!(file, " {variable_name}: {type_name}"); } @@ -212,7 +239,9 @@ pub fn generator(type_data: &[PythonBindType]) -> io::Result<()> { "String" => Cow::Borrowed("\"\""), "Vec" => Cow::Borrowed("b\"\""), t => { - if python_type.starts_with("Optional") || t.starts_with("Option<") { + if python_type.starts_with("Optional") + || t.starts_with("Option<") + { Cow::Borrowed("None") } else if t.starts_with("Vec<") { Cow::Borrowed("[]") @@ -228,7 +257,10 @@ pub fn generator(type_data: &[PythonBindType]) -> io::Result<()> { } }; - write_fmt!(file, " {variable_name}: {python_type} = {default_value},"); + write_fmt!( + file, + " {variable_name}: {python_type} = {default_value}," + ); } write_str!(file, " ): ..."); diff --git a/codegen/structs.rs b/codegen/structs.rs index 8985227..3db77ef 100644 --- a/codegen/structs.rs +++ b/codegen/structs.rs @@ -4,6 +4,7 @@ use std::{borrow::Cow, fs, iter::repeat, path::Path}; #[derive(Debug, PartialEq, Eq)] pub enum InnerVecType { U8, + Base(String), String, Custom(String), } @@ -78,8 +79,11 @@ impl StructBindGenerator { let is_frozen = PythonBindType::FROZEN_TYPES.contains(&struct_name.as_str()); let frozen_needs_py = PythonBindType::FROZEN_NEEDS_PY.contains(&struct_name.as_str()); - let is_all_base_types = types.iter().all(|t| matches!(t.rust_type, RustType::Base(_))); - let has_complex_pack = contents.contains("pub fn pack<'b, A: flatbuffers::Allocator + 'b>("); + let is_all_base_types = types + .iter() + .all(|t| matches!(t.rust_type, RustType::Base(_))); + let has_complex_pack = + contents.contains("pub fn pack<'b, A: flatbuffers::Allocator + 'b>("); let mut file_contents = vec![]; @@ -125,7 +129,9 @@ impl StructBindGenerator { let struct_start = contents.find(&struct_start_definition)?; let struct_end_definition = "}\n"; - let struct_end = contents[struct_start..].find(struct_end_definition).unwrap(); + let struct_end = contents[struct_start..] + .find(struct_end_definition) + .unwrap(); let start = struct_start + struct_start_definition.len(); let end = struct_start + struct_end - struct_end_definition.len(); @@ -165,8 +171,13 @@ impl StructBindGenerator { .trim_start_matches("Vec<") .trim_end_matches('>') .trim_end_matches('T'); + ( - RustType::Vec(InnerVecType::Custom(inner_type.to_string())), + RustType::Vec(if PythonBindType::BASE_TYPES.contains(&inner_type) { + InnerVecType::Base(inner_type.to_string()) + } else { + InnerVecType::Custom(inner_type.to_string()) + }), Some(inner_type), ) } @@ -183,9 +194,15 @@ impl StructBindGenerator { Some(inner_type), ) } else if inner == "String" { - (RustType::Option(InnerOptionType::String, inner.to_string()), None) + ( + RustType::Option(InnerOptionType::String, inner.to_string()), + None, + ) } else if PythonBindType::BASE_TYPES.contains(&inner) { - (RustType::Option(InnerOptionType::BaseType, inner.to_string()), None) + ( + RustType::Option(InnerOptionType::BaseType, inner.to_string()), + None, + ) } else { let inner = inner.trim_end_matches('T'); ( @@ -215,22 +232,24 @@ impl StructBindGenerator { (RustType::Other(raw_type.to_string()), Some(raw_type)) }; - let (is_frozen, frozen_needs_py, is_special_base) = if let Some(inner_type) = inner_type { - let is_frozen = PythonBindType::FROZEN_TYPES.contains(&inner_type); - let frozen_needs_py = is_frozen && PythonBindType::FROZEN_NEEDS_PY.contains(&inner_type); - let is_special_base = if inner_type == "Float" { - Some(SpecialBase::FloatT) - } else if inner_type == "Bool" { - Some(SpecialBase::BoolT) + let (is_frozen, frozen_needs_py, is_special_base) = + if let Some(inner_type) = inner_type { + let is_frozen = PythonBindType::FROZEN_TYPES.contains(&inner_type); + let frozen_needs_py = + is_frozen && PythonBindType::FROZEN_NEEDS_PY.contains(&inner_type); + let is_special_base = if inner_type == "Float" { + Some(SpecialBase::FloatT) + } else if inner_type == "Bool" { + Some(SpecialBase::BoolT) + } else { + None + }; + + (is_frozen, frozen_needs_py, is_special_base) } else { - None + (false, false, None) }; - (is_frozen, frozen_needs_py, is_special_base) - } else { - (false, false, None) - }; - CustomType { name: name.to_string(), raw_type: raw_type.to_string(), @@ -296,7 +315,11 @@ impl StructBindGenerator { write_str!(self, " #[allow(clippy::too_many_arguments)]"); } - write_fmt!(self, " #[pyo3(signature = ({}))]", signature_parts.join(", ")); + write_fmt!( + self, + " #[pyo3(signature = ({}))]", + signature_parts.join(", ") + ); write_str!(self, " pub fn new("); if needs_python { @@ -312,6 +335,9 @@ impl StructBindGenerator { } else { format!("Vec>") }), + RustType::Vec(InnerVecType::Base(inner_type)) => { + Cow::Owned(format!("Vec<{}>", inner_type)) + } RustType::Vec(InnerVecType::String) => Cow::Borrowed("Vec"), RustType::Vec(InnerVecType::U8) => Cow::Borrowed("Py"), RustType::Box(inner_type) => Cow::Owned(if self.is_frozen { @@ -334,7 +360,9 @@ impl StructBindGenerator { }), RustType::Base(inner_type) => Cow::Borrowed(inner_type.as_str()), RustType::String => Cow::Borrowed("String"), - RustType::Union(inner_type) => Cow::Owned(format!("Option")), + RustType::Union(inner_type) => { + Cow::Owned(format!("Option")) + } RustType::Custom(inner_type) => Cow::Owned(if self.is_frozen { format!("super::{inner_type}") } else { @@ -416,7 +444,11 @@ impl StructBindGenerator { }) .collect::>() .join(", "); - write_fmt!(self, " \"{}({repr_signature})\",", self.struct_name); + write_fmt!( + self, + " \"{}({repr_signature})\",", + self.struct_name + ); for variable_info in &self.types { let variable_name = variable_info.name.as_str(); @@ -434,6 +466,10 @@ impl StructBindGenerator { write_str!(self, " .iter()"); write_str!(self, " .map(|s| format!(\"{s:?}\"))"); } + InnerVecType::Base(_) => { + write_str!(self, " .iter()"); + write_str!(self, " .map(ToString::to_string)"); + } InnerVecType::Custom(_) => { write_str!(self, " .iter()"); write_str!( @@ -491,7 +527,10 @@ impl StructBindGenerator { } RustType::Base(inner_type) => { if inner_type == "bool" { - write_fmt!(self, " crate::bool_to_str(self.{variable_name}),"); + write_fmt!( + self, + " crate::bool_to_str(self.{variable_name})," + ); } else { write_fmt!(self, " self.{variable_name},"); } @@ -562,7 +601,10 @@ impl StructBindGenerator { ); if self.has_complex_pack { - write_str!(self, " let size = flat_t.get_size().next_power_of_two();"); + write_str!( + self, + " let size = flat_t.get_size().next_power_of_two();" + ); write_str!(self, ""); write_str!( self, @@ -571,7 +613,10 @@ impl StructBindGenerator { write_str!(self, " let offset = flat_t.pack(&mut builder);"); write_str!(self, " builder.finish(offset, None);"); write_str!(self, ""); - write_str!(self, " PyBytes::new_bound(py, builder.finished_data())"); + write_str!( + self, + " PyBytes::new_bound(py, builder.finished_data())" + ); } else { write_str!(self, " let item = flat_t.pack();"); write_str!(self, ""); @@ -589,11 +634,22 @@ impl StructBindGenerator { } else if self.is_frozen { ("", "Self", "flat_t.unpack().into()") } else { - ("py: Python, ", "Py", "crate::into_py_from(py, flat_t.unpack())") + ( + "py: Python, ", + "Py", + "crate::into_py_from(py, flat_t.unpack())", + ) }; - write_fmt!(self, " fn unpack({py_arg}data: &[u8]) -> PyResult<{return_val}> {{"); - write_fmt!(self, " match root::(data) {{", self.struct_name); + write_fmt!( + self, + " fn unpack({py_arg}data: &[u8]) -> PyResult<{return_val}> {{" + ); + write_fmt!( + self, + " match root::(data) {{", + self.struct_name + ); write_fmt!(self, " Ok(flat_t) => Ok({out_map}),"); write_str!(self, " Err(e) => Err(flat_err_to_py(e)),"); write_str!(self, " }"); @@ -622,7 +678,10 @@ impl Generator for StructBindGenerator { contents = contents.replace("\r\n", "\n"); } - contents = contents.replace("use self::flatbuffers", "use get_size::GetSize;\nuse self::flatbuffers"); + contents = contents.replace( + "use self::flatbuffers", + "use get_size::GetSize;\nuse self::flatbuffers", + ); contents = contents.replace( "#[derive(Debug, Clone, PartialEq)]\n", @@ -659,7 +718,9 @@ impl Generator for StructBindGenerator { write_str!( self, if self.is_frozen || self.is_all_base_types { - if !self.is_all_base_types || self.types.iter().any(|t| t.rust_type == RustType::String) { + if !self.is_all_base_types + || self.types.iter().any(|t| t.rust_type == RustType::String) + { "#[derive(Debug, Default, Clone)]" } else { "#[derive(Debug, Default, Clone, Copy)]" @@ -676,6 +737,7 @@ impl Generator for StructBindGenerator { let variable_type = match &variable_info.rust_type { RustType::Vec(InnerVecType::U8) => String::from("Py"), RustType::Vec(InnerVecType::String) => String::from("Vec"), + RustType::Vec(InnerVecType::Base(inner_type)) => format!("Vec<{}>", inner_type), RustType::Vec(InnerVecType::Custom(inner_type)) => { if self.is_frozen { format!("Vec") @@ -691,7 +753,9 @@ impl Generator for StructBindGenerator { } } RustType::Option(InnerOptionType::BaseType, inner_type) - | RustType::Option(InnerOptionType::String, inner_type) => format!("Option<{inner_type}>"), + | RustType::Option(InnerOptionType::String, inner_type) => { + format!("Option<{inner_type}>") + } RustType::Option(_, inner_type) => { if self.is_frozen { format!("Option") @@ -733,13 +797,19 @@ impl Generator for StructBindGenerator { let variable_name = variable_info.name.as_str(); let end = match &variable_info.rust_type { - RustType::Vec(InnerVecType::U8) => Cow::Borrowed("PyBytes::new_bound(py, &[]).unbind()"), - RustType::Vec(InnerVecType::Custom(_) | InnerVecType::String) => Cow::Borrowed("Vec::new()"), + RustType::Vec(InnerVecType::U8) => { + Cow::Borrowed("PyBytes::new_bound(py, &[]).unbind()") + } + RustType::Vec(_) => Cow::Borrowed("Vec::new()"), RustType::Option(_, _) => Cow::Borrowed("None"), - RustType::Union(inner_type) | RustType::Box(inner_type) | RustType::Custom(inner_type) => { + RustType::Union(inner_type) + | RustType::Box(inner_type) + | RustType::Custom(inner_type) => { Cow::Owned(format!("super::{inner_type}::py_default(py)")) } - RustType::String | RustType::Base(_) | RustType::Other(_) => Cow::Borrowed("Default::default()"), + RustType::String | RustType::Base(_) | RustType::Other(_) => { + Cow::Borrowed("Default::default()") + } }; write_fmt!(self, " {variable_name}: {end},"); @@ -776,13 +846,20 @@ impl Generator for StructBindGenerator { (false, "FromGil", "from_gil", "py: Python, ") }; - write_fmt!(self, "impl {trait_name}<{impl_type}> for {} {{", self.struct_name); + write_fmt!( + self, + "impl {trait_name}<{impl_type}> for {} {{", + self.struct_name + ); if !is_simple { write_str!(self, " #[allow(unused_variables)]") } - write_fmt!(self, " fn {fn_name}({python_arg}flat_t: {impl_type}) -> Self {{"); + write_fmt!( + self, + " fn {fn_name}({python_arg}flat_t: {impl_type}) -> Self {{" + ); write_fmt!(self, " {} {{", self.struct_name); for variable_info in &self.types { @@ -795,7 +872,7 @@ impl Generator for StructBindGenerator { " {variable_name}: PyBytes::new_bound(py, &flat_t.{variable_name}).unbind()," ) } - RustType::Vec(InnerVecType::String) => { + RustType::Vec(InnerVecType::String | InnerVecType::Base(_)) => { write_fmt!(self, " {variable_name}: flat_t.{variable_name},") } RustType::Vec(InnerVecType::Custom(_)) => { @@ -867,7 +944,10 @@ impl Generator for StructBindGenerator { write_fmt!(self, " {variable_name}: flat_t.{variable_name},"); } RustType::Other(_) => { - write_fmt!(self, " {variable_name}: flat_t.{variable_name}.into(),",); + write_fmt!( + self, + " {variable_name}: flat_t.{variable_name}.into(),", + ); } } } @@ -898,7 +978,11 @@ impl Generator for StructBindGenerator { (false, "FromGil", "from_gil", "py: Python, ") }; - write_fmt!(self, "impl {trait_name}<&{}> for {impl_type} {{", self.struct_name); + write_fmt!( + self, + "impl {trait_name}<&{}> for {impl_type} {{", + self.struct_name + ); if !is_simple { write_str!(self, " #[allow(unused_variables)]") @@ -921,8 +1005,11 @@ impl Generator for StructBindGenerator { " {variable_name}: py_type.{variable_name}.as_bytes(py).to_vec()," ) } - RustType::Vec(InnerVecType::String) => { - write_fmt!(self, " {variable_name}: py_type.{variable_name}.clone(),") + RustType::Vec(InnerVecType::String | InnerVecType::Base(_)) => { + write_fmt!( + self, + " {variable_name}: py_type.{variable_name}.clone()," + ) } RustType::Vec(InnerVecType::Custom(_)) => { if self.is_frozen { @@ -953,7 +1040,10 @@ impl Generator for StructBindGenerator { write_fmt!(self, " {variable_name}: py_type.{variable_name}.as_ref().map(|x| Box::new({inner})),"); } RustType::Option(InnerOptionType::String, _) => { - write_fmt!(self, " {variable_name}: py_type.{variable_name}.clone(),"); + write_fmt!( + self, + " {variable_name}: py_type.{variable_name}.clone()," + ); } RustType::Option(_, _) => { write_fmt!( @@ -988,13 +1078,22 @@ impl Generator for StructBindGenerator { write_fmt!(self, " {variable_name}: {end},",); } RustType::String => { - write_fmt!(self, " {variable_name}: py_type.{variable_name}.clone(),",); + write_fmt!( + self, + " {variable_name}: py_type.{variable_name}.clone(),", + ); } RustType::Base(_) => { - write_fmt!(self, " {variable_name}: py_type.{variable_name},"); + write_fmt!( + self, + " {variable_name}: py_type.{variable_name}," + ); } RustType::Other(_) => { - write_fmt!(self, " {variable_name}: (&py_type.{variable_name}).into(),",); + write_fmt!( + self, + " {variable_name}: (&py_type.{variable_name}).into(),", + ); } } } diff --git a/codegen/unions.rs b/codegen/unions.rs index 1e1892a..3ae6737 100644 --- a/codegen/unions.rs +++ b/codegen/unions.rs @@ -61,7 +61,10 @@ impl UnionBindGenerator { write_str!(self, " }"); write_str!(self, ""); write_str!(self, " #[getter(item)]"); - write_str!(self, " pub fn get(&self, py: Python) -> Option {"); + write_str!( + self, + " pub fn get(&self, py: Python) -> Option {" + ); write_str!(self, " match self.item.as_ref() {"); for variable_info in &self.types { @@ -123,7 +126,11 @@ impl UnionBindGenerator { self.struct_name, self.struct_name ); } else { - write_fmt!(self, " None => String::from(\"{}()\"),", self.struct_name); + write_fmt!( + self, + " None => String::from(\"{}()\"),", + self.struct_name + ); } } @@ -153,7 +160,10 @@ impl Generator for UnionBindGenerator { contents = contents.replace("\r\n", "\n"); } - contents = contents.replace("use self::flatbuffers", "use get_size::GetSize;\nuse self::flatbuffers"); + contents = contents.replace( + "use self::flatbuffers", + "use get_size::GetSize;\nuse self::flatbuffers", + ); contents = contents.replace( "#[derive(Debug, Clone, PartialEq)]\n", @@ -265,7 +275,11 @@ impl Generator for UnionBindGenerator { let variable_name = variable_info.name.as_str(); if let Some(ref value) = variable_info.value { - write_fmt!(self, " Some({}Union::{value}(item)) => {{", self.struct_name,); + write_fmt!( + self, + " Some({}Union::{value}(item)) => {{", + self.struct_name, + ); write_fmt!( self, " flat::{}::{variable_name}(Box::new(crate::from_py_into(py, item)))", diff --git a/flatbuffers-schema b/flatbuffers-schema index f01d710..15d09b4 160000 --- a/flatbuffers-schema +++ b/flatbuffers-schema @@ -1 +1 @@ -Subproject commit f01d710b63cf86e971c9ff19afe5672815aa53c8 +Subproject commit 15d09b465b0620ec3eac114d9996a673b478d258 diff --git a/pybench.py b/pybench.py index 7e4da0c..a87dfc3 100644 --- a/pybench.py +++ b/pybench.py @@ -6,18 +6,18 @@ def test_gtp(): times = [] - gtp = flat.GameTickPacket( + gtp = flat.GamePacket( balls=[flat.BallInfo(shape=flat.SphereShape()) for _ in range(32)], players=[flat.PlayerInfo() for _ in range(128)], boost_pads=[flat.BoostPadState() for _ in range(128)], teams=[flat.TeamInfo() for _ in range(2)], ) - for _ in range(15_000): + for _ in range(20_000): start = time_ns() packed = gtp.pack() - flat.GameTickPacket.unpack(packed) + flat.GamePacket.unpack(packed) times.append(time_ns() - start) @@ -32,7 +32,7 @@ def test_ballpred(): ballPred = flat.BallPrediction([flat.PredictionSlice(1) for _ in range(960)]) - for _ in range(10_000): + for _ in range(100_000): start = time_ns() packed = ballPred.pack() diff --git a/pytest.py b/pytest.py index ae44253..29445dc 100644 --- a/pytest.py +++ b/pytest.py @@ -41,8 +41,9 @@ def random_script_config(): player_info = PlayerInfo(accolades=["MVP", "Hat Trick"]) eval(repr(player_info)) + print() - connection_settings = ConnectionSettings(True, close_after_match=True) + connection_settings = ConnectionSettings("rlbot/abot", True, close_after_match=True) print(hash(connection_settings)) print(connection_settings) eval(repr(connection_settings)) diff --git a/rustfmt.toml b/rustfmt.toml index 0149958..65a8834 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,2 @@ use_field_init_shorthand = true -use_try_shorthand = true -max_width = 115 \ No newline at end of file +use_try_shorthand = true \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 1f4851f..e9aeee6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,7 +17,12 @@ use pyo3::{create_exception, exceptions::PyValueError, prelude::*, types::PyByte use python::*; use std::panic::Location; -create_exception!(rlbot_flatbuffers, InvalidFlatbuffer, PyValueError, "Invalid FlatBuffer"); +create_exception!( + rlbot_flatbuffers, + InvalidFlatbuffer, + PyValueError, + "Invalid FlatBuffer" +); #[track_caller] pub fn flat_err_to_py(err: flatbuffers::InvalidFlatbuffer) -> PyErr { @@ -186,6 +191,8 @@ pynamedmodule! { Color, ConnectionSettings, ConsoleCommand, + ControllableInfo, + ControllableTeamInfo, ControllerState, CylinderShape, DemolishOption, @@ -201,13 +208,12 @@ pynamedmodule! { GameEventOption, GameInfo, GameMode, + GamePacket, GameSpeedOption, - GameStateType, - GameTickPacket, + GameStatus, GoalInfo, GravityOption, Human, - InitComplete, Launcher, Line3D, LoadoutPaint, @@ -254,6 +260,7 @@ pynamedmodule! { TextHAlign, TextVAlign, Touch, + Vector2, Vector3, Vector3Partial ],