mod grouped;
mod paged;
use crate::{prelude::*, traits::EntityValue, types::Id, value::Value};
use thiserror::Error as ThisError;
mod private {
pub trait Sealed {}
}
pub use grouped::{GroupedRow, PagedGroupedExecution, PagedGroupedExecutionWithTrace};
pub use paged::{PagedLoadExecution, PagedLoadExecutionWithTrace};
pub trait ResponseRow: private::Sealed {}
impl ResponseRow for GroupedRow {}
impl private::Sealed for GroupedRow {}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Row<E: EntityKind> {
id: Id<E>,
entity: E,
}
impl<E: EntityKind> Row<E> {
#[must_use]
pub const fn new(id: Id<E>, entity: E) -> Self {
Self { id, entity }
}
#[must_use]
pub const fn id(&self) -> Id<E> {
self.id
}
#[must_use]
pub fn entity(self) -> E {
self.entity
}
#[must_use]
pub const fn entity_ref(&self) -> &E {
&self.entity
}
#[must_use]
pub fn into_parts(self) -> (Id<E>, E) {
(self.id, self.entity)
}
}
impl<E: EntityKind> From<(Id<E>, E)> for Row<E> {
fn from(value: (Id<E>, E)) -> Self {
Self::new(value.0, value.1)
}
}
impl<E: EntityKind> private::Sealed for Row<E> {}
impl<E: EntityKind> ResponseRow for Row<E> {}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ProjectedRow<E: EntityKind> {
id: Id<E>,
values: Vec<Value>,
}
impl<E: EntityKind> ProjectedRow<E> {
#[must_use]
pub const fn new(id: Id<E>, values: Vec<Value>) -> Self {
Self { id, values }
}
#[must_use]
pub const fn id(&self) -> Id<E> {
self.id
}
#[must_use]
pub const fn values(&self) -> &[Value] {
self.values.as_slice()
}
#[must_use]
pub fn into_parts(self) -> (Id<E>, Vec<Value>) {
(self.id, self.values)
}
}
impl<E: EntityKind> private::Sealed for ProjectedRow<E> {}
impl<E: EntityKind> ResponseRow for ProjectedRow<E> {}
#[derive(Debug, ThisError)]
pub enum ResponseError {
#[error("expected exactly one row, found 0 (entity {entity})")]
NotFound { entity: &'static str },
#[error("expected exactly one row, found {count} (entity {entity})")]
NotUnique { entity: &'static str, count: u32 },
}
impl ResponseError {
#[must_use]
pub const fn not_found(entity: &'static str) -> Self {
Self::NotFound { entity }
}
#[must_use]
pub const fn not_unique(entity: &'static str, count: u32) -> Self {
Self::NotUnique { entity, count }
}
}
#[derive(Debug)]
pub struct Response<R: ResponseRow>(Vec<R>);
pub type EntityResponse<E> = Response<Row<E>>;
pub type ProjectionResponse<E> = Response<ProjectedRow<E>>;
impl<R: ResponseRow> Response<R> {
#[must_use]
pub const fn new(rows: Vec<R>) -> Self {
Self(rows)
}
#[must_use]
pub fn from_rows<T>(rows: Vec<T>) -> Self
where
T: Into<R>,
{
Self(rows.into_iter().map(Into::into).collect())
}
#[must_use]
pub const fn len(&self) -> usize {
self.0.len()
}
#[must_use]
#[expect(clippy::cast_possible_truncation)]
pub const fn count(&self) -> u32 {
self.0.len() as u32
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[must_use]
pub fn rows(self) -> Vec<R> {
self.0
}
pub fn iter(&self) -> std::slice::Iter<'_, R> {
self.0.iter()
}
}
impl<R: ResponseRow> AsRef<[R]> for Response<R> {
fn as_ref(&self) -> &[R] {
self.0.as_slice()
}
}
impl<R: ResponseRow> std::ops::Deref for Response<R> {
type Target = [R];
fn deref(&self) -> &Self::Target {
self.0.as_slice()
}
}
impl<E: EntityKind> Response<Row<E>> {
#[must_use]
pub fn id(&self) -> Option<Id<E>> {
self.0.first().map(Row::id)
}
#[must_use]
pub fn entities(self) -> Vec<E> {
self.0.into_iter().map(Row::entity).collect()
}
pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_ {
self.0.iter().map(Row::id)
}
pub fn contains_id(&self, id: &Id<E>) -> bool {
self.0.iter().any(|row| row.id() == *id)
}
}
impl<R: ResponseRow> IntoIterator for Response<R> {
type Item = R;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a, R: ResponseRow> IntoIterator for &'a Response<R> {
type Item = &'a R;
type IntoIter = std::slice::Iter<'a, R>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Debug)]
pub struct WriteBatchResponse<E> {
entities: Vec<E>,
}
impl<E> WriteBatchResponse<E> {
#[must_use]
pub const fn new(entities: Vec<E>) -> Self {
Self { entities }
}
#[must_use]
pub const fn len(&self) -> usize {
self.entities.len()
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.entities.is_empty()
}
#[must_use]
pub fn entities(self) -> Vec<E> {
self.entities
}
pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_
where
E: EntityValue,
{
self.entities.iter().map(EntityValue::id)
}
pub fn iter(&self) -> std::slice::Iter<'_, E> {
self.entities.iter()
}
}
impl<E> IntoIterator for WriteBatchResponse<E> {
type Item = E;
type IntoIter = std::vec::IntoIter<E>;
fn into_iter(self) -> Self::IntoIter {
self.entities.into_iter()
}
}
impl<'a, E> IntoIterator for &'a WriteBatchResponse<E> {
type Item = &'a E;
type IntoIter = std::slice::Iter<'a, E>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}