Derive Macro scylla::DeserializeValue
source · #[derive(DeserializeValue)]
{
// Attributes available to this derive:
#[scylla]
}
Expand description
Derive macro for the DeserializeValue
trait that generates an implementation
which deserializes a User Defined Type with the same layout as the Rust
struct.
At the moment, only structs with named fields are supported.
This macro properly supports structs with lifetimes, meaning that you can deserialize UDTs with fields that borrow memory from the serialized response.
§Example
A UDT defined like this:
CREATE TYPE ks.my_udt (a i32, b text, c blob);
…can be deserialized using the following struct:
#[derive(DeserializeValue)]
struct MyUdt<'a> {
a: i32,
b: Option<String>,
c: &'a [u8],
}
§Attributes
The macro supports a number of attributes that customize the generated
implementation. Many of the attributes were inspired by procedural macros
from serde
and try to follow the same naming conventions.
§Struct attributes
#[scylla(crate = "crate_name")]
By default, the code generated by the derive macro will refer to the items
defined by the driver (types, traits, etc.) via the ::scylla
path.
For example, it will refer to the DeserializeValue
trait using the following path:
use ::scylla::_macro_internal::DeserializeValue;
Most users will simply add scylla
to their dependencies, then use
the derive macro and the path above will work. However, there are some
niche cases where this path will not work:
- The
scylla
crate is imported under a different name, - The
scylla
crate is not imported at all - the macro actually is defined in thescylla-macros
crate and the generated code depends on items defined inscylla-cql
.
It’s not possible to automatically resolve those issues in the procedural
macro itself, so in those cases the user must provide an alternative path
to either the scylla
or scylla-cql
crate.
#[scylla(flavor = "flavor_name")]
Allows to choose one of the possible “flavors”, i.e. the way how the generated code will approach deserialization. Possible flavors are:
"match_by_name"
(default) - the generated implementation does not require the fields in the Rust struct to be in the same order as the fields in the UDT. During deserialization, the implementation will take care to deserialize the fields in the order which the database expects."enforce_order"
- the generated implementation requires the fields in the Rust struct to be in the same order as the fields in the UDT. If the order is incorrect, type checking/deserialization will fail. This is a less robust flavor than"match_by_name"
, but should be slightly more performant as it doesn’t need to perform lookups by name. The UDT field names will still be checked during the type check phase.
#[(scylla(skip_name_checks))]
This attribute only works when used with flavor = "enforce_order"
.
If set, the generated implementation will not verify the UDT field names at
all. Because it only works with enforce_order
, it will deserialize first
UDT field into the first struct field, second UDT field into the second
struct field and so on. It will still verify that the UDT field types
and struct field types match.
#[(scylla(forbid_excess_udt_fields))]
By default, the generated deserialization code ignores excess UDT fields.
I.e., enforce_order
flavour ignores excess UDT fields in the suffix
of the UDT definition, and the default unordered flavour ignores excess
UDT fields anywhere.
If more strictness is desired, this flag makes sure that no excess fields
are present and forces error in case there are some.
§Field attributes
#[scylla(skip)]
The field will be completely ignored during deserialization and will
be initialized with Default::default()
.
#[scylla(allow_missing)]
If the UDT definition does not contain this field, it will be initialized
with Default::default()
.
#[scylla(default_when_null)]
If the value of the field received from DB is null, the field will be
initialized with Default::default()
.
#[scylla(rename = "field_name")]
By default, the generated implementation will try to match the Rust field to a UDT field with the same name. This attribute instead allows to match to a UDT field with provided name.