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
97
98
99
100
101
102
103
104
105
use std::io::{Read, Write};
use super::*;
#[derive(Debug, PartialEq)]
pub struct TimeOnly {
hour: u8,
minute: u8,
second: u8,
}
impl TimeOnly {
#[inline]
pub fn new(hour: Option<u8>, minute: Option<u8>, second: Option<u8>) -> Result<TimeOnly, CreationError> {
Ok(TimeOnly {
hour: hour_num(hour)?,
minute: minute_num(minute)?,
second: second_num(second)?,
})
}
}
impl Time for TimeOnly {
fn hour(&self) -> Option<u8> {
if self.hour == HOUR_RAW_NONE {
None
} else {
Some(self.hour)
}
}
fn minute(&self) -> Option<u8> {
if self.minute == MINUTE_RAW_NONE {
None
} else {
Some(self.minute)
}
}
fn second(&self) -> Option<u8> {
if self.second == SECOND_RAW_NONE {
None
} else {
Some(self.second)
}
}
}
impl Serializable for TimeOnly {
fn max_serialized_size() -> usize {
SERIALIZED_SIZE
}
fn serialized_size(&self) -> usize {
SERIALIZED_SIZE
}
fn serialize<W: Write>(&self, writer: &mut W) -> Result<usize, SerializationError> {
let b0 = TIME_TAG | self.hour >> 4;
let b1 = (self.hour << 4) | (self.minute >> 2);
let b2 = (self.minute << 6) | (self.second);
write_array_map_err(&[b0, b1, b2], writer)
.map_err(|_| SerializationError::IoError)
}
}
impl Deserializable for TimeOnly {
fn deserialize<R: Read>(reader: &mut R) -> Result<TimeOnly, DeserializationError> {
let mut buf = [0; SERIALIZED_SIZE];
read_exact(reader, &mut buf)?;
let byte0 = buf[0];
if byte0 & 0b1111_1110 != TIME_TAG {
return Err(DeserializationError::IncorrectTypeTag);
}
let mut raw_hour = byte0 << 4;
let byte1 = buf[1];
raw_hour |= (byte1 & 0xF0) >> 4;
let mut raw_minute = (byte1 & 0x0F) << 2;
let byte2 = buf[2];
raw_minute |= (byte2 & 0xC0) >> 6;
let raw_second = byte2 & 0x3F;
check_deser_in_range_or_none(raw_hour, HOUR_MIN, HOUR_MAX, HOUR_RAW_NONE)?;
check_deser_in_range_or_none(raw_minute, MINUTE_MIN, MINUTE_MAX, MINUTE_RAW_NONE)?;
check_deser_in_range_or_none(raw_second, SECOND_MIN, SECOND_MAX, SECOND_RAW_NONE)?;
Ok(TimeOnly {
hour: raw_hour,
minute: raw_minute,
second: raw_second
})
}
}
const SERIALIZED_SIZE: usize = 3;