1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//! The module contains the traits for encoding and decoding the types(a.k.a Codec).
//! It implements common codecs and encoders, but it is always possible to define own codecs.

use crate::kv_store::Value;
use std::{
    borrow::Cow,
    ops::Deref,
};

pub mod manual;
pub mod postcard;
pub mod primitive;
pub mod raw;

/// The trait is usually implemented by the encoder that stores serialized objects.
pub trait Encoder {
    /// Returns the serialized object as a slice.
    fn as_bytes(&self) -> Cow<[u8]>;
}

/// The trait encodes the type to the bytes and passes it to the `Encoder`,
/// which stores it and provides a reference to it. That allows gives more
/// flexibility and more performant encoding, allowing the use of slices and arrays
/// instead of vectors in some cases. Since the [`Encoder`] returns `Cow<[u8]>`,
/// it is always possible to take ownership of the serialized value.
pub trait Encode<T: ?Sized> {
    /// The encoder type that stores serialized object.
    type Encoder<'a>: Encoder
    where
        T: 'a;

    /// Encodes the object to the bytes and passes it to the `Encoder`.
    fn encode(t: &T) -> Self::Encoder<'_>;

    /// Returns the serialized object as an [`Value`].
    fn encode_as_value(t: &T) -> Value {
        Value::new(Self::encode(t).as_bytes().into_owned())
    }
}

/// The trait decodes the type from the bytes.
pub trait Decode<T> {
    /// Decodes the type `T` from the bytes.
    fn decode(bytes: &[u8]) -> anyhow::Result<T>;

    /// Decodes the type `T` from the [`Value`].
    fn decode_from_value(value: Value) -> anyhow::Result<T> {
        Self::decode(value.deref())
    }
}

impl<'a> Encoder for Cow<'a, [u8]> {
    fn as_bytes(&self) -> Cow<[u8]> {
        match self {
            Cow::Borrowed(borrowed) => Cow::Borrowed(borrowed),
            Cow::Owned(owned) => Cow::Borrowed(owned.as_ref()),
        }
    }
}

impl<const SIZE: usize> Encoder for [u8; SIZE] {
    fn as_bytes(&self) -> Cow<[u8]> {
        Cow::Borrowed(self.as_slice())
    }
}