#[make_varule]Expand description
Generate a corresponding VarULE type and the relevant EncodeAsVarULE/zerofrom::ZeroFrom
implementations for this type
This can be attached to structs containing only AsULE types with the last fields being
Cow<'a, str>, ZeroSlice, or VarZeroSlice. If there is more than one such field, it will be represented
using MultiFieldsULE and getters will be generated. Other VarULE fields will be detected if they are
tagged with #[zerovec::varule(NameOfVarULETy)].
The type must be PartialEq and Eq.
EncodeAsVarULE and zerofrom::ZeroFrom are useful for avoiding the need to deal with
the VarULE type directly. In particular, it is recommended to use zerofrom::ZeroFrom
to convert the VarULE type back to this type in a cheap, zero-copy way (see the example below
for more details).
#[make_varule] will automatically derive the following traits on the VarULE type:
To disable one of the automatic derives, use #[zerovec::skip_derive(...)] like so: #[zerovec::skip_derive(ZeroMapKV)].
Ord and PartialOrd are implemented as a unit and can only be disabled as a group with #[zerovec::skip_derive(Ord)].
The following traits are available to derive, but not automatic:
To enable one of these additional derives, use #[zerovec::derive(...)] like so: #[zerovec::derive(Debug)].
In most cases these derives will defer to the impl of the same trait on the current type, so such impls must exist.
This implementation will also by default autogenerate Ord and PartialOrd on the VarULE type based on
the implementation on Self. You can opt out of this with #[zerovec::skip_derive(Ord)]
Note that this implementation will autogenerate EncodeAsVarULE impls for both Self and &Self
for convenience. This allows for a little more flexibility encoding slices.
In case there are multiple VarULE (i.e., variable-sized) fields, this macro will produce private fields that
appropriately pack the data together, with the packing format by default being crate::vecs::Index16, but can be
overridden with #[zerovec::format(zerovec::vecs::Index8)].
§Example
use std::borrow::Cow;
use zerofrom::ZeroFrom;
use zerovec::ule::encode_varule_to_box;
use zerovec::{VarZeroVec, ZeroMap, ZeroVec};
// custom fixed-size ULE type for ZeroVec
#[zerovec::make_ule(DateULE)]
#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, serde::Serialize, serde::Deserialize)]
struct Date {
y: u64,
m: u8,
d: u8,
}
// custom variable sized VarULE type for VarZeroVec
#[zerovec::make_varule(PersonULE)]
#[zerovec::derive(Serialize, Deserialize)]
#[derive(Clone, PartialEq, Eq, Ord, PartialOrd, serde::Serialize, serde::Deserialize)]
struct Person<'a> {
birthday: Date,
favorite_character: char,
#[serde(borrow)]
name: Cow<'a, str>,
}
#[derive(serde::Serialize, serde::Deserialize)]
struct Data<'a> {
// note: VarZeroVec always must reference the ULE type directly
#[serde(borrow)]
important_people: VarZeroVec<'a, PersonULE>,
}
let person1 = Person {
birthday: Date {
y: 1990,
m: 9,
d: 7,
},
favorite_character: 'π',
name: Cow::from("Kate"),
};
let person2 = Person {
birthday: Date {
y: 1960,
m: 5,
d: 25,
},
favorite_character: '冇',
name: Cow::from("Jesse"),
};
let important_people = VarZeroVec::from(&[person1, person2]);
let data = Data { important_people };
let bincode_bytes = bincode::serialize(&data).expect("Serialization should be successful");
// Will deserialize without allocations
let deserialized: Data =
bincode::deserialize(&bincode_bytes).expect("Deserialization should be successful");
assert_eq!(&deserialized.important_people.get(1).unwrap().name, "Jesse");
assert_eq!(&deserialized.important_people.get(0).unwrap().name, "Kate");
// Since VarZeroVec produces PersonULE types, it's convenient to use ZeroFrom
// to recoup Person values in a zero-copy way
let person_converted: Person =
ZeroFrom::zero_from(deserialized.important_people.get(1).unwrap());
assert_eq!(person_converted.name, "Jesse");
assert_eq!(person_converted.birthday.y, 1960);Full docs for this proc macro can be found on the zerovec crate.