Trait bonsaidb::core::key::Key

pub trait Key<'k>: KeyEncoding<Self> + Clone + Send + Sync {
    const CAN_OWN_BYTES: bool;

    // Required method
    fn from_ord_bytes<'e>(
        bytes: ByteSource<'k, 'e>
    ) -> Result<Self, Self::Error>;

    // Provided methods
    fn first_value() -> Result<Self, NextValueError> { ... }
    fn next_value(&self) -> Result<Self, NextValueError> { ... }
}
Expand description

A trait that enables a type to convert itself into a memcmp-compatible sequence of bytes.

Deriving this trait

This trait can be derived on structs and enums whose members all implement Key. It is important to note that the order of individual fields and enum variants is important, so special care must be taken when updating enums and structs when trying to preserve backwards compatibility with existing data.

use bonsaidb_core::key::Key;

#[derive(Key, Clone, Debug)]
struct CompositeKey {
    user_id: u64,
    task_id: u32,
}

Each field or enum variant is encoded and decoded in the order in which it appears in the source code. The implementation uses CompositeKeyEncoder and CompositeKeyDecoder to encode each field.

Changing the enum representation type

By default, the derived Key implementation will use an isize for its representation, which is encoded using ordered_varint. If you wish to use a fixed-size encoding or use usize, enum_repr can be used to control the type being encoded.

The default behavior produces compact output for simple enums, but can also support growing to the limits of isize:

use bonsaidb_core::key::{Key, KeyEncoding};

#[derive(Key, Clone, Debug)]
enum Color {
    Red,
    Green,
    Blue,
}

let encoded = Color::Red.as_ord_bytes().unwrap();
assert_eq!(encoded.len(), 1);

If a #[repr(...)] attribute exists and its parameter is a built-in integer type, the Key derive will use that type for its representation instead:

use bonsaidb_core::key::{Key, KeyEncoding};

#[derive(Key, Clone, Debug)]
#[repr(u32)]
enum Color {
    Red = 0xFF0000FF,
    Green = 0x00FF00FF,
    Blue = 0x0000FFFF,
}

let encoded = Color::Red.as_ord_bytes().unwrap();
assert_eq!(encoded.len(), 4);

If the type would rather use a different type for the key encoding than it uses for in-memory representation, the enum_repr parameter can be used:

use bonsaidb_core::key::{Key, KeyEncoding};

#[derive(Key, Clone, Debug)]
#[key(enum_repr = u32)]
#[repr(usize)]
enum Color {
    Red = 0xFF0000FF,
    Green = 0x00FF00FF,
    Blue = 0x0000FFFF,
}

let encoded = Color::Red.as_ord_bytes().unwrap();
assert_eq!(encoded.len(), 4);

null_handling

The derive macro offers an argument null_handling, which defaults to escape. Escaping null bytes in variable length fields ensures all data encoded will sort correctly. In situations where speed is more important than sorting behavior, allow or deny can be specified. allow will permit null bytes to pass through encoding and decoding without being checked. deny will check for null bytes when encoding and return an error if any are present.

Null bytes can cause problematic sort behavior when multiple variable-length encoded fields are encoded as a composite key. Consider this example:

use bonsaidb_core::key::Key;

#[derive(Key, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
#[key(null_handling = allow)]
struct CompositeKey {
    a: String,
    b: String,
}

With this structure, we can cause sorting misbehaviors using this data set:

abEncoded Bytes
"a""c"6100 6300 0101
"a\0b""a"6100 6200 610003 01
"b""a"6200 6100 0101

In this table, a and b are ordered as CompositeKey would be ordered when compared using Ord. However, the order of the encoded bytes does not match.

This null-byte edge case only applies to variable length Keys (KeyEncoding::LENGTH is None).

Required Associated Constants§

const CAN_OWN_BYTES: bool

If true, this type can benefit from an owned Vec<u8>. This flag is used as a hint of whether to attempt to do memcpy operations in some decoding operations to avoid extra allocations.

Required Methods§

fn from_ord_bytes<'e>(bytes: ByteSource<'k, 'e>) -> Result<Self, Self::Error>

Deserialize a sequence of bytes previously encoded with KeyEncoding::as_ord_bytes.

Provided Methods§

fn first_value() -> Result<Self, NextValueError>

Return the first value in sequence for this type. Not all types implement this.

fn next_value(&self) -> Result<Self, NextValueError>

Return the next value in sequence for this type. Not all types implement this. Instead of wrapping/overflowing, None should be returned.

Implementations on Foreign Types§

§

impl<'k> Key<'k> for Cow<'k, str>

§

const CAN_OWN_BYTES: bool = true

§

fn from_ord_bytes<'e>( bytes: ByteSource<'k, 'e> ) -> Result<Cow<'k, str>, <Cow<'k, str> as KeyEncoding<Cow<'k, str>>>::Error>

§

impl<'k> Key<'k> for NonZeroU32

§

impl<'k> Key<'k> for NonZeroI128

§

impl<'k> Key<'k> for Duration

§

impl<'k> Key<'k> for i16

§

impl<'k> Key<'k> for isize

§

impl<'k> Key<'k> for NonZeroI32

§

impl<'k> Key<'k> for Cow<'k, [u8]>

§

const CAN_OWN_BYTES: bool = true

§

fn from_ord_bytes<'e>( bytes: ByteSource<'k, 'e> ) -> Result<Cow<'k, [u8]>, <Cow<'k, [u8]> as KeyEncoding<Cow<'k, [u8]>>>::Error>

§

impl<'k, T1, T2, T3> Key<'k> for (T1, T2, T3)where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>,

§

impl<'k, T1, T2, T3, T4, T5> Key<'k> for (T1, T2, T3, T4, T5)where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>, T4: for<'ke> Key<'ke>, T5: for<'ke> Key<'ke>,

§

impl<'k> Key<'k> for ()

§

const CAN_OWN_BYTES: bool = false

§

fn from_ord_bytes<'b>( _: ByteSource<'k, 'b> ) -> Result<(), <() as KeyEncoding<()>>::Error>

§

impl<'k, T1, T2, T3, T4> Key<'k> for (T1, T2, T3, T4)where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>, T4: for<'ke> Key<'ke>,

§

impl<'k> Key<'k> for String

§

const CAN_OWN_BYTES: bool = true

§

fn from_ord_bytes<'b>( bytes: ByteSource<'k, 'b> ) -> Result<String, <String as KeyEncoding<String>>::Error>

§

impl<'k, T1> Key<'k> for (T1,)where T1: for<'ke> Key<'ke>,

§

const CAN_OWN_BYTES: bool = false

§

fn from_ord_bytes<'e>( bytes: ByteSource<'k, 'e> ) -> Result<(T1,), <(T1,) as KeyEncoding<(T1,)>>::Error>

§

impl<'k, T> Key<'k> for Option<T>where T: Key<'k>, Option<T>: KeyEncoding<Option<T>, Error = <T as KeyEncoding<T>>::Error>,

§

const CAN_OWN_BYTES: bool = T::CAN_OWN_BYTES

§

fn from_ord_bytes<'e>( bytes: ByteSource<'k, 'e> ) -> Result<Option<T>, <Option<T> as KeyEncoding<Option<T>>>::Error>

§

fn first_value() -> Result<Option<T>, NextValueError>

§

fn next_value(&self) -> Result<Option<T>, NextValueError>

§

impl<'k> Key<'k> for NonZeroI8

§

impl<'k> Key<'k> for u16

§

impl<'k> Key<'k> for u32

§

impl<'k, T1, T2> Key<'k> for (T1, T2)where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>,

§

impl<'k> Key<'k> for SystemTime

§

impl<'k, const N: usize> Key<'k> for [u8; N]

§

const CAN_OWN_BYTES: bool = false

§

fn from_ord_bytes<'e>( bytes: ByteSource<'k, 'e> ) -> Result<[u8; N], <[u8; N] as KeyEncoding<[u8; N]>>::Error>

§

impl<'k> Key<'k> for bool

§

const CAN_OWN_BYTES: bool = false

§

fn from_ord_bytes<'b>( bytes: ByteSource<'k, 'b> ) -> Result<bool, <bool as KeyEncoding<bool>>::Error>

§

impl<'k> Key<'k> for NonZeroIsize

§

impl<'k, T, E> Key<'k> for Result<T, E>where T: Key<'k>, E: Key<'k, Error = <T as KeyEncoding<T>>::Error>, Result<T, E>: KeyEncoding<Result<T, E>, Error = <T as KeyEncoding<T>>::Error>,

§

const CAN_OWN_BYTES: bool = T::CAN_OWN_BYTES || E::CAN_OWN_BYTES

§

fn from_ord_bytes<'b>( bytes: ByteSource<'k, 'b> ) -> Result<Result<T, E>, <Result<T, E> as KeyEncoding<Result<T, E>>>::Error>

§

fn first_value() -> Result<Result<T, E>, NextValueError>

§

fn next_value(&self) -> Result<Result<T, E>, NextValueError>

§

impl<'k> Key<'k> for usize

§

impl<'k, T1, T2, T3, T4, T5, T6, T7, T8> Key<'k> for (T1, T2, T3, T4, T5, T6, T7, T8)where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>, T4: for<'ke> Key<'ke>, T5: for<'ke> Key<'ke>, T6: for<'ke> Key<'ke>, T7: for<'ke> Key<'ke>, T8: for<'ke> Key<'ke>,

§

impl<'k> Key<'k> for i32

§

impl<'k> Key<'k> for u8

§

impl<'k> Key<'k> for NonZeroUsize

§

impl<'k> Key<'k> for i8

§

impl<'k> Key<'k> for NonZeroU16

§

impl<'k> Key<'k> for i64

§

impl<'k> Key<'k> for u128

§

impl<'k> Key<'k> for NonZeroI16

§

impl<'k> Key<'k> for Uuid

§

const CAN_OWN_BYTES: bool = false

§

fn from_ord_bytes<'e>( bytes: ByteSource<'k, 'e> ) -> Result<Uuid, <Uuid as KeyEncoding<Uuid>>::Error>

§

impl<'k> Key<'k> for NonZeroU128

§

impl<'k> Key<'k> for NonZeroU8

§

impl<'k> Key<'k> for u64

§

impl<'k, T1, T2, T3, T4, T5, T6, T7> Key<'k> for (T1, T2, T3, T4, T5, T6, T7)where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>, T4: for<'ke> Key<'ke>, T5: for<'ke> Key<'ke>, T6: for<'ke> Key<'ke>, T7: for<'ke> Key<'ke>,

§

impl<'k, T1, T2, T3, T4, T5, T6> Key<'k> for (T1, T2, T3, T4, T5, T6)where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>, T4: for<'ke> Key<'ke>, T5: for<'ke> Key<'ke>, T6: for<'ke> Key<'ke>,

§

impl<'k> Key<'k> for NonZeroU64

§

impl<'k> Key<'k> for NonZeroI64

§

impl<'k> Key<'k> for i128

§

impl<'k> Key<'k> for Vec<u8, Global>

§

const CAN_OWN_BYTES: bool = true

§

fn from_ord_bytes<'e>( bytes: ByteSource<'k, 'e> ) -> Result<Vec<u8, Global>, <Vec<u8, Global> as KeyEncoding<Vec<u8, Global>>>::Error>

Implementors§

§

impl<'a, 'k, TOwned, TBorrowed> Key<'k> for MaybeOwned<'a, TOwned, TBorrowed>where TBorrowed: KeyEncoding<TOwned, Error = <TOwned as KeyEncoding<TOwned>>::Error> + PartialEq<TBorrowed> + ?Sized, TOwned: Key<'k> + PartialEq<TBorrowed>,

§

const CAN_OWN_BYTES: bool = TOwned::CAN_OWN_BYTES

§

impl<'k> Key<'k> for Bytes

§

const CAN_OWN_BYTES: bool = true

§

impl<'k> Key<'k> for CowBytes<'k>

§

const CAN_OWN_BYTES: bool = true

§

impl<'k> Key<'k> for ArcBytes<'k>

§

const CAN_OWN_BYTES: bool = true

§

impl<'k> Key<'k> for SensitiveBytes

§

const CAN_OWN_BYTES: bool = true

§

impl<'k> Key<'k> for SensitiveString

§

const CAN_OWN_BYTES: bool = true

§

impl<'k> Key<'k> for DocumentId

§

const CAN_OWN_BYTES: bool = false

§

impl<'k> Key<'k> for Timestamp

§

const CAN_OWN_BYTES: bool = false

§

impl<'k> Key<'k> for Signed

§

const CAN_OWN_BYTES: bool = false

§

impl<'k> Key<'k> for Unsigned

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, Resolution> Key<'k> for LimitedResolutionDuration<Resolution>where Resolution: TimeResolution,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, Resolution, Epoch> Key<'k> for LimitedResolutionTimestamp<Resolution, Epoch>where Resolution: TimeResolution, Epoch: TimeEpoch,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, T1> Key<'k> for TupleEncodingV1<(T1,)>where T1: for<'ke> Key<'ke>,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, T1, T2> Key<'k> for TupleEncodingV1<(T1, T2)>where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, T1, T2, T3> Key<'k> for TupleEncodingV1<(T1, T2, T3)>where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, T1, T2, T3, T4> Key<'k> for TupleEncodingV1<(T1, T2, T3, T4)>where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>, T4: for<'ke> Key<'ke>,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, T1, T2, T3, T4, T5> Key<'k> for TupleEncodingV1<(T1, T2, T3, T4, T5)>where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>, T4: for<'ke> Key<'ke>, T5: for<'ke> Key<'ke>,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, T1, T2, T3, T4, T5, T6> Key<'k> for TupleEncodingV1<(T1, T2, T3, T4, T5, T6)>where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>, T4: for<'ke> Key<'ke>, T5: for<'ke> Key<'ke>, T6: for<'ke> Key<'ke>,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, T1, T2, T3, T4, T5, T6, T7> Key<'k> for TupleEncodingV1<(T1, T2, T3, T4, T5, T6, T7)>where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>, T4: for<'ke> Key<'ke>, T5: for<'ke> Key<'ke>, T6: for<'ke> Key<'ke>, T7: for<'ke> Key<'ke>,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, T1, T2, T3, T4, T5, T6, T7, T8> Key<'k> for TupleEncodingV1<(T1, T2, T3, T4, T5, T6, T7, T8)>where T1: for<'ke> Key<'ke>, T2: for<'ke> Key<'ke>, T3: for<'ke> Key<'ke>, T4: for<'ke> Key<'ke>, T5: for<'ke> Key<'ke>, T6: for<'ke> Key<'ke>, T7: for<'ke> Key<'ke>, T8: for<'ke> Key<'ke>,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, T> Key<'k> for EnumKey<T>where T: ToPrimitive + FromPrimitive + Clone + Eq + Ord + Debug + Send + Sync,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, T> Key<'k> for OptionKeyV1<T>where T: Key<'k>, OptionKeyV1<T>: KeyEncoding<OptionKeyV1<T>, Error = <T as KeyEncoding<T>>::Error>,

§

const CAN_OWN_BYTES: bool = false

§

impl<'k, T> Key<'k> for VarInt<T>where T: VariableInteger,

§

const CAN_OWN_BYTES: bool = false