use core::str::Utf8Error;
use core::fmt::{self, Display, Formatter};
use std::io;
use std::error::Error as StdError;
use std::borrow::Cow;
use rusqlite::{Error as SqlError, types::FromSqlError};
use thiserror::Error;
#[cfg(feature = "not-nan")]
use ordered_float::FloatIsNan;
#[allow(missing_docs)]
#[derive(Debug, Error)]
pub enum Error {
#[error("UTF-8 error: {0}")]
Utf8Error(#[from] Utf8Error),
#[error("formatting error")]
Fmt(#[from] fmt::Error),
#[error("I/O error: {0}")]
Io(#[from] io::Error),
#[error("SQLite error: {0}")]
Sqlite(#[from] SqlError),
#[error("SQL conversion error: {0}")]
FromSql(#[from] FromSqlError),
#[error("query expects {expected} parameters but {actual} were bound")]
ParamCountMismatch {
expected: usize,
actual: usize,
},
#[error("expected {expected} rows but {actual} were returned")]
RowCountMismatch {
expected: RowCount,
actual: RowCount,
},
#[error("expected {expected} columns but result set has {actual}")]
ColumnCountMismatch {
expected: usize,
actual: usize,
},
#[error("unknown parameter name `{0}`")]
UnknownParam(Cow<'static, str>),
#[error(transparent)]
Other(#[from] Box<dyn StdError + Send + Sync + 'static>),
}
impl Error {
pub fn other<E>(error: E) -> Self
where
E: StdError + Send + Sync + 'static
{
Error::Other(Box::new(error))
}
pub fn message<T: Display>(message: T) -> Self {
Error::Other(message.to_string().into())
}
pub fn unknown_param(name: &'static str) -> Self {
Error::UnknownParam(Cow::Borrowed(name))
}
pub fn unknown_param_dyn<T: Display>(message: T) -> Self {
Error::UnknownParam(Cow::Owned(message.to_string()))
}
}
#[cfg(feature = "not-nan")]
impl From<FloatIsNan> for Error {
fn from(error: FloatIsNan) -> Self {
Error::other(error)
}
}
pub type Result<T, E = Error> = core::result::Result<T, E>;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct RowCount {
pub min: usize,
pub max: Option<usize>,
}
impl RowCount {
pub const fn new(min: usize, max: usize) -> Self {
RowCount {
min,
max: Some(max),
}
}
pub const fn exactly(count: usize) -> Self {
RowCount {
min: count,
max: Some(count),
}
}
pub const fn at_least(min: usize) -> Self {
RowCount {
min,
max: None,
}
}
pub const fn at_most(max: usize) -> Self {
RowCount {
min: 0,
max: Some(max),
}
}
}
impl Display for RowCount {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let min = self.min;
if let Some(max) = self.max {
if min == max {
write!(f, "exactly {min}")
} else if min == 0 {
write!(f, "at most {max}")
} else {
write!(f, "{min}...{max}")
}
} else {
write!(f, "at least {min}")
}
}
}