///|
/// Encode a frame's arbitration and control fields before CRC.
pub fn encode_bits(frame : Frame) -> Array[Bool] {
  let bits : Array[Bool] = []
  append_bits(bits, frame.id(), if frame.is_extended() { 29 } else { 11 })
  bits.push(frame.is_extended())
  match frame.kind() {
    Data => bits.push(false)
    Remote => bits.push(true)
    Error => bits.push(false)
  }
  append_bits(bits, frame.dlc().to_uint(), 4)
  for byte in frame.data() {
    append_bits(bits, byte.to_uint(), 8)
  }
  bits
}

///|
/// Apply CAN bit stuffing to a bit sequence.
pub fn stuff(bits : Array[Bool]) -> Array[Bool] {
  let result : Array[Bool] = []
  if bits.is_empty() {
    return result
  }
  let mut previous = bits[0]
  result.push(previous)
  let mut run = 1
  for i in 1.. Array[Bool] raise WireError {
  let result : Array[Bool] = []
  if bits.is_empty() {
    return result
  }
  let mut previous = bits[0]
  let mut run = 1
  let mut expect_stuffed = false
  result.push(previous)
  let mut i = 1
  while i < bits.length() {
    let bit = bits[i]
    if expect_stuffed {
      if bit == previous {
        raise WireError::InvalidStuffedBit
      }
      expect_stuffed = false
    } else {
      result.push(bit)
      if bit == previous {
        run += 1
      } else {
        previous = bit
        run = 1
      }
      if run > 0 && run % 5 == 0 {
        expect_stuffed = true
      }
    }
    i += 1
  }
  result
}

///|
/// Calculate the arbitration winner: the numerically lowest identifier wins.
pub fn arbitration_winner(frames : Array[Frame]) -> Frame? {
  if frames.is_empty() {
    return None
  }
  let mut winner = frames[0]
  for frame in frames[1:] {
    if frame.id() < winner.id() {
      winner = frame
    }
  }
  Some(winner)
}