Skip to content

Commit 39f360e

Browse files
committed
Compute an error when encoding/decoding in bytes
1 parent ba079e2 commit 39f360e

19 files changed

+190
-183
lines changed

heed-traits/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
use std::borrow::Cow;
2+
use std::error::Error as StdError;
3+
4+
/// A boxed `Send + Sync + 'static` error.
5+
pub type BoxedError = Box<dyn StdError + Send + Sync + 'static>;
26

37
pub trait BytesEncode<'a> {
48
type EItem: ?Sized + 'a;
59

6-
fn bytes_encode(item: &'a Self::EItem) -> Option<Cow<'a, [u8]>>;
10+
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<'a, [u8]>, BoxedError>;
711
}
812

913
pub trait BytesDecode<'a> {
1014
type DItem: 'a;
1115

12-
fn bytes_decode(bytes: &'a [u8]) -> Option<Self::DItem>;
16+
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError>;
1317
}

heed-types/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ edition = "2018"
1010

1111
[dependencies]
1212
bincode = { version = "1.2.1", optional = true }
13-
bytemuck = { version = "1.5.0", features = ["extern_crate_alloc"] }
13+
bytemuck = { version = "1.5.0", features = ["extern_crate_alloc", "extern_crate_std"] }
1414
byteorder = "1.4.2"
1515
heed-traits = { version = "0.7.0", path = "../heed-traits" }
1616
serde = { version = "1.0.117", optional = true }

heed-types/src/cow_slice.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::borrow::Cow;
22

33
use bytemuck::{pod_collect_to_vec, try_cast_slice, AnyBitPattern, NoUninit, PodCastError};
4-
use heed_traits::{BytesDecode, BytesEncode};
4+
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
55

66
/// Describes a slice that must be [memory aligned] and
77
/// will be reallocated if it is not.
@@ -23,19 +23,19 @@ pub struct CowSlice<T>(std::marker::PhantomData<T>);
2323
impl<'a, T: NoUninit> BytesEncode<'a> for CowSlice<T> {
2424
type EItem = [T];
2525

26-
fn bytes_encode(item: &'a Self::EItem) -> Option<Cow<[u8]>> {
27-
try_cast_slice(item).map(Cow::Borrowed).ok()
26+
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
27+
try_cast_slice(item).map(Cow::Borrowed).map_err(Into::into)
2828
}
2929
}
3030

3131
impl<'a, T: AnyBitPattern + NoUninit> BytesDecode<'a> for CowSlice<T> {
3232
type DItem = Cow<'a, [T]>;
3333

34-
fn bytes_decode(bytes: &'a [u8]) -> Option<Self::DItem> {
34+
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
3535
match try_cast_slice(bytes) {
36-
Ok(items) => Some(Cow::Borrowed(items)),
37-
Err(PodCastError::AlignmentMismatch) => Some(Cow::Owned(pod_collect_to_vec(bytes))),
38-
Err(_) => None,
36+
Ok(items) => Ok(Cow::Borrowed(items)),
37+
Err(PodCastError::AlignmentMismatch) => Ok(Cow::Owned(pod_collect_to_vec(bytes))),
38+
Err(error) => Err(error.into()),
3939
}
4040
}
4141
}

heed-types/src/cow_type.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::borrow::Cow;
22

33
use bytemuck::{bytes_of, bytes_of_mut, try_from_bytes, AnyBitPattern, NoUninit, PodCastError};
4-
use heed_traits::{BytesDecode, BytesEncode};
4+
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
55

66
/// Describes a type that must be [memory aligned] and
77
/// will be reallocated if it is not.
@@ -29,23 +29,23 @@ pub struct CowType<T>(std::marker::PhantomData<T>);
2929
impl<'a, T: NoUninit> BytesEncode<'a> for CowType<T> {
3030
type EItem = T;
3131

32-
fn bytes_encode(item: &'a Self::EItem) -> Option<Cow<[u8]>> {
33-
Some(Cow::Borrowed(bytes_of(item)))
32+
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
33+
Ok(Cow::Borrowed(bytes_of(item)))
3434
}
3535
}
3636

3737
impl<'a, T: AnyBitPattern + NoUninit> BytesDecode<'a> for CowType<T> {
3838
type DItem = Cow<'a, T>;
3939

40-
fn bytes_decode(bytes: &'a [u8]) -> Option<Self::DItem> {
40+
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
4141
match try_from_bytes(bytes) {
42-
Ok(item) => Some(Cow::Borrowed(item)),
42+
Ok(item) => Ok(Cow::Borrowed(item)),
4343
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) => {
4444
let mut item = T::zeroed();
4545
bytes_of_mut(&mut item).copy_from_slice(bytes);
46-
Some(Cow::Owned(item))
46+
Ok(Cow::Owned(item))
4747
}
48-
Err(_) => None,
48+
Err(error) => Err(error.into()),
4949
}
5050
}
5151
}

heed-types/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ mod serde_bincode;
3737
#[cfg(feature = "serde-json")]
3838
mod serde_json;
3939

40+
use heed_traits::BoxedError;
41+
4042
pub use self::cow_slice::CowSlice;
4143
pub use self::cow_type::CowType;
4244
pub use self::integer::*;
@@ -62,8 +64,8 @@ pub struct DecodeIgnore;
6264
impl heed_traits::BytesDecode<'_> for DecodeIgnore {
6365
type DItem = ();
6466

65-
fn bytes_decode(_bytes: &[u8]) -> Option<Self::DItem> {
66-
Some(())
67+
fn bytes_decode(_bytes: &[u8]) -> Result<Self::DItem, BoxedError> {
68+
Ok(())
6769
}
6870
}
6971

heed-types/src/owned_slice.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::borrow::Cow;
22

33
use bytemuck::{try_cast_slice, AnyBitPattern, NoUninit};
4-
use heed_traits::{BytesDecode, BytesEncode};
4+
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
55

66
use crate::CowSlice;
77

@@ -23,15 +23,15 @@ pub struct OwnedSlice<T>(std::marker::PhantomData<T>);
2323
impl<'a, T: NoUninit> BytesEncode<'a> for OwnedSlice<T> {
2424
type EItem = [T];
2525

26-
fn bytes_encode(item: &'a Self::EItem) -> Option<Cow<[u8]>> {
27-
try_cast_slice(item).map(Cow::Borrowed).ok()
26+
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
27+
try_cast_slice(item).map(Cow::Borrowed).map_err(Into::into)
2828
}
2929
}
3030

3131
impl<'a, T: AnyBitPattern + NoUninit> BytesDecode<'a> for OwnedSlice<T> {
3232
type DItem = Vec<T>;
3333

34-
fn bytes_decode(bytes: &[u8]) -> Option<Self::DItem> {
34+
fn bytes_decode(bytes: &[u8]) -> Result<Self::DItem, BoxedError> {
3535
CowSlice::<T>::bytes_decode(bytes).map(Cow::into_owned)
3636
}
3737
}

heed-types/src/owned_type.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::borrow::Cow;
22

33
use bytemuck::{bytes_of, AnyBitPattern, NoUninit};
4-
use heed_traits::{BytesDecode, BytesEncode};
4+
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
55

66
use crate::CowType;
77

@@ -29,15 +29,15 @@ pub struct OwnedType<T>(std::marker::PhantomData<T>);
2929
impl<'a, T: NoUninit> BytesEncode<'a> for OwnedType<T> {
3030
type EItem = T;
3131

32-
fn bytes_encode(item: &'a Self::EItem) -> Option<Cow<[u8]>> {
33-
Some(Cow::Borrowed(bytes_of(item)))
32+
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
33+
Ok(Cow::Borrowed(bytes_of(item)))
3434
}
3535
}
3636

3737
impl<'a, T: AnyBitPattern + NoUninit> BytesDecode<'a> for OwnedType<T> {
3838
type DItem = T;
3939

40-
fn bytes_decode(bytes: &[u8]) -> Option<Self::DItem> {
40+
fn bytes_decode(bytes: &[u8]) -> Result<Self::DItem, BoxedError> {
4141
CowType::<T>::bytes_decode(bytes).map(Cow::into_owned)
4242
}
4343
}

heed-types/src/serde_bincode.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::borrow::Cow;
22

3-
use heed_traits::{BytesDecode, BytesEncode};
3+
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
44
use serde::{Deserialize, Serialize};
55

66
/// Describes a type that is [`Serialize`]/[`Deserialize`] and uses `bincode` to do so.
@@ -14,8 +14,8 @@ where
1414
{
1515
type EItem = T;
1616

17-
fn bytes_encode(item: &'a Self::EItem) -> Option<Cow<[u8]>> {
18-
bincode::serialize(item).map(Cow::Owned).ok()
17+
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
18+
bincode::serialize(item).map(Cow::Owned).map_err(Into::into)
1919
}
2020
}
2121

@@ -25,8 +25,8 @@ where
2525
{
2626
type DItem = T;
2727

28-
fn bytes_decode(bytes: &'a [u8]) -> Option<Self::DItem> {
29-
bincode::deserialize(bytes).ok()
28+
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
29+
bincode::deserialize(bytes).map_err(Into::into)
3030
}
3131
}
3232

heed-types/src/serde_json.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::borrow::Cow;
22

3-
use heed_traits::{BytesDecode, BytesEncode};
3+
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
44
use serde::{Deserialize, Serialize};
55

66
/// Describes a type that is [`Serialize`]/[`Deserialize`] and uses `serde_json` to do so.
@@ -14,8 +14,8 @@ where
1414
{
1515
type EItem = T;
1616

17-
fn bytes_encode(item: &Self::EItem) -> Option<Cow<[u8]>> {
18-
serde_json::to_vec(item).map(Cow::Owned).ok()
17+
fn bytes_encode(item: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
18+
serde_json::to_vec(item).map(Cow::Owned).map_err(Into::into)
1919
}
2020
}
2121

@@ -25,8 +25,8 @@ where
2525
{
2626
type DItem = T;
2727

28-
fn bytes_decode(bytes: &'a [u8]) -> Option<Self::DItem> {
29-
serde_json::from_slice(bytes).ok()
28+
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
29+
serde_json::from_slice(bytes).map_err(Into::into)
3030
}
3131
}
3232

heed-types/src/str.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
use std::borrow::Cow;
22

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

55
/// Describes an [`prim@str`].
66
pub struct Str;
77

88
impl BytesEncode<'_> for Str {
99
type EItem = str;
1010

11-
fn bytes_encode(item: &Self::EItem) -> Option<Cow<[u8]>> {
12-
Some(Cow::Borrowed(item.as_bytes()))
11+
fn bytes_encode(item: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
12+
Ok(Cow::Borrowed(item.as_bytes()))
1313
}
1414
}
1515

1616
impl<'a> BytesDecode<'a> for Str {
1717
type DItem = &'a str;
1818

19-
fn bytes_decode(bytes: &'a [u8]) -> Option<Self::DItem> {
20-
std::str::from_utf8(bytes).ok()
19+
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
20+
std::str::from_utf8(bytes).map_err(Into::into)
2121
}
2222
}

heed-types/src/unaligned_slice.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::borrow::Cow;
22

33
use bytemuck::{try_cast_slice, AnyBitPattern, NoUninit};
4-
use heed_traits::{BytesDecode, BytesEncode};
4+
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
55

66
/// Describes a type that is totally borrowed and doesn't
77
/// depends on any [memory alignment].
@@ -16,16 +16,16 @@ pub struct UnalignedSlice<T>(std::marker::PhantomData<T>);
1616
impl<'a, T: NoUninit> BytesEncode<'a> for UnalignedSlice<T> {
1717
type EItem = [T];
1818

19-
fn bytes_encode(item: &'a Self::EItem) -> Option<Cow<[u8]>> {
20-
try_cast_slice(item).map(Cow::Borrowed).ok()
19+
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
20+
try_cast_slice(item).map(Cow::Borrowed).map_err(Into::into)
2121
}
2222
}
2323

2424
impl<'a, T: AnyBitPattern> BytesDecode<'a> for UnalignedSlice<T> {
2525
type DItem = &'a [T];
2626

27-
fn bytes_decode(bytes: &'a [u8]) -> Option<Self::DItem> {
28-
try_cast_slice(bytes).ok()
27+
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
28+
try_cast_slice(bytes).map_err(Into::into)
2929
}
3030
}
3131

heed-types/src/unaligned_type.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::borrow::Cow;
22

33
use bytemuck::{bytes_of, try_from_bytes, AnyBitPattern, NoUninit};
4-
use heed_traits::{BytesDecode, BytesEncode};
4+
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
55

66
/// Describes a slice that is totally borrowed and doesn't
77
/// depends on any [memory alignment].
@@ -22,16 +22,16 @@ pub struct UnalignedType<T>(std::marker::PhantomData<T>);
2222
impl<'a, T: NoUninit> BytesEncode<'a> for UnalignedType<T> {
2323
type EItem = T;
2424

25-
fn bytes_encode(item: &'a Self::EItem) -> Option<Cow<[u8]>> {
26-
Some(Cow::Borrowed(bytes_of(item)))
25+
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
26+
Ok(Cow::Borrowed(bytes_of(item)))
2727
}
2828
}
2929

3030
impl<'a, T: AnyBitPattern> BytesDecode<'a> for UnalignedType<T> {
3131
type DItem = &'a T;
3232

33-
fn bytes_decode(bytes: &'a [u8]) -> Option<Self::DItem> {
34-
try_from_bytes(bytes).ok()
33+
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
34+
try_from_bytes(bytes).map_err(Into::into)
3535
}
3636
}
3737

heed-types/src/unit.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
use std::borrow::Cow;
22

3-
use heed_traits::{BytesDecode, BytesEncode};
3+
use bytemuck::PodCastError;
4+
use heed_traits::{BoxedError, BytesDecode, BytesEncode};
45

56
/// Describes the `()` type.
67
pub struct Unit;
78

89
impl BytesEncode<'_> for Unit {
910
type EItem = ();
1011

11-
fn bytes_encode(_item: &Self::EItem) -> Option<Cow<[u8]>> {
12-
Some(Cow::Borrowed(&[]))
12+
fn bytes_encode(_item: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
13+
Ok(Cow::Borrowed(&[]))
1314
}
1415
}
1516

1617
impl BytesDecode<'_> for Unit {
1718
type DItem = ();
1819

19-
fn bytes_decode(bytes: &[u8]) -> Option<Self::DItem> {
20+
fn bytes_decode(bytes: &[u8]) -> Result<Self::DItem, BoxedError> {
2021
if bytes.is_empty() {
21-
Some(())
22+
Ok(())
2223
} else {
23-
None
24+
Err(PodCastError::SizeMismatch.into())
2425
}
2526
}
2627
}

0 commit comments

Comments
 (0)