saleae_csv/
common.rs

1use core::str::FromStr;
2
3/// Time since capture start
4#[derive(Debug, Clone, Copy)]
5pub struct StartTime(pub f64);
6
7impl TryFrom<&str> for StartTime {
8    type Error = <f64 as FromStr>::Err;
9
10    fn try_from(value: &str) -> Result<Self, Self::Error> {
11        Ok(Self(value.parse()?))
12    }
13}
14
15/// CSV Row type
16#[derive(Debug, Clone, Copy)]
17pub enum RowType {
18    /// Address
19    Address,
20    /// Start
21    Start,
22    /// Stop
23    Stop,
24    /// Data
25    Data,
26}
27
28impl TryFrom<&str> for RowType {
29    type Error = Error;
30
31    fn try_from(value: &str) -> Result<Self, Self::Error> {
32        match value.trim().replace("\"", "").to_ascii_lowercase().as_str() {
33            "address" => Ok(Self::Address),
34            "start" => Ok(Self::Start),
35            "stop" => Ok(Self::Stop),
36            "data" => Ok(Self::Data),
37            _ => Err(Error::InvalidRow),
38        }
39    }
40}
41
42/// Saleae Logic 2 Channel Name
43#[derive(Debug, Clone)]
44pub struct ChannelName(String);
45
46impl<T: AsRef<str>> From<T> for ChannelName {
47    fn from(value: T) -> Self {
48        Self(value.as_ref().trim().replace("\"", ""))
49    }
50}
51
52/// Error type
53#[derive(Debug, Clone, Copy)]
54pub enum Error {
55    /// Failed to parse
56    Parse,
57    /// Invalid CSV row
58    InvalidRow,
59}
60
61/// Parse hex number formatted as '0xFF'
62pub(crate) fn parse_hex(input: &str) -> Option<u8> {
63    let chars = input
64        .chars()
65        .map(|c| c.to_ascii_lowercase())
66        .collect::<Vec<char>>();
67    match *chars.as_slice() {
68        ['0', 'x', u, l] => Some(((hex_nibble_to_byte(u)?) << 4) | (hex_nibble_to_byte(l)?)),
69        _ => None,
70    }
71}
72
73/// Convert hex nibble to byte
74pub(crate) fn hex_nibble_to_byte(c: char) -> Option<u8> {
75    match c {
76        '0'..='9' => Some((c as u8) - 48),
77        'a'..='f' => Some((c as u8) - 55 - 32),
78        _ => None,
79    }
80}