Overview
The SerializeRow trait enables serialization of Rust types into CQL query bind values. It’s a low-level trait that handles converting Rust data structures into the format expected by the CQL protocol.
Most users should use the #[derive(SerializeRow)] macro instead of implementing this trait manually.
Source: scylla-cql/src/serialize/row.rs:57
Trait Definition
pub trait SerializeRow {
fn serialize(
&self,
ctx: &RowSerializationContext<'_>,
writer: &mut RowWriter,
) -> Result<(), SerializationError>;
fn is_empty(&self) -> bool;
}
Methods
serialize
Serializes the row according to column specifications in the context.
fn serialize(
&self,
ctx: &RowSerializationContext<'_>,
writer: &mut RowWriter,
) -> Result<(), SerializationError>
ctx
&RowSerializationContext
required
Contains column metadata from prepared statement or query
Target writer for serialized values
result
Result<(), SerializationError>
Ok(()) on success, or serialization error
is_empty
Returns whether the row contains any values.
fn is_empty(&self) -> bool
true if row has no values
RowSerializationContext
pub struct RowSerializationContext<'a> {
// ... fields
}
Methods
from_prepared
Creates context from prepared statement metadata.
pub fn from_prepared(prepared: &'a PreparedMetadata) -> Self
from_specs
Creates context from column specifications.
pub fn from_specs(specs: &'a [ColumnSpec<'a>]) -> Self
empty
Creates an empty context (for statements with no bind markers).
pub const fn empty() -> Self
columns
Returns column specifications.
pub fn columns(&self) -> &'a [ColumnSpec<'_>]
Built-in Implementations
Unit Type
impl SerializeRow for ()
impl SerializeRow for [u8; 0]
For statements with no bind markers.
Slices and Vectors
impl<'a, T: SerializeValue + 'a> SerializeRow for &'a [T]
impl<T: SerializeValue> SerializeRow for Vec<T>
Serializes each element as a separate column value.
Example:
// For query: "INSERT INTO users (id, name, email) VALUES (?, ?, ?)"
let values = vec![42i32, "Alice".to_string(), "[email protected]".to_string()];
// Error: type mismatch - values must be same type in Vec
// Use tuple instead:
let values = (42i32, "Alice", "[email protected]");
Maps
impl<T: SerializeValue> SerializeRow for BTreeMap<String, T>
impl<T: SerializeValue> SerializeRow for BTreeMap<&str, T>
impl<T: SerializeValue, S: BuildHasher> SerializeRow for HashMap<String, T, S>
impl<T: SerializeValue, S: BuildHasher> SerializeRow for HashMap<&str, T, S>
Serializes values by matching column names.
Example:
use std::collections::HashMap;
let mut values = HashMap::new();
values.insert("id", 42);
values.insert("name", "Alice");
values.insert("email", "[email protected]");
session.execute_unpaged(&prepared, &values).await?;
Tuples
impl<T0: SerializeValue> SerializeRow for (T0,)
impl<T0: SerializeValue, T1: SerializeValue> SerializeRow for (T0, T1)
// ... up to 16 elements
Serializes tuple elements in order.
Example:
// For query: "INSERT INTO users (id, name, email) VALUES (?, ?, ?)"
let values = (42, "Alice", "[email protected]");
session.execute_unpaged(&prepared, values).await?;
References and Smart Pointers
impl<T: SerializeRow + ?Sized> SerializeRow for &T
impl<T: SerializeRow + ?Sized> SerializeRow for Box<T>
SerializedValues
A buffer containing pre-serialized row values.
pub struct SerializedValues {
// ... internal fields
}
Methods
new
pub const fn new() -> Self
from_serializable
Serializes a row into a buffer.
pub fn from_serializable<T: SerializeRow + ?Sized>(
ctx: &RowSerializationContext,
row: &T,
) -> Result<Self, SerializationError>
add_value
Manually adds a value to the buffer.
pub fn add_value<T: SerializeValue>(
&mut self,
val: &T,
typ: &ColumnType,
) -> Result<(), SerializationError>
is_empty
pub fn is_empty(&self) -> bool
element_count
Returns the number of values.
pub fn element_count(&self) -> u16
iter
Iterates over serialized values.
pub fn iter(&self) -> impl Iterator<Item = RawValue<'_>>
Derive Macro
The #[derive(SerializeRow)] macro automatically implements SerializeRow for structs.
Basic Usage
use scylla::macros::SerializeRow;
#[derive(SerializeRow)]
struct User {
id: i32,
name: String,
email: Option<String>,
}
let user = User {
id: 42,
name: "Alice".to_string(),
email: Some("[email protected]".to_string()),
};
session.execute_unpaged(&prepared, user).await?;
Field Attributes
#[scylla(rename = "...")]
Renames a field for serialization.
#[derive(SerializeRow)]
struct User {
#[scylla(rename = "user_id")]
id: i32,
name: String,
}
#[scylla(skip)]
Skips a field during serialization.
#[derive(SerializeRow)]
struct User {
id: i32,
name: String,
#[scylla(skip)]
local_cache: String,
}
Type Attributes
#[scylla(crate = ...)]
Specifies the path to the scylla crate.
#[derive(SerializeRow)]
#[scylla(crate = "scylla_cql")]
struct User {
id: i32,
}
#[scylla(skip_name_checks)]
Skips column name validation (matches fields by position).
#[derive(SerializeRow)]
#[scylla(skip_name_checks)]
struct UserTuple {
field_0: i32,
field_1: String,
}
Using skip_name_checks can lead to silent data corruption if field order doesn’t match column order. Use with caution.
Error Types
BuiltinTypeCheckError
pub struct BuiltinTypeCheckError {
pub rust_name: &'static str,
pub kind: BuiltinTypeCheckErrorKind,
}
BuiltinTypeCheckErrorKind
pub enum BuiltinTypeCheckErrorKind {
WrongColumnCount { rust_cols: usize, cql_cols: usize },
NoColumnWithName { name: String },
ValueMissingForColumn { name: String },
ColumnNameMismatch { rust_column_name: String, db_column_name: String },
}
BuiltinSerializationError
pub struct BuiltinSerializationError {
pub rust_name: &'static str,
pub kind: BuiltinSerializationErrorKind,
}
BuiltinSerializationErrorKind
pub enum BuiltinSerializationErrorKind {
ColumnSerializationFailed { name: String, err: SerializationError },
TooManyValues,
}
Examples
Struct with Derived SerializeRow
use scylla::macros::SerializeRow;
#[derive(SerializeRow)]
struct InsertUser {
id: i32,
name: String,
email: Option<String>,
created_at: i64,
}
let user = InsertUser {
id: 1,
name: "Alice".to_string(),
email: Some("[email protected]".to_string()),
created_at: 1234567890,
};
let prepared = session
.prepare("INSERT INTO users (id, name, email, created_at) VALUES (?, ?, ?, ?)")
.await?;
session.execute_unpaged(&prepared, user).await?;
Using HashMap
use std::collections::HashMap;
let mut values = HashMap::new();
values.insert("id", 42);
values.insert("name", "Bob");
session.execute_unpaged(&prepared, values).await?;
Using Tuples
// Simple tuple for ordered values
let values = (42, "Charlie", "[email protected]");
session.execute_unpaged(&prepared, values).await?;
See Also