Skip to content

Commit

Permalink
Add support for msgpack deserialization
Browse files Browse the repository at this point in the history
  • Loading branch information
fasterthanlime committed Oct 6, 2024
1 parent d13ba63 commit 052fdef
Show file tree
Hide file tree
Showing 24 changed files with 1,036 additions and 169 deletions.
52 changes: 52 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
[workspace]
resolver = "2"
members = ["merde", "merde_json", "merde_time", "merde_core", "merde_yaml"]
exclude = ["zerodeps-example"]
members = [
"merde",
"merde_json",
"merde_time",
"merde_core",
"merde_yaml",
"merde_msgpack",
"merde_loggingserializer",
]
exclude = ["zerodeps-example", "merde_msgpack/testdata-maker"]
3 changes: 3 additions & 0 deletions merde/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ required-features = ["json", "ahash"]
merde_core = { version = "6.1.0", path = "../merde_core", optional = true }
merde_json = { version = "6.1.0", path = "../merde_json", optional = true }
merde_yaml = { version = "7.1.0", path = "../merde_yaml", optional = true }
merde_msgpack = { version = "7.1.0", path = "../merde_msgpack", optional = true }
merde_time = { version = "4.0.15", path = "../merde_time", optional = true, features = [
"merde",
"deserialize",
Expand All @@ -62,6 +63,7 @@ full = [
"deserialize",
"json",
"yaml",
"msgpack",
"time",
"rusqlite",
"compact_str",
Expand All @@ -76,6 +78,7 @@ rusqlite = ["merde_core/rusqlite"]
# non-core crates
json = ["dep:merde_json", "merde_time/json"]
yaml = ["dep:merde_yaml"]
msgpack = ["dep:merde_msgpack"]
time = ["dep:merde_time"]

# others
Expand Down
10 changes: 9 additions & 1 deletion merde_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,22 @@ categories = ["encoding", "parser-implementations"]

[dependencies]
compact_str = { version = "0.8.0", optional = true }
compact_bytes = { version = "0.1.3", optional = true }
ordered-float = "4.3.0"
rubicon = "3.4.9"
rusqlite = { version = "0.32.1", optional = true }
serde = { version = "1", optional = true }

[features]
default = []
full = ["compact_str", "serde", "rusqlite"]
full = [
# (1 per line)
"compact_str",
"compact_bytes",
"serde",
"rusqlite",
]
compact_str = ["dep:compact_str"]
compact_bytes = ["dep:compact_bytes"]
serde = ["dep:serde", "compact_str/serde"]
rusqlite = ["dep:rusqlite"]
154 changes: 154 additions & 0 deletions merde_core/src/cowbytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
use std::{
borrow::Cow,
fmt,
hash::{Hash, Hasher},
ops::Deref,
};

#[cfg(feature = "compact_bytes")]
use compact_bytes::CompactBytes;

use crate::IntoStatic;

/// A copy-on-write bytes type that uses [`CompactBytes`] for
/// the "owned" variant.
#[derive(Clone)]
pub enum CowBytes<'a> {
Borrowed(&'a [u8]),
#[cfg(feature = "compact_bytes")]
Owned(CompactBytes),
#[cfg(not(feature = "compact_bytes"))]
Owned(Vec<u8>),
}

impl<'a> CowBytes<'a> {
pub fn new(bytes: &'a [u8]) -> Self {
CowBytes::Borrowed(bytes)
}

pub fn into_owned(self) -> Vec<u8> {
match self {
CowBytes::Borrowed(b) => b.to_vec(),
#[cfg(feature = "compact_bytes")]
CowBytes::Owned(b) => b.to_vec(),
#[cfg(not(feature = "compact_bytes"))]
CowBytes::Owned(b) => b,
}
}
}

impl AsRef<[u8]> for CowBytes<'_> {
fn as_ref(&self) -> &[u8] {
match self {
CowBytes::Borrowed(b) => b,
CowBytes::Owned(b) => b.as_ref(),
}
}
}

impl Deref for CowBytes<'_> {
type Target = [u8];

fn deref(&self) -> &Self::Target {
self.as_ref()
}
}

impl<'a> From<&'a [u8]> for CowBytes<'a> {
fn from(b: &'a [u8]) -> Self {
CowBytes::Borrowed(b)
}
}

impl<'a> From<Vec<u8>> for CowBytes<'a> {
fn from(v: Vec<u8>) -> Self {
#[cfg(feature = "compact_bytes")]
{
CowBytes::Owned(CompactBytes::new(v))
}
#[cfg(not(feature = "compact_bytes"))]
{
CowBytes::Owned(v)
}
}
}

impl<'a> From<Cow<'a, [u8]>> for CowBytes<'a> {
fn from(cow: Cow<'a, [u8]>) -> Self {
match cow {
Cow::Borrowed(b) => CowBytes::Borrowed(b),
Cow::Owned(v) => v.into(),
}
}
}

impl<'a, 'b> PartialEq<CowBytes<'a>> for CowBytes<'b> {
fn eq(&self, other: &CowBytes<'a>) -> bool {
self.deref() == other.deref()
}
}

impl PartialEq<[u8]> for CowBytes<'_> {
fn eq(&self, other: &[u8]) -> bool {
self.deref() == other
}
}

impl PartialEq<CowBytes<'_>> for [u8] {
fn eq(&self, other: &CowBytes<'_>) -> bool {
self == other.deref()
}
}

impl Eq for CowBytes<'_> {}

impl Hash for CowBytes<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.deref().hash(state)
}
}

impl fmt::Debug for CowBytes<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.deref(), f)
}
}

impl IntoStatic for CowBytes<'_> {
type Output = CowBytes<'static>;

fn into_static(self) -> Self::Output {
match self {
#[cfg(feature = "compact_bytes")]
CowBytes::Borrowed(b) => CowBytes::Owned(CompactBytes::new(b)),
#[cfg(not(feature = "compact_bytes"))]
CowBytes::Borrowed(b) => CowBytes::Owned(b.to_vec()),
CowBytes::Owned(b) => CowBytes::Owned(b),
}
}
}

#[cfg(feature = "serde")]
mod serde_impls {
use super::*;
use serde::{Deserialize, Serialize};

impl Serialize for CowBytes<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_bytes(self)
}
}

impl<'de> Deserialize<'de> for CowBytes<'_> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let bytes = Vec::<u8>::deserialize(deserializer)?;
Ok(CowBytes::from(bytes))
}
}
}
Loading

0 comments on commit 052fdef

Please sign in to comment.