1use super::utils::decode_frame_payload;
6use crate::utils::buf_as_hex_to_io_write;
7use afibex::fibex::{FibexData, FibexError};
8use lazy_static::lazy_static;
9use std::io::Write;
10
11lazy_static! {
12 static ref NO_CHANNEL_NAME: String = "<no CHANNEL NAME>".to_string();
13}
14fn find_frame_ref(
16 fd: &FibexData,
17 channel_id: &Option<&String>,
18 frame_id: u32,
19) -> Option<(String, String)> {
20 if let Some(channel_id) = channel_id {
21 if let Some(channel) = fd.elements.channels.get(*channel_id) {
22 return channel
23 .frame_ref_by_frame_triggering_identifier
24 .get(&frame_id)
25 .map(|frame_id| {
26 (
27 channel.short_name.as_ref().unwrap_or(channel_id).to_owned(),
28 frame_id.to_owned(),
29 )
30 });
31 }
32 } else {
33 for (channel_name, channel) in &fd.elements.channels {
35 if let Some(frame_ref) = channel
36 .frame_ref_by_frame_triggering_identifier
37 .get(&frame_id)
38 {
39 return Some((
40 channel
41 .short_name
42 .as_ref()
43 .unwrap_or(channel_name)
44 .to_owned(),
45 frame_ref.to_owned(),
46 ));
47 }
48 }
49 }
50 None
51}
52
53pub fn decode_can_frame(
63 fd: &FibexData,
64 is_rx: bool,
65 channel_id: &Option<&String>,
66 frame_id: u32,
67 payload: &[u8],
68 decode_payload: bool,
69 decode_compu_methods: bool,
70) -> Result<String, FibexError> {
71 if frame_id == 0 {
72 Err(FibexError::new("can: frame_id 0 is invalid"))
73 } else {
74 let mut writer = Vec::with_capacity(2 * 1024); if let Some((channel_name, frame_ref)) = find_frame_ref(fd, channel_id, frame_id) {
78 write!(
80 writer,
81 "{} {} 0x{:03x}",
82 if is_rx { '>' } else { '<' },
83 channel_name,
84 frame_id,
85 )
86 .map_err(|e| FibexError { msg: e.to_string() })?;
87 if let Some(frame) = fd.elements.frames_map_by_id.get(&frame_ref) {
88 if let Some(short_name) = &frame.short_name {
89 write!(writer, " {} ", short_name)
90 .map_err(|e| FibexError { msg: e.to_string() })?;
91 } else {
92 write!(writer, " <no short-name id={}> ", frame.id)
93 .map_err(|e| FibexError { msg: e.to_string() })?;
94 }
95 write!(writer, "[").map_err(|e| FibexError { msg: e.to_string() })?;
97 buf_as_hex_to_io_write(&mut writer, payload)
98 .map_err(|e| FibexError { msg: e.to_string() })?;
99 write!(writer, "]").map_err(|e| FibexError { msg: e.to_string() })?;
100
101 if decode_payload {
102 write!(writer, ":").map_err(|e| FibexError { msg: e.to_string() })?;
103 decode_frame_payload(frame, &mut writer, fd, payload, decode_compu_methods)
104 .map_err(|e| FibexError { msg: e.to_string() })?;
105 }
106 } else {
107 write!(
108 writer,
109 " <frame_ref {} not found!> {:?}",
110 frame_ref, payload
111 )
112 .map_err(|e| FibexError { msg: e.to_string() })?;
113 }
114 } else {
115 write!(
117 writer,
118 "{} {} 0x{:03x} <unknown frame> ",
119 if is_rx { '>' } else { '<' },
120 if let Some(channel_id) = channel_id {
121 let name = fd
122 .elements
123 .channels
124 .get(*channel_id)
125 .and_then(|c| c.short_name.as_ref())
126 .unwrap_or(channel_id);
127 name
128 } else {
129 &NO_CHANNEL_NAME
130 },
131 frame_id,
132 )
133 .map_err(|e| FibexError { msg: e.to_string() })?;
134 write!(writer, "[").map_err(|e| FibexError { msg: e.to_string() })?;
135 buf_as_hex_to_io_write(&mut writer, payload)
136 .map_err(|e| FibexError { msg: e.to_string() })?;
137 write!(writer, "]").map_err(|e| FibexError { msg: e.to_string() })?;
138 }
139 let res = unsafe { String::from_utf8_unchecked(writer) }; Ok(res)
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn frame_id_0() {
150 let fd = FibexData::new();
151
152 let r = decode_can_frame(&fd, true, &None, 0, &[], false, false);
153 assert!(r.is_err());
154 }
155
156 }