From 008b6efc6a8135fc6402f25e61b428d8aaac8cf4 Mon Sep 17 00:00:00 2001 From: Vo Van Nghia Date: Fri, 13 Sep 2024 01:59:23 +0200 Subject: [PATCH] use convert_from for uuid --- Cargo.toml | 1 + src/derive/convert_from.rs | 56 +++++++++++++++++++++++++++++++++++++ src/derive/impls.rs | 7 +++-- src/derive/ip_addr.rs | 57 +------------------------------------- src/derive/mod.rs | 6 ++-- src/derive/uuid.rs | 54 ++++++------------------------------ 6 files changed, 74 insertions(+), 107 deletions(-) create mode 100644 src/derive/convert_from.rs diff --git a/Cargo.toml b/Cargo.toml index 65f4ff7..a7c3912 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ paste = "1.0.14" rand = "0.8.5" rand_chacha = "0.3.1" serde = { version = "1.0", features = [ "derive" ] } +uuid ={ version = "1.10", features = [ "v4" ]} # zstd doesn't compile with miri big-endian. [target.'cfg(not(miri))'.dev-dependencies] diff --git a/src/derive/convert_from.rs b/src/derive/convert_from.rs new file mode 100644 index 0000000..9f41aab --- /dev/null +++ b/src/derive/convert_from.rs @@ -0,0 +1,56 @@ +use crate::coder::{Buffer, Decoder, Encoder, Result, View}; +use crate::derive::{Decode, Encode}; +use core::num::NonZeroUsize; + +// Like [`From`] but we can implement it ourselves. +pub(crate) trait ConvertFrom: Sized { + fn convert_from(value: T) -> Self; +} + +pub struct ConvertIntoEncoder(T::Encoder); + +// Can't derive since it would bound T: Default. +impl Default for ConvertIntoEncoder { + fn default() -> Self { + Self(Default::default()) + } +} + +impl ConvertFrom<&'a D>> Encoder for ConvertIntoEncoder { + #[inline(always)] + fn encode(&mut self, t: &D) { + self.0.encode(&T::convert_from(t)); + } +} + +impl Buffer for ConvertIntoEncoder { + fn collect_into(&mut self, out: &mut Vec) { + self.0.collect_into(out); + } + fn reserve(&mut self, additional: NonZeroUsize) { + self.0.reserve(additional); + } +} + +/// Decodes a `T` and then converts it with [`ConvertFrom`]. +pub struct ConvertFromDecoder<'a, T: Decode<'a>>(T::Decoder); + +// Can't derive since it would bound T: Default. +impl<'a, T: Decode<'a>> Default for ConvertFromDecoder<'a, T> { + fn default() -> Self { + Self(Default::default()) + } +} + +impl<'a, T: Decode<'a>> View<'a> for ConvertFromDecoder<'a, T> { + fn populate(&mut self, input: &mut &'a [u8], length: usize) -> Result<()> { + self.0.populate(input, length) + } +} + +impl<'a, F: ConvertFrom, T: Decode<'a>> Decoder<'a, F> for ConvertFromDecoder<'a, T> { + #[inline(always)] + fn decode(&mut self) -> F { + F::convert_from(self.0.decode()) + } +} diff --git a/src/derive/impls.rs b/src/derive/impls.rs index 81a3b4c..f17c2e6 100644 --- a/src/derive/impls.rs +++ b/src/derive/impls.rs @@ -187,10 +187,10 @@ impl<'a, T: Decode<'a>, E: Decode<'a>> Decode<'a> for core::result::Result macro_rules! impl_convert { ($want: path, $have: ty) => { impl Encode for $want { - type Encoder = super::ip_addr::ConvertIntoEncoder<$have>; + type Encoder = super::convert_from::ConvertIntoEncoder<$have>; } impl<'a> Decode<'a> for $want { - type Decoder = super::ip_addr::ConvertFromDecoder<'a, $have>; + type Decoder = super::convert_from::ConvertFromDecoder<'a, $have>; } }; } @@ -221,6 +221,9 @@ impl_convert!( #[cfg(feature = "std")] impl_convert!(std::net::SocketAddr, super::ip_addr::SocketAddrConversion); +#[cfg(feature = "uuid")] +impl_convert!(uuid::Uuid, u128); + impl Encode for PhantomData { type Encoder = EmptyCoder; } diff --git a/src/derive/ip_addr.rs b/src/derive/ip_addr.rs index ff359f9..947a4a7 100644 --- a/src/derive/ip_addr.rs +++ b/src/derive/ip_addr.rs @@ -1,6 +1,4 @@ -use crate::coder::{Buffer, Decoder, Encoder, Result, View}; -use crate::derive::{Decode, Encode}; -use core::num::NonZeroUsize; +use super::convert_from::ConvertFrom; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; macro_rules! ipvx_addr { @@ -94,56 +92,3 @@ impl ConvertFrom for SocketAddr { } } } - -// Like [`From`] but we can implement it ourselves. -pub(crate) trait ConvertFrom: Sized { - fn convert_from(value: T) -> Self; -} - -pub struct ConvertIntoEncoder(T::Encoder); - -// Can't derive since it would bound T: Default. -impl Default for ConvertIntoEncoder { - fn default() -> Self { - Self(Default::default()) - } -} - -impl ConvertFrom<&'a D>> Encoder for ConvertIntoEncoder { - #[inline(always)] - fn encode(&mut self, t: &D) { - self.0.encode(&T::convert_from(t)); - } -} - -impl Buffer for ConvertIntoEncoder { - fn collect_into(&mut self, out: &mut Vec) { - self.0.collect_into(out); - } - fn reserve(&mut self, additional: NonZeroUsize) { - self.0.reserve(additional); - } -} - -/// Decodes a `T` and then converts it with [`ConvertFrom`]. -pub struct ConvertFromDecoder<'a, T: Decode<'a>>(T::Decoder); - -// Can't derive since it would bound T: Default. -impl<'a, T: Decode<'a>> Default for ConvertFromDecoder<'a, T> { - fn default() -> Self { - Self(Default::default()) - } -} - -impl<'a, T: Decode<'a>> View<'a> for ConvertFromDecoder<'a, T> { - fn populate(&mut self, input: &mut &'a [u8], length: usize) -> Result<()> { - self.0.populate(input, length) - } -} - -impl<'a, F: ConvertFrom, T: Decode<'a>> Decoder<'a, F> for ConvertFromDecoder<'a, T> { - #[inline(always)] - fn decode(&mut self) -> F { - F::convert_from(self.0.decode()) - } -} diff --git a/src/derive/mod.rs b/src/derive/mod.rs index 9e9e6ac..e340505 100644 --- a/src/derive/mod.rs +++ b/src/derive/mod.rs @@ -5,6 +5,7 @@ use alloc::vec::Vec; use core::num::NonZeroUsize; mod array; +mod convert_from; mod duration; mod empty; mod impls; @@ -139,10 +140,7 @@ mod tests { test!([0, -1, 0, -1, 0, -1, 0], [i8; 7]); test!([], [u8; 0]); #[cfg(feature = "uuid")] - test!( - uuid::uuid!("d1660702-561b-48e7-add0-c222143ca13c"), - uuid::Uuid - ); + test!(uuid::Uuid::new_v4(), uuid::Uuid); } #[derive(Encode, Decode)] diff --git a/src/derive/uuid.rs b/src/derive/uuid.rs index 0ddb695..64a16a3 100644 --- a/src/derive/uuid.rs +++ b/src/derive/uuid.rs @@ -1,63 +1,27 @@ -use crate::coder::{Buffer, Decoder, Encoder, Result, View}; -use crate::derive::{Decode, Encode}; -use core::num::NonZeroUsize; use uuid::Uuid; -#[derive(Default)] -pub struct UuidEncoder(::Encoder); +use super::convert_from::ConvertFrom; -impl Encoder for UuidEncoder { - #[inline(always)] - fn encode(&mut self, t: &Uuid) { - self.0.encode(&t.as_u128()); +impl ConvertFrom<&Uuid> for u128 { + fn convert_from(value: &Uuid) -> Self { + value.as_u128() } } -impl Buffer for UuidEncoder { - fn collect_into(&mut self, out: &mut Vec) { - self.0.collect_into(out); +impl ConvertFrom for Uuid { + fn convert_from(value: u128) -> Self { + Uuid::from_u128(value) } - - fn reserve(&mut self, additional: NonZeroUsize) { - self.0.reserve(additional); - } -} - -impl Encode for Uuid { - type Encoder = UuidEncoder; -} - -#[derive(Default)] -pub struct UuidDecoder<'a>(>::Decoder); - -impl<'a> View<'a> for UuidDecoder<'a> { - fn populate(&mut self, input: &mut &'a [u8], length: usize) -> Result<()> { - self.0.populate(input, length) - } -} - -impl<'a> Decoder<'a, Uuid> for UuidDecoder<'a> { - #[inline(always)] - fn decode(&mut self) -> Uuid { - Uuid::from_u128(self.0.decode()) - } -} - -impl<'a> Decode<'a> for Uuid { - type Decoder = UuidDecoder<'a>; } #[cfg(test)] mod tests { use alloc::vec::Vec; - use uuid::{uuid, Uuid}; + use uuid::Uuid; #[test] fn test() { - assert!(crate::decode::(&crate::encode(&uuid!( - "d1660702-561b-48e7-add0-c222143ca13c" - ))) - .is_ok()); + assert!(crate::decode::(&crate::encode(&Uuid::new_v4())).is_ok()); } fn bench_data() -> Vec {