DBKey Macros
The db-key macros generate a structure that can used as a fixed-size key for a key-value database. Both macros take a prototype (or definition) structure and create a tuple struture wrapped around an array.
use db_key;
let key = new;
assert_eq!;
assert_eq!;
assert_eq!;
Currently, the data types that can be used in the definition structure are
limited to unsigned integers (except usize), and arrays of u8. The key data
is always packed and lexographically ordered so that the definition structure
and the key structure will have the same order when sorted.
There are two DBKey macros supplied by this crate: an attribute macro
(#[db_key]) and a derive macro (DBKey). They each provide similar
functionality of creating a fixed-length key type for key-value databases that
use a slice of bytes as the key. The generated code is documented with
examples.
For clarification the definition structure is the struture used to define the key, the key struture is the tuple structure wrapping an array, and the argument struture provides an easy way to define a key from the individual components.
# use db_key;
// Definition struture:
// The generated key struture:
;
// The (generated) argument struture:
The attribute macro consumes the definition structure and generates both a key struture and an argument structure. The derive macro only generates a key struture and the definition struture can be used an the argument struture.
With the attribute macro, the name of the definition structure is used for the
key structure and the argument structure uses the definition structure name
with Args appended to the end. With the derive macro, the definition
structure becomes the argument structure, and the key structure is given the
name of the definition structure with Key appended to the end.
| Macro Type | Definition Name | Key Struct Name | Argument Struct Name |
|---|---|---|---|
| Attribute | ExampleKey | ExampleKey | ExampleKeyArgs |
| Derive | Example | ExampleKey | Example |
The key options for the attribute macro are defined in the attribute macro call.
# use db_key;
The key options for the derive macro are defined in a separate key attribute
macro.
# use DBKey;
The key struture always derives Clone, Hash, PartialEq, Eq,
PartialOrd, and Ord. If the size of the key is 64-bytes or less, than it
also derives Copy as well. A custom Debug implementation is supplied for
the key structure. For the attribute macro, the argument structure has all the
same derived implementations except Hash and it uses the standard derived
Debug.
Since the attribute macro replaces the definition structure, it is more permissive about the data that is allowed in the definition strucure.
# use db_key;
Since the derive macro uses the definition structure as the argument structure, it is more restrictive about what is expected.
# use DBKey;
Adding Functions
There are non-public constants and functions that can be used when implementing additional methods for the key structure.
For every field in the structure, there are 4 constants defined. There is a
size usize constant with the size of the field in bytes. There is a start index
and end index usize constants set to the index of the first byte of the field
in the key and the byte after the last byte in the key. And there is a range
constant with the range of bytes used by the field of the key. The range
constant has a Range<usize> type.
For an example field example: u32, the size constant is EXAMPLE_SIZE, the
start index constant is EXAMPLE_START, the end index constant is
EXAMPLE_END and the range constant is EXAMPLE_RANGE.
Example
use db_key;
use Range;
/// A key for storing food records for tracking what you eat in a day.
/// This is a date structure used to combine the year, month, and day.
let date = Date ;
let key = new_from_date;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Future Plans
I keep on thinking of things I want to add to this, but I want to get it out in the world sometime. Here are a list of features I am thinking of adding in the future.
- Support signed integers in definition structure.
- Add option to allow string input/output for arrays (and even integer types).
- Add option to hide fields from interface (either so the developer can write thier own, or because they want them to always be the default value/padding)
- Support floating point values in the definition structure. This will partially break the parity between args atructure and key structure.
- Add option to store keys in little endian order. Breaks ordering.
- Make as many generated functions const as possible.