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:
a | b | Encoded 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 Key
s
(KeyEncoding::LENGTH
is None
).
Required Associated Constants§
const CAN_OWN_BYTES: bool
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>
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>
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>
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.