Derive Macro scylla::SerializeValue
source · #[derive(SerializeValue)]
{
// Attributes available to this derive:
#[scylla]
}
Expand description
Derive macro for the SerializeValue
trait
which serializes given Rust structure as a User Defined Type (UDT).
At the moment, only structs with named fields are supported.
Serialization will fail if there are some fields in the Rust struct that don’t match to any of the UDT fields.
If there are fields in UDT that are not present in Rust definition:
- serialization will succeed in “match_by_name” flavor (default). Missing fields in the middle of UDT will be sent as NULLs, missing fields at the end will not be sent at all.
- serialization will succeed if suffix of UDT fields is missing. If there are missing fields in the middle it will fail. Note that if “skip_name_checks” is enabled, and the types happen to match, it is possible for serialization to succeed with unexpected result.
This behavior is the default to support ALTERing UDTs by adding new fields.
You can forbid excess fields in the UDT using forbid_excess_udt_fields
attribute.
In case of failure, either BuiltinTypeCheckError
or BuiltinSerializationError
will be returned.
§Example
A UDT defined like this:
CREATE TYPE ks.my_udt (a int, b text, c blob);
…can be serialized using the following struct:
#[derive(SerializeValue)]
struct MyUdt {
a: i32,
b: Option<String>,
// No "c" field - it is not mandatory by default for all fields to be present
}
§Struct attributes
#[scylla(flavor = "flavor_name")]
Allows to choose one of the possible “flavors”, i.e. the way how the generated code will approach serialization. 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 serialization, the implementation will take care to serialize 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/serialization 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.
#[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 SerializeValue
trait
using the following path:
use ::scylla::_macro_internal::SerializeValue;
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(skip_name_checks)]
Specific only to the enforce_order
flavor.
Skips checking Rust field names against names of the UDT fields. With this annotation, the generated implementation will allow mismatch between Rust struct field names and UDT field names, i.e. it’s OK if i-th field has a different name in Rust and in the UDT. Fields are still being type-checked.
#[scylla(forbid_excess_udt_fields)]
Forces Rust struct to have all the fields present in UDT, otherwise serialization fails.
§Field attributes
#[scylla(rename = "name_in_the_udt")]
Serializes the field to the UDT struct field with given name instead of its Rust name.
#[scylla(skip)]
Don’t use the field during serialization.
Documentation for this macro can only be found
in scylla
crate - not in scylla-macros nor in scylla-cql.
This is because of rustdocs limitations that are hard to explain here.