use crate::{
db::data::{DataKey, PersistedRow, RawRow},
error::InternalError,
traits::{EntityKind, EntityValue},
};
use std::fmt::Display;
pub(in crate::db) fn decode_raw_row_for_entity_key<E>(
data_key: &DataKey,
raw_row: &RawRow,
) -> Result<(E::Key, E), InternalError>
where
E: PersistedRow + EntityValue,
{
let expected_key = data_key.try_key::<E>()?;
let entity = RawRow::try_decode::<E>(raw_row).map_err(|err| {
InternalError::serialize_corruption(decode_failure_message(data_key, err))
})?;
let actual_key = entity.id().key();
if expected_key != actual_key {
let expected = format_entity_key_for_mismatch::<E>(expected_key);
let found = format_entity_key_for_mismatch::<E>(actual_key);
return Err(InternalError::store_corruption(key_mismatch_message(
expected, found,
)));
}
Ok((expected_key, entity))
}
fn decode_failure_message(data_key: &DataKey, err: impl Display) -> String {
format!("failed to deserialize row: {data_key} ({err})")
}
fn key_mismatch_message(expected: impl Display, actual: impl Display) -> String {
format!("row key mismatch: expected {expected}, found {actual}")
}
fn format_entity_key_for_mismatch<E>(key: E::Key) -> String
where
E: EntityKind,
E::Key: std::fmt::Debug,
{
DataKey::try_new::<E>(key).map_or_else(|_| format!("{key:?}"), |key| key.to_string())
}