use crate::db::schema::enum_catalog::normalize_and_admit_nullable_value;
use crate::value::Value;
use crate::{
db::schema::{
AcceptedFieldKind, AcceptedValueCatalogHandle, FieldStorageDecode,
enum_catalog::{
AcceptedValueContract, AcceptedValueRef, AdmittedOwnedValue, CanonicalValue,
ValueAdmissionBudget, ValueAdmissionError, admit_canonical_value,
validate_nullable_canonical_value, with_normalized_accepted_value,
},
},
value::InputValue,
};
use std::borrow::Cow;
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct AcceptedValueAdmissionContract<'a> {
catalogs: &'a AcceptedValueCatalogHandle,
value_contract: Cow<'a, AcceptedValueContract>,
nullable: bool,
}
impl<'a> AcceptedValueAdmissionContract<'a> {
pub(in crate::db::schema) const fn borrowed(
catalogs: &'a AcceptedValueCatalogHandle,
value_contract: &'a AcceptedValueContract,
nullable: bool,
) -> Self {
Self {
catalogs,
value_contract: Cow::Borrowed(value_contract),
nullable,
}
}
pub(in crate::db::schema) const fn owned(
catalogs: &'a AcceptedValueCatalogHandle,
value_contract: AcceptedValueContract,
nullable: bool,
) -> Self {
Self {
catalogs,
value_contract: Cow::Owned(value_contract),
nullable,
}
}
#[must_use]
pub(in crate::db) fn value_contract(&self) -> &AcceptedValueContract {
self.value_contract.as_ref()
}
#[must_use]
pub(in crate::db) fn collection_element_contract(&self) -> Option<Self> {
let value_contract = self
.value_contract()
.collection_element_contract()
.or_else(|| {
let collection_kind = self
.catalogs
.composite_catalog()
.resolve_newtype_value_kind(self.value_contract().kind())?;
let element_kind = match collection_kind {
AcceptedFieldKind::List(inner) | AcceptedFieldKind::Set(inner) => *inner,
_ => return None,
};
AcceptedValueContract::from_candidate_catalogs(
self.catalogs.enum_catalog(),
self.catalogs.composite_catalog(),
&element_kind,
FieldStorageDecode::ByKind,
)
.ok()
})?;
Some(Self::owned(self.catalogs, value_contract, false))
}
pub(in crate::db) fn normalize_and_admit(
&self,
input: InputValue,
budget: &mut ValueAdmissionBudget,
) -> Result<AdmittedOwnedValue, ValueAdmissionError> {
normalize_and_admit_nullable_value(
self.catalogs,
self.value_contract(),
self.nullable,
input,
budget,
)
}
pub(in crate::db) fn admit_canonical(
&self,
value: CanonicalValue,
budget: &mut ValueAdmissionBudget,
) -> Result<AdmittedOwnedValue, ValueAdmissionError> {
admit_canonical_value(
self.catalogs,
self.value_contract(),
self.nullable,
value,
budget,
)
}
pub(in crate::db) fn normalize_input_to_runtime(
&self,
input: InputValue,
budget: &mut ValueAdmissionBudget,
) -> Result<Value, ValueAdmissionError> {
self.normalize_and_admit(input, budget)
.map(AdmittedOwnedValue::into_value)
}
pub(in crate::db) fn with_normalized<R>(
&self,
input: InputValue,
budget: &mut ValueAdmissionBudget,
use_value: impl for<'value> FnOnce(AcceptedValueRef<'value>) -> R,
) -> Result<R, ValueAdmissionError> {
with_normalized_accepted_value(
self.catalogs,
self.value_contract(),
self.nullable,
input,
budget,
use_value,
)
}
pub(in crate::db) fn with_validated<R>(
&self,
value: &CanonicalValue,
budget: &mut ValueAdmissionBudget,
use_value: impl for<'value> FnOnce(AcceptedValueRef<'value>) -> R,
) -> Result<R, ValueAdmissionError> {
let accepted = validate_nullable_canonical_value(
self.catalogs,
self.value_contract(),
self.nullable,
value,
budget,
)?;
Ok(use_value(accepted))
}
}