decoder: signed layouts (two's complement, lengths 8 and 16)
/ crosscheck (push) Successful in 1s
Rust (L4T) / Clippy, test, build, glibc (push) Successful in 15s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDwfd6Ki8UfG4hK6W5YpJz
This commit is contained in:
2026-10-15 21:21:49 +09:00
parent 7355b0d26b
commit 3bb6c936c8
+13 -1
View File
@@ -21,6 +21,8 @@ pub struct Layout {
pub bit: u32,
/// Length 16 only: true = `byte` is the most significant.
pub big: bool,
/// Lengths 8 and 16: two's complement (`"signed": true` in the can block).
pub signed: bool,
pub scale: f64,
pub offset: f64,
pub kind: Kind,
@@ -48,7 +50,12 @@ impl Layout {
Some(match self.kind {
Kind::Bool => Value::Bool(raw != 0),
Kind::Number => {
let v = raw as f64 * self.scale + self.offset;
let raw = match (self.signed, self.length) {
(true, 8) => raw as u8 as i8 as f64,
(true, 16) => raw as u16 as i16 as f64,
_ => raw as f64,
};
let v = raw * self.scale + self.offset;
// Three decimals: 0.4 × 98 should read 39.2, not 39.200000000000003.
let v = (v * 1000.0).round() / 1000.0;
serde_json::Number::from_f64(v).map(Value::Number).unwrap_or(Value::Null)
@@ -97,6 +104,7 @@ pub fn load(registry: &str) -> Result<Vec<Layout>, String> {
length,
bit,
big,
signed: c["signed"].as_bool().unwrap_or(false),
scale: c["scale"].as_f64().unwrap_or(1.0),
offset: c["offset"].as_f64().unwrap_or(0.0),
kind,
@@ -136,6 +144,10 @@ mod tests {
let pedal = &one(json!({"id": "0x210", "byte": 0, "length": 8, "scale": 0.4}), "number").unwrap()[0];
assert_eq!(pedal.value(&[0xFA]), Some(json!(100.0)));
assert_eq!(pedal.value(&[98]), Some(json!(39.2)));
// Signed: 0C0's steering angle, 0.1° per count, little-endian two's complement.
let steer = &one(json!({"id": "0x0C0", "byte": 0, "length": 16, "order": "little", "signed": true, "scale": 0.1}), "number").unwrap()[0];
assert_eq!(steer.value(&[0x41, 0xED]), Some(json!(-479.9))); // 0xED41 = -4799
assert_eq!(steer.value(&[0x69, 0x12]), Some(json!(471.3))); // 0x1269 = 4713
let brake = &one(json!({"id": "0x231", "byte": 4, "bit": 1, "length": 1}), "boolean").unwrap()[0];
assert_eq!(brake.value(&[0, 0, 0, 0, 0x02]), Some(json!(true)));
assert_eq!(brake.value(&[0, 0, 0, 0, 0xFD]), Some(json!(false)));