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

Serialises UUID as [u8:16] #331

Merged
merged 8 commits into from
Oct 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ version = "0.6"
optional = true
version = "2"

[dev-dependencies]
serde_derive = "1.0.79"

[dev-dependencies.serde_test]
version = "1.0.56"

Expand Down
117 changes: 117 additions & 0 deletions src/adapter/compact.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//! Module for use with `#[serde(with = "...")]` to serialize a [`Uuid`]
//! as a `[u8; 16]
//!
//! [`Uuid`]: ../../struct.Uuid.html

use serde::de::{self, Error, SeqAccess};
use serde::ser::SerializeTuple;
use serde::{Deserializer, Serializer};

use prelude::*;

use std::fmt;

/// Serializer for a [`Uuid`] into a `[u8; 16]`
///
/// [`Uuid`]: ../../struct.Uuid.html
pub fn serialize<S: Serializer>(
u: &Uuid,
serializer: S,
) -> Result<S::Ok, S::Error> {
let mut seq = serializer.serialize_tuple(16)?;

for byte in u.as_bytes() {
seq.serialize_element(byte)?;
}

seq.end()
}

/// Deserializer from a `[u8; 16]` into a [`Uuid`]
///
/// [`Uuid`]: ../../struct.Uuid.html
pub fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Uuid, D::Error> {
struct DenseUuidBytesVisitor;
Dylan-DPC-zz marked this conversation as resolved.
Show resolved Hide resolved

impl<'vi> de::Visitor<'vi> for DenseUuidBytesVisitor {
type Value = Uuid;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "tuple")
}

fn visit_seq<A: SeqAccess<'vi>>(
self,
mut seq: A,
) -> Result<Self::Value, A::Error> {
if seq.size_hint() == Some(16) {
let mut buf = [0; 16];
for i in 0..16 {
buf[i] = seq.next_element().unwrap().unwrap()
}
Ok(Uuid::from_bytes(buf))
} else {
Err(Error::custom("Uuid must be 16 bytes long"))
}
}
}

deserializer.deserialize_tuple(16, DenseUuidBytesVisitor)
}

#[cfg(test)]
mod tests {
use serde_test;

use prelude::*;

#[derive(Serialize, Debug, Deserialize, PartialEq)]
struct UuidContainer {
#[serde(with = "super")]
u: Uuid,
}

#[test]
fn test_serialize_compact() {
use serde_test::Configure;

let uuid_bytes = b"F9168C5E-CEB2-4F";
let container = UuidContainer {
u: Uuid::from_slice(uuid_bytes).unwrap(),
};

// more complex because of the struct wrapping the actual UUID
// serialization
serde_test::assert_tokens(
&container.compact(),
&[
serde_test::Token::Struct {
name: "UuidContainer",
len: 1,
},
serde_test::Token::Str("u"),
serde_test::Token::Tuple { len: 16 },
serde_test::Token::U8(uuid_bytes[0]),
serde_test::Token::U8(uuid_bytes[1]),
serde_test::Token::U8(uuid_bytes[2]),
serde_test::Token::U8(uuid_bytes[3]),
serde_test::Token::U8(uuid_bytes[4]),
serde_test::Token::U8(uuid_bytes[5]),
serde_test::Token::U8(uuid_bytes[6]),
serde_test::Token::U8(uuid_bytes[7]),
serde_test::Token::U8(uuid_bytes[8]),
serde_test::Token::U8(uuid_bytes[9]),
serde_test::Token::U8(uuid_bytes[10]),
serde_test::Token::U8(uuid_bytes[11]),
serde_test::Token::U8(uuid_bytes[12]),
serde_test::Token::U8(uuid_bytes[13]),
serde_test::Token::U8(uuid_bytes[14]),
serde_test::Token::U8(uuid_bytes[15]),
serde_test::Token::TupleEnd,
serde_test::Token::StructEnd,
],
)
}
}
3 changes: 3 additions & 0 deletions src/adapter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ use prelude::*;

mod core_support;

#[cfg(feature = "serde")]
pub mod compact;

/// An adaptor for formatting an [`Uuid`] as a hyphenated string.
///
/// Takes an owned instance of the [`Uuid`].
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ extern crate rand;
extern crate serde;
#[cfg(all(feature = "serde", test))]
extern crate serde_test;
#[cfg(all(feature = "serde", test))]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "sha1")]
extern crate sha1;
#[cfg(feature = "slog")]
Expand Down
6 changes: 4 additions & 2 deletions src/serde_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use core::fmt;
use prelude::*;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

#[cfg(feature = "serde")]
impl Serialize for Uuid {
fn serialize<S: Serializer>(
&self,
Expand All @@ -27,6 +28,7 @@ impl Serialize for Uuid {
}
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Uuid {
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
Expand Down Expand Up @@ -86,8 +88,8 @@ impl<'de> Deserialize<'de> for Uuid {
}
}

#[cfg(test)]
mod tests {
#[cfg(all(test, feature = "serde"))]
mod serde_tests {
use serde_test;

use prelude::*;
Expand Down