1use std::net::IpAddr;
2
3use md5::{Digest, Md5};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
7pub struct ReferenceId(u32);
8
9impl ReferenceId {
10 pub const KISS_DENY: ReferenceId = ReferenceId(u32::from_be_bytes(*b"DENY"));
12 pub const KISS_RATE: ReferenceId = ReferenceId(u32::from_be_bytes(*b"RATE"));
13 pub const KISS_RSTR: ReferenceId = ReferenceId(u32::from_be_bytes(*b"RSTR"));
14 pub const NONE: ReferenceId = ReferenceId(u32::from_be_bytes(*b"XNON"));
15 pub const SOCK: ReferenceId = ReferenceId(u32::from_be_bytes(*b"SOCK"));
16 pub const PPS: ReferenceId = ReferenceId(u32::from_be_bytes(*b"PPS\0"));
17
18 pub const KISS_NTSN: ReferenceId = ReferenceId(u32::from_be_bytes(*b"NTSN"));
20
21 pub fn from_ip(addr: IpAddr) -> ReferenceId {
22 match addr {
23 IpAddr::V4(addr) => ReferenceId(u32::from_be_bytes(addr.octets())),
24 IpAddr::V6(addr) => ReferenceId(u32::from_be_bytes(
25 Md5::digest(addr.octets())[0..4].try_into().unwrap(),
26 )),
27 }
28 }
29
30 pub(crate) const fn from_int(value: u32) -> ReferenceId {
31 ReferenceId(value)
32 }
33
34 pub(crate) fn is_deny(&self) -> bool {
35 *self == Self::KISS_DENY
36 }
37
38 pub(crate) fn is_rate(&self) -> bool {
39 *self == Self::KISS_RATE
40 }
41
42 pub(crate) fn is_rstr(&self) -> bool {
43 *self == Self::KISS_RSTR
44 }
45
46 pub(crate) fn is_ntsn(&self) -> bool {
47 *self == Self::KISS_NTSN
48 }
49
50 pub(crate) fn to_bytes(self) -> [u8; 4] {
51 self.0.to_be_bytes()
52 }
53
54 pub(crate) fn from_bytes(bits: [u8; 4]) -> ReferenceId {
55 ReferenceId(u32::from_be_bytes(bits))
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn referenceid_serialization_roundtrip() {
65 let a = [12, 34, 56, 78];
66 let b = ReferenceId::from_bytes(a);
67 let c = b.to_bytes();
68 let d = ReferenceId::from_bytes(c);
69 assert_eq!(a, c);
70 assert_eq!(b, d);
71 }
72
73 #[test]
74 fn referenceid_kiss_codes() {
75 let a = [b'R', b'A', b'T', b'E'];
76 let b = ReferenceId::from_bytes(a);
77 assert!(b.is_rate());
78
79 let a = [b'R', b'S', b'T', b'R'];
80 let b = ReferenceId::from_bytes(a);
81 assert!(b.is_rstr());
82
83 let a = [b'D', b'E', b'N', b'Y'];
84 let b = ReferenceId::from_bytes(a);
85 assert!(b.is_deny());
86 }
87
88 #[test]
89 fn referenceid_from_ipv4() {
90 let ip: IpAddr = "12.34.56.78".parse().unwrap();
91 let rep = [12, 34, 56, 78];
92 let a = ReferenceId::from_ip(ip);
93 let b = ReferenceId::from_bytes(rep);
94 assert_eq!(a, b);
95
96 }
99}