1use core::str::Utf8Error;
4use core::fmt::{self, Display, Formatter};
5use std::io;
6use std::error::Error as StdError;
7use std::borrow::Cow;
8use rusqlite::{Error as SqlError, types::FromSqlError};
9use thiserror::Error;
10#[cfg(feature = "not-nan")]
11use ordered_float::FloatIsNan;
12
13
14#[allow(missing_docs)]
16#[derive(Debug, Error)]
17pub enum Error {
18 #[error("UTF-8 error: {0}")]
19 Utf8Error(#[from] Utf8Error),
20
21 #[error("formatting error")]
22 Fmt(#[from] fmt::Error),
23
24 #[error("I/O error: {0}")]
25 Io(#[from] io::Error),
26
27 #[error("SQLite error: {0}")]
28 Sqlite(#[from] SqlError),
29
30 #[error("SQL conversion error: {0}")]
31 FromSql(#[from] FromSqlError),
32
33 #[error("query expects {expected} parameters but {actual} were bound")]
34 ParamCountMismatch {
35 expected: usize,
36 actual: usize,
37 },
38
39 #[error("expected {expected} rows but {actual} were returned")]
40 RowCountMismatch {
41 expected: RowCount,
42 actual: RowCount,
43 },
44
45 #[error("expected {expected} columns but result set has {actual}")]
46 ColumnCountMismatch {
47 expected: usize,
48 actual: usize,
49 },
50
51 #[error("unknown parameter name `{0}`")]
52 UnknownParam(Cow<'static, str>),
53
54 #[error(transparent)]
55 Other(#[from] Box<dyn StdError + Send + Sync + 'static>),
56}
57
58impl Error {
59 pub fn other<E>(error: E) -> Self
61 where
62 E: StdError + Send + Sync + 'static
63 {
64 Error::Other(Box::new(error))
65 }
66
67 pub fn message<T: Display>(message: T) -> Self {
69 Error::Other(message.to_string().into())
70 }
71
72 pub fn unknown_param(name: &'static str) -> Self {
74 Error::UnknownParam(Cow::Borrowed(name))
75 }
76
77 pub fn unknown_param_dyn<T: Display>(message: T) -> Self {
79 Error::UnknownParam(Cow::Owned(message.to_string()))
80 }
81}
82
83#[cfg(feature = "not-nan")]
84impl From<FloatIsNan> for Error {
85 fn from(error: FloatIsNan) -> Self {
86 Error::other(error)
87 }
88}
89
90pub type Result<T, E = Error> = core::result::Result<T, E>;
92
93#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
96pub struct RowCount {
97 pub min: usize,
99 pub max: Option<usize>,
102}
103
104impl RowCount {
105 pub const fn new(min: usize, max: usize) -> Self {
107 RowCount {
108 min,
109 max: Some(max),
110 }
111 }
112
113 pub const fn exactly(count: usize) -> Self {
115 RowCount {
116 min: count,
117 max: Some(count),
118 }
119 }
120
121 pub const fn at_least(min: usize) -> Self {
123 RowCount {
124 min,
125 max: None,
126 }
127 }
128
129 pub const fn at_most(max: usize) -> Self {
131 RowCount {
132 min: 0,
133 max: Some(max),
134 }
135 }
136}
137
138impl Display for RowCount {
139 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
140 let min = self.min;
141 if let Some(max) = self.max {
142 if min == max {
143 write!(f, "exactly {min}")
144 } else if min == 0 {
145 write!(f, "at most {max}")
146 } else {
147 write!(f, "{min}...{max}")
148 }
149 } else {
150 write!(f, "at least {min}")
151 }
152 }
153}