Skip to main content

serde_shape/impls/
time.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::vec;
16use alloc::vec::Vec;
17use core::any::type_name;
18use core::time::Duration;
19#[cfg(feature = "std")]
20use std::time::SystemTime;
21
22use crate::DefaultShape;
23use crate::DeserializeContainerAttributes;
24use crate::DeserializeDefinitionKind;
25use crate::DeserializeFieldShape;
26use crate::DeserializeShape;
27use crate::DeserializeShapeContext;
28use crate::DeserializeStructShape;
29use crate::FieldMember;
30use crate::FieldWireShape;
31use crate::FieldsStyle;
32use crate::SerializeContainerAttributes;
33use crate::SerializeDefinitionKind;
34use crate::SerializeFieldShape;
35use crate::SerializeShape;
36use crate::SerializeShapeContext;
37use crate::SerializeStructShape;
38use crate::ShapeRef;
39use crate::TypeName;
40
41macro_rules! time_shape {
42    ($ty:ty, $name:literal, $($field:literal => $shape:expr),+ $(,)?) => {
43        impl SerializeShape for $ty {
44            fn serialize_shape_in(context: &mut SerializeShapeContext) -> ShapeRef {
45                serialize_time_shape(
46                    context,
47                    type_name::<Self>(),
48                    $name,
49                    [$(($field, $shape)),+],
50                )
51            }
52        }
53
54        impl DeserializeShape for $ty {
55            fn deserialize_shape_in(context: &mut DeserializeShapeContext) -> ShapeRef {
56                deserialize_time_shape(
57                    context,
58                    type_name::<Self>(),
59                    $name,
60                    [$(($field, $shape)),+],
61                )
62            }
63        }
64    };
65}
66
67time_shape!(Duration, "Duration", "secs" => ShapeRef::U64, "nanos" => ShapeRef::U32);
68
69#[cfg(feature = "std")]
70time_shape!(
71    SystemTime,
72    "SystemTime",
73    "secs_since_epoch" => ShapeRef::U64,
74    "nanos_since_epoch" => ShapeRef::U32,
75);
76
77fn serialize_time_shape<const N: usize>(
78    context: &mut SerializeShapeContext,
79    rust_name: &'static str,
80    name: &'static str,
81    fields: [(&'static str, ShapeRef); N],
82) -> ShapeRef {
83    let fields: Vec<_> = fields
84        .into_iter()
85        .map(|(name, shape)| SerializeFieldShape {
86            member: FieldMember::Named(name),
87            name,
88            description: None,
89            wire_shape: FieldWireShape::Value(shape),
90            skip_if: None,
91        })
92        .collect();
93    context.define_named_type(TypeName { rust_name, name }, move |_| {
94        SerializeDefinitionKind::Struct(SerializeStructShape {
95            style: FieldsStyle::Struct,
96            fields,
97            attributes: SerializeContainerAttributes::default(),
98        })
99    })
100}
101
102fn deserialize_time_shape<const N: usize>(
103    context: &mut DeserializeShapeContext,
104    rust_name: &'static str,
105    name: &'static str,
106    fields: [(&'static str, ShapeRef); N],
107) -> ShapeRef {
108    let fields: Vec<_> = fields
109        .into_iter()
110        .map(|(name, shape)| DeserializeFieldShape {
111            member: FieldMember::Named(name),
112            name,
113            aliases: vec![name],
114            description: None,
115            wire_shape: FieldWireShape::Value(shape),
116            default: DefaultShape::None,
117        })
118        .collect();
119    context.define_named_type(TypeName { rust_name, name }, move |_| {
120        DeserializeDefinitionKind::Struct(DeserializeStructShape {
121            style: FieldsStyle::Struct,
122            fields,
123            attributes: DeserializeContainerAttributes {
124                deny_unknown_fields: true,
125                ..DeserializeContainerAttributes::default()
126            },
127        })
128    })
129}