Skip to main content

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
writer
&mut RowWriter
required
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
empty
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

Build docs developers (and LLMs) love