Skip to content

Commit 874f360

Browse files
committed
Fix issue with decoding signed values of non-standard length
1 parent a3fec55 commit 874f360

File tree

4 files changed

+251
-14
lines changed

4 files changed

+251
-14
lines changed

src/lib.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ fn signal_from_payload(mut w: impl Write, signal: &Signal, msg: &Message) -> Res
832832

833833
format!(
834834
"self.raw.view_bits::<Lsb0>()[{start}..{end}].load_le::<{typ}>()",
835-
typ = signal_to_rust_uint(signal),
835+
typ = signal_to_rust_int(signal),
836836
start = start_bit,
837837
end = end_bit,
838838
)
@@ -842,7 +842,7 @@ fn signal_from_payload(mut w: impl Write, signal: &Signal, msg: &Message) -> Res
842842

843843
format!(
844844
"self.raw.view_bits::<Msb0>()[{start}..{end}].load_be::<{typ}>()",
845-
typ = signal_to_rust_uint(signal),
845+
typ = signal_to_rust_int(signal),
846846
start = start_bit,
847847
end = end_bit
848848
)
@@ -852,14 +852,6 @@ fn signal_from_payload(mut w: impl Write, signal: &Signal, msg: &Message) -> Res
852852
writeln!(&mut w, r#"let signal = {};"#, read_fn)?;
853853
writeln!(&mut w)?;
854854

855-
if *signal.value_type() == can_dbc::ValueType::Signed {
856-
writeln!(
857-
&mut w,
858-
"let signal = {}::from_ne_bytes(signal.to_ne_bytes());",
859-
signal_to_rust_int(signal)
860-
)?;
861-
};
862-
863855
if signal.signal_size == 1 {
864856
writeln!(&mut w, "signal == 1")?;
865857
} else if signal_is_float_in_rust(signal) {

testing/can-messages/src/messages.rs

Lines changed: 224 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ pub enum Messages {
4242
LargerIntsWithOffsets(LargerIntsWithOffsets),
4343
/// MsgWithoutSignals
4444
MsgWithoutSignals(MsgWithoutSignals),
45+
/// TruncatedBeSignal
46+
TruncatedBeSignal(TruncatedBeSignal),
47+
/// TruncatedLeSignal
48+
TruncatedLeSignal(TruncatedLeSignal),
4549
}
4650

4751
impl Messages {
@@ -59,6 +63,8 @@ impl Messages {
5963
1344 => Messages::NegativeFactorTest(NegativeFactorTest::try_from(payload)?),
6064
1338 => Messages::LargerIntsWithOffsets(LargerIntsWithOffsets::try_from(payload)?),
6165
513 => Messages::MsgWithoutSignals(MsgWithoutSignals::try_from(payload)?),
66+
9001 => Messages::TruncatedBeSignal(TruncatedBeSignal::try_from(payload)?),
67+
9002 => Messages::TruncatedLeSignal(TruncatedLeSignal::try_from(payload)?),
6268
n => return Err(CanError::UnknownMessageId(n)),
6369
};
6470
Ok(res)
@@ -159,9 +165,8 @@ impl Foo {
159165
/// - Value type: Signed
160166
#[inline(always)]
161167
pub fn current_raw(&self) -> f32 {
162-
let signal = self.raw.view_bits::<Lsb0>()[0..16].load_le::<u16>();
168+
let signal = self.raw.view_bits::<Lsb0>()[0..16].load_le::<i16>();
163169

164-
let signal = i16::from_ne_bytes(signal.to_ne_bytes());
165170
let factor = 0.0625_f32;
166171
let offset = 0_f32;
167172
(signal as f32) * factor + offset
@@ -1930,9 +1935,8 @@ impl NegativeFactorTest {
19301935
/// - Value type: Signed
19311936
#[inline(always)]
19321937
pub fn width_more_than_min_max_raw(&self) -> i16 {
1933-
let signal = self.raw.view_bits::<Lsb0>()[16..26].load_le::<u16>();
1938+
let signal = self.raw.view_bits::<Lsb0>()[16..26].load_le::<i16>();
19341939

1935-
let signal = i16::from_ne_bytes(signal.to_ne_bytes());
19361940
let factor = 1;
19371941
let signal = signal as i16;
19381942
i16::from(signal).saturating_mul(factor).saturating_add(0)
@@ -2215,6 +2219,222 @@ impl<'a> Arbitrary<'a> for MsgWithoutSignals {
22152219
}
22162220
}
22172221

2222+
/// TruncatedBeSignal
2223+
///
2224+
/// - ID: 9001 (0x2329)
2225+
/// - Size: 8 bytes
2226+
/// - Transmitter: Ipsum
2227+
#[derive(Clone, Copy)]
2228+
pub struct TruncatedBeSignal {
2229+
raw: [u8; 8],
2230+
}
2231+
2232+
impl TruncatedBeSignal {
2233+
pub const MESSAGE_ID: u32 = 9001;
2234+
2235+
pub const FOO_MIN: i16 = -100_i16;
2236+
pub const FOO_MAX: i16 = 100_i16;
2237+
2238+
/// Construct new TruncatedBeSignal from values
2239+
pub fn new(foo: i16) -> Result<Self, CanError> {
2240+
let mut res = Self { raw: [0u8; 8] };
2241+
res.set_foo(foo)?;
2242+
Ok(res)
2243+
}
2244+
2245+
/// Access message payload raw value
2246+
pub fn raw(&self) -> &[u8; 8] {
2247+
&self.raw
2248+
}
2249+
2250+
/// Foo
2251+
///
2252+
/// - Min: -100
2253+
/// - Max: 100
2254+
/// - Unit: ""
2255+
/// - Receivers: Vector__XXX
2256+
#[inline(always)]
2257+
pub fn foo(&self) -> i16 {
2258+
self.foo_raw()
2259+
}
2260+
2261+
/// Get raw value of Foo
2262+
///
2263+
/// - Start bit: 0
2264+
/// - Signal size: 12 bits
2265+
/// - Factor: 1
2266+
/// - Offset: 0
2267+
/// - Byte order: BigEndian
2268+
/// - Value type: Signed
2269+
#[inline(always)]
2270+
pub fn foo_raw(&self) -> i16 {
2271+
let signal = self.raw.view_bits::<Msb0>()[7..19].load_be::<i16>();
2272+
2273+
let factor = 1;
2274+
let signal = signal as i16;
2275+
i16::from(signal).saturating_mul(factor).saturating_add(0)
2276+
}
2277+
2278+
/// Set value of Foo
2279+
#[inline(always)]
2280+
pub fn set_foo(&mut self, value: i16) -> Result<(), CanError> {
2281+
if value < -100_i16 || 100_i16 < value {
2282+
return Err(CanError::ParameterOutOfRange { message_id: 9001 });
2283+
}
2284+
let factor = 1;
2285+
let value = value
2286+
.checked_sub(0)
2287+
.ok_or(CanError::ParameterOutOfRange { message_id: 9001 })?;
2288+
let value = (value / factor) as i16;
2289+
2290+
let value = u16::from_ne_bytes(value.to_ne_bytes());
2291+
self.raw.view_bits_mut::<Msb0>()[7..19].store_be(value);
2292+
Ok(())
2293+
}
2294+
}
2295+
2296+
impl core::convert::TryFrom<&[u8]> for TruncatedBeSignal {
2297+
type Error = CanError;
2298+
2299+
#[inline(always)]
2300+
fn try_from(payload: &[u8]) -> Result<Self, Self::Error> {
2301+
if payload.len() != 8 {
2302+
return Err(CanError::InvalidPayloadSize);
2303+
}
2304+
let mut raw = [0u8; 8];
2305+
raw.copy_from_slice(&payload[..8]);
2306+
Ok(Self { raw })
2307+
}
2308+
}
2309+
2310+
impl core::fmt::Debug for TruncatedBeSignal {
2311+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2312+
if f.alternate() {
2313+
f.debug_struct("TruncatedBeSignal")
2314+
.field("foo", &self.foo())
2315+
.finish()
2316+
} else {
2317+
f.debug_tuple("TruncatedBeSignal").field(&self.raw).finish()
2318+
}
2319+
}
2320+
}
2321+
2322+
#[cfg(feature = "arb")]
2323+
impl<'a> Arbitrary<'a> for TruncatedBeSignal {
2324+
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> {
2325+
let foo = u.int_in_range(-100..=100)?;
2326+
TruncatedBeSignal::new(foo).map_err(|_| arbitrary::Error::IncorrectFormat)
2327+
}
2328+
}
2329+
2330+
/// TruncatedLeSignal
2331+
///
2332+
/// - ID: 9002 (0x232a)
2333+
/// - Size: 8 bytes
2334+
/// - Transmitter: Ipsum
2335+
#[derive(Clone, Copy)]
2336+
pub struct TruncatedLeSignal {
2337+
raw: [u8; 8],
2338+
}
2339+
2340+
impl TruncatedLeSignal {
2341+
pub const MESSAGE_ID: u32 = 9002;
2342+
2343+
pub const FOO_MIN: i16 = -100_i16;
2344+
pub const FOO_MAX: i16 = 100_i16;
2345+
2346+
/// Construct new TruncatedLeSignal from values
2347+
pub fn new(foo: i16) -> Result<Self, CanError> {
2348+
let mut res = Self { raw: [0u8; 8] };
2349+
res.set_foo(foo)?;
2350+
Ok(res)
2351+
}
2352+
2353+
/// Access message payload raw value
2354+
pub fn raw(&self) -> &[u8; 8] {
2355+
&self.raw
2356+
}
2357+
2358+
/// Foo
2359+
///
2360+
/// - Min: -100
2361+
/// - Max: 100
2362+
/// - Unit: ""
2363+
/// - Receivers: Vector__XXX
2364+
#[inline(always)]
2365+
pub fn foo(&self) -> i16 {
2366+
self.foo_raw()
2367+
}
2368+
2369+
/// Get raw value of Foo
2370+
///
2371+
/// - Start bit: 0
2372+
/// - Signal size: 12 bits
2373+
/// - Factor: 1
2374+
/// - Offset: 0
2375+
/// - Byte order: LittleEndian
2376+
/// - Value type: Signed
2377+
#[inline(always)]
2378+
pub fn foo_raw(&self) -> i16 {
2379+
let signal = self.raw.view_bits::<Lsb0>()[0..12].load_le::<i16>();
2380+
2381+
let factor = 1;
2382+
let signal = signal as i16;
2383+
i16::from(signal).saturating_mul(factor).saturating_add(0)
2384+
}
2385+
2386+
/// Set value of Foo
2387+
#[inline(always)]
2388+
pub fn set_foo(&mut self, value: i16) -> Result<(), CanError> {
2389+
if value < -100_i16 || 100_i16 < value {
2390+
return Err(CanError::ParameterOutOfRange { message_id: 9002 });
2391+
}
2392+
let factor = 1;
2393+
let value = value
2394+
.checked_sub(0)
2395+
.ok_or(CanError::ParameterOutOfRange { message_id: 9002 })?;
2396+
let value = (value / factor) as i16;
2397+
2398+
let value = u16::from_ne_bytes(value.to_ne_bytes());
2399+
self.raw.view_bits_mut::<Lsb0>()[0..12].store_le(value);
2400+
Ok(())
2401+
}
2402+
}
2403+
2404+
impl core::convert::TryFrom<&[u8]> for TruncatedLeSignal {
2405+
type Error = CanError;
2406+
2407+
#[inline(always)]
2408+
fn try_from(payload: &[u8]) -> Result<Self, Self::Error> {
2409+
if payload.len() != 8 {
2410+
return Err(CanError::InvalidPayloadSize);
2411+
}
2412+
let mut raw = [0u8; 8];
2413+
raw.copy_from_slice(&payload[..8]);
2414+
Ok(Self { raw })
2415+
}
2416+
}
2417+
2418+
impl core::fmt::Debug for TruncatedLeSignal {
2419+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2420+
if f.alternate() {
2421+
f.debug_struct("TruncatedLeSignal")
2422+
.field("foo", &self.foo())
2423+
.finish()
2424+
} else {
2425+
f.debug_tuple("TruncatedLeSignal").field(&self.raw).finish()
2426+
}
2427+
}
2428+
}
2429+
2430+
#[cfg(feature = "arb")]
2431+
impl<'a> Arbitrary<'a> for TruncatedLeSignal {
2432+
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> {
2433+
let foo = u.int_in_range(-100..=100)?;
2434+
TruncatedLeSignal::new(foo).map_err(|_| arbitrary::Error::IncorrectFormat)
2435+
}
2436+
}
2437+
22182438
/// This is just to make testing easier
22192439
#[allow(dead_code)]
22202440
fn main() {}

testing/can-messages/tests/all.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use can_messages::{
44
Amet, Bar, BarThree, CanError, Foo, LargerIntsWithOffsets, MultiplexTest,
55
MultiplexTestMultiplexorIndex, MultiplexTestMultiplexorM0, NegativeFactorTest,
6+
TruncatedBeSignal, TruncatedLeSignal,
67
};
78

89
#[test]
@@ -75,6 +76,24 @@ fn pack_unpack_message_containing_multiplexed_signals() {
7576
}
7677
}
7778

79+
#[test]
80+
fn pack_unpack_signed_truncated_signal() {
81+
let result = TruncatedBeSignal::new(42).unwrap();
82+
assert_eq!(result.foo_raw(), 42);
83+
84+
let result = TruncatedLeSignal::new(42).unwrap();
85+
assert_eq!(result.foo_raw(), 42);
86+
}
87+
88+
#[test]
89+
fn pack_unpack_signed_truncated_signal_negative() {
90+
let result = TruncatedBeSignal::new(-42).unwrap();
91+
assert_eq!(result.foo_raw(), -42);
92+
93+
let result = TruncatedLeSignal::new(-42).unwrap();
94+
assert_eq!(result.foo_raw(), -42);
95+
}
96+
7897
#[test]
7998
fn offset_integers() {
8099
let mut m = LargerIntsWithOffsets::new(100, 30000).unwrap();

testing/dbc-examples/example.dbc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ BO_ 1338 LargerIntsWithOffsets: 8 Sit
5757

5858
BO_ 513 MsgWithoutSignals: 8 Ipsum
5959

60+
BO_ 9001 TruncatedBeSignal: 8 Ipsum
61+
SG_ Foo : 0|12@0- (1,0) [-100|100] "" Vector__XXX
62+
63+
BO_ 9002 TruncatedLeSignal: 8 Ipsum
64+
SG_ Foo : 0|12@1- (1,0) [-100|100] "" Vector__XXX
65+
6066
VAL_ 512 Three 0 "OFF" 1 "ON" 2 "ONER" 3 "ONEST";
6167
VAL_ 512 Four 0 "Off" 1 "On" 2 "Oner" 3 "Onest";
6268
VAL_ 512 Type 0 "0Off" 1 "1On";

0 commit comments

Comments
 (0)