Skip to content

Commit

Permalink
use convert from
Browse files Browse the repository at this point in the history
  • Loading branch information
vnghia committed Sep 20, 2024
1 parent c1ef658 commit 4a2b32f
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 65 deletions.
37 changes: 36 additions & 1 deletion src/derive/datetime.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use bytemuck::CheckedBitPattern;

use super::Decode;
use super::{
convert::{ConvertFrom, ConvertIntoEncoder},
Decode, Encode,
};

/// A u8 guaranteed to be < 24.
#[derive(Copy, Clone)]
Expand All @@ -14,6 +17,14 @@ unsafe impl CheckedBitPattern for Hour {
*bits < 24
}
}
impl ConvertFrom<&Hour> for u8 {
fn convert_from(value: &Hour) -> Self {
value.0
}
}
impl Encode for Hour {
type Encoder = ConvertIntoEncoder<u8>;
}
impl<'a> Decode<'a> for Hour {
type Decoder = crate::int::CheckedIntDecoder<'a, Hour, u8>;
}
Expand All @@ -30,6 +41,14 @@ unsafe impl CheckedBitPattern for Minute {
*bits < 60
}
}
impl ConvertFrom<&Minute> for u8 {
fn convert_from(value: &Minute) -> Self {
value.0
}
}
impl Encode for Minute {
type Encoder = ConvertIntoEncoder<u8>;
}
impl<'a> Decode<'a> for Minute {
type Decoder = crate::int::CheckedIntDecoder<'a, Minute, u8>;
}
Expand All @@ -46,6 +65,14 @@ unsafe impl CheckedBitPattern for Second {
*bits < 60
}
}
impl ConvertFrom<&Second> for u8 {
fn convert_from(value: &Second) -> Self {
value.0
}
}
impl Encode for Second {
type Encoder = ConvertIntoEncoder<u8>;
}
impl<'a> Decode<'a> for Second {
type Decoder = crate::int::CheckedIntDecoder<'a, Second, u8>;
}
Expand All @@ -62,6 +89,14 @@ unsafe impl CheckedBitPattern for Nanoseconds {
*bits < 1_000_000_000
}
}
impl ConvertFrom<&Nanoseconds> for u32 {
fn convert_from(value: &Nanoseconds) -> Self {
value.0
}
}
impl Encode for Nanoseconds {
type Encoder = ConvertIntoEncoder<u32>;
}
impl<'a> Decode<'a> for Nanoseconds {
type Decoder = crate::int::CheckedIntDecoder<'a, Nanoseconds, u32>;
}
10 changes: 10 additions & 0 deletions src/derive/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,16 @@ impl<'a, T> Decode<'a> for PhantomData<T> {
type Decoder = EmptyCoder;
}

#[cfg(feature = "time")]
mod with_time {
use crate::convert::impl_convert;
use crate::datetime::{Hour, Minute, Nanoseconds, Second};
use crate::derive::{Decode, Encode};
use time::Time;

impl_convert!(Time, (Hour, Minute, Second, Nanoseconds));
}

macro_rules! impl_tuples {
($(($($n:tt $name:ident)*))+) => {
$(
Expand Down
81 changes: 17 additions & 64 deletions src/ext/time_crate/time.rs
Original file line number Diff line number Diff line change
@@ -1,82 +1,35 @@
use crate::coder::{Buffer, Decoder, Encoder, Result, View};
use crate::convert::ConvertFrom;
use crate::datetime::{Hour, Minute, Nanoseconds, Second};
use crate::{Decode, Encode};
use alloc::vec::Vec;
use core::num::NonZeroUsize;
use time::Time;

#[derive(Default)]
pub struct TimeEncoder {
hour: <u8 as Encode>::Encoder,
minute: <u8 as Encode>::Encoder,
second: <u8 as Encode>::Encoder,
nanosecond: <u32 as Encode>::Encoder,
}
impl Encoder<Time> for TimeEncoder {
#[inline(always)]
fn encode(&mut self, t: &Time) {
let (hour, minute, second, nanosecond) = t.as_hms_nano();
self.hour.encode(&hour);
self.minute.encode(&minute);
self.second.encode(&second);
self.nanosecond.encode(&nanosecond);
}
}
impl Buffer for TimeEncoder {
fn collect_into(&mut self, out: &mut Vec<u8>) {
self.hour.collect_into(out);
self.minute.collect_into(out);
self.second.collect_into(out);
self.nanosecond.collect_into(out);
}

fn reserve(&mut self, additional: NonZeroUsize) {
self.hour.reserve(additional);
self.minute.reserve(additional);
self.second.reserve(additional);
self.nanosecond.reserve(additional);
impl ConvertFrom<&Time> for (Hour, Minute, Second, Nanoseconds) {
fn convert_from(value: &Time) -> Self {
let (hour, minute, second, nanosecond) = value.as_hms_nano();
(
Hour(hour),
Minute(minute),
Second(second),
Nanoseconds(nanosecond),
)
}
}
impl Encode for Time {
type Encoder = TimeEncoder;
}

#[derive(Default)]
pub struct TimeDecoder<'a> {
hour: <Hour as Decode<'a>>::Decoder,
minute: <Minute as Decode<'a>>::Decoder,
second: <Second as Decode<'a>>::Decoder,
nanosecond: <Nanoseconds as Decode<'a>>::Decoder,
}
impl<'a> View<'a> for TimeDecoder<'a> {
fn populate(&mut self, input: &mut &'a [u8], length: usize) -> Result<()> {
self.hour.populate(input, length)?;
self.minute.populate(input, length)?;
self.second.populate(input, length)?;
self.nanosecond.populate(input, length)?;
Ok(())
}
}
impl<'a> Decoder<'a, Time> for TimeDecoder<'a> {
#[inline(always)]
fn decode(&mut self) -> Time {
let Hour(hour) = self.hour.decode();
let Minute(minute) = self.minute.decode();
let Second(second) = self.second.decode();
let Nanoseconds(nanosecond) = self.nanosecond.decode();
impl ConvertFrom<(Hour, Minute, Second, Nanoseconds)> for Time {
fn convert_from(value: (Hour, Minute, Second, Nanoseconds)) -> Self {
let (Hour(hour), Minute(minute), Second(second), Nanoseconds(nanosecond)) = value;
// Safety: should not fail because all input values are validated with CheckedBitPattern.
unsafe { Time::from_hms_nano(hour, minute, second, nanosecond).unwrap_unchecked() }
}
}
impl<'a> Decode<'a> for Time {
type Decoder = TimeDecoder<'a>;
}

#[cfg(test)]
mod tests {
#[test]
fn test() {
assert!(crate::decode::<Time>(&crate::encode(&(23, 59, 59, 999_999_999))).is_ok());
assert!(crate::decode::<Time>(&crate::encode(
&Time::from_hms_nano(23, 59, 59, 999_999_999).unwrap()
))
.is_ok());
assert!(crate::decode::<Time>(&crate::encode(&(24, 59, 59, 999_999_999))).is_err());
assert!(crate::decode::<Time>(&crate::encode(&(23, 60, 59, 999_999_999))).is_err());
assert!(crate::decode::<Time>(&crate::encode(&(23, 59, 60, 999_999_999))).is_err());
Expand Down

0 comments on commit 4a2b32f

Please sign in to comment.