use crate::{
error::InternalError,
value::{InputValue, OutputValue},
};
use candid::CandidType;
use icydb_schema::ScalarType;
use serde::Deserialize;
#[doc(hidden)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum DynamicWriteCell {
Omitted,
Default,
Null,
Value(InputValue),
}
#[doc(hidden)]
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct DynamicStructuralPatch {
fields: Vec<(String, DynamicWriteCell)>,
}
impl DynamicStructuralPatch {
#[must_use]
pub const fn new(fields: Vec<(String, DynamicWriteCell)>) -> Self {
Self { fields }
}
#[must_use]
pub const fn fields(&self) -> &[(String, DynamicWriteCell)] {
self.fields.as_slice()
}
}
#[doc(hidden)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum DynamicMutation {
Insert {
entity: String,
patch: DynamicStructuralPatch,
},
Update {
entity: String,
key: InputValue,
patch: DynamicStructuralPatch,
},
Replace {
entity: String,
key: InputValue,
patch: DynamicStructuralPatch,
},
Delete {
entity: String,
key: InputValue,
},
}
impl DynamicMutation {
#[must_use]
pub const fn entity(&self) -> &str {
match self {
Self::Insert { entity, .. }
| Self::Update { entity, .. }
| Self::Replace { entity, .. }
| Self::Delete { entity, .. } => entity.as_str(),
}
}
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct DynamicMutationResult {
pub entity: String,
pub columns: Vec<String>,
pub rows: Vec<Vec<OutputValue>>,
pub affected_rows: u32,
}
#[doc(hidden)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DynamicTypedFieldBindingRequest {
pub(crate) field_type: DynamicTypedFieldType,
pub(crate) nullable: bool,
pub(crate) source_key: String,
}
impl DynamicTypedFieldBindingRequest {
#[must_use]
pub const fn new(
source_key: String,
field_type: DynamicTypedFieldType,
nullable: bool,
) -> Self {
Self {
field_type,
nullable,
source_key,
}
}
}
#[doc(hidden)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum DynamicTypedFieldType {
Scalar(ScalarType),
List(Box<Self>),
Named(String),
}
#[doc(hidden)]
#[derive(Debug)]
pub enum DynamicTypedBindingError {
FieldUnavailable,
IncompatibleField,
Internal(InternalError),
}
impl From<InternalError> for DynamicTypedBindingError {
fn from(error: InternalError) -> Self {
Self::Internal(error)
}
}
#[doc(hidden)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DynamicTypedEntityBinding {
pub(crate) database_incarnation: [u8; 16],
pub(crate) entity: String,
pub(crate) entity_tag: u64,
pub(crate) accepted_revision: u64,
pub(crate) accepted_fingerprint: [u8; 16],
pub(crate) entity_generation: u32,
pub(crate) fields: Vec<(String, String)>,
pub(crate) named_types: Vec<(String, String)>,
pub(crate) enum_variants: Vec<(String, String, String)>,
pub(crate) composite_fields: Vec<(String, String, String)>,
}
impl DynamicTypedEntityBinding {
#[must_use]
pub const fn entity(&self) -> &str {
self.entity.as_str()
}
#[must_use]
pub fn field_name(&self, source_key: &str) -> Option<&str> {
self.fields
.iter()
.find_map(|(source, name)| (source == source_key).then_some(name.as_str()))
}
#[must_use]
pub fn named_type_name(&self, source_key: &str) -> Option<&str> {
self.named_types
.iter()
.find_map(|(source, name)| (source == source_key).then_some(name.as_str()))
}
#[must_use]
pub fn enum_variant_name(&self, type_source_key: &str, source_key: &str) -> Option<&str> {
self.enum_variants
.iter()
.find_map(|(bound_type, source, name)| {
(bound_type == type_source_key && source == source_key).then_some(name.as_str())
})
}
#[must_use]
pub fn composite_field_name(&self, type_source_key: &str, source_key: &str) -> Option<&str> {
self.composite_fields
.iter()
.find_map(|(bound_type, source, name)| {
(bound_type == type_source_key && source == source_key).then_some(name.as_str())
})
}
}