Skip to content

Commit

Permalink
Merge pull request #72 from projectgus/bugfix/offset_integers
Browse files Browse the repository at this point in the history
Fix signed offset integers where scaled int size equals raw size.
  • Loading branch information
Pascal Hertleif authored May 13, 2024
2 parents 1054804 + 74fbd9c commit 9bf8813
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 5 deletions.
13 changes: 10 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -868,18 +868,25 @@ fn signal_from_payload(mut w: impl Write, signal: &Signal, msg: &Message) -> Res
writeln!(&mut w, "(signal as f32) * factor + offset")?;
} else {
writeln!(&mut w, "let factor = {};", signal.factor)?;
let scaled_type = scaled_signal_to_rust_int(signal);

if scaled_type == signal_to_rust_uint(signal).replace('u', "i") {
// Can't do iNN::from(uNN) if they both fit in the same integer type,
// so cast first
writeln!(&mut w, "let signal = signal as {};", scaled_type)?;
}

if signal.offset >= 0.0 {
writeln!(
&mut w,
"{}::from(signal).saturating_mul(factor).saturating_add({})",
scaled_signal_to_rust_int(signal),
signal.offset,
scaled_type, signal.offset,
)?;
} else {
writeln!(
&mut w,
"{}::from(signal).saturating_mul(factor).saturating_sub({})",
scaled_signal_to_rust_int(signal),
scaled_type,
signal.offset.abs(),
)?;
}
Expand Down
164 changes: 164 additions & 0 deletions testing/can-messages/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub enum Messages {
MultiplexTest(MultiplexTest),
/// IntegerFactorOffset
IntegerFactorOffset(IntegerFactorOffset),
/// LargerIntsWithOffsets
LargerIntsWithOffsets(LargerIntsWithOffsets),
/// MsgWithoutSignals
MsgWithoutSignals(MsgWithoutSignals),
}
Expand All @@ -52,6 +54,7 @@ impl Messages {
1028 => Messages::Dolor(Dolor::try_from(payload)?),
200 => Messages::MultiplexTest(MultiplexTest::try_from(payload)?),
1337 => Messages::IntegerFactorOffset(IntegerFactorOffset::try_from(payload)?),
1338 => Messages::LargerIntsWithOffsets(LargerIntsWithOffsets::try_from(payload)?),
513 => Messages::MsgWithoutSignals(MsgWithoutSignals::try_from(payload)?),
n => return Err(CanError::UnknownMessageId(n)),
};
Expand Down Expand Up @@ -1826,6 +1829,167 @@ impl<'a> Arbitrary<'a> for IntegerFactorOffset {
}
}

/// LargerIntsWithOffsets
///
/// - ID: 1338 (0x53a)
/// - Size: 8 bytes
/// - Transmitter: Sit
#[derive(Clone, Copy)]
pub struct LargerIntsWithOffsets {
raw: [u8; 8],
}

impl LargerIntsWithOffsets {
pub const MESSAGE_ID: u32 = 1338;

pub const TWELVE_MIN: i16 = -1000_i16;
pub const TWELVE_MAX: i16 = 3000_i16;
pub const SIXTEEN_MIN: i32 = -1000_i32;
pub const SIXTEEN_MAX: i32 = 64535_i32;

/// Construct new LargerIntsWithOffsets from values
pub fn new(twelve: i16, sixteen: i32) -> Result<Self, CanError> {
let mut res = Self { raw: [0u8; 8] };
res.set_twelve(twelve)?;
res.set_sixteen(sixteen)?;
Ok(res)
}

/// Access message payload raw value
pub fn raw(&self) -> &[u8; 8] {
&self.raw
}

/// Twelve
///
/// - Min: -1000
/// - Max: 3000
/// - Unit: ""
/// - Receivers: XXX
#[inline(always)]
pub fn twelve(&self) -> i16 {
self.twelve_raw()
}

/// Get raw value of Twelve
///
/// - Start bit: 0
/// - Signal size: 12 bits
/// - Factor: 1
/// - Offset: -1000
/// - Byte order: LittleEndian
/// - Value type: Unsigned
#[inline(always)]
pub fn twelve_raw(&self) -> i16 {
let signal = self.raw.view_bits::<Lsb0>()[0..12].load_le::<u16>();

let factor = 1;
let signal = signal as i16;
i16::from(signal)
.saturating_mul(factor)
.saturating_sub(1000)
}

/// Set value of Twelve
#[inline(always)]
pub fn set_twelve(&mut self, value: i16) -> Result<(), CanError> {
if value < -1000_i16 || 3000_i16 < value {
return Err(CanError::ParameterOutOfRange { message_id: 1338 });
}
let factor = 1;
let value = value
.checked_add(1000)
.ok_or(CanError::ParameterOutOfRange { message_id: 1338 })?;
let value = (value / factor) as u16;

self.raw.view_bits_mut::<Lsb0>()[0..12].store_le(value);
Ok(())
}

/// Sixteen
///
/// - Min: -1000
/// - Max: 64535
/// - Unit: ""
/// - Receivers: XXX
#[inline(always)]
pub fn sixteen(&self) -> i32 {
self.sixteen_raw()
}

/// Get raw value of Sixteen
///
/// - Start bit: 12
/// - Signal size: 16 bits
/// - Factor: 1
/// - Offset: -1000
/// - Byte order: LittleEndian
/// - Value type: Unsigned
#[inline(always)]
pub fn sixteen_raw(&self) -> i32 {
let signal = self.raw.view_bits::<Lsb0>()[12..28].load_le::<u16>();

let factor = 1;
i32::from(signal)
.saturating_mul(factor)
.saturating_sub(1000)
}

/// Set value of Sixteen
#[inline(always)]
pub fn set_sixteen(&mut self, value: i32) -> Result<(), CanError> {
if value < -1000_i32 || 64535_i32 < value {
return Err(CanError::ParameterOutOfRange { message_id: 1338 });
}
let factor = 1;
let value = value
.checked_add(1000)
.ok_or(CanError::ParameterOutOfRange { message_id: 1338 })?;
let value = (value / factor) as u16;

self.raw.view_bits_mut::<Lsb0>()[12..28].store_le(value);
Ok(())
}
}

impl core::convert::TryFrom<&[u8]> for LargerIntsWithOffsets {
type Error = CanError;

#[inline(always)]
fn try_from(payload: &[u8]) -> Result<Self, Self::Error> {
if payload.len() != 8 {
return Err(CanError::InvalidPayloadSize);
}
let mut raw = [0u8; 8];
raw.copy_from_slice(&payload[..8]);
Ok(Self { raw })
}
}

impl core::fmt::Debug for LargerIntsWithOffsets {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if f.alternate() {
f.debug_struct("LargerIntsWithOffsets")
.field("twelve", &self.twelve())
.field("sixteen", &self.sixteen())
.finish()
} else {
f.debug_tuple("LargerIntsWithOffsets")
.field(&self.raw)
.finish()
}
}
}

#[cfg(feature = "arb")]
impl<'a> Arbitrary<'a> for LargerIntsWithOffsets {
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> {
let twelve = u.int_in_range(-1000..=3000)?;
let sixteen = u.int_in_range(-1000..=64535)?;
LargerIntsWithOffsets::new(twelve, sixteen).map_err(|_| arbitrary::Error::IncorrectFormat)
}
}

/// MsgWithoutSignals
///
/// - ID: 513 (0x201)
Expand Down
38 changes: 36 additions & 2 deletions testing/can-messages/tests/all.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#![allow(clippy::float_cmp)]

use can_messages::{
Amet, Bar, BarThree, CanError, Foo, MultiplexTest, MultiplexTestMultiplexorIndex,
MultiplexTestMultiplexorM0,
Amet, Bar, BarThree, CanError, Foo, LargerIntsWithOffsets, MultiplexTest,
MultiplexTestMultiplexorIndex, MultiplexTestMultiplexorM0,
};

#[test]
Expand Down Expand Up @@ -77,6 +77,40 @@ fn pack_unpack_message_containing_multiplexed_signals() {
}
}

#[test]
fn offset_integers() {
let mut m = LargerIntsWithOffsets::new(100, 30000).unwrap();

// Check min/max limits
assert_eq!(LargerIntsWithOffsets::TWELVE_MIN, -1000);
assert_eq!(LargerIntsWithOffsets::TWELVE_MAX, 3000);
assert_eq!(LargerIntsWithOffsets::SIXTEEN_MIN, -1000);
assert_eq!(LargerIntsWithOffsets::SIXTEEN_MAX, 64535);

// Setting at the min/max limits
m.set_twelve(-1000).unwrap();
m.set_sixteen(64535).unwrap();
assert_eq!(m.raw(), b"\x00\xf0\xff\x0f\x00\x00\x00\x00");
assert_eq!(m.twelve(), -1000);
assert_eq!(m.sixteen(), 64535);

m.set_twelve(3000).unwrap();
m.set_sixteen(-1000).unwrap();
assert_eq!(m.raw(), b"\xa0\x0f\x00\x00\x00\x00\x00\x00");
assert_eq!(m.twelve(), 3000);
assert_eq!(m.sixteen(), -1000);

// Setting out of range values
assert!(matches!(
m.set_twelve(-2000),
Err(CanError::ParameterOutOfRange { message_id: 1338 })
));
assert!(matches!(
m.set_sixteen(65536),
Err(CanError::ParameterOutOfRange { message_id: 1338 })
));
}

#[test]
#[cfg(feature = "debug")]
fn debug_impl() {
Expand Down
4 changes: 4 additions & 0 deletions testing/dbc-examples/example.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ BO_ 1337 IntegerFactorOffset: 8 Sit
SG_ ByteWithNegativeOffset : 24|8@1+ (1,-1) [0|255] "" Vector__XXX
SG_ ByteWithNegativeMin : 32|8@1+ (1,-1) [-127|127] "" Vector__XXX

BO_ 1338 LargerIntsWithOffsets: 8 Sit
SG_ Twelve : 0|12@1+ (1,-1000) [-1000|3000] "" XXX
SG_ Sixteen : 12|16@1+ (1,-1000) [-1000|64535] "" XXX

BO_ 513 MsgWithoutSignals: 8 Ipsum

VAL_ 512 Three 0 "OFF" 1 "ON" 2 "ONER" 3 "ONEST";
Expand Down

0 comments on commit 9bf8813

Please sign in to comment.