Get rid of ErrorKind

This commit is contained in:
Ivan Ukhov 2015-08-01 17:38:08 -04:00
parent ba257b99bc
commit 167ac90578
2 changed files with 52 additions and 144 deletions

View File

@ -1,135 +0,0 @@
use ffi;
use std::convert::{From, Into};
use std::{error, fmt};
/// An error.
#[derive(Debug)]
pub struct Error {
pub kind: ErrorKind,
pub message: Option<String>,
}
macro_rules! declare(
($($left:ident => $right:ident,)*) => (
/// An error kind.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorKind {
$($left = ffi::$right as isize,)*
Unknown,
}
impl From<isize> for ErrorKind {
fn from(code: isize) -> ErrorKind {
match code as ::libc::c_int {
$(ffi::$right => ErrorKind::$left,)*
_ => ErrorKind::Unknown,
}
}
}
);
);
declare!(
Abort => SQLITE_ABORT,
Authorization => SQLITE_AUTH,
Busy => SQLITE_BUSY,
CantOpen => SQLITE_CANTOPEN,
Constraint => SQLITE_CONSTRAINT,
Corruption => SQLITE_CORRUPT,
Done => SQLITE_DONE,
Empty => SQLITE_EMPTY,
Error => SQLITE_ERROR,
Format => SQLITE_FORMAT,
Full => SQLITE_FULL,
Internal => SQLITE_INTERNAL,
Interruption => SQLITE_INTERRUPT,
IOError => SQLITE_IOERR,
Locked => SQLITE_LOCKED,
Mismatch => SQLITE_MISMATCH,
Misuse => SQLITE_MISUSE,
NoLargeFileSupport => SQLITE_NOLFS,
NoMemory => SQLITE_NOMEM,
NotDatabase => SQLITE_NOTADB,
NotFound => SQLITE_NOTFOUND,
Notice => SQLITE_NOTICE,
OK => SQLITE_OK,
Permission => SQLITE_PERM,
Protocol => SQLITE_PROTOCOL,
Range => SQLITE_RANGE,
ReadOnly => SQLITE_READONLY,
Row => SQLITE_ROW,
Schema => SQLITE_SCHEMA,
TooBig => SQLITE_TOOBIG,
Warning => SQLITE_WARNING,
);
impl<T> From<T> for Error where T: Into<String> {
#[inline]
fn from(message: T) -> Error {
Error { kind: ErrorKind::Unknown, message: Some(message.into()) }
}
}
impl From<ErrorKind> for Error {
#[inline]
fn from(kind: ErrorKind) -> Error {
Error { kind: kind, message: None }
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self.message {
Some(ref message) => message.fmt(formatter),
_ => self.kind.fmt(formatter),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match self.message {
Some(ref message) => message,
_ => "an SQLite error",
}
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self {
ErrorKind::Unknown => write!(formatter, "an unknown SQLite result code"),
_ => write!(formatter, "SQLite result code {}", *self as isize),
}
}
}
pub fn last(raw: *mut ffi::sqlite3) -> Option<Error> {
unsafe {
let code = ffi::sqlite3_errcode(raw);
if code == ffi::SQLITE_OK {
return None;
}
let message = ffi::sqlite3_errmsg(raw);
if message.is_null() {
return None;
}
Some(Error {
kind: ErrorKind::from(code as isize),
message: Some(c_str_to_string!(message)),
})
}
}
#[cfg(test)]
mod tests {
use super::ErrorKind;
#[test]
fn fmt() {
assert_eq!(format!("{}", ErrorKind::OK),
String::from("SQLite result code 0"));
assert_eq!(format!("{}", ErrorKind::from(777)),
String::from("an unknown SQLite result code"));
}
}

View File

@ -48,14 +48,16 @@
extern crate libc;
extern crate sqlite3_sys as ffi;
use std::{error, fmt};
macro_rules! raise(
($message:expr) => (return Err(::Error::from($message)));
($message:expr) => (return Err(::Error { code: None, message: Some($message.to_string()) }));
);
macro_rules! error(
($connection:expr, $code:expr) => (match ::error::last($connection) {
($connection:expr, $code:expr) => (match ::last_error($connection) {
Some(error) => return Err(error),
_ => return Err(::Error::from(::ErrorKind::from($code as isize))),
_ => return Err(::Error { code: Some($code as isize), message: None }),
});
);
@ -66,7 +68,7 @@ macro_rules! ok(
});
($result:expr) => (match $result {
::ffi::SQLITE_OK => {},
code => return Err(::Error::from(::ErrorKind::from(code as isize))),
code => return Err(::Error { code: Some(code as isize), message: None }),
});
);
@ -98,6 +100,18 @@ macro_rules! str_to_cstr(
});
);
/// An error.
#[derive(Debug)]
pub struct Error {
/// The error code.
pub code: Option<isize>,
/// The error message.
pub message: Option<String>,
}
/// A result.
pub type Result<T> = std::result::Result<T, Error>;
/// A data type.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Type {
@ -113,19 +127,48 @@ pub enum Type {
String,
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match (self.code, &self.message) {
(Some(code), &Some(ref message)) => write!(formatter, "{} (code {})", message, code),
(Some(code), _) => write!(formatter, "an SQLite error (code {})", code),
(_, &Some(ref message)) => message.fmt(formatter),
_ => write!(formatter, "an SQLite error"),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match self.message {
Some(ref message) => message,
_ => "an SQLite error",
}
}
}
mod connection;
mod error;
mod statement;
pub use connection::Connection;
pub use error::{Error, ErrorKind};
pub use statement::{Statement, State, Parameter, Value};
/// A result.
pub type Result<T> = std::result::Result<T, Error>;
/// Open a connection to a new or existing database.
#[inline]
pub fn open<T: AsRef<std::path::Path>>(path: T) -> Result<Connection> {
Connection::open(path)
}
fn last_error(raw: *mut ffi::sqlite3) -> Option<Error> {
unsafe {
let code = ffi::sqlite3_errcode(raw);
if code == ffi::SQLITE_OK {
return None;
}
let message = ffi::sqlite3_errmsg(raw);
if message.is_null() {
return None;
}
Some(Error { code: Some(code as isize), message: Some(c_str_to_string!(message)) })
}
}