Add mixed text/plot transport and improve plot UI

This commit is contained in:
2026-06-09 00:51:34 +08:00
parent 25433038d5
commit d5b6bb52c8
18 changed files with 2101 additions and 192 deletions

View File

@@ -5,10 +5,12 @@ use xserial_core::frame::{
fixed::FixedLengthFramer,
length::{LengthConfig, LengthPrefixedFramer},
line::{LineConfig, LineFramer},
mixed::{MixedTextPlotConfig as MixedFramerConfig, MixedTextPlotFramer},
};
use xserial_core::protocol::{
ProtocolDecoder,
hex::{HexConfig, HexDecoder},
mixed::{MixedTextPlotConfig as MixedDecoderConfig, MixedTextPlotDecoder},
plot::{PlotConfig, PlotDecoder, PlotFormat, SampleType},
text::{TextDecoder, TextEncoding},
};
@@ -39,6 +41,14 @@ pub enum FramerConfig {
#[serde(default = "default_max_frame")]
max_frame: usize,
},
MixedTextPlot {
#[serde(default = "default_true")]
strip_cr: bool,
#[serde(default = "default_max_line")]
max_line_len: usize,
#[serde(default = "default_max_frame")]
max_plot_frame: usize,
},
}
fn default_true() -> bool {
@@ -80,6 +90,15 @@ impl FramerConfig {
max_payload,
})),
FramerConfig::Cobs { max_frame } => Box::new(CobsFramer::new(max_frame)),
FramerConfig::MixedTextPlot {
strip_cr,
max_line_len,
max_plot_frame,
} => Box::new(MixedTextPlotFramer::new(MixedFramerConfig {
strip_cr,
max_line_len,
max_plot_frame,
})),
}
}
}
@@ -109,6 +128,10 @@ pub enum DecoderConfig {
#[serde(default)]
format: PlotFormat,
},
MixedTextPlot {
#[serde(default)]
encoding: TextEncoding,
},
}
fn default_sep() -> String {
@@ -144,6 +167,9 @@ impl DecoderConfig {
channels,
format,
})),
DecoderConfig::MixedTextPlot { encoding } => {
Box::new(MixedTextPlotDecoder::new(MixedDecoderConfig { encoding }))
}
}
}
}
@@ -240,6 +266,25 @@ mod tests {
assert!(matches!(cfg, FramerConfig::Cobs { max_frame: 8192 }));
}
#[test]
fn framer_mixed_serde() {
let json =
r#"{"MixedTextPlot":{"strip_cr":true,"max_line_len":4096,"max_plot_frame":8192}}"#;
let cfg: FramerConfig = serde_json::from_str(json).unwrap();
match cfg {
FramerConfig::MixedTextPlot {
strip_cr,
max_line_len,
max_plot_frame,
} => {
assert!(strip_cr);
assert_eq!(max_line_len, 4096);
assert_eq!(max_plot_frame, 8192);
}
_ => panic!("expected MixedTextPlot"),
}
}
#[test]
fn decoder_text_serde() {
let cfg: DecoderConfig = serde_json::from_str(r#"{"Text":{"encoding":"Latin1"}}"#).unwrap();
@@ -290,6 +335,16 @@ mod tests {
}
}
#[test]
fn decoder_mixed_serde() {
let cfg: DecoderConfig =
serde_json::from_str(r#"{"MixedTextPlot":{"encoding":"Utf8"}}"#).unwrap();
match cfg {
DecoderConfig::MixedTextPlot { encoding } => assert_eq!(encoding, TextEncoding::Utf8),
_ => panic!("expected MixedTextPlot"),
}
}
#[test]
fn session_config_full_roundtrip() {
let json = r#"{
@@ -327,6 +382,11 @@ mod tests {
max_payload: 65536,
},
FramerConfig::Cobs { max_frame: 1024 },
FramerConfig::MixedTextPlot {
strip_cr: true,
max_line_len: 256,
max_plot_frame: 1024,
},
] {
let f = cfg.build();
assert_eq!(f.pending_len(), 0);
@@ -365,5 +425,13 @@ mod tests {
.name(),
"Plot"
);
assert_eq!(
DecoderConfig::MixedTextPlot {
encoding: TextEncoding::Utf8
}
.build()
.name(),
"MixedTextPlot"
);
}
}