11// SPDX-License-Identifier: (Apache-2.0 OR MIT)
22
3+ use crate :: exc:: * ;
34use crate :: typeref:: * ;
4- use serde:: ser:: { Error , Serialize , Serializer } ;
5+ use serde:: ser:: { Serialize , Serializer } ;
56
67pub const NAIVE_UTC : u16 = 1 << 1 ;
78pub const OMIT_MICROSECONDS : u16 = 1 << 2 ;
@@ -15,12 +16,6 @@ const COLON: u8 = 58; // ":"
1516const PERIOD : u8 = 46 ; // ":"
1617const Z : u8 = 90 ; // "Z"
1718
18- macro_rules! err {
19- ( $msg: expr) => {
20- return Err ( Error :: custom( $msg) ) ;
21- } ;
22- }
23-
2419pub type DateTimeBuffer = heapless:: Vec < u8 , heapless:: consts:: U32 > ;
2520
2621macro_rules! write_double_digit {
@@ -55,13 +50,7 @@ impl Date {
5550 pub fn new ( ptr : * mut pyo3:: ffi:: PyObject ) -> Self {
5651 Date { ptr : ptr }
5752 }
58- }
59- impl < ' p > Serialize for Date {
60- fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
61- where
62- S : Serializer ,
63- {
64- let mut buf: DateTimeBuffer = heapless:: Vec :: new ( ) ;
53+ pub fn write_buf ( & self , buf : & mut DateTimeBuffer ) {
6554 {
6655 let year = ffi ! ( PyDateTime_GET_YEAR ( self . ptr) ) as i32 ;
6756 buf. extend_from_slice ( itoa:: Buffer :: new ( ) . format ( year) . as_bytes ( ) )
@@ -77,33 +66,39 @@ impl<'p> Serialize for Date {
7766 let day = ffi ! ( PyDateTime_GET_DAY ( self . ptr) ) as u32 ;
7867 write_double_digit ! ( buf, day) ;
7968 }
69+ }
70+ }
71+ impl < ' p > Serialize for Date {
72+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
73+ where
74+ S : Serializer ,
75+ {
76+ let mut buf: DateTimeBuffer = heapless:: Vec :: new ( ) ;
77+ self . write_buf ( & mut buf) ;
8078 serializer. serialize_str ( str_from_slice ! ( buf. as_ptr( ) , buf. len( ) ) )
8179 }
8280}
8381
82+ pub enum TimeError {
83+ HasTimezone ,
84+ }
85+
8486pub struct Time {
8587 ptr : * mut pyo3:: ffi:: PyObject ,
8688 opts : u16 ,
8789}
8890
8991impl Time {
90- pub fn new ( ptr : * mut pyo3:: ffi:: PyObject , opts : u16 ) -> Self {
91- Time {
92+ pub fn new ( ptr : * mut pyo3:: ffi:: PyObject , opts : u16 ) -> Result < Self , TimeError > {
93+ if unsafe { ( * ( ptr as * mut pyo3:: ffi:: PyDateTime_Time ) ) . hastzinfo == 1 } {
94+ return Err ( TimeError :: HasTimezone ) ;
95+ }
96+ Ok ( Time {
9297 ptr : ptr,
9398 opts : opts,
94- }
99+ } )
95100 }
96- }
97-
98- impl < ' p > Serialize for Time {
99- fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
100- where
101- S : Serializer ,
102- {
103- if unsafe { ( * ( self . ptr as * mut pyo3:: ffi:: PyDateTime_Time ) ) . hastzinfo == 1 } {
104- err ! ( "datetime.time must not have tzinfo set" )
105- }
106- let mut buf: DateTimeBuffer = heapless:: Vec :: new ( ) ;
101+ pub fn write_buf ( & self , buf : & mut DateTimeBuffer ) {
107102 {
108103 let hour = ffi ! ( PyDateTime_TIME_GET_HOUR ( self . ptr) ) as u8 ;
109104 write_double_digit ! ( buf, hour) ;
@@ -122,10 +117,24 @@ impl<'p> Serialize for Time {
122117 let microsecond = ffi ! ( PyDateTime_TIME_GET_MICROSECOND ( self . ptr) ) as u32 ;
123118 write_microsecond ! ( buf, microsecond) ;
124119 }
120+ }
121+ }
122+
123+ impl < ' p > Serialize for Time {
124+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
125+ where
126+ S : Serializer ,
127+ {
128+ let mut buf: DateTimeBuffer = heapless:: Vec :: new ( ) ;
129+ self . write_buf ( & mut buf) ;
125130 serializer. serialize_str ( str_from_slice ! ( buf. as_ptr( ) , buf. len( ) ) )
126131 }
127132}
128133
134+ pub enum DateTimeError {
135+ LibraryUnsupported ,
136+ }
137+
129138pub struct DateTime {
130139 ptr : * mut pyo3:: ffi:: PyObject ,
131140 opts : u16 ,
@@ -138,14 +147,7 @@ impl DateTime {
138147 opts : opts,
139148 }
140149 }
141- }
142-
143- impl < ' p > Serialize for DateTime {
144- fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
145- where
146- S : Serializer ,
147- {
148- let mut buf: DateTimeBuffer = heapless:: Vec :: new ( ) ;
150+ pub fn write_buf ( & self , buf : & mut DateTimeBuffer ) -> Result < ( ) , DateTimeError > {
149151 let has_tz = unsafe { ( * ( self . ptr as * mut pyo3:: ffi:: PyDateTime_DateTime ) ) . hastzinfo == 1 } ;
150152 let offset_day: i32 ;
151153 let mut offset_second: i32 ;
@@ -195,7 +197,7 @@ impl<'p> Serialize for DateTime {
195197 offset_second = ffi ! ( PyDateTime_DELTA_GET_SECONDS ( offset) ) as i32 ;
196198 offset_day = ffi ! ( PyDateTime_DELTA_GET_DAYS ( offset) ) ;
197199 } else {
198- err ! ( "datetime's timezone library is not supported: use datetime.timezone.utc, pendulum, pytz, or dateutil" )
200+ return Err ( DateTimeError :: LibraryUnsupported ) ;
199201 }
200202 } else {
201203 offset_second = 0 ;
@@ -285,6 +287,19 @@ impl<'p> Serialize for DateTime {
285287 }
286288 }
287289 }
290+ Ok ( ( ) )
291+ }
292+ }
293+
294+ impl < ' p > Serialize for DateTime {
295+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
296+ where
297+ S : Serializer ,
298+ {
299+ let mut buf: DateTimeBuffer = heapless:: Vec :: new ( ) ;
300+ if self . write_buf ( & mut buf) . is_err ( ) {
301+ err ! ( DATETIME_LIBRARY_UNSUPPORTED )
302+ }
288303 serializer. serialize_str ( str_from_slice ! ( buf. as_ptr( ) , buf. len( ) ) )
289304 }
290305}
0 commit comments