///|
/// Database inventory, with message byte length separated from transport semantics.
pub(all) struct DatabaseStats {
nodes : Int
messages : Int
signals : Int
standard_messages : Int
extended_messages : Int
classic_sized_messages : Int
fd_sized_messages : Int
multiplexed_messages : Int
value_descriptions : Int
errors : Int
warnings : Int
} derive(Eq, @debug.Debug)
///|
/// Count semantic objects and actual validation findings.
pub fn inspect_database(db : Database) -> DatabaseStats {
let mut signals = 0
let mut extended = 0
let mut fd = 0
let mut mux = 0
let mut values = 0
for m in db.messages {
if m.frame_id.extended {
extended += 1
}
if m.length > 8 {
fd += 1
}
if m.signals.iter().any(fn(s) { s.multiplex == Multiplexer }) {
mux += 1
}
signals += m.signals.length()
for s in m.signals {
values += s.values.length()
}
}
let diagnostics = validate_database(db)
let errors = diagnostics.filter(fn(d) { d.severity == Error }).length()
{
nodes: db.nodes.length(),
messages: db.messages.length(),
signals,
standard_messages: db.messages.length() - extended,
extended_messages: extended,
classic_sized_messages: db.messages.length() - fd,
fd_sized_messages: fd,
multiplexed_messages: mux,
value_descriptions: values,
errors,
warnings: diagnostics.length() - errors,
}
}
///|
/// Occupancy of one payload bit; multiple exclusive branch owners are retained.
pub(all) struct BitCell {
position : Int
owners : Array[String]
} derive(Eq, @debug.Debug)
///|
/// Compute a real bit layout for 0..64 bytes without hardcoded demo coordinates.
pub fn message_layout(message : Message) -> Array[BitCell] raise DbcError {
if message.length < 0 || message.length > 64 {
fail("message.length", "payload must be 0..64 bytes")
}
let cells = Array::makei(message.length * 8, fn(position) {
BitCell::{ position, owners: [] }
})
for s in message.signals {
let tag = match s.multiplex {
Always => s.name
Multiplexer => s.name + "(M)"
Branch(n) => s.name + "(m\{n})"
}
for bit in signal_bits(s, message.length) {
cells[bit].owners.push(tag)
}
}
cells
}
///|
/// Display each byte from bit 7 through bit 0; '.' denotes unoccupied bits.
pub fn render_layout(message : Message) -> String raise DbcError {
let cells = message_layout(message)
let lines = [
"Message: \{message.name} ID: \{message.raw_dbc_id} Length: \{message.length}",
"Bits per byte: 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0",
]
for byte = 0; byte < message.length; byte = byte + 1 {
let columns = []
for bit = 7; bit >= 0; bit = bit - 1 {
let owners = cells[byte * 8 + bit].owners
columns.push(if owners.length() == 0 { "." } else { owners.join("/") })
}
lines.push("Byte \{byte}: " + columns.join(" | "))
}
lines.join("\n")
}