1use std::str::FromStr;
4
5use regex::Regex;
6use serde::{Deserialize, Serialize};
7
8const REGEX_PATTERN: &str = r"DX de (?P<spotter>[A-Z\d\\/-]+)-#:\s*(?P<frequency>[\d.]+)\s+(?P<spotted>[A-Z\d\\/-]+)\s+(?P<mode>[A-Z\d]+)\s+(?P<snr>[\d-]+) dB\s+(?P<speed>\d+) [WPMBPS]+\s+(?P<message>[A-Za-z\\d ]+)\s*(?P<time>[0-9]{4})Z";
10
11#[derive(Debug, PartialEq, PartialOrd, Clone, Deserialize, Serialize)]
13pub struct RbnPacket {
14 pub spotter: String,
16 pub frequency: f32,
18 pub spotted: String,
20 pub mode: String,
22 pub snr: f32,
24 pub speed: u8,
26 pub message: String,
28 pub time: String,
30}
31
32impl RbnPacket {
33 pub fn dirty_hash(&self) -> String {
35 format!(
36 "{}-{}-{}-{}",
37 self.spotted, self.frequency, self.mode, self.time
38 )
39 }
40}
41
42impl FromStr for RbnPacket {
43 type Err = ();
44
45 fn from_str(s: &str) -> Result<Self, Self::Err> {
46 let regex = Regex::new(REGEX_PATTERN).unwrap();
47 let mut captures = regex.captures_iter(s);
48 let first = captures.next();
49 if first.is_none() {
50 return Err(());
51 }
52 let first = first.unwrap();
53
54 Ok(Self {
56 spotter: first["spotter"].to_string(),
57 frequency: first["frequency"].parse().unwrap_or(0.0),
58 spotted: first["spotted"].to_string(),
59 mode: first["mode"].to_string(),
60 snr: first["snr"].parse().unwrap_or(0.0),
61 speed: first["speed"].parse().unwrap_or(0),
62 message: first["message"].to_string(),
63 time: first["time"].to_string(),
64 })
65 }
66}