dbent/
lib.rs

1#![doc = include_str!("../README.md")]
2#![deny(missing_docs)]
3
4use core::fmt;
5use thiserror::Error;
6
7#[cfg(feature = "rusqlite")]
8use rusqlite::types::{
9    FromSql,
10    FromSqlResult,
11    ToSql,
12    ToSqlOutput,
13    ValueRef
14};
15
16#[cfg(feature = "serde")]
17use serde::{Serialize, Deserialize};
18
19#[cfg(test)]
20mod tests;
21
22//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
23//<<>><=========================  TRAITS  ===========================><<>>//
24//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
25
26/// Trait for entities to define which struct field holds their primary key
27pub trait Keyed {
28    /// The type of the Key
29    type KeyType;
30
31    /// Returns the Key for the Entity
32    fn key(&self) -> Result<&Key<Self::KeyType>>;
33}
34
35/// Trait for entities that optionally have a label defined
36///
37/// This is needed for using EntityLabels.
38pub trait Label {
39    /// The type of the Label
40    type LabelType;
41
42    /// Returns the Label for the Entity
43    fn label(&self) -> Result<&Self::LabelType>;
44}
45
46/// Struct that holds both key and label for convenience
47#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
48#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)]
49pub struct Tag {
50    /// Entity key
51    pub key: String,
52    /// Entity label
53    pub label: String,
54}
55
56/// Convenience trait for returning both key and label as a Tag
57///
58/// There is a blanket implementation for all entities that
59/// implement both Keyed and Label
60pub trait Tagged {
61    /// Returns the Tag for the Entity
62    fn tag(&self) -> Result<Tag>;
63    /// The entity does not have a valid tag if it doesn't have a Key
64    fn has_tag(&self) -> bool;
65}
66
67impl<K, T, L> Tagged for T
68where
69    T: Keyed<KeyType = K> + Label<LabelType = L>,
70    K: fmt::Display,
71    L: fmt::Display,
72{
73    fn tag(&self) -> Result<Tag> {
74        Ok(
75            Tag {
76                key: self.key()?.to_string(),
77                label: self.label()?.to_string(),
78            }
79        )
80    }
81
82    fn has_tag(&self) -> bool {
83        self.key().map(|v| v.is_some()).unwrap_or(false)
84    }
85}
86
87//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
88//<<>><==========================  KEY  =============================><<>>//
89//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
90
91/// A newtype for defining a Key on entities
92#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
93#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)]
94pub struct Key<K>(pub Option<K>);
95
96impl<K> Key<K> {
97    /// Creates a new Key from a value `K`
98    pub fn new(value: K) -> Self {
99        Self(Some(value))
100    }
101
102    /// Converts this Key into an Entity
103    pub fn into_entity<T>(self) -> Entity<K, T> {
104        Entity::Key(self)
105    }
106
107    /// Converts this Key to an Entity
108    pub fn to_entity<T>(&self) -> Entity<K, T> where K: Clone {
109        Entity::Key(self.clone())
110    }
111}
112
113impl<K> core::ops::Deref for Key<K> {
114    type Target = Option<K>;
115
116    fn deref(&self) -> &Self::Target {
117        &self.0
118    }
119}
120
121impl<K> core::ops::DerefMut for Key<K> {
122    fn deref_mut(&mut self) -> &mut Self::Target {
123        &mut self.0
124    }
125}
126
127impl<K: fmt::Display> fmt::Display for Key<K> {
128    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129        match &self.0 {
130            Some(value) => write!(f, "{value}"),
131            None => write!(f, "None"),
132        }
133    }
134}
135
136impl<K> From<Option<K>> for Key<K> {
137    fn from(value: Option<K>) -> Self {
138        Self(value)
139    }
140}
141
142impl<K: Clone> From<&Option<K>> for Key<K> {
143    fn from(value: &Option<K>) -> Self {
144        Self(value.as_ref().cloned())
145    }
146}
147
148#[cfg(feature = "rusqlite")]
149impl<K: FromSql> FromSql for Key<K> {
150    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
151        match value {
152            ValueRef::Null => Ok(Key(None)),
153            _ => FromSql::column_result(value).map(|v| Key(Some(v))),
154        }
155    }
156}
157
158#[cfg(feature = "rusqlite")]
159impl<K: ToSql> ToSql for Key<K> {
160    fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
161        self.0.to_sql()
162    }
163}
164
165//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
166//<<>><=========================  ENTITY  ===========================><<>>//
167//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
168
169/// Enum for defining a simple entity that will hold a Key
170/// or the created/fetched data
171#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
172#[derive(Clone, PartialEq, Eq, Debug, Default)]
173pub enum Entity<K, T> {
174    /// Key of the entity
175    Key(Key<K>),
176    /// Created/Fetched data for the entity
177    Data(Box<T>),
178    #[default]
179    /// For when you have no data to fill or null from database
180    None,
181}
182
183impl<K, T> Keyed for Entity<K, T>
184where
185    T: Keyed<KeyType = K>,
186{
187    type KeyType = K;
188
189    fn key(&self) -> Result<&Key<Self::KeyType>> {
190        match self {
191            Entity::Key(key) => Ok(key),
192            Entity::Data(data) => data.key(),
193            Entity::None => Err(Error::EntityEmpty),
194        }
195    }
196}
197
198impl<K, T> Entity<K, T> {
199    /// Returns the data if it exists and was fetched/created
200    pub fn data(&self) -> Result<&T> {
201        match self {
202            Entity::Data(data) => Ok(data),
203            Entity::Key(_) => Err(Error::EntityNotFetched),
204            Entity::None => Err(Error::EntityEmpty),
205        }
206    }
207
208    /// Returns the mutable data if it exists and was fetched/created
209    pub fn data_mut(&mut self) -> Result<&mut T> {
210        match self {
211            Entity::Data(ref mut data) => Ok(data),
212            Entity::Key(_) => Err(Error::EntityNotFetched),
213            Entity::None => Err(Error::EntityEmpty),
214        }
215    }
216
217    /// Is this a Key variant?
218    pub fn is_key(&self) -> bool {
219        matches!(self, Self::Key(..))
220    }
221
222    /// Is this a Data variant?
223    pub fn is_data(&self) -> bool {
224        matches!(self, Self::Data(..))
225    }
226
227    /// Is this a None variant?
228    pub fn is_none(&self) -> bool {
229        matches!(self, Self::None)
230    }
231}
232
233impl<K, T> From<T> for Entity<K, T> {
234    fn from(entity: T) -> Self {
235        Self::Data(Box::new(entity))
236    }
237}
238
239//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
240//<<>><======================  ENTITY LABEL  ========================><<>>//
241//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
242
243/// Enum for situations when you want to define not just a Key but also a Label
244///
245/// This may be useful for faster access to avoid an extra LEFT JOIN or because
246/// you may have missing data, thus no Key, and having the Label makes the entity
247/// still valid
248#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
249#[derive(Clone, PartialEq, Eq, Debug, Default)]
250pub enum EntityLabel<K, T, L> {
251    /// Key and Label for this entity
252    KeyLabel(Key<K>, L),
253    /// Created/Fetched data for the entity
254    Data(Box<T>),
255    /// For when you have no data to fill or null from database
256    #[default]
257    None,
258}
259
260impl<K, T, L> Keyed for EntityLabel<K, T, L>
261where
262    T: Keyed<KeyType = K>,
263{
264    type KeyType = K;
265
266    fn key(&self) -> Result<&Key<Self::KeyType>> {
267        match self {
268            EntityLabel::KeyLabel(key, _) => Ok(key),
269            EntityLabel::Data(data) => data.key(),
270            EntityLabel::None => Err(Error::EntityLabelEmpty),
271        }
272    }
273}
274
275impl<K, T, L> Label for EntityLabel<K, T, L>
276where
277    T: Label<LabelType = L>,
278{
279    type LabelType = L;
280
281    fn label(&self) -> Result<&Self::LabelType> {
282        match self {
283            EntityLabel::KeyLabel(_, label) => Ok(label),
284            EntityLabel::Data(data) => data.label(),
285            EntityLabel::None => Err(Error::EntityLabelEmpty),
286        }
287    }
288}
289
290impl<K, T, L> EntityLabel<K, T, L> {
291    /// Returns the data if it exists and was fetched/created
292    pub fn data(&self) -> Result<&T> {
293        match self {
294            EntityLabel::Data(data) => Ok(data),
295            EntityLabel::KeyLabel(..) => Err(Error::EntityLabelNotFetched),
296            EntityLabel::None => Err(Error::EntityLabelEmpty),
297        }
298    }
299
300    /// Returns the mutable data if it exists and was fetched/created
301    pub fn data_mut(&mut self) -> Result<&mut T> {
302        match self {
303            EntityLabel::Data(ref mut data) => Ok(data),
304            EntityLabel::KeyLabel(..) => Err(Error::EntityLabelNotFetched),
305            EntityLabel::None => Err(Error::EntityLabelEmpty),
306        }
307    }
308
309    /// Is this a KeyLabel variant?
310    pub fn is_keylabel(&self) -> bool {
311        matches!(self, Self::KeyLabel(..))
312    }
313
314    /// Is this a Data variant?
315    pub fn is_data(&self) -> bool {
316        matches!(self, Self::Data(..))
317    }
318
319    /// Is this a None variant?
320    pub fn is_none(&self) -> bool {
321        matches!(self, Self::None)
322    }
323}
324
325impl<K, T, L> From<T> for EntityLabel<K, T, L> {
326    fn from(entity: T) -> Self {
327        Self::Data(Box::new(entity))
328    }
329}
330
331//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
332//<<>><==========================  MANY  ============================><<>>//
333//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
334
335/// Enum for defining one-to-many or many-to-many relationships
336#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
337#[derive(Clone, PartialEq, Eq, Debug, Default)]
338pub enum Many<T> {
339    /// This holds the created/fetched data in a vector
340    Data(Vec<T>),
341    /// For when the data exists but is not fetched
342    NotFetched,
343    /// For when you have no data to fill or fetch from the DB
344    #[default]
345    None,
346}
347
348impl<T> Many<T> {
349    /// Returns the `Vec` of data if they exist and were fetched/created
350    pub fn data(&self) -> Result<&Vec<T>> {
351        match self {
352            Many::Data(data) => Ok(data),
353            Many::NotFetched => Err(Error::ManyNotFetched),
354            Many::None => Err(Error::ManyEmpty),
355        }
356    }
357
358    /// Returns the mutable `Vec` of data if they exist and were fetched/created
359    pub fn data_mut(&mut self) -> Result<&mut Vec<T>> {
360        match self {
361            Many::Data(ref mut data) => Ok(data),
362            Many::NotFetched => Err(Error::ManyNotFetched),
363            Many::None => Err(Error::ManyEmpty),
364        }
365    }
366
367    /// Is this a Data variant?
368    pub fn is_data(&self) -> bool {
369        matches!(self, Self::Data(..))
370    }
371
372    /// Is this a NotFetched variant?
373    pub fn is_not_fetched(&self) -> bool {
374        matches!(self, Self::NotFetched)
375    }
376
377    /// Is this a None variant?
378    pub fn is_none(&self) -> bool {
379        matches!(self, Self::None)
380    }
381}
382
383impl<T> From<Vec<T>> for Many<T> {
384    fn from(entities: Vec<T>) -> Self {
385        Self::Data(entities)
386    }
387}
388
389//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
390//<<>><==========================  ERROR  ===========================><<>>//
391//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
392
393/// The error type for all errors in this crate
394#[derive(Error, Debug)]
395pub enum Error {
396    /// for an empty entity
397    #[error("nothing set for this Entity")]
398    EntityEmpty,
399    /// for an empty entity label
400    #[error("nothing set for this EntityLabel")]
401    EntityLabelEmpty,
402    /// for an entity that was not fetched
403    #[error("data was not fetched from the database for this Entity")]
404    EntityNotFetched,
405    /// for an entity label that was not fetched
406    #[error("data was not fetched from the database for this EntityLabel")]
407    EntityLabelNotFetched,
408    /// for a Many that has no data
409    #[error("no data set for this Many")]
410    ManyEmpty,
411    /// for a Many that has no data fetched
412    #[error("data were not fetched from the database for this Many")]
413    ManyNotFetched,
414}
415
416/// The result typedef for this crate for convenience
417pub type Result<T> = core::result::Result<T, Error>;
418
419//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
420//<<>><======================  CONVENIENCE  =========================><<>>//
421//<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>//
422
423/// An Int typedef for convenience to be used as Key number
424pub type Int = usize;
425/// An Entity that has an Int as key
426pub type EntityInt<T> = Entity<Int, T>;
427/// An Entity that has a String as key
428pub type EntityString<T> = Entity<String, T>;
429/// An EntityLabel that has an Int as key
430pub type EntityLabelInt<T> = EntityLabel<Int, T, String>;
431/// An EntityLabel that has a String as key
432pub type EntityLabelString<T> = EntityLabel<String, T, String>;
433
434pub mod prelude {
435    //! Convenience re-export of common members
436    //!
437    //! This module simplifies importing of common items, while excluding
438    //! ones that can easily clash with other crates.
439    //!
440    //! ```
441    //! use dbent::prelude::*;
442    //! ```
443
444    #[cfg(feature = "derive")]
445    pub use dbent_derive::{
446        Entity,
447        Label,
448    };
449
450    pub use crate::{
451        Key,
452        Keyed,
453        Label,
454        Tagged,
455        Tag,
456        Entity,
457        EntityLabel,
458        Many,
459        Int,
460        EntityInt,
461        EntityString,
462        EntityLabelInt,
463        EntityLabelString,
464    };
465}
466