///|
fn valid_transform_name(value : String) -> Bool {
if value.length() == 0 || !is_identifier_start(value[0].to_int()) {
return false
}
for index in 1.. Bool {
for node in database.nodes() {
if node.name() == name {
return true
}
}
false
}
///|
fn renamed_receivers(
values : Array[String],
before : String,
after : String,
) -> Array[String] {
let result : Array[String] = []
for value in values {
result.push(if value == before { after } else { value })
}
result
}
///|
pub fn rename_node(
database : DbcDatabase,
before : String,
after : String,
) -> Result[DbcDatabase, DbcError] {
if !valid_transform_name(after) {
return Err(
DbcError::new(
InvalidIdentifier,
"replacement node name is invalid",
1,
1,
context=after,
),
)
}
if !has_node(database, before) {
return Err(
DbcError::new(
InvalidIdentifier,
"node to rename does not exist",
1,
1,
context=before,
),
)
}
if before != after && has_node(database, after) {
return Err(
DbcError::new(
InvalidIdentifier,
"replacement node already exists",
1,
1,
context=after,
),
)
}
let nodes : Array[DbcNode] = []
for node in database.nodes() {
nodes.push(
DbcNode::new(if node.name() == before { after } else { node.name() }),
)
}
let messages : Array[DbcMessage] = []
for original in database.messages() {
let transmitter = if original.transmitter() == before {
after
} else {
original.transmitter()
}
let signals : Array[DbcSignal] = []
for signal in original.signals() {
signals.push(
signal.with_receivers(
renamed_receivers(signal.receivers(), before, after),
),
)
}
messages.push(original.with_transmitter(transmitter).with_signals(signals))
}
Ok(
DbcDatabase::new(
database.version(),
nodes,
messages,
ignored_statement_count=database.ignored_statement_count(),
),
)
}
///|
pub fn rename_message(
database : DbcDatabase,
id : Int,
after : String,
) -> Result[DbcDatabase, DbcError] {
if !valid_transform_name(after) {
return Err(
DbcError::new(
InvalidIdentifier,
"replacement message name is invalid",
1,
1,
context=after,
),
)
}
if database.find_message_by_id(id) is None {
return Err(
DbcError::new(
UnknownMessage,
"message to rename does not exist",
1,
1,
context=id.to_string(),
),
)
}
match database.find_message_by_name(after) {
Some(existing) if existing.id() != id =>
return Err(
DbcError::new(
DuplicateMessageName,
"replacement message name already exists",
1,
1,
context=after,
),
)
_ => ()
}
let messages : Array[DbcMessage] = []
for message in database.messages() {
messages.push(
if message.id() == id {
message.with_name(after)
} else {
message
},
)
}
Ok(
DbcDatabase::new(
database.version(),
database.nodes(),
messages,
ignored_statement_count=database.ignored_statement_count(),
),
)
}
///|
pub fn rename_signal(
database : DbcDatabase,
message_id : Int,
before : String,
after : String,
) -> Result[DbcDatabase, DbcError] {
if !valid_transform_name(after) {
return Err(
DbcError::new(
InvalidIdentifier,
"replacement signal name is invalid",
1,
1,
context=after,
),
)
}
let target = match database.find_message_by_id(message_id) {
Some(value) => value
None =>
return Err(
DbcError::new(UnknownMessage, "signal message does not exist", 1, 1),
)
}
if target.find_signal(before) is None {
return Err(
DbcError::new(
UnknownSignal,
"signal to rename does not exist",
target.source_line(),
1,
context=before,
),
)
}
if after != before && target.find_signal(after) is Some(_) {
return Err(
DbcError::new(
DuplicateSignalName,
"replacement signal name already exists",
target.source_line(),
1,
context=after,
),
)
}
let messages : Array[DbcMessage] = []
for message in database.messages() {
if message.id() != message_id {
messages.push(message)
} else {
let signals : Array[DbcSignal] = []
for signal in message.signals() {
signals.push(
if signal.name() == before {
signal.with_name(after)
} else {
signal
},
)
}
messages.push(message.with_signals(signals))
}
}
Ok(
DbcDatabase::new(
database.version(),
database.nodes(),
messages,
ignored_statement_count=database.ignored_statement_count(),
),
)
}
///|
fn node_used(messages : Array[DbcMessage], name : String) -> Bool {
for message in messages {
if message.transmitter() == name {
return true
}
for signal in message.signals() {
if signal_has_receiver(signal, name) {
return true
}
}
}
false
}
///|
pub fn select_database_messages(
database : DbcDatabase,
ids : Array[Int],
) -> Result[DbcDatabase, DbcError] {
let messages : Array[DbcMessage] = []
for index, id in ids {
for previous in 0.. messages.push(message)
None =>
return Err(
DbcError::new(
UnknownMessage,
"selected message does not exist",
1,
1,
context=id.to_string(),
),
)
}
}
let nodes : Array[DbcNode] = []
for node in database.nodes() {
if node_used(messages, node.name()) {
nodes.push(node)
}
}
Ok(DbcDatabase::new(database.version(), nodes, messages))
}
///|
fn combined_nodes(
left : Array[DbcNode],
right : Array[DbcNode],
) -> Array[DbcNode] {
let result = left.copy()
for node in right {
let mut exists = false
for current in result {
if current.name() == node.name() {
exists = true
break
}
}
if !exists {
result.push(node)
}
}
result
}
///|
pub fn merge_databases(
left : DbcDatabase,
right : DbcDatabase,
) -> Result[DbcDatabase, DbcError] {
let messages = left.messages()
for message in right.messages() {
if left.find_message_by_id(message.id()) is Some(_) {
return Err(
DbcError::new(
DuplicateMessageId,
"merged database repeats a message id",
message.source_line(),
1,
context=message.id().to_string(),
),
)
}
if left.find_message_by_name(message.name()) is Some(_) {
return Err(
DbcError::new(
DuplicateMessageName,
"merged database repeats a message name",
message.source_line(),
1,
context=message.name(),
),
)
}
messages.push(message)
}
let version = if left.version() == right.version() {
left.version()
} else {
""
}
Ok(
DbcDatabase::new(
version,
combined_nodes(left.nodes(), right.nodes()),
messages,
ignored_statement_count=left.ignored_statement_count() +
right.ignored_statement_count(),
),
)
}