///|
pub struct FrameBatchItem {
index_value : Int
frame_value : CanFrame
decoded_value : DecodedFrame?
error_value : DbcError?
} derive(Eq, Debug)
///|
pub struct MessageFrameCount {
message_id_value : Int
message_name_value : String
count_value : Int
} derive(Eq, Debug)
///|
pub struct FrameBatchResult {
items_value : Array[FrameBatchItem]
accepted_value : Int
rejected_value : Int
total_data_bytes_value : Int
message_counts_value : Array[MessageFrameCount]
} derive(Eq, Debug)
///|
pub fn FrameBatchItem::index(self : FrameBatchItem) -> Int {
self.index_value
}
///|
pub fn FrameBatchItem::frame(self : FrameBatchItem) -> CanFrame {
self.frame_value
}
///|
pub fn FrameBatchItem::accepted(self : FrameBatchItem) -> Bool {
self.decoded_value is Some(_)
}
///|
pub fn FrameBatchItem::decoded(self : FrameBatchItem) -> DecodedFrame? {
self.decoded_value
}
///|
pub fn FrameBatchItem::error(self : FrameBatchItem) -> DbcError? {
self.error_value
}
///|
pub fn MessageFrameCount::message_id(self : MessageFrameCount) -> Int {
self.message_id_value
}
///|
pub fn MessageFrameCount::message_name(self : MessageFrameCount) -> String {
self.message_name_value
}
///|
pub fn MessageFrameCount::count(self : MessageFrameCount) -> Int {
self.count_value
}
///|
pub fn FrameBatchResult::items(
self : FrameBatchResult,
) -> Array[FrameBatchItem] {
self.items_value.copy()
}
///|
pub fn FrameBatchResult::accepted(self : FrameBatchResult) -> Int {
self.accepted_value
}
///|
pub fn FrameBatchResult::rejected(self : FrameBatchResult) -> Int {
self.rejected_value
}
///|
pub fn FrameBatchResult::total_data_bytes(self : FrameBatchResult) -> Int {
self.total_data_bytes_value
}
///|
pub fn FrameBatchResult::acceptance_ratio(self : FrameBatchResult) -> Double {
let total = self.accepted_value + self.rejected_value
if total == 0 {
1.0
} else {
self.accepted_value.to_double() / total.to_double()
}
}
///|
pub fn FrameBatchResult::message_counts(
self : FrameBatchResult,
) -> Array[MessageFrameCount] {
self.message_counts_value.copy()
}
///|
pub fn FrameBatchResult::find_message_count(
self : FrameBatchResult,
message_id : Int,
) -> MessageFrameCount? {
for count in self.message_counts_value {
if count.message_id() == message_id {
return Some(count)
}
}
None
}
///|
pub fn FrameBatchResult::find_item(
self : FrameBatchResult,
index : Int,
) -> FrameBatchItem? {
for item in self.items_value {
if item.index() == index {
return Some(item)
}
}
None
}
///|
fn increment_message_count(
counts : Array[MessageFrameCount],
message : DbcMessage,
) -> Unit {
for index, count in counts {
if count.message_id() == message.id() {
counts[index] = {
message_id_value: count.message_id(),
message_name_value: count.message_name(),
count_value: count.count() + 1,
}
return
}
}
counts.push({
message_id_value: message.id(),
message_name_value: message.name(),
count_value: 1,
})
}
///|
pub fn decode_frame_batch(
database : DbcDatabase,
frames : Array[CanFrame],
max_frames? : Int = 100000,
max_total_data_bytes? : Int = 16 * 1024 * 1024,
) -> Result[FrameBatchResult, DbcError] {
if max_frames < 0 || max_total_data_bytes < 0 {
return Err(
DbcError::new(
InputLimitExceeded,
"frame batch limits cannot be negative",
1,
1,
),
)
}
if frames.length() > max_frames {
return Err(
DbcError::new(
InputLimitExceeded,
"frame batch count exceeds configured limit",
1,
1,
),
)
}
let mut total_bytes = 0
for frame in frames {
total_bytes = total_bytes + frame.data().length()
if total_bytes > max_total_data_bytes {
return Err(
DbcError::new(
InputLimitExceeded,
"frame batch bytes exceed configured limit",
1,
1,
),
)
}
}
let items : Array[FrameBatchItem] = []
let counts : Array[MessageFrameCount] = []
let mut accepted = 0
let mut rejected = 0
for index, frame in frames {
match decode_frame(database, frame) {
Ok(decoded) => {
accepted = accepted + 1
increment_message_count(counts, decoded.message())
items.push({
index_value: index,
frame_value: frame,
decoded_value: Some(decoded),
error_value: None,
})
}
Err(error) => {
rejected = rejected + 1
items.push({
index_value: index,
frame_value: frame,
decoded_value: None,
error_value: Some(error),
})
}
}
}
Ok({
items_value: items,
accepted_value: accepted,
rejected_value: rejected,
total_data_bytes_value: total_bytes,
message_counts_value: counts,
})
}
///|
pub fn render_frame_batch_text(result : FrameBatchResult) -> String {
let mut output = "Frame batch: accepted=\{result.accepted()}, rejected=\{result.rejected()}, bytes=\{result.total_data_bytes()}\n"
for count in result.message_counts() {
output = output +
"message \{count.message_id()} \{count.message_name()}: \{count.count()} frame(s)\n"
}
for item in result.items() {
if !item.accepted() {
match item.error() {
Some(error) =>
output = output +
"rejected index=\{item.index()} id=\{item.frame().id()}: \{error.code()}\n"
None => ()
}
}
}
output
}
///|
pub fn render_frame_batch_json(result : FrameBatchResult) -> String {
let mut output = "{\"accepted\":\{result.accepted()},\"rejected\":\{result.rejected()},\"total_data_bytes\":\{result.total_data_bytes()},\"message_counts\":["
for index, count in result.message_counts() {
if index > 0 {
output = output + ","
}
output = output +
"{\"message_id\":\{count.message_id()},\"message_name\":" +
json_string(count.message_name()) +
",\"count\":\{count.count()}}"
}
output = output + "],\"rejections\":["
let mut rejection_index = 0
for item in result.items() {
match item.error() {
Some(error) => {
if rejection_index > 0 {
output = output + ","
}
output = output +
"{\"index\":\{item.index()},\"message_id\":\{item.frame().id()},\"code\":" +
json_string(error.code()) +
",\"message\":" +
json_string(error.message()) +
"}"
rejection_index = rejection_index + 1
}
None => ()
}
}
output + "]}"
}