1use std::io::{Read, Write};
2
3use super::*;
4
5#[derive(Debug, PartialEq)]
7pub struct DateTime {
8 year: u16,
9 month: u8,
10 day: u8,
11 hour: u8,
12 minute: u8,
13 second: u8,
14}
15
16impl DateTime {
17 #[inline]
18 pub fn new(year: Option<u16>, month: Option<u8>, day: Option<u8>, hour: Option<u8>,
19 minute: Option<u8>, second: Option<u8>) -> Result<DateTime, CreationError> {
20 Ok(DateTime {
21 year: year_num(year)?,
22 month: month_num(month)?,
23 day: day_num(day)?,
24 hour: hour_num(hour)?,
25 minute: minute_num(minute)?,
26 second: second_num(second)?,
27 })
28 }
29}
30
31impl Date for DateTime {
32 fn year(&self) -> Option<u16> {
33 if self.year == YEAR_RAW_NONE {
34 None
35 } else {
36 Some(self.year)
37 }
38 }
39
40 fn month(&self) -> Option<u8> {
41 if self.month == MONTH_RAW_NONE {
42 None
43 } else {
44 Some(self.month + 1)
45 }
46 }
47
48 fn day(&self) -> Option<u8> {
49 if self.day == DAY_RAW_NONE {
50 None
51 } else {
52 Some(self.day + 1)
53 }
54 }
55}
56
57impl Time for DateTime {
58 fn hour(&self) -> Option<u8> {
59 if self.hour == HOUR_RAW_NONE {
60 None
61 } else {
62 Some(self.hour)
63 }
64 }
65
66 fn minute(&self) -> Option<u8> {
67 if self.minute == MINUTE_RAW_NONE {
68 None
69 } else {
70 Some(self.minute)
71 }
72 }
73
74 fn second(&self) -> Option<u8> {
75 if self.second == SECOND_RAW_NONE {
76 None
77 } else {
78 Some(self.second)
79 }
80 }
81}
82
83impl Serializable for DateTime {
84 fn max_serialized_size() -> usize {
85 SERIALIZED_SIZE
86 }
87
88 fn serialized_size(&self) -> usize {
89 SERIALIZED_SIZE
90 }
91
92 fn serialize<W: Write>(&self, writer: &mut W) -> Result<usize, SerializationError> {
93 let b0 = DATE_TIME_TAG | (self.year >> 6) as u8;
94 let b1 = ((self.year << 2) as u8) | (self.month >> 2);
95 let b2 = (self.month << 6) | (self.day << 1) | (self.hour >> 4);
96 let b3 = (self.hour << 4) | (self.minute >> 2);
97 let b4 = (self.minute << 6) | self.second;
98
99 write_array_map_err(&[b0, b1, b2, b3, b4], writer)
100 .map_err(|_| SerializationError::IoError)
101 }
102}
103
104impl Deserializable for DateTime {
105 fn deserialize<R: Read>(reader: &mut R) -> Result<DateTime, DeserializationError> {
106 let mut buf = [0; SERIALIZED_SIZE];
107 read_exact(reader, &mut buf)?;
108
109 let byte0 = buf[0];
110
111 if byte0 & 0b1100_0000 != DATE_TIME_TAG {
112 return Err(DeserializationError::IncorrectTypeTag);
113 }
114
115 let byte1 = buf[1];
119 let mut raw_year = ((byte0 & 0x3F) as u16) << 6;
120 raw_year |= (byte1 >> 2) as u16;
121
122 let byte2 = buf[2];
123 let raw_month = ((byte1 & 0x03) << 2) | (byte2 >> 6);
124
125 let raw_day = (byte2 & 0x3E) >> 1;
126
127 let byte3 = buf[3];
128 let raw_hour = ((byte2 & 0x01) << 4) | (byte3 >> 4);
129
130 let byte4 = buf[4];
131 let raw_minute = ((byte3 & 0x0F) << 2) | (byte4 >> 6);
132
133 let raw_second = byte4 & 0x3F;
134
135 check_deser_in_range_or_none(raw_month, MONTH_RAW_MIN, MONTH_RAW_MAX, MONTH_RAW_NONE)?;
137 check_deser_in_range_or_none(raw_hour, HOUR_MIN, HOUR_MAX, HOUR_RAW_NONE)?;
139 check_deser_in_range_or_none(raw_minute, MINUTE_MIN, MINUTE_MAX, MINUTE_RAW_NONE)?;
140 check_deser_in_range_or_none(raw_second, SECOND_MIN, SECOND_MAX, SECOND_RAW_NONE)?;
141
142 Ok(DateTime {
143 year: raw_year,
144 month: raw_month,
145 day: raw_day,
146 hour: raw_hour,
147 minute: raw_minute,
148 second: raw_second,
149 })
150 }
151}
152
153const SERIALIZED_SIZE: usize = 5;