1use std::fmt;
4use std::net::Ipv6Addr;
5
6use super::{FIPS_ADDRESS_PREFIX, IdentityError, NodeAddr};
7
8#[derive(Clone, Copy, PartialEq, Eq, Hash)]
14pub struct FipsAddress([u8; 16]);
15
16impl FipsAddress {
17 pub fn from_bytes(bytes: [u8; 16]) -> Result<Self, IdentityError> {
19 if bytes[0] != FIPS_ADDRESS_PREFIX {
20 return Err(IdentityError::InvalidAddressPrefix(bytes[0]));
21 }
22 Ok(Self(bytes))
23 }
24
25 pub fn from_slice(slice: &[u8]) -> Result<Self, IdentityError> {
27 if slice.len() != 16 {
28 return Err(IdentityError::InvalidAddressLength(slice.len()));
29 }
30 let mut bytes = [0u8; 16];
31 bytes.copy_from_slice(slice);
32 Self::from_bytes(bytes)
33 }
34
35 pub fn from_node_addr(node_addr: &NodeAddr) -> Self {
39 let mut bytes = [0u8; 16];
40 bytes[0] = FIPS_ADDRESS_PREFIX;
41 bytes[1..16].copy_from_slice(&node_addr.as_bytes()[0..15]);
42 Self(bytes)
43 }
44
45 pub fn as_bytes(&self) -> &[u8; 16] {
47 &self.0
48 }
49
50 pub fn to_ipv6(&self) -> Ipv6Addr {
52 Ipv6Addr::from(self.0)
53 }
54}
55
56impl From<FipsAddress> for Ipv6Addr {
57 fn from(addr: FipsAddress) -> Self {
58 Ipv6Addr::from(addr.0)
59 }
60}
61
62impl fmt::Debug for FipsAddress {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "FipsAddress({})", self.to_ipv6())
65 }
66}
67
68impl fmt::Display for FipsAddress {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "{}", self.to_ipv6())
71 }
72}