1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! Facet implementation for `core::net` types
#![cfg(feature = "net")]
extern crate alloc;
use crate::{
Def, Facet, PtrConst, Shape, ShapeBuilder, TryFromOutcome, VTableDirect, vtable_direct,
};
/// Generate a try_from function for a net type that converts from &str via FromStr
macro_rules! net_try_from {
($type:ty) => {{
/// # Safety
/// `dst` must be valid for writes, `src` must point to valid data of type described by `src_shape`
unsafe fn try_from_str(
dst: *mut $type,
src_shape: &'static Shape,
src: PtrConst,
) -> TryFromOutcome {
// Check if source is &str (Copy type, use get - doesn't consume)
if src_shape.id == <&str as Facet>::SHAPE.id {
let str_ref: &str = unsafe { *src.get::<&str>() };
match str_ref.parse::<$type>() {
Ok(val) => {
unsafe { dst.write(val) };
TryFromOutcome::Converted
}
Err(_) => TryFromOutcome::Failed(
alloc::format!(
"failed to parse '{}' as {}",
str_ref,
stringify!($type)
)
.into(),
),
}
} else if src_shape.id == <alloc::string::String as Facet>::SHAPE.id {
// Consume the String
let string: alloc::string::String = unsafe { src.read::<alloc::string::String>() };
match string.parse::<$type>() {
Ok(val) => {
unsafe { dst.write(val) };
TryFromOutcome::Converted
}
Err(_) => TryFromOutcome::Failed(
alloc::format!(
"failed to parse '{}' as {}",
string,
stringify!($type)
)
.into(),
),
}
} else {
TryFromOutcome::Unsupported
}
}
try_from_str
}};
}
macro_rules! impl_facet_for_net_type {
($type:ty, $name:literal) => {
unsafe impl Facet<'_> for $type {
const SHAPE: &'static Shape = &const {
const VTABLE: VTableDirect = vtable_direct!($type =>
FromStr,
Display,
Debug,
Hash,
PartialEq,
PartialOrd,
Ord,
[try_from = net_try_from!($type)],
);
ShapeBuilder::for_sized::<$type>($name)
.def(Def::Scalar)
.vtable_direct(&VTABLE)
.eq()
.copy()
.send()
.sync()
.build()
};
}
};
}
impl_facet_for_net_type!(core::net::SocketAddr, "SocketAddr");
impl_facet_for_net_type!(core::net::SocketAddrV4, "SocketAddrV4");
impl_facet_for_net_type!(core::net::SocketAddrV6, "SocketAddrV6");
impl_facet_for_net_type!(core::net::IpAddr, "IpAddr");
impl_facet_for_net_type!(core::net::Ipv4Addr, "Ipv4Addr");
impl_facet_for_net_type!(core::net::Ipv6Addr, "Ipv6Addr");