Introduce Value representing an arbitrary value for binding and reading

This commit is contained in:
Ivan Ukhov 2015-08-02 20:34:27 -04:00
parent 611beaebb9
commit 825afe4537
2 changed files with 64 additions and 14 deletions

View File

@ -121,10 +121,25 @@ pub enum Type {
Float, Float,
/// The integer type. /// The integer type.
Integer, Integer,
/// The null type.
Null,
/// The string type. /// The string type.
String, String,
/// The null type.
Null,
}
/// A typed value.
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
/// Binary data.
Binary(Vec<u8>),
/// A floating-point number.
Float(f64),
/// An integer.
Integer(i64),
/// A string.
String(String),
/// A null value.
Null,
} }
impl fmt::Display for Error { impl fmt::Display for Error {

View File

@ -2,7 +2,7 @@ use ffi;
use libc::{c_double, c_int}; use libc::{c_double, c_int};
use std::marker::PhantomData; use std::marker::PhantomData;
use {Result, Type}; use {Result, Type, Value};
/// A prepared statement. /// A prepared statement.
pub struct Statement<'l> { pub struct Statement<'l> {
@ -51,8 +51,8 @@ impl<'l> Statement<'l> {
ffi::SQLITE_BLOB => Type::Binary, ffi::SQLITE_BLOB => Type::Binary,
ffi::SQLITE_FLOAT => Type::Float, ffi::SQLITE_FLOAT => Type::Float,
ffi::SQLITE_INTEGER => Type::Integer, ffi::SQLITE_INTEGER => Type::Integer,
ffi::SQLITE_NULL => Type::Null,
ffi::SQLITE_TEXT => Type::String, ffi::SQLITE_TEXT => Type::String,
ffi::SQLITE_NULL => Type::Null,
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -100,6 +100,31 @@ impl<'l> Drop for Statement<'l> {
} }
} }
impl Bindable for Value {
fn bind(&self, statement: &mut Statement, i: usize) -> Result<()> {
match self {
&Value::Binary(ref value) => (value as &[u8]).bind(statement, i),
&Value::Float(value) => value.bind(statement, i),
&Value::Integer(value) => value.bind(statement, i),
&Value::String(ref value) => (value as &str).bind(statement, i),
&Value::Null => ().bind(statement, i),
}
}
}
impl<'l> Bindable for &'l [u8] {
#[inline]
fn bind(&self, statement: &mut Statement, i: usize) -> Result<()> {
debug_assert!(i > 0, "the indexing starts from 1");
unsafe {
ok!(statement.raw.1, ffi::sqlite3_bind_blob(statement.raw.0, i as c_int,
self.as_ptr() as *const _,
self.len() as c_int, None));
}
Ok(())
}
}
impl Bindable for f64 { impl Bindable for f64 {
#[inline] #[inline]
fn bind(&self, statement: &mut Statement, i: usize) -> Result<()> { fn bind(&self, statement: &mut Statement, i: usize) -> Result<()> {
@ -124,6 +149,17 @@ impl Bindable for i64 {
} }
} }
impl Bindable for () {
#[inline]
fn bind(&self, statement: &mut Statement, i: usize) -> Result<()> {
debug_assert!(i > 0, "the indexing starts from 1");
unsafe {
ok!(statement.raw.1, ffi::sqlite3_bind_null(statement.raw.0, i as c_int));
}
Ok(())
}
}
impl<'l> Bindable for &'l str { impl<'l> Bindable for &'l str {
#[inline] #[inline]
fn bind(&self, statement: &mut Statement, i: usize) -> Result<()> { fn bind(&self, statement: &mut Statement, i: usize) -> Result<()> {
@ -136,16 +172,15 @@ impl<'l> Bindable for &'l str {
} }
} }
impl<'l> Bindable for &'l [u8] { impl Readable for Value {
#[inline] fn read(statement: &Statement, i: usize) -> Result<Self> {
fn bind(&self, statement: &mut Statement, i: usize) -> Result<()> { Ok(match statement.kind(i) {
debug_assert!(i > 0, "the indexing starts from 1"); Type::Binary => Value::Binary(try!(Readable::read(statement, i))),
unsafe { Type::Float => Value::Float(try!(Readable::read(statement, i))),
ok!(statement.raw.1, ffi::sqlite3_bind_blob(statement.raw.0, i as c_int, Type::Integer => Value::Integer(try!(Readable::read(statement, i))),
self.as_ptr() as *const _, Type::String => Value::Binary(try!(Readable::read(statement, i))),
self.len() as c_int, None)); Type::Null => Value::Null,
} })
Ok(())
} }
} }