Skip to main content

serde_shape/impls/
net.rs

1// Copyright 2026 FastLabs Developers
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use alloc::boxed::Box;
16use alloc::vec;
17use core::net::IpAddr;
18use core::net::Ipv4Addr;
19use core::net::Ipv6Addr;
20use core::net::SocketAddr;
21use core::net::SocketAddrV4;
22use core::net::SocketAddrV6;
23
24use crate::DefaultShape;
25use crate::DeserializeContainerAttributes;
26use crate::DeserializeDefinitionKind;
27use crate::DeserializeEnumShape;
28use crate::DeserializeFieldShape;
29use crate::DeserializeShape;
30use crate::DeserializeShapeContext;
31use crate::DeserializeVariantContent;
32use crate::DeserializeVariantShape;
33use crate::FieldMember;
34use crate::FieldWireShape;
35use crate::FieldsStyle;
36use crate::SerializeContainerAttributes;
37use crate::SerializeDefinitionKind;
38use crate::SerializeEnumShape;
39use crate::SerializeFieldShape;
40use crate::SerializeShape;
41use crate::SerializeShapeContext;
42use crate::SerializeVariantContent;
43use crate::SerializeVariantShape;
44use crate::ShapeRef;
45use crate::Tagging;
46use crate::TypeName;
47
48macro_rules! union_shape {
49    ($ty:ty => $binary:expr) => {
50        impl SerializeShape for $ty {
51            fn serialize_shape_in(_context: &mut SerializeShapeContext) -> ShapeRef {
52                ShapeRef::union([ShapeRef::String, $binary])
53            }
54        }
55
56        impl DeserializeShape for $ty {
57            fn deserialize_shape_in(_context: &mut DeserializeShapeContext) -> ShapeRef {
58                ShapeRef::union([ShapeRef::String, $binary])
59            }
60        }
61    };
62}
63
64union_shape!(Ipv4Addr => ipv4_binary_shape());
65union_shape!(Ipv6Addr => ipv6_binary_shape());
66union_shape!(SocketAddrV4 => socket_v4_binary_shape());
67union_shape!(SocketAddrV6 => socket_v6_binary_shape());
68
69impl SerializeShape for IpAddr {
70    fn serialize_shape_in(context: &mut SerializeShapeContext) -> ShapeRef {
71        let binary = context.define_named_type(TypeName::of::<Self>("IpAddr"), |_| {
72            SerializeDefinitionKind::Enum(SerializeEnumShape {
73                repr: Tagging::External,
74                variants: vec![
75                    serialize_newtype_variant("V4", ipv4_binary_shape()),
76                    serialize_newtype_variant("V6", ipv6_binary_shape()),
77                ],
78                attributes: serialize_enum_attributes(),
79            })
80        });
81        ShapeRef::union([ShapeRef::String, binary])
82    }
83}
84
85impl DeserializeShape for IpAddr {
86    fn deserialize_shape_in(context: &mut DeserializeShapeContext) -> ShapeRef {
87        let binary = context.define_named_type(TypeName::of::<Self>("IpAddr"), |_| {
88            DeserializeDefinitionKind::Enum(DeserializeEnumShape {
89                repr: Tagging::External,
90                variants: vec![
91                    deserialize_newtype_variant("V4", ipv4_binary_shape()),
92                    deserialize_newtype_variant("V6", ipv6_binary_shape()),
93                ],
94                attributes: deserialize_enum_attributes(),
95            })
96        });
97        ShapeRef::union([ShapeRef::String, binary])
98    }
99}
100
101impl SerializeShape for SocketAddr {
102    fn serialize_shape_in(context: &mut SerializeShapeContext) -> ShapeRef {
103        let binary = context.define_named_type(TypeName::of::<Self>("SocketAddr"), |_| {
104            SerializeDefinitionKind::Enum(SerializeEnumShape {
105                repr: Tagging::External,
106                variants: vec![
107                    serialize_newtype_variant("V4", socket_v4_binary_shape()),
108                    serialize_newtype_variant("V6", socket_v6_binary_shape()),
109                ],
110                attributes: serialize_enum_attributes(),
111            })
112        });
113        ShapeRef::union([ShapeRef::String, binary])
114    }
115}
116
117impl DeserializeShape for SocketAddr {
118    fn deserialize_shape_in(context: &mut DeserializeShapeContext) -> ShapeRef {
119        let binary = context.define_named_type(TypeName::of::<Self>("SocketAddr"), |_| {
120            DeserializeDefinitionKind::Enum(DeserializeEnumShape {
121                repr: Tagging::External,
122                variants: vec![
123                    deserialize_newtype_variant("V4", socket_v4_binary_shape()),
124                    deserialize_newtype_variant("V6", socket_v6_binary_shape()),
125                ],
126                attributes: deserialize_enum_attributes(),
127            })
128        });
129        ShapeRef::union([ShapeRef::String, binary])
130    }
131}
132
133fn ipv4_binary_shape() -> ShapeRef {
134    ShapeRef::Array {
135        item: Box::new(ShapeRef::U8),
136        len: 4,
137    }
138}
139
140fn ipv6_binary_shape() -> ShapeRef {
141    ShapeRef::Array {
142        item: Box::new(ShapeRef::U8),
143        len: 16,
144    }
145}
146
147fn socket_v4_binary_shape() -> ShapeRef {
148    ShapeRef::Tuple(vec![ipv4_binary_shape(), ShapeRef::U16])
149}
150
151fn socket_v6_binary_shape() -> ShapeRef {
152    ShapeRef::Tuple(vec![ipv6_binary_shape(), ShapeRef::U16])
153}
154
155fn serialize_newtype_variant(name: &'static str, shape: ShapeRef) -> SerializeVariantShape {
156    SerializeVariantShape {
157        rust_name: name,
158        name,
159        description: None,
160        style: FieldsStyle::Newtype,
161        content: SerializeVariantContent::Fields(vec![SerializeFieldShape {
162            member: FieldMember::Unnamed(0),
163            name: "0",
164            description: None,
165            wire_shape: FieldWireShape::Value(shape),
166            skip_if: None,
167        }]),
168        untagged: false,
169    }
170}
171
172fn deserialize_newtype_variant(name: &'static str, shape: ShapeRef) -> DeserializeVariantShape {
173    DeserializeVariantShape {
174        rust_name: name,
175        name,
176        aliases: vec![name],
177        description: None,
178        style: FieldsStyle::Newtype,
179        content: DeserializeVariantContent::Fields(vec![DeserializeFieldShape {
180            member: FieldMember::Unnamed(0),
181            name: "0",
182            aliases: vec!["0"],
183            description: None,
184            wire_shape: FieldWireShape::Value(shape),
185            default: DefaultShape::None,
186        }]),
187        other: false,
188        untagged: false,
189    }
190}
191
192fn serialize_enum_attributes() -> SerializeContainerAttributes {
193    SerializeContainerAttributes::default()
194}
195
196fn deserialize_enum_attributes() -> DeserializeContainerAttributes {
197    DeserializeContainerAttributes::default()
198}