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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
use std::io::{Read, Write};
use std::io::ErrorKind;
pub trait Serializable {
fn max_serialized_size() -> usize;
fn serialized_size(&self) -> usize;
}
pub trait Date {
fn year(&self) -> Option<u16>;
fn month(&self) -> Option<u8>;
fn day(&self) -> Option<u8>;
}
pub trait Time {
fn hour(&self) -> Option<u8>;
fn minute(&self) -> Option<u8>;
fn second(&self) -> Option<u8>;
}
pub trait SubSecond {
fn fractional_second(&self) -> FractionalSecond;
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum FractionalSecond {
Milliseconds(u16),
Microseconds(u32),
Nanoseconds(u32),
None
}
pub trait Offset {
fn offset(&self) -> OffsetValue;
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum OffsetValue {
None,
SpecifiedElsewhere,
UtcOffset(i16)
}
mod date_only;
mod time_only;
mod date_time;
mod date_time_offset;
mod date_time_subsecond;
mod date_time_subsecond_offset;
pub use date_only::DateOnly;
pub use time_only::TimeOnly;
pub use date_time::DateTime;
pub use date_time_offset::DateTimeOffset;
pub use date_time_subsecond::DateTimeSubSecond;
pub use date_time_subsecond_offset::DateTimeSubSecondOffset;
#[derive(Debug, PartialEq, Eq)]
pub enum DeserializationError {
IoError(ErrorKind),
IncorrectTypeTag,
IncorrectPrecisionTag
}
#[derive(Debug, PartialEq, Eq)]
pub enum SerializationError {
InvalidFieldValue(TemporalField),
IoError
}
#[derive(Debug, PartialEq, Eq)]
pub enum TemporalField {
Year,
Month,
Day,
Hour,
Minute,
Second,
FractionalSecond,
Offset
}
enum TypeTag {
DateOnly,
TimeOnly,
DateTime,
DateTimeOffset,
DateTimeSubSecond,
DateTimeSubSecondOffset
}
impl TypeTag {
fn matches(&self, byte: u8) -> bool {
let top_three_bits = 0b1110_0000;
let top_two_bits = 0b1100_0000;
let top_seven_bits = 0b1111_1110;
match self {
&TypeTag::DateOnly => byte & top_three_bits == DATE_TAG,
&TypeTag::TimeOnly => byte & top_seven_bits == TIME_TAG,
&TypeTag::DateTime => byte & top_two_bits == DATE_TIME_TAG,
&TypeTag::DateTimeOffset => byte & top_three_bits == DATE_TIME_OFFSET_TAG,
&TypeTag::DateTimeSubSecond => byte & top_two_bits == DATE_TIME_SUBSECOND_TAG,
&TypeTag::DateTimeSubSecondOffset => byte & top_three_bits == DATE_TIME_SUBSECOND_OFFSET_TAG
}
}
}
#[derive(Debug, PartialEq, Eq)]
enum PrecisionTag {
Milli,
Micro,
Nano,
None
}
pub const YEAR_MIN: u16 = 0;
pub const YEAR_MAX: u16 = 4094;
pub const MONTH_MIN: u8 = 1;
pub const MONTH_MAX: u8 = 12;
pub const DAY_MIN: u8 = 1;
pub const DAY_MAX: u8 = 31;
pub const HOUR_MIN: u8 = 0;
pub const HOUR_MAX: u8 = 23;
pub const MINUTE_MIN: u8 = 0;
pub const MINUTE_MAX: u8 = 59;
pub const SECOND_MIN: u8 = 0;
pub const SECOND_MAX: u8 = 60;
pub const MILLIS_MIN: u16 = 0;
pub const MILLIS_MAX: u16 = 999;
pub const MICROS_MIN: u32 = 0;
pub const MICROS_MAX: u32 = 999_999;
pub const NANOS_MIN: u32 = 0;
pub const NANOS_MAX: u32 = 999_999_999;
pub const OFFSET_MIN: i16 = -(64 * 15);
pub const OFFSET_MAX: i16 = (125 - 64) * 15;
const DATE_TAG: u8 = 0b1000_0000;
const TIME_TAG: u8 = 0b1010_0000;
const DATE_TIME_TAG: u8 = 0b0000_0000;
const DATE_TIME_OFFSET_TAG: u8 = 0b1100_0000;
const DATE_TIME_SUBSECOND_TAG: u8 = 0b0100_0000;
const DATE_TIME_SUBSECOND_OFFSET_TAG: u8 = 0b1110_0000;
const PRECISION_DTS_MASK: u8 = 0b0011_0000;
const PRECISION_DTS_MILLIS_TAG: u8 = 0x0;
const PRECISION_DTS_MICROS_TAG: u8 = 0b0001_0000;
const PRECISION_DTS_NANOS_TAG: u8 = 0b0010_0000;
const PRECISION_DTS_NONE_TAG: u8 = 0b0011_0000;
const PRECISION_DTSO_MASK: u8 = PRECISION_DTS_MASK >> 1;
const PRECISION_DTSO_MILLIS_TAG: u8 = PRECISION_DTS_MILLIS_TAG >> 1;
const PRECISION_DTSO_MICROS_TAG: u8 = PRECISION_DTS_MICROS_TAG >> 1;
const PRECISION_DTSO_NANOS_TAG: u8 = PRECISION_DTS_NANOS_TAG >> 1;
const PRECISION_DTSO_NONE_TAG: u8 = PRECISION_DTS_NONE_TAG >> 1;
const YEAR_RAW_NONE: u16 = 4095;
const MONTH_RAW_NONE: u8 = 15;
const DAY_RAW_NONE: u8 = 31;
const HOUR_RAW_NONE: u8 = 31;
const MINUTE_RAW_NONE: u8 = 63;
const SECOND_RAW_NONE: u8 = 63;
const OFFSET_RAW_NONE: u8 = 127;
const OFFSET_RAW_ELSEWHERE: u8 = 126;
fn read_exact<R: Read>(reader: &mut R, buf: &mut [u8]) -> Result<(), DeserializationError> {
reader.read_exact(buf).map_err(|e| DeserializationError::IoError(e.kind()))
}
fn write_array_map_err<W: Write>(bytes: &[u8], writer: &mut W) -> Result<usize, SerializationError> {
writer.write_all(bytes).map_err(|_| SerializationError::IoError).map(|_| bytes.len())
}
fn check_option_outside_range<T: PartialOrd>(val: Option<T>, min: T, max: T, field: TemporalField)
-> Result<(), SerializationError> {
if let Some(v) = val {
return check_outside_range(v, min, max, field);
}
Ok(())
}
fn check_outside_range<T: PartialOrd>(v: T, min: T, max: T, field: TemporalField)
-> Result<(), SerializationError> {
if v < min || v > max {
return Err(SerializationError::InvalidFieldValue(field))
}
Ok(())
}
#[inline]
fn encode_offset_num(offset: OffsetValue) -> Result<u8, SerializationError> {
match offset {
OffsetValue::None => Ok(OFFSET_RAW_NONE),
OffsetValue::SpecifiedElsewhere => Ok(OFFSET_RAW_ELSEWHERE),
OffsetValue::UtcOffset(o) => {
check_outside_range(o, OFFSET_MIN, OFFSET_MAX, TemporalField::Offset)?;
if o % 15 != 0 {
return Err(SerializationError::InvalidFieldValue(TemporalField::Offset));
};
Ok(((o / 15) + 64) as u8)
}
}
}