Drop proto/bambulab/ — plain hand-written Rust structs instead

Reconsidered after actually feeling the friction: this data is JSON over
MQTT (not binary protobuf), only continuum-proxy ever parses it (raw
vendor wire format, never crosses into TS), so none of protobuf's actual
value (cross-language codegen, binary wire efficiency) applied here.
Every gotcha hit while building this (field_attribute's oneof/variant
path collision, needing .bambulab-scoped type_attribute calls, explicit
#[serde(default)] per not-always-present field) came from forcing
prost-build's codegen model onto a plain-JSON, Rust-only use case.

Verified the replacement is strictly simpler, not just smaller: a
hand-written struct's Option<T> field needs zero extra attributes to
handle a missing JSON key (prost's generated String needed an explicit
field_attribute call per field), and #[serde(flatten)] on a hand-written
field has no ambiguity at all (prost-build's oneof/variant path collision
doesn't exist without prost-build's codegen in the picture).

The replacement lives in continuum-proxy: src/printer/bambu_commands/.
continuum.v1 is unaffected — that schema is genuinely cross-language and
proto still earns its keep there.
This commit is contained in:
2026-08-28 22:48:48 +00:00
parent 99c1d038f9
commit bc4ee8690a
7 changed files with 17 additions and 121 deletions
+2 -40
View File
@@ -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])