///|
pub(all) enum ChangeKind {
Added
Removed
Modified
} derive(Eq, Debug)
///|
pub struct SignalChange {
kind_value : ChangeKind
message_id_value : Int
signal_name_value : String
detail_value : String
breaking_value : Bool
} derive(Eq, Debug)
///|
pub struct MessageChange {
kind_value : ChangeKind
message_id_value : Int
message_name_value : String
detail_value : String
breaking_value : Bool
} derive(Eq, Debug)
///|
pub struct DbcComparison {
message_changes_value : Array[MessageChange]
signal_changes_value : Array[SignalChange]
breaking_change_count_value : Int
} derive(Eq, Debug)
///|
pub fn SignalChange::kind(self : SignalChange) -> ChangeKind {
self.kind_value
}
///|
pub fn SignalChange::message_id(self : SignalChange) -> Int {
self.message_id_value
}
///|
pub fn SignalChange::signal_name(self : SignalChange) -> String {
self.signal_name_value
}
///|
pub fn SignalChange::detail(self : SignalChange) -> String {
self.detail_value
}
///|
pub fn SignalChange::is_breaking(self : SignalChange) -> Bool {
self.breaking_value
}
///|
pub fn MessageChange::kind(self : MessageChange) -> ChangeKind {
self.kind_value
}
///|
pub fn MessageChange::message_id(self : MessageChange) -> Int {
self.message_id_value
}
///|
pub fn MessageChange::message_name(self : MessageChange) -> String {
self.message_name_value
}
///|
pub fn MessageChange::detail(self : MessageChange) -> String {
self.detail_value
}
///|
pub fn MessageChange::is_breaking(self : MessageChange) -> Bool {
self.breaking_value
}
///|
pub fn DbcComparison::message_changes(
self : DbcComparison,
) -> Array[MessageChange] {
self.message_changes_value.copy()
}
///|
pub fn DbcComparison::signal_changes(
self : DbcComparison,
) -> Array[SignalChange] {
self.signal_changes_value.copy()
}
///|
pub fn DbcComparison::breaking_change_count(self : DbcComparison) -> Int {
self.breaking_change_count_value
}
///|
pub fn DbcComparison::is_compatible(self : DbcComparison) -> Bool {
self.breaking_change_count_value == 0
}
///|
fn signal_layout_equal(left : DbcSignal, right : DbcSignal) -> Bool {
left.start_bit() == right.start_bit() &&
left.bit_length() == right.bit_length() &&
left.byte_order() == right.byte_order() &&
left.value_type() == right.value_type() &&
left.factor() == right.factor() &&
left.offset() == right.offset()
}
///|
fn signal_metadata_equal(left : DbcSignal, right : DbcSignal) -> Bool {
left.minimum() == right.minimum() &&
left.maximum() == right.maximum() &&
left.unit() == right.unit() &&
left.receivers() == right.receivers() &&
left.values() == right.values() &&
left.comment() == right.comment()
}
///|
fn compare_signals(
before : DbcMessage,
after : DbcMessage,
changes : Array[SignalChange],
) -> Unit {
for signal in before.signals() {
match after.find_signal(signal.name()) {
None =>
changes.push({
kind_value: Removed,
message_id_value: before.id(),
signal_name_value: signal.name(),
detail_value: "signal was removed",
breaking_value: true,
})
Some(next) =>
if !signal_layout_equal(signal, next) {
changes.push({
kind_value: Modified,
message_id_value: before.id(),
signal_name_value: signal.name(),
detail_value: "signal bit layout or scaling changed",
breaking_value: true,
})
} else if !signal_metadata_equal(signal, next) {
changes.push({
kind_value: Modified,
message_id_value: before.id(),
signal_name_value: signal.name(),
detail_value: "signal metadata changed",
breaking_value: false,
})
}
}
}
for signal in after.signals() {
if before.find_signal(signal.name()) is None {
changes.push({
kind_value: Added,
message_id_value: after.id(),
signal_name_value: signal.name(),
detail_value: "signal was added",
breaking_value: false,
})
}
}
}
///|
pub fn compare_dbc(before : DbcDatabase, after : DbcDatabase) -> DbcComparison {
let message_changes : Array[MessageChange] = []
let signal_changes : Array[SignalChange] = []
for message in before.messages() {
match after.find_message_by_id(message.id()) {
None =>
message_changes.push({
kind_value: Removed,
message_id_value: message.id(),
message_name_value: message.name(),
detail_value: "message was removed",
breaking_value: true,
})
Some(next) => {
if message.name() != next.name() ||
message.size() != next.size() ||
message.transmitter() != next.transmitter() {
message_changes.push({
kind_value: Modified,
message_id_value: message.id(),
message_name_value: message.name(),
detail_value: "message name, size, or transmitter changed",
breaking_value: true,
})
} else if message.comment() != next.comment() {
message_changes.push({
kind_value: Modified,
message_id_value: message.id(),
message_name_value: message.name(),
detail_value: "message metadata changed",
breaking_value: false,
})
}
compare_signals(message, next, signal_changes)
}
}
}
for message in after.messages() {
if before.find_message_by_id(message.id()) is None {
message_changes.push({
kind_value: Added,
message_id_value: message.id(),
message_name_value: message.name(),
detail_value: "message was added",
breaking_value: false,
})
}
}
let mut breaking = 0
for change in message_changes {
if change.is_breaking() {
breaking = breaking + 1
}
}
for change in signal_changes {
if change.is_breaking() {
breaking = breaking + 1
}
}
{
message_changes_value: message_changes,
signal_changes_value: signal_changes,
breaking_change_count_value: breaking,
}
}