use crate::{
db::{EntityResponse, ResponseError, Row},
prelude::*,
types::Id,
};
mod private {
use crate::{db::EntityResponse, prelude::*};
pub trait SealedResponseCardinalityExt<E: EntityKind> {}
impl<E: EntityKind> SealedResponseCardinalityExt<E> for EntityResponse<E> {}
}
use private::SealedResponseCardinalityExt;
pub trait ResponseCardinalityExt<E: EntityKind>: SealedResponseCardinalityExt<E> {
fn require_one(&self) -> Result<(), ResponseError>;
fn require_some(&self) -> Result<(), ResponseError>;
fn try_row(self) -> Result<Option<Row<E>>, ResponseError>;
fn row(self) -> Result<Row<E>, ResponseError>;
fn try_entity(self) -> Result<Option<E>, ResponseError>;
fn entity(self) -> Result<E, ResponseError>;
fn require_id(self) -> Result<Id<E>, ResponseError>;
}
impl<E: EntityKind> ResponseCardinalityExt<E> for EntityResponse<E> {
fn require_one(&self) -> Result<(), ResponseError> {
match self.count() {
1 => Ok(()),
0 => Err(ResponseError::not_found(E::PATH)),
n => Err(ResponseError::not_unique(E::PATH, n)),
}
}
fn require_some(&self) -> Result<(), ResponseError> {
if self.is_empty() {
Err(ResponseError::not_found(E::PATH))
} else {
Ok(())
}
}
#[expect(clippy::cast_possible_truncation)]
fn try_row(self) -> Result<Option<Row<E>>, ResponseError> {
let mut rows = self.rows();
match rows.len() {
0 => Ok(None),
1 => Ok(rows.pop()),
n => Err(ResponseError::not_unique(E::PATH, n as u32)),
}
}
fn row(self) -> Result<Row<E>, ResponseError> {
self.try_row()?.ok_or(ResponseError::not_found(E::PATH))
}
fn try_entity(self) -> Result<Option<E>, ResponseError> {
Ok(self.try_row()?.map(Row::entity))
}
fn entity(self) -> Result<E, ResponseError> {
self.try_entity()?.ok_or(ResponseError::not_found(E::PATH))
}
fn require_id(self) -> Result<Id<E>, ResponseError> {
self.row().map(|row| row.id())
}
}