manycast/
custom_module.rs1use std::fmt::Display;
2use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
3
4use manycastr::{address::Value::V4, address::Value::V6, Address, IPv6};
5
6pub mod manycastr {
7 tonic::include_proto!("manycastr");
8}
9
10impl Display for Address {
11 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12 let str = match &self.value {
13 Some(V4(v4)) => Ipv4Addr::from(*v4).to_string(),
14 Some(V6(v6)) => Ipv6Addr::new(
15 (v6.p1 >> 48) as u16,
16 (v6.p1 >> 32) as u16,
17 (v6.p1 >> 16) as u16,
18 v6.p1 as u16,
19 (v6.p2 >> 48) as u16,
20 (v6.p2 >> 32) as u16,
21 (v6.p2 >> 16) as u16,
22 v6.p2 as u16,
23 )
24 .to_string(),
25 None => String::from("None"),
26 };
27 write!(f, "{str}")
28 }
29}
30
31impl Address {
32 pub fn is_v6(&self) -> bool {
33 matches!(&self.value, Some(V6(_)))
34 }
35
36 #[allow(dead_code)]
41 pub fn get_prefix(&self) -> u64 {
42 match &self.value {
43 Some(V4(v4)) => {
44 ((v4 >> 8) & 0x00FFFFFF).into()
46 }
47 Some(V6(v6)) => {
48 (v6.p1 >> 16) & 0x0000FFFFFFFF
50 }
51 None => 0,
52 }
53 }
54
55 pub fn get_v4(&self) -> u32 {
59 match &self.value {
60 Some(V4(v4)) => *v4,
61 _ => panic!("Not a v4 address"),
62 }
63 }
64
65 pub fn get_v6(&self) -> u128 {
69 match &self.value {
70 Some(V6(v6)) => (v6.p1 as u128) << 64 | v6.p2 as u128,
71 _ => panic!("Not a v6 address"),
72 }
73 }
74}
75
76impl From<&[u8]> for Address {
78 fn from(bytes: &[u8]) -> Self {
79 match bytes.len() {
80 4 => {
81 let mut ip = [0; 4];
82 ip.copy_from_slice(bytes);
83 Address {
84 value: Some(V4(u32::from_be_bytes(ip))),
85 }
86 }
87 16 => {
88 let mut ip = [0; 16];
89 ip.copy_from_slice(bytes);
90 Address {
91 value: Some(V6(IPv6 {
92 p1: u64::from_be_bytes(ip[0..8].try_into().unwrap()),
93 p2: u64::from_be_bytes(ip[8..16].try_into().unwrap()),
94 })),
95 }
96 }
97 _ => panic!("Invalid IP address length"),
98 }
99 }
100}
101
102impl From<[u8; 4]> for Address {
103 fn from(bytes: [u8; 4]) -> Self {
104 Address {
105 value: Some(V4(u32::from_be_bytes(bytes))),
106 }
107 }
108}
109
110impl From<u32> for Address {
111 fn from(bytes: u32) -> Self {
112 Address {
113 value: Some(V4(bytes)),
114 }
115 }
116}
117
118impl From<u128> for Address {
119 fn from(bytes: u128) -> Self {
120 Address {
121 value: Some(V6(IPv6 {
122 p1: (bytes >> 64) as u64,
123 p2: (bytes & 0xFFFFFFFFFFFFFFFF) as u64,
124 })),
125 }
126 }
127}
128
129impl From<[u8; 16]> for Address {
130 fn from(bytes: [u8; 16]) -> Self {
131 Address {
132 value: Some(V6(IPv6 {
133 p1: u64::from_be_bytes(bytes[0..8].try_into().unwrap()),
134 p2: u64::from_be_bytes(bytes[8..16].try_into().unwrap()),
135 })),
136 }
137 }
138}
139
140impl From<String> for Address {
142 fn from(s: String) -> Self {
143 if let Ok(ip) = s.parse::<IpAddr>() {
144 match ip {
146 IpAddr::V4(v4_addr) => Address {
147 value: Some(V4(u32::from_be_bytes(v4_addr.octets()))),
148 },
149 IpAddr::V6(v6_addr) => Address {
150 value: Some(V6(IPv6 {
151 p1: u64::from_be_bytes(v6_addr.octets()[0..8].try_into().unwrap()),
152 p2: u64::from_be_bytes(v6_addr.octets()[8..16].try_into().unwrap()),
153 })),
154 },
155 }
156 } else if let Ok(ip_number) = s.parse::<u128>() {
157 if ip_number <= u32::MAX as u128 {
159 Address {
161 value: Some(V4(ip_number as u32)),
162 }
163 } else {
164 Address {
166 value: Some(V6(IPv6 {
167 p1: (ip_number >> 64) as u64, p2: (ip_number & 0xFFFFFFFFFFFFFFFF) as u64, })),
170 }
171 }
172 } else {
173 panic!("Invalid IP address or IP number");
174 }
175 }
176}
177
178impl From<&String> for Address {
179 fn from(s: &String) -> Self {
180 Address::from(s.to_string())
181 }
182}
183
184impl From<&str> for Address {
185 fn from(s: &str) -> Self {
186 Address::from(s.to_string())
187 }
188}
189
190impl From<IpAddr> for Address {
191 fn from(ip: IpAddr) -> Self {
192 match ip {
193 IpAddr::V4(v4_addr) => Address {
194 value: Some(V4(u32::from_be_bytes(v4_addr.octets()))),
195 },
196 IpAddr::V6(v6_addr) => Address {
197 value: Some(V6(IPv6 {
198 p1: u64::from_be_bytes(v6_addr.octets()[0..8].try_into().unwrap()),
199 p2: u64::from_be_bytes(v6_addr.octets()[8..16].try_into().unwrap()),
200 })),
201 },
202 }
203 }
204}
205
206pub trait Separated {
207 fn with_separator(&self) -> String;
208}
209
210fn format_number(number: usize) -> String {
211 let number_str = number.to_string();
212 let chunks: Vec<&str> = number_str
213 .as_bytes()
214 .rchunks(3)
215 .rev()
216 .map(std::str::from_utf8)
217 .collect::<Result<Vec<&str>, _>>()
218 .expect("Unable to format number");
219
220 chunks.join(",")
221}
222
223impl Separated for u32 {
224 fn with_separator(&self) -> String {
225 format_number(*self as usize)
226 }
227}
228
229impl Separated for usize {
230 fn with_separator(&self) -> String {
231 format_number(*self)
232 }
233}