Skip to content

Commit 98c1031

Browse files
committed
add new trait to encode values to bytes
still lots of TODOs
1 parent 817b373 commit 98c1031

File tree

10 files changed

+245
-117
lines changed

10 files changed

+245
-117
lines changed

heed-traits/src/lib.rs

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,80 @@
1212
use std::borrow::Cow;
1313
use std::cmp::{Ord, Ordering};
1414
use std::error::Error as StdError;
15+
use std::fmt;
1516

1617
/// A boxed `Send + Sync + 'static` error.
1718
pub type BoxedError = Box<dyn StdError + Send + Sync + 'static>;
1819

1920
/// A trait that represents an encoding structure.
20-
pub trait BytesEncode<'a> {
21+
#[deprecated = "replaced by `ToBytes` to allow for more optimization"]
22+
#[allow(deprecated)] // deprecated BoxedErrorWrapper is used in a bound
23+
pub trait BytesEncode<'a>:
24+
// TODO are these bound needed?
25+
ToBytes<'a, SelfType = Self::EItem, ReturnBytes = Cow<'a, [u8]>, Error = BoxedErrorWrapper>
26+
{
2127
/// The type to encode.
2228
type EItem: ?Sized + 'a;
2329

2430
/// Encode the given item as bytes.
2531
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<'a, [u8]>, BoxedError>;
2632
}
2733

34+
/// A trait that represents an encoding structure.
35+
pub trait ToBytes<'a> {
36+
/// The type to encode to bytes.
37+
type SelfType: ?Sized + 'a;
38+
39+
/// The type containing the encoded bytes.
40+
type ReturnBytes: Into<Vec<u8>> + AsRef<[u8]> + 'a;
41+
42+
/// The error type to return when decoding goes wrong.
43+
type Error: StdError + Send + Sync + 'static;
44+
45+
/// Encode the given item as bytes.
46+
fn to_bytes(item: &'a Self::SelfType) -> Result<Self::ReturnBytes, Self::Error>;
47+
}
48+
49+
#[allow(deprecated)]
50+
impl<'a, T: BytesEncode<'a>> ToBytes<'a> for T {
51+
type SelfType = <Self as BytesEncode<'a>>::EItem;
52+
53+
type ReturnBytes = Cow<'a, [u8]>;
54+
55+
type Error = BoxedErrorWrapper;
56+
57+
fn to_bytes(item: &'a Self::SelfType) -> Result<Self::ReturnBytes, Self::Error> {
58+
Self::bytes_encode(item).map_err(BoxedErrorWrapper)
59+
}
60+
}
61+
62+
/// Wraps the [`BoxedError`] type alias because for complicated reasons it does not implement
63+
/// [`Error`][StdError]. This wrapper forwards [`Debug`][fmt::Debug], [`Display`][fmt::Display]
64+
/// and [`Error`][StdError] through the wrapper and the [`Box`].
65+
#[deprecated = "this wrapper was added for backwards compatibility of BytesEncode only"]
66+
pub struct BoxedErrorWrapper(BoxedError);
67+
68+
#[allow(deprecated)]
69+
impl fmt::Debug for BoxedErrorWrapper {
70+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71+
<BoxedError as fmt::Debug>::fmt(&self.0, f)
72+
}
73+
}
74+
75+
#[allow(deprecated)]
76+
impl fmt::Display for BoxedErrorWrapper {
77+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78+
<BoxedError as fmt::Display>::fmt(&self.0, f)
79+
}
80+
}
81+
82+
#[allow(deprecated)]
83+
impl StdError for BoxedErrorWrapper {
84+
fn source(&self) -> Option<&(dyn StdError + 'static)> {
85+
self.0.source()
86+
}
87+
}
88+
2889
/// A trait that represents a decoding structure.
2990
pub trait BytesDecode<'a> {
3091
/// The type to decode.

heed-types/src/bytes.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1-
use std::borrow::Cow;
1+
use std::convert::Infallible;
22

3-
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
3+
use heed_traits::{BoxedError, BytesDecode, ToBytes};
44

55
/// Describes a byte slice `[u8]` that is totally borrowed and doesn't depend on
66
/// any [memory alignment].
77
///
88
/// [memory alignment]: std::mem::align_of()
99
pub enum Bytes {}
1010

11-
impl<'a> BytesEncode<'a> for Bytes {
12-
type EItem = [u8];
11+
impl<'a> ToBytes<'a> for Bytes {
12+
type SelfType = [u8];
1313

14-
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
15-
Ok(Cow::Borrowed(item))
14+
type ReturnBytes = &'a [u8];
15+
16+
type Error = Infallible;
17+
18+
fn to_bytes(item: &'a Self::SelfType) -> Result<Self::ReturnBytes, Self::Error> {
19+
Ok(item)
1620
}
1721
}
1822

@@ -23,3 +27,26 @@ impl<'a> BytesDecode<'a> for Bytes {
2327
Ok(bytes)
2428
}
2529
}
30+
31+
/// Like [`Bytes`], but always contains exactly `N` (the generic parameter) bytes.
32+
pub enum FixedSizeBytes<const N: usize> {}
33+
34+
impl<'a, const N: usize> ToBytes<'a> for FixedSizeBytes<N> {
35+
type SelfType = [u8; N];
36+
37+
type ReturnBytes = [u8; N]; // TODO &'a [u8; N] or [u8; N]
38+
39+
type Error = Infallible;
40+
41+
fn to_bytes(item: &'a Self::SelfType) -> Result<Self::ReturnBytes, Self::Error> {
42+
Ok(*item)
43+
}
44+
}
45+
46+
impl<'a, const N: usize> BytesDecode<'a> for FixedSizeBytes<N> {
47+
type DItem = [u8; N]; // TODO &'a [u8; N] or [u8; N]
48+
49+
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
50+
bytes.try_into().map_err(Into::into)
51+
}
52+
}

heed-types/src/integer.rs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1-
use std::borrow::Cow;
1+
use std::convert::Infallible;
22
use std::marker::PhantomData;
33
use std::mem::size_of;
44

55
use byteorder::{ByteOrder, ReadBytesExt};
6-
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
6+
use heed_traits::{BoxedError, BytesDecode, ToBytes};
77

88
/// Encodable version of [`u8`].
99
pub struct U8;
1010

11-
impl BytesEncode<'_> for U8 {
12-
type EItem = u8;
11+
impl ToBytes<'_> for U8 {
12+
type SelfType = u8;
1313

14-
fn bytes_encode(item: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
15-
Ok(Cow::from([*item].to_vec()))
14+
type ReturnBytes = [u8; 1];
15+
16+
type Error = Infallible;
17+
18+
fn to_bytes(item: &Self::SelfType) -> Result<Self::ReturnBytes, Self::Error> {
19+
Ok([*item])
1620
}
1721
}
1822

@@ -27,11 +31,15 @@ impl BytesDecode<'_> for U8 {
2731
/// Encodable version of [`i8`].
2832
pub struct I8;
2933

30-
impl BytesEncode<'_> for I8 {
31-
type EItem = i8;
34+
impl ToBytes<'_> for I8 {
35+
type SelfType = i8;
36+
37+
type ReturnBytes = [u8; 1];
3238

33-
fn bytes_encode(item: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
34-
Ok(Cow::from([*item as u8].to_vec()))
39+
type Error = Infallible;
40+
41+
fn to_bytes(item: &Self::SelfType) -> Result<Self::ReturnBytes, Self::Error> {
42+
Ok([*item as u8])
3543
}
3644
}
3745

@@ -51,13 +59,17 @@ macro_rules! define_type {
5159

5260
pub struct $name<O>(PhantomData<O>);
5361

54-
impl<O: ByteOrder> BytesEncode<'_> for $name<O> {
55-
type EItem = $native;
62+
impl<O: ByteOrder> ToBytes<'_> for $name<O> {
63+
type SelfType = $native;
64+
65+
type ReturnBytes = [u8; size_of::<$native>()];
66+
67+
type Error = Infallible;
5668

57-
fn bytes_encode(item: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
58-
let mut buf = vec![0; size_of::<Self::EItem>()];
69+
fn to_bytes(item: &Self::SelfType) -> Result<Self::ReturnBytes, Self::Error> {
70+
let mut buf = [0; size_of::<$native>()];
5971
O::$write_method(&mut buf, *item);
60-
Ok(Cow::from(buf))
72+
Ok(buf)
6173
}
6274
}
6375

heed-types/src/serde_bincode.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1-
use std::borrow::Cow;
2-
3-
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
1+
use heed_traits::{BoxedError, BytesDecode, ToBytes};
42
use serde::{Deserialize, Serialize};
53

64
/// Describes a type that is [`Serialize`]/[`Deserialize`] and uses `bincode` to do so.
75
///
86
/// It can borrow bytes from the original slice.
97
pub struct SerdeBincode<T>(std::marker::PhantomData<T>);
108

11-
impl<'a, T: 'a> BytesEncode<'a> for SerdeBincode<T>
9+
impl<'a, T: 'a> ToBytes<'a> for SerdeBincode<T>
1210
where
1311
T: Serialize,
1412
{
15-
type EItem = T;
13+
type SelfType = T;
14+
15+
type ReturnBytes = Vec<u8>;
16+
17+
type Error = bincode::Error;
1618

17-
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
18-
bincode::serialize(item).map(Cow::Owned).map_err(Into::into)
19+
fn to_bytes(item: &'a Self::SelfType) -> Result<Self::ReturnBytes, Self::Error> {
20+
bincode::serialize(item)
1921
}
2022
}
2123

heed-types/src/serde_json.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1-
use std::borrow::Cow;
2-
3-
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
1+
use heed_traits::{BoxedError, BytesDecode, ToBytes};
42
use serde::{Deserialize, Serialize};
53

64
/// Describes a type that is [`Serialize`]/[`Deserialize`] and uses `serde_json` to do so.
75
///
86
/// It can borrow bytes from the original slice.
97
pub struct SerdeJson<T>(std::marker::PhantomData<T>);
108

11-
impl<'a, T: 'a> BytesEncode<'a> for SerdeJson<T>
9+
impl<'a, T: 'a> ToBytes<'a> for SerdeJson<T>
1210
where
1311
T: Serialize,
1412
{
15-
type EItem = T;
13+
type SelfType = T;
14+
15+
type ReturnBytes = Vec<u8>;
16+
17+
type Error = serde_json::Error;
1618

17-
fn bytes_encode(item: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
18-
serde_json::to_vec(item).map(Cow::Owned).map_err(Into::into)
19+
fn to_bytes(item: &'a Self::SelfType) -> Result<Self::ReturnBytes, Self::Error> {
20+
serde_json::to_vec(item)
1921
}
2022
}
2123

heed-types/src/serde_rmp.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1-
use std::borrow::Cow;
2-
3-
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
1+
use heed_traits::{BoxedError, BytesDecode, ToBytes};
42
use serde::{Deserialize, Serialize};
53

64
/// Describes a type that is [`Serialize`]/[`Deserialize`] and uses `rmp_serde` to do so.
75
///
86
/// It can borrow bytes from the original slice.
97
pub struct SerdeRmp<T>(std::marker::PhantomData<T>);
108

11-
impl<'a, T: 'a> BytesEncode<'a> for SerdeRmp<T>
9+
impl<'a, T: 'a> ToBytes<'a> for SerdeRmp<T>
1210
where
1311
T: Serialize,
1412
{
15-
type EItem = T;
13+
type SelfType = T;
14+
15+
type ReturnBytes = Vec<u8>;
16+
17+
type Error = rmp_serde::encode::Error;
1618

17-
fn bytes_encode(item: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
18-
rmp_serde::to_vec(item).map(Cow::Owned).map_err(Into::into)
19+
fn to_bytes(item: &'a Self::SelfType) -> Result<Self::ReturnBytes, Self::Error> {
20+
rmp_serde::to_vec(item)
1921
}
2022
}
2123

heed-types/src/str.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
1-
use std::borrow::Cow;
2-
use std::str;
1+
use std::convert::Infallible;
32

4-
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
3+
use heed_traits::{BoxedError, BytesDecode, ToBytes};
54

6-
/// Describes a [`prim@str`].
5+
/// Describes a [`str`].
76
pub enum Str {}
87

9-
impl BytesEncode<'_> for Str {
10-
type EItem = str;
8+
impl<'a> ToBytes<'a> for Str {
9+
type SelfType = str;
1110

12-
fn bytes_encode(item: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
13-
Ok(Cow::Borrowed(item.as_bytes()))
11+
type ReturnBytes = &'a [u8];
12+
13+
type Error = Infallible;
14+
15+
fn to_bytes(item: &'a Self::SelfType) -> Result<Self::ReturnBytes, Self::Error> {
16+
Ok(item.as_bytes())
1417
}
1518
}
1619

1720
impl<'a> BytesDecode<'a> for Str {
1821
type DItem = &'a str;
1922

2023
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
21-
str::from_utf8(bytes).map_err(Into::into)
24+
std::str::from_utf8(bytes).map_err(Into::into)
2225
}
2326
}

heed-types/src/unit.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
use std::borrow::Cow;
1+
use std::convert::Infallible;
22
use std::{error, fmt};
33

4-
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
4+
use heed_traits::{BoxedError, BytesDecode, ToBytes};
55

66
/// Describes the unit `()` type.
77
pub enum Unit {}
88

9-
impl BytesEncode<'_> for Unit {
10-
type EItem = ();
9+
impl ToBytes<'_> for Unit {
10+
type SelfType = ();
1111

12-
fn bytes_encode(_item: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
13-
Ok(Cow::Borrowed(&[]))
12+
type ReturnBytes = [u8; 0];
13+
14+
type Error = Infallible;
15+
16+
fn to_bytes(_item: &'_ Self::SelfType) -> Result<Self::ReturnBytes, Self::Error> {
17+
Ok([])
1418
}
1519
}
1620

0 commit comments

Comments
 (0)