Skip to main content

watchword_core/
sqll015.rs

1//! sqll 0.15 `BindValue`, `Bind` and `FromColumn` for [`UserId`], [`Role`],
2//! [`Access`] and [`Method`].
3
4use sqll015::{Bind, BindValue, Code, Error, FromColumn, Index, Result, Statement, ty};
5
6use crate::{Access, Method, Role, UserId};
7
8#[cfg(test)]
9mod tests;
10
11/// Binds as an SQLite integer with the same bits, so an `INTEGER PRIMARY KEY`
12/// holds every id a store assigns: every id binds, and one beyond `i64::MAX`
13/// binds as a negative integer that no stored user has.
14#[cfg_attr(watchword_docsrs, doc(cfg(feature = "sqll015")))]
15impl BindValue for UserId {
16    #[inline]
17    fn bind_value(&self, stmt: &mut Statement, index: Index) -> Result<()> {
18        (self.0 as i64).bind_value(stmt, index)
19    }
20}
21
22/// Binds as the statement's only parameter, as [`BindValue`] does.
23#[cfg_attr(watchword_docsrs, doc(cfg(feature = "sqll015")))]
24impl Bind for UserId {
25    const COUNT: usize = 1;
26
27    #[inline]
28    fn bind(&self, stmt: &mut Statement) -> Result<()> {
29        self.bind_value(stmt, Index::BIND)
30    }
31}
32
33/// Reads an integer column with the same bits, the reverse of [`BindValue`].
34#[cfg_attr(watchword_docsrs, doc(cfg(feature = "sqll015")))]
35impl FromColumn<'_> for UserId {
36    type Type = ty::Integer;
37
38    #[inline]
39    fn from_column(stmt: &Statement, index: ty::Integer) -> Result<Self> {
40        Ok(UserId(i64::from_column(stmt, index)? as u64))
41    }
42}
43
44/// Implements sqll's traits for a fieldless enum through its stored name.
45macro_rules! named {
46    ($ty:ident, $what:literal) => {
47        #[doc = concat!("Binds the ", $what, "'s name, [`", stringify!($ty), "::as_str`], as text.")]
48        #[cfg_attr(watchword_docsrs, doc(cfg(feature = "sqll015")))]
49        impl BindValue for $ty {
50            #[inline]
51            fn bind_value(&self, stmt: &mut Statement, index: Index) -> Result<()> {
52                self.as_str().bind_value(stmt, index)
53            }
54        }
55
56        /// Binds as the statement's only parameter, as [`BindValue`] does.
57        #[cfg_attr(watchword_docsrs, doc(cfg(feature = "sqll015")))]
58        impl Bind for $ty {
59            const COUNT: usize = 1;
60
61            #[inline]
62            fn bind(&self, stmt: &mut Statement) -> Result<()> {
63                self.bind_value(stmt, Index::BIND)
64            }
65        }
66
67        #[doc = concat!("Reads a text column holding the ", $what, "'s name, failing with")]
68        #[doc = concat!("[`Code::MISMATCH`] on a name that is not one.")]
69        #[cfg_attr(watchword_docsrs, doc(cfg(feature = "sqll015")))]
70        impl<'stmt> FromColumn<'stmt> for $ty {
71            type Type = ty::Text;
72
73            #[inline]
74            fn from_column(stmt: &'stmt Statement, index: ty::Text) -> Result<Self> {
75                let name = <&str>::from_column(stmt, index)?;
76
77                name.parse().map_err(|_| {
78                    Error::new(
79                        Code::MISMATCH,
80                        format_args!(concat!("unknown ", $what, " {:?}"), name),
81                    )
82                })
83            }
84        }
85    };
86}
87
88named!(Role, "role");
89named!(Access, "access state");
90named!(Method, "sign-in method");