1use crate::protocol::{MessageObservation, Response, ResponseData};
2
3pub fn print_response(response: &Response, json: bool) {
4 if json {
5 println!(
6 "{}",
7 serde_json::to_string_pretty(response).expect("response should serialize")
8 );
9 return;
10 }
11
12 if !response.success {
13 eprintln!(
14 "{}",
15 response
16 .error
17 .as_deref()
18 .unwrap_or("request failed without error payload")
19 );
20 return;
21 }
22
23 match response.data.as_ref() {
24 Some(ResponseData::AdaptersList { adapters }) => {
25 if adapters.is_empty() {
26 println!("no supported adapters available on this platform");
27 } else {
28 for adapter in adapters {
29 println!("{adapter}");
30 }
31 }
32 }
33 Some(ResponseData::Connected(connect)) => {
34 println!(
35 "connected created={} already_connected={} adapter={} bitrate={} bitrate_data={} fd={} dbcs={}",
36 connect.created,
37 connect.already_connected,
38 connect.status.adapter,
39 connect.status.bitrate,
40 connect.status.bitrate_data.unwrap_or(0),
41 connect.status.fd,
42 connect.status.dbcs.len()
43 );
44 }
45 Some(ResponseData::Disconnected) => println!("disconnected"),
46 Some(ResponseData::Status(status)) => {
47 println!(
48 "state={} adapter={} bitrate={} bitrate_data={} fd={} dbcs={} trace={} schedules={} backend_error={}",
49 status.connection_state,
50 status.adapter,
51 status.bitrate,
52 status.bitrate_data.unwrap_or(0),
53 status.fd,
54 status.dbcs.len(),
55 status.trace_path.as_deref().unwrap_or("-"),
56 status.periodic_schedules.len(),
57 status.backend_error.as_deref().unwrap_or("-"),
58 );
59 }
60 Some(ResponseData::Schema { messages }) => {
61 for message in messages {
62 println!(
63 "{} arb_id=0x{:X} len={} signals={}",
64 message.qualified_name,
65 message.arb_id,
66 message.len,
67 message.signals.len()
68 );
69 }
70 }
71 Some(ResponseData::MessageList { messages }) => {
72 for message in messages {
73 println!(
74 "{} kind={:?} arb_id=0x{:X} rx={} tx={} last_seen_unix_ms={}",
75 message.label,
76 message.kind,
77 message.arb_id,
78 message.has_rx,
79 message.has_tx,
80 message.last_seen_unix_ms
81 );
82 }
83 }
84 Some(ResponseData::MessageRead(read)) => print_observations(&read.observations),
85 Some(ResponseData::MessageSent(sent)) => {
86 println!(
87 "sent target={} arb_id=0x{:X} len={} periodicity_ms={}",
88 sent.target,
89 sent.arb_id,
90 sent.len,
91 sent.periodicity_ms
92 .map(|value| value.to_string())
93 .unwrap_or_else(|| "-".to_string())
94 );
95 }
96 Some(ResponseData::MessageStopped { target, stopped }) => {
97 println!("stopped target={target} stopped={stopped}");
98 }
99 Some(ResponseData::TraceStarted { path }) => println!("trace started path={path}"),
100 Some(ResponseData::TraceStopped { path }) => {
101 println!("trace stopped path={}", path.as_deref().unwrap_or("-"));
102 }
103 None => println!("ok"),
104 }
105}
106
107fn print_observations(observations: &[MessageObservation]) {
108 for observation in observations {
109 match observation {
110 MessageObservation::Raw {
111 seq,
112 direction,
113 arb_id,
114 payload_hex,
115 ..
116 } => {
117 println!(
118 "seq={seq} direction={direction:?} arb_id=0x{arb_id:X} data={payload_hex}"
119 );
120 }
121 MessageObservation::Semantic {
122 seq,
123 direction,
124 qualified_name,
125 payload_hex,
126 signals,
127 ..
128 } => {
129 let signal_summary = signals
130 .iter()
131 .map(|signal| match &signal.unit {
132 Some(unit) => format!("{}={} {}", signal.name, signal.value, unit),
133 None => format!("{}={}", signal.name, signal.value),
134 })
135 .collect::<Vec<_>>()
136 .join(", ");
137 println!(
138 "seq={seq} direction={direction:?} message={qualified_name} data={payload_hex} signals={signal_summary}"
139 );
140 }
141 }
142 }
143}