///|
/// Ordered payload positions, LSB first for Intel and MSB first for Motorola.
/// Rejects invalid widths/start positions before allocating or shifting.
pub fn signal_bits(
signal : Signal,
payload_length : Int,
) -> Array[Int] raise DbcError {
if payload_length < 0 || payload_length > 64 {
fail("message.length", "payload must be 0..64 bytes")
}
if signal.bit_length < 1 || signal.bit_length > 64 {
fail("signal.length", "integer signals must be 1..64 bits")
}
if signal.start_bit < 0 || signal.start_bit >= payload_length * 8 {
fail("signal.bounds", "start bit exceeds payload")
}
let positions = []
let mut position = signal.start_bit
for i = 0; i < signal.bit_length; i = i + 1 {
if position < 0 || position >= payload_length * 8 {
fail("signal.bounds", "signal exceeds payload")
}
positions.push(position)
position = match signal.byte_order {
Intel => position + 1
Motorola => if position % 8 == 0 { position + 15 } else { position - 1 }
}
}
positions
}
///|
fn active_together(a : MultiplexInfo, b : MultiplexInfo) -> Bool {
match (a, b) {
(Branch(x), Branch(y)) => x == y
_ => true
}
}
///|
/// Return the exact intersecting payload bits, respecting mutually exclusive branches.
pub fn signal_overlap(
a : Signal,
b : Signal,
payload_length : Int,
) -> Array[Int] raise DbcError {
if !active_together(a.multiplex, b.multiplex) {
return []
}
let x = signal_bits(a, payload_length)
let y = signal_bits(b, payload_length)
x.filter(fn(bit) { y.contains(bit) })
}