///|
pub(all) struct MessageMetadata {
name : String
payload_size : Int
transmitter : String
additional_transmitters : Array[String]
} derive(Eq, Debug)
///|
pub(all) enum DatabaseChange {
VersionChangedChange(String?, String?)
NodesChangedChange(Array[String], Array[String])
CommentAddedChange(DbcComment)
CommentRemovedChange(DbcComment)
CommentModifiedChange(DbcCommentTarget, String, String)
MessageAddedChange(Message)
MessageRemovedChange(Message)
MessageMetadataChangedChange(UInt, MessageMetadata, MessageMetadata)
SignalAddedChange(UInt, Signal)
SignalRemovedChange(UInt, Signal)
SignalModifiedChange(UInt, String, Signal, Signal)
ValueTableAddedChange(ValueTable)
ValueTableRemovedChange(ValueTable)
ValueTableModifiedChange(UInt, String, ValueTable, ValueTable)
GlobalValueTableAddedChange(GlobalValueTable)
GlobalValueTableRemovedChange(GlobalValueTable)
GlobalValueTableModifiedChange(String, GlobalValueTable, GlobalValueTable)
EnvironmentVariableAddedChange(EnvironmentVariable)
EnvironmentVariableRemovedChange(EnvironmentVariable)
EnvironmentVariableModifiedChange(
String,
EnvironmentVariable,
EnvironmentVariable
)
SignalGroupAddedChange(SignalGroup)
SignalGroupRemovedChange(SignalGroup)
SignalGroupModifiedChange(UInt, String, SignalGroup, SignalGroup)
AttributesChangedChange(DbcAttributes, DbcAttributes)
} derive(Eq, Debug)
///|
fn message_metadata(message : Message) -> MessageMetadata {
{
name: message.name,
payload_size: message.payload_size,
transmitter: message.transmitter,
additional_transmitters: message.additional_transmitters,
}
}
///|
fn diff_comments(
before : Database,
after : Database,
changes : Array[DatabaseChange],
) -> Unit {
for comment in before.comments {
match after.find_comment(comment.target) {
None => changes.push(CommentRemovedChange(comment))
Some(after_comment) =>
if comment.text != after_comment.text {
changes.push(
CommentModifiedChange(
comment.target,
comment.text,
after_comment.text,
),
)
}
}
}
for comment in after.comments {
if before.find_comment(comment.target) is None {
changes.push(CommentAddedChange(comment))
}
}
}
///|
fn find_signal_in(message : Message, name : StringView) -> Signal? {
for signal in message.signals {
if signal.name.view() == name {
return Some(signal)
}
}
None
}
///|
fn diff_message(
before : Message,
after : Message,
changes : Array[DatabaseChange],
) -> Unit {
let before_metadata = message_metadata(before)
let after_metadata = message_metadata(after)
if before_metadata != after_metadata {
changes.push(
MessageMetadataChangedChange(before.id, before_metadata, after_metadata),
)
}
for signal in before.signals {
match find_signal_in(after, signal.name) {
None => changes.push(SignalRemovedChange(before.id, signal))
Some(after_signal) =>
if signal != after_signal {
changes.push(
SignalModifiedChange(before.id, signal.name, signal, after_signal),
)
}
}
}
for signal in after.signals {
if find_signal_in(before, signal.name) is None {
changes.push(SignalAddedChange(before.id, signal))
}
}
}
///|
fn diff_value_tables(
before : Database,
after : Database,
changes : Array[DatabaseChange],
) -> Unit {
for table in before.value_tables {
match after.find_value_table(table.message_id, table.signal_name) {
None => changes.push(ValueTableRemovedChange(table))
Some(after_table) =>
if table != after_table {
changes.push(
ValueTableModifiedChange(
table.message_id,
table.signal_name,
table,
after_table,
),
)
}
}
}
for table in after.value_tables {
if before.find_value_table(table.message_id, table.signal_name) is None {
changes.push(ValueTableAddedChange(table))
}
}
}
///|
fn diff_signal_groups(
before : Database,
after : Database,
changes : Array[DatabaseChange],
) -> Unit {
for group in before.signal_groups {
match after.find_signal_group(group.message_id, group.name) {
None => changes.push(SignalGroupRemovedChange(group))
Some(after_group) =>
if group != after_group {
changes.push(
SignalGroupModifiedChange(
group.message_id,
group.name,
group,
after_group,
),
)
}
}
}
for group in after.signal_groups {
if before.find_signal_group(group.message_id, group.name) is None {
changes.push(SignalGroupAddedChange(group))
}
}
}
///|
fn diff_global_value_tables(
before : Database,
after : Database,
changes : Array[DatabaseChange],
) -> Unit {
for table in before.global_value_tables {
match after.find_global_value_table(table.name) {
None => changes.push(GlobalValueTableRemovedChange(table))
Some(after_table) =>
if table != after_table {
changes.push(
GlobalValueTableModifiedChange(table.name, table, after_table),
)
}
}
}
for table in after.global_value_tables {
if before.find_global_value_table(table.name) is None {
changes.push(GlobalValueTableAddedChange(table))
}
}
}
///|
fn diff_environment_variables(
before : Database,
after : Database,
changes : Array[DatabaseChange],
) -> Unit {
for variable in before.environment_variables {
match after.find_environment_variable(variable.name) {
None => changes.push(EnvironmentVariableRemovedChange(variable))
Some(after_variable) =>
if variable != after_variable {
changes.push(
EnvironmentVariableModifiedChange(
variable.name,
variable,
after_variable,
),
)
}
}
}
for variable in after.environment_variables {
if before.find_environment_variable(variable.name) is None {
changes.push(EnvironmentVariableAddedChange(variable))
}
}
}
///|
/// Compare this database with a newer database. Changes are returned in a
/// deterministic order: global metadata, removals/modifications, then additions.
pub fn Database::diff(
self : Database,
newer : Database,
) -> Array[DatabaseChange] {
let changes : Array[DatabaseChange] = []
if self.version != newer.version {
changes.push(VersionChangedChange(self.version, newer.version))
}
if self.nodes != newer.nodes {
changes.push(NodesChangedChange(self.nodes, newer.nodes))
}
diff_comments(self, newer, changes)
for message in self.messages {
match newer.find_message(message.id) {
None => changes.push(MessageRemovedChange(message))
Some(newer_message) => diff_message(message, newer_message, changes)
}
}
for message in newer.messages {
if self.find_message(message.id) is None {
changes.push(MessageAddedChange(message))
}
}
diff_value_tables(self, newer, changes)
diff_global_value_tables(self, newer, changes)
diff_environment_variables(self, newer, changes)
diff_signal_groups(self, newer, changes)
if self.attributes != newer.attributes {
changes.push(AttributesChangedChange(self.attributes, newer.attributes))
}
changes
}