Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for uuid::Uuid #34

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ bitcode_derive = { version = "0.6.3", path = "./bitcode_derive", optional = true
bytemuck = { version = "1.14", features = [ "min_const_generics", "must_cast" ] }
glam = { version = ">=0.21", default-features = false, optional = true }
serde = { version = "1.0", default-features = false, features = [ "alloc" ], optional = true }
uuid = { version = "1.10", default-features = false, optional = true }

[dev-dependencies]
arrayvec = { version = "0.7", features = [ "serde" ] }
Expand All @@ -30,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]
Expand All @@ -39,6 +41,7 @@ zstd = "0.13.0"
derive = [ "dep:bitcode_derive" ]
std = [ "serde?/std", "glam?/std", "arrayvec?/std" ]
default = [ "derive", "std" ]
uuid = [ "dep:uuid" ]

[package.metadata.docs.rs]
features = [ "derive", "serde", "std" ]
Expand Down
56 changes: 56 additions & 0 deletions src/derive/convert_from.rs
Original file line number Diff line number Diff line change
@@ -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<T>: Sized {
fn convert_from(value: T) -> Self;
}

pub struct ConvertIntoEncoder<T: Encode>(T::Encoder);

// Can't derive since it would bound T: Default.
impl<T: Encode> Default for ConvertIntoEncoder<T> {
fn default() -> Self {
Self(Default::default())
}
}

impl<D, T: Encode + for<'a> ConvertFrom<&'a D>> Encoder<D> for ConvertIntoEncoder<T> {
#[inline(always)]
fn encode(&mut self, t: &D) {
self.0.encode(&T::convert_from(t));
}
}

impl<T: Encode> Buffer for ConvertIntoEncoder<T> {
fn collect_into(&mut self, out: &mut Vec<u8>) {
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>, T: Decode<'a>> Decoder<'a, F> for ConvertFromDecoder<'a, T> {
#[inline(always)]
fn decode(&mut self) -> F {
F::convert_from(self.0.decode())
}
}
7 changes: 5 additions & 2 deletions src/derive/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,10 @@ impl<'a, T: Decode<'a>, E: Decode<'a>> Decode<'a> for core::result::Result<T, E>
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>;
}
};
}
Expand Down Expand Up @@ -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<T> Encode for PhantomData<T> {
type Encoder = EmptyCoder;
}
Expand Down
57 changes: 1 addition & 56 deletions src/derive/ip_addr.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -94,56 +92,3 @@ impl ConvertFrom<SocketAddrConversion> for SocketAddr {
}
}
}

// Like [`From`] but we can implement it ourselves.
pub(crate) trait ConvertFrom<T>: Sized {
fn convert_from(value: T) -> Self;
}

pub struct ConvertIntoEncoder<T: Encode>(T::Encoder);

// Can't derive since it would bound T: Default.
impl<T: Encode> Default for ConvertIntoEncoder<T> {
fn default() -> Self {
Self(Default::default())
}
}

impl<D, T: Encode + for<'a> ConvertFrom<&'a D>> Encoder<D> for ConvertIntoEncoder<T> {
#[inline(always)]
fn encode(&mut self, t: &D) {
self.0.encode(&T::convert_from(t));
}
}

impl<T: Encode> Buffer for ConvertIntoEncoder<T> {
fn collect_into(&mut self, out: &mut Vec<u8>) {
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>, T: Decode<'a>> Decoder<'a, F> for ConvertFromDecoder<'a, T> {
#[inline(always)]
fn decode(&mut self) -> F {
F::convert_from(self.0.decode())
}
}
5 changes: 5 additions & 0 deletions src/derive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use alloc::vec::Vec;
use core::num::NonZeroUsize;

mod array;
mod convert_from;
mod duration;
mod empty;
mod impls;
Expand All @@ -16,6 +17,8 @@ mod map;
mod option;
mod result;
mod smart_ptr;
#[cfg(feature = "uuid")]
mod uuid;
mod variant;
pub(crate) mod vec;

Expand Down Expand Up @@ -136,6 +139,8 @@ mod tests {
test!([0, 1, 2], [u8; 3]);
test!([0, -1, 0, -1, 0, -1, 0], [i8; 7]);
test!([], [u8; 0]);
#[cfg(feature = "uuid")]
test!(uuid::Uuid::new_v4(), uuid::Uuid);
}

#[derive(Encode, Decode)]
Expand Down
34 changes: 34 additions & 0 deletions src/derive/uuid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use uuid::Uuid;

use super::convert_from::ConvertFrom;

impl ConvertFrom<&Uuid> for u128 {
fn convert_from(value: &Uuid) -> Self {
value.as_u128()
}
}

impl ConvertFrom<u128> for Uuid {
fn convert_from(value: u128) -> Self {
Uuid::from_u128(value)
}
}

#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use uuid::Uuid;

#[test]
fn test() {
assert!(crate::decode::<Uuid>(&crate::encode(&Uuid::new_v4())).is_ok());
}

fn bench_data() -> Vec<Uuid> {
crate::random_data(1000)
.into_iter()
.map(|n: u128| Uuid::from_u128(n))
.collect()
}
crate::bench_encode_decode!(uuid_vec: Vec<_>);
}
Loading