diff --git a/packages/rust-types/build.rs b/packages/rust-types/build.rs index be59304..2d99ad9 100644 --- a/packages/rust-types/build.rs +++ b/packages/rust-types/build.rs @@ -11,11 +11,6 @@ fn main() { proto_root.join("continuum/v1/print_params.proto"), proto_root.join("continuum/v1/template.proto"), proto_root.join("continuum/v1/print_job.proto"), - proto_root.join("bambulab/common.proto"), - proto_root.join("bambulab/v1/request.proto"), - proto_root.join("bambulab/v1/report.proto"), - proto_root.join("bambulab/v2/request.proto"), - proto_root.join("bambulab/v2/report.proto"), ]; for file in &proto_files { @@ -23,41 +18,8 @@ fn main() { } let mut config = prost_build::Config::new(); - - // continuum.v1 — Continuum's own cross-service API. camelCase to match - // the TS side's existing convention (this is a schema we designed - // ourselves, so we get to pick the convention). - config.type_attribute(".continuum", "#[derive(serde::Serialize, serde::Deserialize)]"); - config.type_attribute(".continuum", "#[serde(rename_all = \"camelCase\")]"); - - // bambulab.* — mirrors Bambu's actual MQTT wire JSON exactly - // (snake_case), because this isn't a schema we get to design: it's - // edge-only traffic (continuum-proxy only, never crosses into TS) that - // has to match whatever the printer actually sends, byte for byte. - // - // IMPORTANT: these two type_attribute calls are scoped to ".bambulab" - // specifically, not "." (global) — type_attribute calls are cumulative, - // so a "." blanket rule here would stack a second, conflicting - // #[serde(rename_all = ...)] onto every bambulab type alongside this - // one and fail to compile. Verified: see commit history for this file. - config.type_attribute(".bambulab", "#[derive(serde::Serialize, serde::Deserialize)]"); - config.type_attribute(".bambulab", "#[serde(rename_all = \"snake_case\")]"); - - // Some Bambu response fields aren't always present (e.g. `result`/ - // `reason` on some info responses) — serde requires every struct field - // present in the JSON unless told otherwise. Add one line per such - // field as you find them, e.g.: - // config.field_attribute(".bambulab.v1.InfoResponse.result", "#[serde(default)]"); - // - // Do NOT try to model the top-level {"info": {...}} / {"pushing": {...}} - // envelope as a proto `oneof` here — prost-build's field/variant - // attribute matching can't distinguish "the oneof field" from "the - // variants inside it" (both match the same path prefix), so - // `#[serde(flatten)]` lands in the wrong place and won't compile. Write - // the envelope as a plain Rust enum instead, in continuum-proxy — - // serde's default enum representation already produces exactly - // {"info": {...}} with no configuration at all. See - // continuum-proxy/src/printer/bambu_protocol.rs. + config.type_attribute(".", "#[derive(serde::Serialize, serde::Deserialize)]"); + config.type_attribute(".", "#[serde(rename_all = \"camelCase\")]"); config .compile_protos(&proto_files, &[proto_root]) diff --git a/packages/rust-types/src/lib.rs b/packages/rust-types/src/lib.rs index dd49945..66fcf88 100644 --- a/packages/rust-types/src/lib.rs +++ b/packages/rust-types/src/lib.rs @@ -8,20 +8,18 @@ pub use continuum::v1::{ MaterialProfile, PrintJob, PrintJobStatus, PrintParameters, Template, }; -pub mod bambulab { - // common.proto and bambulab/v2/*.proto have no messages yet, so - // there's nothing for prost to emit for them — `include!` against a - // nonexistent file breaks the build. Uncomment each once it has real - // content: - // - // include!(concat!(env!("OUT_DIR"), "/bambulab.rs")); // common.proto's messages - pub mod v1 { - // request.proto + report.proto both declare `package bambulab.v1;`, - // so prost combines them into one output file, regardless of which - // input file each message came from. - include!(concat!(env!("OUT_DIR"), "/bambulab.v1.rs")); - } - // pub mod v2 { - // include!(concat!(env!("OUT_DIR"), "/bambulab.v2.rs")); - // } -} +// Bambu's raw MQTT command/report structs are NOT modeled here — they're +// plain hand-written Rust + serde in continuum-proxy's +// src/printer/bambu_commands/, not proto. That data is JSON-over-MQTT +// (not binary protobuf), and only continuum-proxy ever needs to parse it +// — none of protobuf's actual value (cross-language codegen, binary wire +// efficiency) applies, and forcing it through prost-build's codegen model +// anyway produced real, avoidable friction (see this crate's git history +// for the specifics: a field/variant attribute-matching collision on +// `oneof`, needing package-scoped `type_attribute` calls, explicit +// `field_attribute(..., "#[serde(default)]")` for fields that aren't +// always present — every one of these disappears with a hand-written +// struct, where `Option` and `#[serde(flatten)]` just work with zero +// configuration). Proto stays for continuum.v1 above, which — unlike +// this — is a schema we designed ourselves and that both TS and Rust +// genuinely need. diff --git a/proto/bambulab/common.proto b/proto/bambulab/common.proto deleted file mode 100644 index aebc009..0000000 --- a/proto/bambulab/common.proto +++ /dev/null @@ -1,9 +0,0 @@ -syntax = "proto3"; - -package bambulab; - -// Fields/messages genuinely shared between v1 and v2 (unversioned, since -// they don't change across generations) go here — composition, embedded as -// a field in v1/v2 messages via `import "bambulab/common.proto";`, not -// inheritance. e.g. every Bambu command/response shares sequence_id + -// command; that's a good candidate for a message here. diff --git a/proto/bambulab/v1/report.proto b/proto/bambulab/v1/report.proto deleted file mode 100644 index dbfff32..0000000 --- a/proto/bambulab/v1/report.proto +++ /dev/null @@ -1,15 +0,0 @@ -syntax = "proto3"; - -package bambulab.v1; - -// import "bambulab/common.proto"; once common.proto has a shared message -// worth embedding (composition, not inheritance — see that file). - -// Your report/response messages go here, e.g.: -// -// message InfoResponse { -// string sequence_id = 1; -// string command = 2; -// string result = 3; // not always present — see build.rs field_attribute -// string reason = 4; // not always present — see build.rs field_attribute -// } diff --git a/proto/bambulab/v1/request.proto b/proto/bambulab/v1/request.proto deleted file mode 100644 index e0a19eb..0000000 --- a/proto/bambulab/v1/request.proto +++ /dev/null @@ -1,23 +0,0 @@ -syntax = "proto3"; - -package bambulab.v1; - -// One real, fully-wired example — copy this shape for every other command -// (pushing/pushall, print control, etc.). sequence_id is `string`, not -// int64: Bambu sends it as a JSON string ("0"), and this crosses the wire -// as JSON over MQTT, not binary protobuf — the Rust type needs to match -// what serde_json actually produces, not what "feels more correct" for a -// counter. -message InfoCommand { - string sequence_id = 1; - string command = 2; -} - -// Add your next message here, e.g.: -// -// message PushingCommand { -// string sequence_id = 1; -// string command = 2; -// int32 version = 3; -// int32 push_target = 4; -// } diff --git a/proto/bambulab/v2/report.proto b/proto/bambulab/v2/report.proto deleted file mode 100644 index 16fdfc1..0000000 --- a/proto/bambulab/v2/report.proto +++ /dev/null @@ -1,9 +0,0 @@ -syntax = "proto3"; - -package bambulab.v2; - -// import "bambulab/common.proto"; once common.proto has a shared message -// worth embedding (composition, not inheritance — see that file). - -// V2-generation (X1/H2 series) report/response messages go here — e.g. -// whatever AMS/report-schema fields V2 has that V1 doesn't. diff --git a/proto/bambulab/v2/request.proto b/proto/bambulab/v2/request.proto deleted file mode 100644 index e771e9a..0000000 --- a/proto/bambulab/v2/request.proto +++ /dev/null @@ -1,8 +0,0 @@ -syntax = "proto3"; - -package bambulab.v2; - -// import "bambulab/common.proto"; once common.proto has a shared message -// worth embedding (composition, not inheritance — see that file). - -// V2-generation (X1/H2 series) command messages go here.