Attribute Macro zerovec::make_varule

source ·
#[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.

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.