icydb_core/db/
response.rs1use crate::{prelude::*, view::View};
2use thiserror::Error as ThisError;
3
4pub type Row<E> = (Key, E);
9
10#[derive(Debug, ThisError)]
16pub enum ResponseError {
17 #[error("expected exactly one row, found 0 (entity {entity})")]
18 NotFound { entity: &'static str },
19
20 #[error("expected exactly one row, found {count} (entity {entity})")]
21 NotUnique { entity: &'static str, count: u32 },
22}
23
24impl ResponseError {
25 const fn not_found<E: EntityKind>() -> Self {
26 Self::NotFound { entity: E::PATH }
27 }
28
29 const fn not_unique<E: EntityKind>(count: u32) -> Self {
30 Self::NotUnique {
31 entity: E::PATH,
32 count,
33 }
34 }
35}
36
37#[derive(Debug)]
49pub struct Response<E: EntityKind>(pub Vec<Row<E>>);
50
51impl<E: EntityKind> Response<E> {
52 #[must_use]
57 #[allow(clippy::cast_possible_truncation)]
58 pub const fn count(&self) -> u32 {
59 self.0.len() as u32
60 }
61
62 #[must_use]
63 pub const fn is_empty(&self) -> bool {
64 self.0.is_empty()
65 }
66
67 pub const fn require_one(&self) -> Result<(), ResponseError> {
72 match self.count() {
73 1 => Ok(()),
74 0 => Err(ResponseError::NotFound { entity: E::PATH }),
75 n => Err(ResponseError::NotUnique {
76 entity: E::PATH,
77 count: n,
78 }),
79 }
80 }
81
82 pub const fn require_some(&self) -> Result<(), ResponseError> {
83 if self.is_empty() {
84 Err(ResponseError::NotFound { entity: E::PATH })
85 } else {
86 Ok(())
87 }
88 }
89
90 #[allow(clippy::cast_possible_truncation)]
95 pub fn try_row(self) -> Result<Option<Row<E>>, ResponseError> {
96 match self.0.len() {
97 0 => Ok(None),
98 1 => Ok(Some(self.0.into_iter().next().unwrap())),
99 n => Err(ResponseError::not_unique::<E>(n as u32)),
100 }
101 }
102
103 pub fn row(self) -> Result<Row<E>, ResponseError> {
104 self.try_row()?.ok_or_else(ResponseError::not_found::<E>)
105 }
106
107 #[must_use]
108 pub fn rows(self) -> Vec<Row<E>> {
109 self.0
110 }
111
112 pub fn try_entity(self) -> Result<Option<E>, ResponseError> {
117 Ok(self.try_row()?.map(|(_, e)| e))
118 }
119
120 pub fn entity(self) -> Result<E, ResponseError> {
121 self.row().map(|(_, e)| e)
122 }
123
124 #[must_use]
125 pub fn entities(self) -> Vec<E> {
126 self.0.into_iter().map(|(_, e)| e).collect()
127 }
128
129 #[must_use]
134 pub fn key(&self) -> Option<Key> {
135 self.0.first().map(|(k, _)| *k)
136 }
137
138 pub fn key_strict(self) -> Result<Key, ResponseError> {
139 self.row().map(|(k, _)| k)
140 }
141
142 pub fn try_key(self) -> Result<Option<Key>, ResponseError> {
143 Ok(self.try_row()?.map(|(k, _)| k))
144 }
145
146 #[must_use]
147 pub fn keys(&self) -> Vec<Key> {
148 self.0.iter().map(|(k, _)| *k).collect()
149 }
150
151 #[must_use]
152 pub fn contains_key(&self, key: &Key) -> bool {
153 self.0.iter().any(|(k, _)| k == key)
154 }
155
156 pub fn primary_key(self) -> Result<E::PrimaryKey, ResponseError> {
161 Ok(self.entity()?.primary_key())
162 }
163
164 pub fn try_primary_key(self) -> Result<Option<E::PrimaryKey>, ResponseError> {
165 Ok(self.try_entity()?.map(|e| e.primary_key()))
166 }
167
168 #[must_use]
169 pub fn primary_keys(self) -> Vec<E::PrimaryKey> {
170 self.0.into_iter().map(|(_, e)| e.primary_key()).collect()
171 }
172
173 pub fn view(&self) -> Result<View<E>, ResponseError> {
178 self.require_one()?;
179 Ok(self.0[0].1.to_view())
180 }
181
182 pub fn view_opt(&self) -> Result<Option<View<E>>, ResponseError> {
183 match self.count() {
184 0 => Ok(None),
185 1 => Ok(Some(self.0[0].1.to_view())),
186 n => Err(ResponseError::not_unique::<E>(n)),
187 }
188 }
189
190 #[must_use]
191 pub fn views(&self) -> Vec<View<E>> {
192 self.0.iter().map(|(_, e)| e.to_view()).collect()
193 }
194}
195
196impl<E: EntityKind> IntoIterator for Response<E> {
197 type Item = Row<E>;
198 type IntoIter = std::vec::IntoIter<Self::Item>;
199
200 fn into_iter(self) -> Self::IntoIter {
201 self.0.into_iter()
202 }
203}