1#![doc = include_str!("../README.md")]
2
3#[cfg(feature = "ufmt")]
4#[doc(hidden)]
5pub mod ufmt;
6
7use std::{fmt, net::Ipv4Addr, str};
8
9const MAX_LEN: usize = 3 * 4 + 3;
10type Buf = [u8; MAX_LEN];
11
12macro_rules! write_octet {
13 ($octet:expr, $buf:ident, $at:ident) => {
14 let octet = $octet;
15 if octet >= 100 {
16 $buf[$at] = b'0' + octet / 100;
17 $at += 1;
18 }
19 if octet >= 10 {
20 $buf[$at] = b'0' + (octet / 10) % 10;
21 $at += 1;
22 }
23 $buf[$at] = b'0' + octet % 10;
24 $at += 1;
25 };
26}
27
28const fn ipv4_display(ip: Ipv4Addr) -> (Buf, usize) {
29 let mut arr: Buf = [b'.'; MAX_LEN];
30 let mut at = 0;
31
32 let [a, b, c, d] = ip.octets();
33 write_octet!(a, arr, at);
34 at += 1;
35 write_octet!(b, arr, at);
36 at += 1;
37 write_octet!(c, arr, at);
38 at += 1;
39 write_octet!(d, arr, at);
40
41 (arr, at)
42}
43
44#[repr(transparent)]
45#[derive(Clone, Copy)]
46pub struct Ipv4AddrDisplay(Ipv4Addr);
59
60impl Ipv4AddrDisplay {
61 #[inline]
62 pub fn new(addr: Ipv4Addr) -> Self {
63 Self(addr)
64 }
65}
66
67impl From<Ipv4Addr> for Ipv4AddrDisplay {
68 #[inline]
69 fn from(addr: Ipv4Addr) -> Self {
70 Self(addr)
71 }
72}
73
74impl fmt::Display for Ipv4AddrDisplay {
75 #[inline]
76 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 let (arr, len) = ipv4_display(self.0);
78 f.write_str(unsafe { str::from_utf8_unchecked(&arr[..len]) })
79 }
80}
81
82impl fmt::Debug for Ipv4AddrDisplay {
83 #[inline]
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 fmt::Display::fmt(self, f)
86 }
87}