Skip to content

Commit

Permalink
serialize: document all public items
Browse files Browse the repository at this point in the history
Put the `#![warn(missing_docs)]` attribute at the top of the
`types::serialize` module to trigger warnings for undocumented public
items, and then add docstrings to the items reported by the warnings.
  • Loading branch information
piodul committed Dec 13, 2023
1 parent 86c0acb commit 5511cea
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 18 deletions.
22 changes: 22 additions & 0 deletions scylla-cql/src/types/serialize/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#![warn(missing_docs)]

//! Types and traits related to serialization of values to the CQL format.
use std::{error::Error, fmt::Display, sync::Arc};

use thiserror::Error;
Expand All @@ -7,6 +11,24 @@ pub mod value;
pub mod writers;

pub use writers::{CellValueBuilder, CellWriter, RowWriter};

/// An error indicating that a failure happened during serialization.
///
/// The error is type-erased so that the crate users can define their own
/// serialization impls and their errors. As for the impls defined or generated
/// by the driver itself, the following errors can be returned:
///
/// - [`row::BuiltinSerializationError`] is returned when serialization of
/// one of types with an impl built into the driver fails. It is also returned
/// from impls generated by the `SerializeRow` macro.
/// - [`value::BuiltinSerializationError`] is analogous to the above but is
/// returned from [`SerializeCql::serialize`](value::SerializeCql::serialize)
/// instead both in the case of builtin impls and impls generated by the
/// `SerializeCql` macro. It won't be returned by the `Session` directly,
/// but it might be nested in the [`row::BuiltinSerializationError`].
/// - [`row::ValueListToSerializeRowAdapterError`] is returned in case when
/// a list of values encoded with the legacy `ValueList` trait is passed
/// as an argument to the statement.
#[derive(Debug, Clone, Error)]
pub struct SerializationError(Arc<dyn Error + Send + Sync>);

Expand Down
79 changes: 69 additions & 10 deletions scylla-cql/src/types/serialize/row.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Contains the [`SerializeRow`] trait and its implementations.
use std::borrow::Cow;
use std::collections::{BTreeMap, HashSet};
use std::fmt::Display;
Expand All @@ -24,6 +26,7 @@ pub struct RowSerializationContext<'a> {
}

impl<'a> RowSerializationContext<'a> {
/// Creates the serialization context from prepared statement metadata.
#[inline]
pub fn from_prepared(prepared: &'a PreparedMetadata) -> Self {
Self {
Expand All @@ -45,14 +48,30 @@ impl<'a> RowSerializationContext<'a> {
}
}

/// Represents a set of values that can be sent along a CQL statement.
///
/// This is a low-level trait that is exposed to the specifics to the CQL
/// protocol and usually does not have to be implemented directly. See the
/// chapter on "Query Values" in the driver docs for information about how
/// this trait is supposed to be used.
pub trait SerializeRow {
/// Serializes the row according to the information in the given context.
///
/// It's the trait's responsibility to produce values in the order as
/// specified in given serialization context.
fn serialize(
&self,
ctx: &RowSerializationContext<'_>,
writer: &mut RowWriter,
) -> Result<(), SerializationError>;

/// Returns whether this row contains any values or not.
///
/// This method is used before executing a simple statement in order to check
/// whether there are any values provided to it. If there are some, then
/// the query will be prepared first in order to obtain information about
/// the bind marker types and names so that the values can be properly
/// type checked and serialized.
fn is_empty(&self) -> bool;
}

Expand Down Expand Up @@ -424,7 +443,8 @@ pub fn serialize_legacy_row<T: ValueList>(
RawValue::Null => cell_writer.set_null(),
RawValue::Unset => cell_writer.set_unset(),
// The unwrap below will succeed because the value was successfully
// deserialized from the CQL format, so it must have
// deserialized from the CQL format, so it must have had correct
// size.
RawValue::Value(v) => cell_writer.set_value(v).unwrap(),
};
};
Expand Down Expand Up @@ -527,19 +547,35 @@ fn mk_ser_err_named(
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum BuiltinTypeCheckErrorKind {
/// The Rust type expects `asked_for` column, but the query requires `actual`.
WrongColumnCount { actual: usize, asked_for: usize },
/// The Rust type expects `actual` column, but the statement requires `asked_for`.
WrongColumnCount {
/// The number of values that the Rust type provides.
actual: usize,

/// The number of columns that the statement requires.
asked_for: usize,
},

/// The Rust type provides a value for some column, but that column is not
/// present in the statement.
NoColumnWithName { name: String },
NoColumnWithName {
/// Name of the column that is missing in the statement.
name: String,
},

/// A value required by the statement is not provided by the Rust type.
ValueMissingForColumn { name: String },
ValueMissingForColumn {
/// Name of the column for which the Rust type doesn't
/// provide a value.
name: String,
},

/// A different column name was expected at given position.
ColumnNameMismatch {
/// Name of the column, as expected by the Rust type.
rust_column_name: String,

/// Name of the column for which the DB requested a value.
db_column_name: String,
},
}
Expand Down Expand Up @@ -576,7 +612,10 @@ impl Display for BuiltinTypeCheckErrorKind {
pub enum BuiltinSerializationErrorKind {
/// One of the columns failed to serialize.
ColumnSerializationFailed {
/// Name of the column that failed to serialize.
name: String,

/// The error that caused the column serialization to fail.
err: SerializationError,
},
}
Expand All @@ -591,13 +630,27 @@ impl Display for BuiltinSerializationErrorKind {
}
}

/// Describes a failure to translate the output of the [`ValueList`] legacy trait
/// into an output of the [`SerializeRow`] trait.
#[derive(Error, Debug)]
pub enum ValueListToSerializeRowAdapterError {
/// The values generated by the [`ValueList`] trait were provided in
/// name-value pairs, and there is a column in the statement for which
/// there is no corresponding named value.
#[error("Missing named value for column {name}")]
ValueMissingForBindMarker { name: String },
ValueMissingForBindMarker {
/// Name of the bind marker for which there is no value.
name: String,
},

/// The values generated by the [`ValueList`] trait were provided in
/// name-value pairs, and there is a named value which does not match
/// to any of the columns.
#[error("There is no bind marker with name {name}, but a value for it was provided")]
NoBindMarkerWithName { name: String },
NoBindMarkerWithName {
/// Name of the value that does not match to any of the bind markers.
name: String,
},
}

/// A buffer containing already serialized values.
Expand All @@ -614,6 +667,7 @@ pub struct SerializedValues {
}

impl SerializedValues {
/// Constructs a new, empty `SerializedValues`.
pub const fn new() -> Self {
SerializedValues {
serialized_values: Vec::new(),
Expand All @@ -624,6 +678,7 @@ impl SerializedValues {
/// A const empty instance, useful for taking references
pub const EMPTY: &'static SerializedValues = &SerializedValues::new();

/// Constructs `SerializedValues` from given [`SerializeRow`] object.
pub fn from_serializable<T: SerializeRow>(
ctx: &RowSerializationContext,
row: &T,
Expand All @@ -648,25 +703,27 @@ impl SerializedValues {
})
}

/// Returns `true` if the row contains no elements.
#[inline]
pub fn is_empty(&self) -> bool {
self.element_count() == 0
}

/// Returns an iterator over the values serialized into the object so far.
#[inline]
pub fn iter(&self) -> impl Iterator<Item = RawValue> {
SerializedValuesIterator {
serialized_values: &self.serialized_values,
}
}

/// Returns the number of values written so far.
#[inline]
pub fn element_count(&self) -> u16 {
// We initialize first two bytes in new() and BufBackedRowWriter does too,
// so this unwrap is safe
self.element_count
}

/// Returns the total serialized size of the values written so far.
#[inline]
pub fn buffer_size(&self) -> usize {
self.serialized_values.len()
Expand Down Expand Up @@ -717,7 +774,8 @@ impl SerializedValues {
})
}

// Temporary function, to be removed when we implement new batching API (right now it is needed in frame::request::mod.rs tests)
/// Temporary function, to be removed when we implement new batching API (right now it is needed in frame::request::mod.rs tests)
// TODO: Remove
pub fn to_old_serialized_values(&self) -> LegacySerializedValues {
let mut frame = Vec::new();
self.write_to_request(&mut frame);
Expand All @@ -731,6 +789,7 @@ impl Default for SerializedValues {
}
}

/// An iterator over raw values in some [`SerializedValues`].
#[derive(Clone, Copy)]
pub struct SerializedValuesIterator<'a> {
serialized_values: &'a [u8],
Expand Down
Loading

0 comments on commit 5511cea

Please sign in to comment.