mod by_kind;
mod meta;
mod scalar;
pub(super) mod strategy;
mod structured;
mod traversal;
use crate::db::data::persisted_row::codec::strategy::StorageStrategy;
use crate::{
db::data::storage::{decode as storage_decode, encode as storage_encode},
error::InternalError,
value::Value,
};
pub use by_kind::{
decode_persisted_option_slot_payload_by_kind, decode_persisted_slot_payload_by_kind,
encode_persisted_slot_payload_by_kind,
};
pub use meta::{
decode_persisted_option_slot_payload_by_meta, decode_persisted_slot_payload_by_meta,
encode_persisted_option_slot_payload_by_meta, encode_persisted_slot_payload_by_meta,
};
pub use scalar::{
PersistedScalar, ScalarSlotValueRef, ScalarValueRef,
decode_persisted_option_scalar_slot_payload, decode_persisted_scalar_slot_payload,
encode_persisted_option_scalar_slot_payload, encode_persisted_scalar_slot_payload,
};
pub(super) use scalar::{decode_scalar_slot_value, encode_scalar_slot_value};
pub use structured::{
decode_persisted_custom_many_slot_payload, decode_persisted_custom_slot_payload,
encode_persisted_custom_many_slot_payload, encode_persisted_custom_slot_payload,
};
fn encode_null_with_strategy(
strategy: StorageStrategy,
field_name: &'static str,
) -> Result<Vec<u8>, InternalError> {
match strategy {
StorageStrategy::Scalar => Ok(scalar::encode_null_slot_payload()),
StorageStrategy::ByKind(kind) => {
by_kind::encode_explicit_value(kind, &Value::Null, field_name)
}
StorageStrategy::Structured => Ok(storage_encode::null()),
}
}
pub(in crate::db::data::persisted_row::codec) fn encode_with_strategy<T: ?Sized>(
strategy: StorageStrategy,
value: Option<&T>,
field_name: &'static str,
encode_value: impl FnOnce(StorageStrategy, &T, &'static str) -> Result<Vec<u8>, InternalError>,
) -> Result<Vec<u8>, InternalError> {
value.map_or_else(
|| encode_null_with_strategy(strategy, field_name),
|value| encode_value(strategy, value, field_name),
)
}
pub(in crate::db::data::persisted_row::codec) fn decode_with_strategy<T>(
strategy: StorageStrategy,
bytes: &[u8],
field_name: &'static str,
decode_value: impl FnOnce(StorageStrategy, &[u8], &'static str) -> Result<Option<T>, InternalError>,
) -> Result<Option<T>, InternalError> {
decode_value(strategy, bytes, field_name)
}
pub(in crate::db::data::persisted_row::codec) fn decode_required_with_strategy<T>(
strategy: StorageStrategy,
bytes: &[u8],
field_name: &'static str,
null_message: &'static str,
decode_value: impl FnOnce(StorageStrategy, &[u8], &'static str) -> Result<Option<T>, InternalError>,
) -> Result<T, InternalError> {
let decoded = decode_value(strategy, bytes, field_name)?;
require_decoded(decoded, || {
InternalError::persisted_row_field_decode_failed(field_name, null_message)
})
}
pub(in crate::db::data::persisted_row::codec) fn require_decoded<T>(
value: Option<T>,
err: impl FnOnce() -> InternalError,
) -> Result<T, InternalError> {
value.ok_or_else(err)
}
pub(in crate::db::data::persisted_row::codec) fn encode_runtime_value_with_strategy(
strategy: StorageStrategy,
value: &Value,
field_name: &'static str,
) -> Result<Vec<u8>, InternalError> {
match strategy {
StorageStrategy::Scalar => Err(InternalError::persisted_row_field_encode_failed(
field_name,
"scalar strategy does not encode runtime values",
)),
StorageStrategy::ByKind(kind) => by_kind::encode_explicit_value(kind, value, field_name),
StorageStrategy::Structured => storage_encode::value(value)
.map_err(|err| InternalError::persisted_row_field_encode_failed(field_name, err)),
}
}
pub(in crate::db::data::persisted_row::codec) fn decode_runtime_value_option_with_strategy(
strategy: StorageStrategy,
bytes: &[u8],
field_name: &'static str,
) -> Result<Option<Value>, InternalError> {
let runtime_value = match strategy {
StorageStrategy::Scalar => {
return Err(InternalError::persisted_row_field_decode_failed(
field_name,
"scalar strategy does not decode runtime values",
));
}
StorageStrategy::ByKind(kind) => by_kind::decode_explicit_value(bytes, kind, field_name)?,
StorageStrategy::Structured => Some(
storage_decode::value(bytes)
.map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?,
),
};
Ok(runtime_value.filter(|value| !matches!(value, Value::Null)))
}