use std::{convert, result};
use std::marker::PhantomData;
use super::{Statement, Error, Result};
use types::{FromSql, FromSqlError};
use statement::StatementCrateImpl;
pub struct Rows<'stmt> {
stmt: Option<&'stmt Statement<'stmt>>,
}
impl<'stmt> Rows<'stmt> {
fn reset(&mut self) {
if let Some(stmt) = self.stmt.take() {
stmt.reset();
}
}
pub fn next<'a>(&'a mut self) -> Option<Result<Row<'a, 'stmt>>> {
self.stmt
.and_then(|stmt| match stmt.step() {
Ok(true) => {
Some(Ok(Row {
stmt: stmt,
phantom: PhantomData,
}))
}
Ok(false) => {
self.reset();
None
}
Err(err) => {
self.reset();
Some(Err(err))
}
})
}
}
pub trait RowsCrateImpl<'stmt> {
fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt>;
fn get_expected_row<'a>(&'a mut self) -> Result<Row<'a, 'stmt>>;
}
impl<'stmt> RowsCrateImpl<'stmt> for Rows<'stmt> {
fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> {
Rows { stmt: Some(stmt) }
}
fn get_expected_row<'a>(&'a mut self) -> Result<Row<'a, 'stmt>> {
match self.next() {
Some(row) => row,
None => Err(Error::QueryReturnedNoRows),
}
}
}
impl<'stmt> Drop for Rows<'stmt> {
fn drop(&mut self) {
self.reset();
}
}
pub struct MappedRows<'stmt, F> {
rows: Rows<'stmt>,
map: F,
}
pub trait MappedRowsCrateImpl<'stmt, T, F> {
fn new(rows: Rows<'stmt>, f: F) -> MappedRows<'stmt, F>;
}
impl<'stmt, T, F> MappedRowsCrateImpl<'stmt, T, F> for MappedRows<'stmt, F>
where F: FnMut(&Row) -> T
{
fn new(rows: Rows<'stmt>, f: F) -> MappedRows<'stmt, F> {
MappedRows { rows: rows, map: f }
}
}
impl<'conn, T, F> Iterator for MappedRows<'conn, F>
where F: FnMut(&Row) -> T
{
type Item = Result<T>;
fn next(&mut self) -> Option<Result<T>> {
let map = &mut self.map;
self.rows
.next()
.map(|row_result| row_result.map(|row| (map)(&row)))
}
}
pub struct AndThenRows<'stmt, F> {
rows: Rows<'stmt>,
map: F,
}
pub trait AndThenRowsCrateImpl<'stmt, T, E, F> {
fn new(rows: Rows<'stmt>, f: F) -> AndThenRows<'stmt, F>;
}
impl<'stmt, T, E, F> AndThenRowsCrateImpl<'stmt, T, E, F> for AndThenRows<'stmt, F>
where F: FnMut(&Row) -> result::Result<T, E>
{
fn new(rows: Rows<'stmt>, f: F) -> AndThenRows<'stmt, F> {
AndThenRows { rows: rows, map: f }
}
}
impl<'stmt, T, E, F> Iterator for AndThenRows<'stmt, F>
where E: convert::From<Error>,
F: FnMut(&Row) -> result::Result<T, E>
{
type Item = result::Result<T, E>;
fn next(&mut self) -> Option<Self::Item> {
let map = &mut self.map;
self.rows
.next()
.map(|row_result| row_result.map_err(E::from).and_then(|row| (map)(&row)))
}
}
pub struct Row<'a, 'stmt> {
stmt: &'stmt Statement<'stmt>,
phantom: PhantomData<&'a ()>,
}
impl<'a, 'stmt> Row<'a, 'stmt> {
pub fn get<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
self.get_checked(idx).unwrap()
}
pub fn get_checked<I: RowIndex, T: FromSql>(&self, idx: I) -> Result<T> {
let idx = try!(idx.idx(self.stmt));
let value = self.stmt.value_ref(idx);
FromSql::column_result(value).map_err(|err| match err {
FromSqlError::InvalidType => {
Error::InvalidColumnType(idx,
value.data_type())
}
FromSqlError::OutOfRange(i) => {
Error::IntegralValueOutOfRange(idx, i)
}
FromSqlError::Other(err) => {
Error::FromSqlConversionFailure(idx as usize, value.data_type(), err)
}
})
}
pub fn column_count(&self) -> i32 {
self.stmt.column_count()
}
}
pub trait RowIndex {
fn idx(&self, stmt: &Statement) -> Result<i32>;
}
impl RowIndex for i32 {
#[inline]
fn idx(&self, stmt: &Statement) -> Result<i32> {
if *self < 0 || *self >= stmt.column_count() {
Err(Error::InvalidColumnIndex(*self))
} else {
Ok(*self)
}
}
}
impl<'a> RowIndex for &'a str {
#[inline]
fn idx(&self, stmt: &Statement) -> Result<i32> {
stmt.column_index(*self)
}
}