icydb_core/db/query/api/
result_ext.rs1use crate::{
7 db::{EntityResponse, ResponseError, Row, query::api::private::SealedResponseCardinalityExt},
8 prelude::*,
9 types::Id,
10};
11
12pub trait ResponseCardinalityExt<E: EntityKind>: SealedResponseCardinalityExt<E> {
21 fn require_one(&self) -> Result<(), ResponseError>;
23
24 fn require_some(&self) -> Result<(), ResponseError>;
26
27 fn try_row(self) -> Result<Option<Row<E>>, ResponseError>;
29
30 fn row(self) -> Result<Row<E>, ResponseError>;
32
33 fn try_entity(self) -> Result<Option<E>, ResponseError>;
35
36 fn entity(self) -> Result<E, ResponseError>;
38
39 fn require_id(self) -> Result<Id<E>, ResponseError>;
41}
42
43impl<E: EntityKind> ResponseCardinalityExt<E> for EntityResponse<E> {
44 fn require_one(&self) -> Result<(), ResponseError> {
45 match self.count() {
46 1 => Ok(()),
47 0 => Err(ResponseError::not_found(E::PATH)),
48 n => Err(ResponseError::not_unique(E::PATH, n)),
49 }
50 }
51
52 fn require_some(&self) -> Result<(), ResponseError> {
53 if self.is_empty() {
54 Err(ResponseError::not_found(E::PATH))
55 } else {
56 Ok(())
57 }
58 }
59
60 #[expect(clippy::cast_possible_truncation)]
61 fn try_row(self) -> Result<Option<Row<E>>, ResponseError> {
62 let mut rows = self.rows();
63
64 match rows.len() {
65 0 => Ok(None),
66 1 => Ok(rows.pop()),
67 n => Err(ResponseError::not_unique(E::PATH, n as u32)),
68 }
69 }
70
71 fn row(self) -> Result<Row<E>, ResponseError> {
72 self.try_row()?.ok_or(ResponseError::not_found(E::PATH))
73 }
74
75 fn try_entity(self) -> Result<Option<E>, ResponseError> {
76 Ok(self.try_row()?.map(Row::entity))
77 }
78
79 fn entity(self) -> Result<E, ResponseError> {
80 self.try_entity()?.ok_or(ResponseError::not_found(E::PATH))
81 }
82
83 fn require_id(self) -> Result<Id<E>, ResponseError> {
84 self.row().map(|row| row.id())
85 }
86}