libtelnet_rs/
compatibility.rs1#[derive(Clone, Copy)]
3pub struct CompatibilityEntry {
4 pub local: bool,
6 pub remote: bool,
8 pub local_state: bool,
10 pub remote_state: bool,
12}
13
14impl CompatibilityEntry {
15 pub fn new(local: bool, remote: bool, local_state: bool, remote_state: bool) -> Self {
16 Self {
17 local,
18 remote,
19 local_state,
20 remote_state,
21 }
22 }
23 pub fn into_u8(self) -> u8 {
25 let mut res: u8 = 0;
26 if self.local {
27 res |= CompatibilityTable::ENABLED_LOCAL;
28 }
29 if self.remote {
30 res |= CompatibilityTable::ENABLED_REMOTE;
31 }
32 if self.local_state {
33 res |= CompatibilityTable::LOCAL_STATE;
34 }
35 if self.remote_state {
36 res |= CompatibilityTable::REMOTE_STATE;
37 }
38 res
39 }
40 pub fn from(value: u8) -> Self {
42 Self {
43 local: value & CompatibilityTable::ENABLED_LOCAL == CompatibilityTable::ENABLED_LOCAL,
44 remote: value & CompatibilityTable::ENABLED_REMOTE == CompatibilityTable::ENABLED_REMOTE,
45 local_state: value & CompatibilityTable::LOCAL_STATE == CompatibilityTable::LOCAL_STATE,
46 remote_state: value & CompatibilityTable::REMOTE_STATE == CompatibilityTable::REMOTE_STATE,
47 }
48 }
49}
50
51#[derive(Clone)]
53pub struct CompatibilityTable {
54 options: [u8; 256],
55}
56
57impl Default for CompatibilityTable {
58 fn default() -> Self {
59 Self { options: [0; 256] }
60 }
61}
62
63impl CompatibilityTable {
64 pub const ENABLED_LOCAL: u8 = 1;
66 pub const ENABLED_REMOTE: u8 = 1 << 1;
68 pub const LOCAL_STATE: u8 = 1 << 2;
70 pub const REMOTE_STATE: u8 = 1 << 3;
72 pub fn new() -> Self {
73 Self::default()
74 }
75 pub fn from_options(values: &[(u8, u8)]) -> Self {
85 let mut options: [u8; 256] = [0; 256];
86 for (opt, val) in values {
87 options[*opt as usize] = *val;
88 }
89 Self { options }
90 }
91 pub fn support_local(&mut self, option: u8) {
93 let mut opt = CompatibilityEntry::from(self.options[option as usize]);
94 opt.local = true;
95 self.set_option(option, opt);
96 }
97 pub fn support_remote(&mut self, option: u8) {
99 let mut opt = CompatibilityEntry::from(self.options[option as usize]);
100 opt.remote = true;
101 self.set_option(option, opt);
102 }
103 pub fn support(&mut self, option: u8) {
105 let mut opt = CompatibilityEntry::from(self.options[option as usize]);
106 opt.local = true;
107 opt.remote = true;
108 self.set_option(option, opt);
109 }
110 pub fn get_option(&self, option: u8) -> CompatibilityEntry {
112 CompatibilityEntry::from(self.options[option as usize])
113 }
114 pub fn set_option(&mut self, option: u8, entry: CompatibilityEntry) {
116 self.options[option as usize] = entry.clone().into_u8();
117 }
118
119 pub fn reset_states(&mut self) {
121 for opt in self.options.iter_mut() {
122 let mut entry = CompatibilityEntry::from(*opt);
123 entry.local_state = false;
124 entry.remote_state = false;
125 *opt = entry.into_u8();
126 }
127 }
128}
129
130#[cfg(test)]
131mod test_compat {
132 use super::*;
133
134 #[test]
135 fn test_reset() {
136 let mut table = CompatibilityTable::default();
137 let entry = CompatibilityEntry::new(true, true, true, true);
138 assert_eq!(entry.remote, true);
139 assert_eq!(entry.local, true);
140 assert_eq!(entry.remote_state, true);
141 assert_eq!(entry.local_state, true);
142 table.set_option(201, entry);
143 table.reset_states();
144 let entry = table.get_option(201);
145 assert_eq!(entry.remote, true);
146 assert_eq!(entry.local, true);
147 assert_eq!(entry.remote_state, false);
148 assert_eq!(entry.local_state, false);
149 }
150}