]> code.octet-stream.net Git - m17rt/blob - m17app/src/link_setup.rs
Address more clippy lints
[m17rt] / m17app / src / link_setup.rs
1 use std::fmt::Display;
2
3 use m17core::{
4 address::{Address, Callsign, ALPHABET},
5 protocol::LsfFrame,
6 };
7
8 use crate::error::M17Error;
9
10 pub struct LinkSetup {
11 pub(crate) raw: LsfFrame,
12 }
13
14 impl LinkSetup {
15 /// Provide a completed LsfFrame.
16 pub fn new_raw(frame: LsfFrame) -> Self {
17 Self { raw: frame }
18 }
19
20 pub fn source(&self) -> M17Address {
21 M17Address(self.raw.source())
22 }
23
24 pub fn destination(&self) -> M17Address {
25 M17Address(self.raw.destination())
26 }
27
28 /// Set up an unencrypted voice stream with channel access number 0 and the given source and destination.
29 pub fn new_voice(source: &M17Address, destination: &M17Address) -> Self {
30 Self {
31 raw: LsfFrame::new_voice(source.address(), destination.address()),
32 }
33 }
34
35 /// Set up an unencrypted packet data transmission with channel access number 0 and the given source and destination.
36 pub fn new_packet(source: &M17Address, destination: &M17Address) -> Self {
37 Self {
38 raw: LsfFrame::new_packet(source.address(), destination.address()),
39 }
40 }
41
42 /// Configure the channel access number for this transmission, which may be from 0 to 15 inclusive.
43 pub fn set_channel_access_number(&mut self, channel_access_number: u8) {
44 self.raw.set_channel_access_number(channel_access_number);
45 }
46
47 pub fn lich_part(&self, counter: u8) -> [u8; 5] {
48 let idx = counter as usize;
49 self.raw.0[idx * 5..(idx + 1) * 5].try_into().unwrap()
50 }
51 }
52
53 /// Station address. High level version of `Address` from core.
54
55 #[derive(Debug, Clone)]
56 pub struct M17Address(Address);
57
58 impl M17Address {
59 pub fn new_broadcast() -> Self {
60 Self(Address::Broadcast)
61 }
62
63 pub fn from_callsign(callsign: &str) -> Result<Self, M17Error> {
64 let trimmed = callsign.trim().to_uppercase();
65 let len = trimmed.len();
66 if len > 9 {
67 return Err(M17Error::CallsignTooLong(len));
68 }
69 let mut address = [b' '; 9];
70 for (i, c) in trimmed.chars().enumerate() {
71 if !c.is_ascii() {
72 return Err(M17Error::InvalidCallsignCharacters(c));
73 }
74 if !ALPHABET.contains(&(c as u8)) {
75 return Err(M17Error::InvalidCallsignCharacters(c));
76 }
77 address[i] = c as u8;
78 }
79 Ok(Self(Address::Callsign(Callsign(address))))
80 }
81
82 pub(crate) fn address(&self) -> &Address {
83 &self.0
84 }
85 }
86
87 impl Display for M17Address {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 match self.0 {
90 Address::Invalid => unreachable!(),
91 Address::Callsign(ref callsign) => {
92 write!(
93 f,
94 "{}",
95 callsign
96 .0
97 .iter()
98 .map(|c| *c as char)
99 .collect::<String>()
100 .trim()
101 )
102 }
103 Address::Reserved(_) => unreachable!(),
104 Address::Broadcast => {
105 write!(f, "<BROADCAST>")
106 }
107 }
108 }
109 }