Trait bonsaidb::core::key::Key

source ·
pub trait Key<'k>: KeyEncoding + 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§

source

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§

source

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§

source

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

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

source

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.

Object Safety§

This trait is not object safe.

Implementations on Foreign Types§

source§

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

source§

const CAN_OWN_BYTES: bool = true

source§

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

source§

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

source§

const CAN_OWN_BYTES: bool = true

source§

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

source§

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

source§

const CAN_OWN_BYTES: bool = false

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

const CAN_OWN_BYTES: bool = true

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

const CAN_OWN_BYTES: bool = false

source§

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

source§

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

source§

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

source§

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>,

source§

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>,

source§

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>,

source§

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>,

source§

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>,

source§

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>,

source§

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

source§

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

source§

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

source§

const CAN_OWN_BYTES: bool = false

source§

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

Implementors§

source§

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

source§

const CAN_OWN_BYTES: bool = TOwned::CAN_OWN_BYTES

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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

source§

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>,

source§

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>,

source§

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>,

source§

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>,

source§

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>,

source§

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>,

source§

impl<'k, T> Key<'k> for EnumKey<T>

source§

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

source§

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