icydb_core/db/response/
mod.rs

1use crate::{Error, Key, ThisError, db::DbError, traits::EntityKind};
2
3///
4/// ResponseError
5///
6
7#[derive(Debug, ThisError)]
8pub enum ResponseError {
9    #[error("expected one or more rows, found 0 (entity {0})")]
10    NoRowsFound(String),
11}
12
13impl From<ResponseError> for Error {
14    fn from(err: ResponseError) -> Self {
15        DbError::from(err).into()
16    }
17}
18
19///
20/// Response
21///
22
23#[derive(Debug)]
24pub struct Response<E: EntityKind>(pub Vec<(Key, E)>);
25
26impl<E> Response<E>
27where
28    E: EntityKind,
29{
30    // count
31    // not len, as it returns a u32 so could get confusing
32    #[must_use]
33    #[allow(clippy::cast_possible_truncation)]
34    /// Number of rows in the response, truncated to `u32`.
35    pub const fn count(&self) -> u32 {
36        self.0.len() as u32
37    }
38
39    #[must_use]
40    /// True when no rows were returned.
41    pub const fn is_empty(&self) -> bool {
42        self.0.is_empty()
43    }
44
45    ///
46    /// Key
47    ///
48
49    #[must_use]
50    /// First key in the response, if present.
51    pub fn key(&self) -> Option<Key> {
52        self.0.first().map(|(key, _)| *key)
53    }
54
55    /// Return the first key or an error if no rows were returned.
56    pub fn try_key(&self) -> Result<Key, Error> {
57        let key = self
58            .key()
59            .ok_or_else(|| ResponseError::NoRowsFound(E::PATH.to_string()))?;
60
61        Ok(key)
62    }
63
64    #[must_use]
65    /// Collect all keys in order.
66    pub fn keys(&self) -> Vec<Key> {
67        self.0.iter().map(|(key, _)| *key).collect()
68    }
69
70    /// Iterate keys without cloning entities.
71    pub fn keys_iter(self) -> impl Iterator<Item = Key> {
72        self.0.into_iter().map(|(key, _)| key)
73    }
74
75    ///
76    /// Pk
77    ///
78
79    #[must_use]
80    /// First primary key in the response, if present.
81    pub fn pk(&self) -> Option<E::PrimaryKey> {
82        self.0.first().map(|(_, e)| e.primary_key())
83    }
84
85    /// Return the first primary key or an error if no rows were returned.
86    pub fn try_pk(&self) -> Result<E::PrimaryKey, Error> {
87        let pk = self
88            .pk()
89            .ok_or_else(|| ResponseError::NoRowsFound(E::PATH.to_string()))?;
90
91        Ok(pk)
92    }
93
94    #[must_use]
95    /// Collect all primary keys in order.
96    pub fn pks(&self) -> Vec<E::PrimaryKey> {
97        self.0.iter().map(|(_, e)| e.primary_key()).collect()
98    }
99
100    /// Iterate primary keys without cloning entities.
101    pub fn pks_iter(self) -> impl Iterator<Item = E::PrimaryKey> {
102        self.0.into_iter().map(|(_, e)| e.primary_key())
103    }
104
105    ///
106    /// Entity
107    ///
108
109    #[must_use]
110    /// Consume the response and return the first entity.
111    pub fn entity(self) -> Option<E> {
112        self.0.into_iter().next().map(|(_, e)| e)
113    }
114
115    /// Return the first entity or an error if no rows were returned.
116    pub fn try_entity(self) -> Result<E, Error> {
117        let res = self
118            .entity()
119            .ok_or_else(|| ResponseError::NoRowsFound(E::PATH.to_string()))?;
120
121        Ok(res)
122    }
123
124    #[must_use]
125    /// Consume the response and collect all entities.
126    pub fn entities(self) -> Vec<E> {
127        self.0.into_iter().map(|(_, e)| e).collect()
128    }
129
130    /// Iterate entities without materializing a `Vec`.
131    pub fn entities_iter(self) -> impl Iterator<Item = E> {
132        self.0.into_iter().map(|(_, e)| e)
133    }
134
135    ///
136    /// View
137    ///
138
139    #[must_use]
140    /// Convert the first entity to its view type.
141    pub fn view(self) -> Option<E::ViewType> {
142        self.entity().map(|e| e.to_view())
143    }
144
145    /// Convert the first entity to its view type or error if empty.
146    pub fn try_view(self) -> Result<E::ViewType, Error> {
147        self.try_entity().map(|e| e.to_view())
148    }
149
150    #[must_use]
151    /// Convert all entities to their view types and collect them.
152    pub fn views(self) -> Vec<E::ViewType> {
153        self.entities().into_iter().map(|e| e.to_view()).collect()
154    }
155
156    /// Iterate over view types without cloning entities.
157    pub fn views_iter(self) -> impl Iterator<Item = E::ViewType> {
158        self.entities().into_iter().map(|e| e.to_view())
159    }
160}
161
162impl<E: EntityKind> IntoIterator for Response<E> {
163    type Item = (Key, E);
164    type IntoIter = std::vec::IntoIter<Self::Item>;
165
166    fn into_iter(self) -> Self::IntoIter {
167        self.0.into_iter()
168    }
169}