<commit_before>use std::collections::HashMap;
use aggregate::{Aggregate, AggregateCall};
use answer::Answer;
use data::Data;
use expr::Expr;
use query::{Query, SortDirection};
use row::Row;
use source::{Source, SourceError};

#[derive(Clone, Debug, PartialEq)]
pub enum ExecuteError {
    SourceError(String),
    InvalidOrderClause(Expr),
}

impl From<SourceError> for ExecuteError {
    fn from(e: SourceError) -> Self {
        ExecuteError::SourceError(e.description)
    }
}

struct Executor {
    query: Query,
    aggregate_calls: Vec<AggregateCall>,
    order_indices: Vec<(usize, SortDirection)>,
}

impl Executor {
    fn new(query: Query) -> Result<Self, ExecuteError> {
        let aggregates = query.select.iter()
            .filter_map(|expr| expr.get_aggregate_call())
            .collect();

        let mut order_indices = Vec::new();
        for sort_field in query.order.iter() {
            let position = query.select.iter().position(|select| select == &sort_field.expr);
            let index = match position {
                Some(i) => i,
                None => return Err(ExecuteError::InvalidOrderClause(sort_field.expr.clone())),
            };
            let direction = sort_field.direction.clone().unwrap_or(SortDirection::Asc);
            order_indices.push((index, direction));
        }

        Ok(Executor {
            query: query,
            aggregate_calls: aggregates,
            order_indices: order_indices,
        })
    }

    fn execute(&self, source: Source) -> Result<Answer, ExecuteError> {
        let mut answer = if self.aggregate_calls.is_empty() {
            self.execute_non_aggregate(source)?
        } else {
            self.execute_aggregate(source)?
        };

        answer.sort(&self.order_indices);
        Ok(answer)
    }

    fn execute_non_aggregate(&self, source: Source) -> Result<Answer, ExecuteError> {
        let mut rows = Vec::new();
        for row in source {
            let row = row?;
            if !self.passes_condition(&row) {
                continue;
            }

            let output_row = self.query.select.iter()
                .map(|field| field.eval(&row))
                .collect();
            rows.push(output_row);
        }

        Ok(Answer {
            columns: self.get_columns(),
            rows: rows,
        })
    }

    fn execute_aggregate(&self, source: Source) -> Result<Answer, ExecuteError> {
        let aggregates = self.build_aggregates(source)?;
        let aggregate_rows = self.aggregates_to_rows(aggregates);

        let mut rows = Vec::new();
        for aggregate_row in aggregate_rows {
            let output_row = self.query.select.iter()
                .map(|field| field.eval(&aggregate_row))
                .collect();
            rows.push(output_row);
        }

        Ok(Answer {
            columns: self.get_columns(),
            rows: rows,
        })
    }

    fn build_aggregates(&self, source: Source) -> Result<HashMap<Vec<Data>, Vec<Aggregate>>, ExecuteError> {
        let mut groups = HashMap::new();
        for row in source {
            let row = row?;
            if !self.passes_condition(&row) {
                continue;
            }

            let group_aggregates = groups
                .entry(self.get_group(&row))
                .or_insert_with(|| self.make_aggregates());

            for (i, aggregate) in group_aggregates.iter_mut().enumerate() {
                aggregate.apply(self.aggregate_calls[i].argument.eval(&row));
            }
        }

        Ok(groups)
    }

    fn aggregates_to_rows(&self, aggregates: HashMap<Vec<Data>, Vec<Aggregate>>) -> Vec<Row> {
        let mut rows = Vec::with_capacity(aggregates.len());
        for (group, aggregates) in aggregates {
            let mut row = Row::new();
            for (i, aggregate) in aggregates.into_iter().enumerate() {
                let call = self.aggregate_calls[i].clone();
                row.fields.insert(Expr::AggregateCall(call), aggregate.final_value());
            }
            for (index, val) in group.iter().enumerate() {
                row.fields.insert(self.query.group[index].clone(), val.clone());
            }
            rows.push(row);
        }

        rows
    }

    fn passes_condition(&self, row: &Row) -> bool {
        match self.query.condition {
            Some(ref cond) => cond.eval(row) == Data::Bool(true),
            None => true,
        }
    }

    fn get_columns(&self) -> Vec<String> {
        self.query.select.iter()
            .map(|field| format!("{}", field))
            .collect()
    }

    fn get_group(&self, row: &Row) -> Vec<Data> {
        self.query.group.iter()
            .map(|field| field.eval(row))
            .collect()
    }

    fn make_aggregates(&self) -> Vec<Aggregate> {
        self.aggregate_calls.iter()
            .map(|call| call.function.aggregate())
            .collect()
    }
}

pub fn execute(query: Query, source: Source) -> Result<Answer, ExecuteError> {
    Executor::new(query)?.execute(source)
}

#[cfg(test)]
mod tests {
    use super::*;
    use aggregate::{AggregateCall, AggregateFunction};
    use data::Data;
    use expr::Expr;
    use query::OrderField;
    use row::make_rows;

    #[test]
    fn aggregate_query() {
        let source = make_rows(
            vec!["a"],
            vec![
                data_vec![1],
                data_vec![2],
                data_vec![3],
                data_vec![4],
                data_vec![5],
            ],
        );

        let call = AggregateCall{
            function: AggregateFunction::Sum,
            argument: Box::new(Expr::Column(String::from("a"))),
        };

        let query = Query {
            select: vec![Expr::AggregateCall(call)],
            from: String::new(),
            condition: None,
            group: vec![],
            order: vec![],
        };

        let actual = execute(query, Box::new(source.into_iter())).unwrap();
        let expected = Answer {
            columns: vec![String::from("sum(a)")],
            rows: vec![data_vec![15]],
        };

        assert_eq!(expected, actual);
    }

    #[test]
    fn non_aggregate_query() {
        let source = make_rows(
            vec!["a"],
            vec![
                data_vec![1],
                data_vec![2],
                data_vec![3],
                data_vec![4],
                data_vec![5],
            ],
        );

        let query = Query {
            select: vec![Expr::Column(String::from("a"))],
            from: String::new(),
            condition: None,
            group: vec![],
            order: vec![],
        };

        let actual = execute(query, Box::new(source.clone().into_iter())).unwrap();
        let expected = Answer {
            columns: vec![String::from("a")],
            rows: vec![
                data_vec![1],
                data_vec![2],
                data_vec![3],
                data_vec![4],
                data_vec![5],
            ],
        };

        assert_eq!(expected, actual);
    }

    #[test]
    fn invalid_order_clause() {
        let source = make_rows(
            vec!["a"],
            vec![],
        );

        let query = Query {
            select: vec![],
            from: String::new(),
            condition: None,
            group: vec![],
            order: vec![OrderField {
                expr: Expr::Column(String::from("a")),
                direction: None,
            }],
        };
        let actual = execute(query, Box::new(source.clone().into_iter()));
        let expected = Err(ExecuteError::InvalidOrderClause(Expr::Column(String::from("a"))));
        assert_eq!(expected, actual);
    }
}
<commit_msg>Unify aggregate and non-aggregate execution<commit_after>use std::collections::HashMap;
use aggregate::{Aggregate, AggregateCall};
use answer::Answer;
use data::Data;
use expr::Expr;
use query::{Query, SortDirection};
use row::Row;
use source::{Source, SourceError};

#[derive(Clone, Debug, PartialEq)]
pub enum ExecuteError {
    SourceError(String),
    InvalidOrderClause(Expr),
}

impl From<SourceError> for ExecuteError {
    fn from(e: SourceError) -> Self {
        ExecuteError::SourceError(e.description)
    }
}

struct Executor {
    query: Query,
    aggregate_calls: Vec<AggregateCall>,
    order_indices: Vec<(usize, SortDirection)>,
}

impl Executor {
    fn new(query: Query) -> Result<Self, ExecuteError> {
        let aggregates = query.select.iter()
            .filter_map(|expr| expr.get_aggregate_call())
            .collect();

        let mut order_indices = Vec::new();
        for sort_field in query.order.iter() {
            let position = query.select.iter().position(|select| select == &sort_field.expr);
            let index = match position {
                Some(i) => i,
                None => return Err(ExecuteError::InvalidOrderClause(sort_field.expr.clone())),
            };
            let direction = sort_field.direction.clone().unwrap_or(SortDirection::Asc);
            order_indices.push((index, direction));
        }

        Ok(Executor {
            query: query,
            aggregate_calls: aggregates,
            order_indices: order_indices,
        })
    }

    fn execute(&self, source: Source) -> Result<Answer, ExecuteError> {
        let mut source = self.apply_condition(source);
        source = self.compute_aggregates(source)?;

        let mut answer = self.apply_select(source)?;
        answer.sort(&self.order_indices);
        Ok(answer)
    }

    fn build_aggregates(&self,
                        source: Source)
                        -> Result<HashMap<Vec<Data>, Vec<Aggregate>>, ExecuteError> {
        let mut groups = HashMap::new();
        for row in source {
            let row = row?;
            if !self.passes_condition(&row) {
                continue;
            }

            let group_aggregates = groups
                .entry(self.get_group(&row))
                .or_insert_with(|| self.make_aggregates());

            for (i, aggregate) in group_aggregates.iter_mut().enumerate() {
                aggregate.apply(self.aggregate_calls[i].argument.eval(&row));
            }
        }

        Ok(groups)
    }

    fn aggregates_to_source(&self, aggregates: HashMap<Vec<Data>, Vec<Aggregate>>) -> Source {
        let mut rows = Vec::with_capacity(aggregates.len());
        for (group, aggregates) in aggregates {
            let mut row = Row::new();
            for (i, aggregate) in aggregates.into_iter().enumerate() {
                let call = self.aggregate_calls[i].clone();
                row.fields.insert(Expr::AggregateCall(call), aggregate.final_value());
            }
            for (index, val) in group.iter().enumerate() {
                row.fields.insert(self.query.group[index].clone(), val.clone());
            }
            rows.push(Ok(row));
        }

        Box::new(rows.into_iter())
    }

    fn apply_condition(&self, source: Source) -> Source {
        let condition = match self.query.condition {
            Some(ref cond) => cond.clone(),
            None => return source,
        };

        Box::new(source.filter(move |row| {
            match row {
                &Err(_) => true,
                &Ok(ref row) => condition.eval(row) == Data::Bool(true),
            }
        }))
    }

    fn compute_aggregates(&self, source: Source) -> Result<Source, ExecuteError> {
        if self.aggregate_calls.is_empty() {
            return Ok(source);
        }

        let aggregates = self.build_aggregates(source)?;
        Ok(self.aggregates_to_source(aggregates))
    }

    fn apply_select(&self, source: Source) -> Result<Answer, ExecuteError> {
        let mut rows = Vec::new();

        for row in source {
            let row = row?;
            let output_row = self.query
                .select
                .iter()
                .map(|field| field.eval(&row))
                .collect();
            rows.push(output_row);
        }

        Ok(Answer {
            columns: self.get_columns(),
            rows: rows,
        })
    }

    fn passes_condition(&self, row: &Row) -> bool {
        match self.query.condition {
            Some(ref cond) => cond.eval(row) == Data::Bool(true),
            None => true,
        }
    }

    fn get_columns(&self) -> Vec<String> {
        self.query.select.iter()
            .map(|field| format!("{}", field))
            .collect()
    }

    fn get_group(&self, row: &Row) -> Vec<Data> {
        self.query.group.iter()
            .map(|field| field.eval(row))
            .collect()
    }

    fn make_aggregates(&self) -> Vec<Aggregate> {
        self.aggregate_calls.iter()
            .map(|call| call.function.aggregate())
            .collect()
    }
}

pub fn execute(query: Query, source: Source) -> Result<Answer, ExecuteError> {
    Executor::new(query)?.execute(source)
}

#[cfg(test)]
mod tests {
    use super::*;
    use aggregate::{AggregateCall, AggregateFunction};
    use data::Data;
    use expr::Expr;
    use query::OrderField;
    use row::make_rows;

    #[test]
    fn aggregate_query() {
        let source = make_rows(
            vec!["a"],
            vec![
                data_vec![1],
                data_vec![2],
                data_vec![3],
                data_vec![4],
                data_vec![5],
            ],
        );

        let call = AggregateCall{
            function: AggregateFunction::Sum,
            argument: Box::new(Expr::Column(String::from("a"))),
        };

        let query = Query {
            select: vec![Expr::AggregateCall(call)],
            from: String::new(),
            condition: None,
            group: vec![],
            order: vec![],
        };

        let actual = execute(query, Box::new(source.into_iter())).unwrap();
        let expected = Answer {
            columns: vec![String::from("sum(a)")],
            rows: vec![data_vec![15]],
        };

        assert_eq!(expected, actual);
    }

    #[test]
    fn non_aggregate_query() {
        let source = make_rows(
            vec!["a"],
            vec![
                data_vec![1],
                data_vec![2],
                data_vec![3],
                data_vec![4],
                data_vec![5],
            ],
        );

        let query = Query {
            select: vec![Expr::Column(String::from("a"))],
            from: String::new(),
            condition: None,
            group: vec![],
            order: vec![],
        };

        let actual = execute(query, Box::new(source.clone().into_iter())).unwrap();
        let expected = Answer {
            columns: vec![String::from("a")],
            rows: vec![
                data_vec![1],
                data_vec![2],
                data_vec![3],
                data_vec![4],
                data_vec![5],
            ],
        };

        assert_eq!(expected, actual);
    }

    #[test]
    fn invalid_order_clause() {
        let source = make_rows(
            vec!["a"],
            vec![],
        );

        let query = Query {
            select: vec![],
            from: String::new(),
            condition: None,
            group: vec![],
            order: vec![OrderField {
                expr: Expr::Column(String::from("a")),
                direction: None,
            }],
        };
        let actual = execute(query, Box::new(source.clone().into_iter()));
        let expected = Err(ExecuteError::InvalidOrderClause(Expr::Column(String::from("a"))));
        assert_eq!(expected, actual);
    }
}
<|endoftext|>


<commit_before>//! Representations of C types and arrays thereof.

use std::{mem, ptr};
use libc;

use c;
use low;

type FfiType_      = *mut low::ffi_type;
type FfiTypeArray_ = *mut FfiType_;
type Owned<T>      = T;

#[derive(Debug)]
pub struct FfiType(FfiType_);

#[derive(Debug)]
pub struct FfiTypeArray(FfiTypeArray_);

/// Computes the length of a raw `FfiTypeArray_` by searching for the
/// null terminator.
unsafe fn ffi_type_array_len(mut array: FfiTypeArray_) -> usize {
    let mut current = array;
    let mut count   = 0;
    while !(*current).is_null() {
        count += 1;
    }
    count
}

/// Creates an empty `FfiTypeArray_` with null terminator.
unsafe fn ffi_type_array_create_empty(len: usize) -> Owned<FfiTypeArray_> {
    let array = libc::malloc((len + 1) * mem::size_of::<FfiType_>())
                    as FfiTypeArray_;
    *array.offset(len as isize) = ptr::null::<low::ffi_type>() as FfiType_;
    array
}

/// Creates a null-terminated array of FfiType_. Takes ownership of
/// the elements.
unsafe fn ffi_type_array_create(elements: Vec<FfiType>)
    -> Owned<FfiTypeArray_>
{
    let size = elements.len();
    let new  = ffi_type_array_create_empty(size);
    for i in 0 .. size {
        *new.offset(i as isize) = elements[i].0;
    }

    for t in elements {
        mem::forget(t);
    }

    println!("ffi_type_array_create(...) = {:?}", new);

    new
}

/// Creates a struct type from a raw array of element types.
unsafe fn ffi_type_struct_create_raw(elements: FfiTypeArray_)
    -> Owned<FfiType_>
{
    let new = libc::malloc(mem::size_of::<low::ffi_type>()) as FfiType_;

    (*new).size      = 0;
    (*new).alignment = 0;
    (*new).type_     = c::ffi_type_enum::STRUCT as ::libc::c_ushort;
    (*new).elements  = elements;

    println!("ffi_type_struct_create_raw({:?}) = {:?}", elements, new);

    new
}

/// Creates a struct ffi_type with the given elements. Takes ownership
/// of the elements.
unsafe fn ffi_type_struct_create(elements: Vec<FfiType>) -> Owned<FfiType_> {
    println!("ffi_type_array_create({:?})", elements);
    ffi_type_struct_create_raw(ffi_type_array_create(elements))
}

/// Makes a copy of a type array.
unsafe fn ffi_type_array_clone(old: FfiTypeArray_) -> Owned<FfiTypeArray_> {
    let size = ffi_type_array_len(old);
    let new  = ffi_type_array_create_empty(size);

    for i in 0 .. size {
        *new.offset(i as isize) = ffi_type_clone(*old.offset(i as isize));
    }

    new
}

/// Makes a copy of a type.
unsafe fn ffi_type_clone(old: FfiType_) -> Owned<FfiType_> {
    if (*old).type_ == c::ffi_type_enum::STRUCT as u16 {
        ffi_type_struct_create_raw(ffi_type_array_clone((*old).elements))
    } else {
        old
    }
}

/// Destroys an array of FfiType_ and all of its elements.
unsafe fn ffi_type_array_destroy(victim: Owned<FfiTypeArray_>) {
    println!("ffi_type_array_destroy({:?})", victim);
    let mut current = victim;
    while !(*current).is_null() {
        ffi_type_destroy(*current);
        current = current.offset(1);
    }

    libc::free(victim as *mut libc::c_void);
}

/// Destroys an FfiType_ if it was dynamically allocated.
unsafe fn ffi_type_destroy(victim: Owned<FfiType_>) {
    println!("ffi_type_destroy({:?})", victim);
    if (*victim).type_ == c::ffi_type_enum::STRUCT as u16 {
        ffi_type_array_destroy((*victim).elements);
        libc::free(victim as *mut libc::c_void);
    }
}

impl Drop for FfiType {
    fn drop(&mut self) {
        unsafe { ffi_type_destroy(self.0) }
    }
}

impl Drop for FfiTypeArray {
    fn drop(&mut self) {
        unsafe { ffi_type_array_destroy(self.0) }
    }
}

impl Clone for FfiType {
    fn clone(&self) -> Self {
        unsafe { FfiType(ffi_type_clone(self.0)) }
    }
}

impl Clone for FfiTypeArray {
    fn clone(&self) -> Self {
        unsafe { FfiTypeArray(ffi_type_array_clone(self.0)) }
    }
}

impl FfiType {
    pub fn void() -> Self {
        FfiType(unsafe { &mut low::ffi_type_void })
    }

    pub fn uint8() -> Self {
        FfiType(unsafe { &mut low::ffi_type_uint8 })
    }

    pub fn sint8() -> Self {
        FfiType(unsafe { &mut low::ffi_type_sint8 })
    }

    pub fn uint16() -> Self {
        FfiType(unsafe { &mut low::ffi_type_uint16 })
    }

    pub fn sint16() -> Self {
        FfiType(unsafe { &mut low::ffi_type_sint16 })
    }

    pub fn uint32() -> Self {
        FfiType(unsafe { &mut low::ffi_type_uint32 })
    }

    pub fn sint32() -> Self {
        FfiType(unsafe { &mut low::ffi_type_sint32 })
    }

    pub fn uint64() -> Self {
        FfiType(unsafe { &mut low::ffi_type_uint64 })
    }

    pub fn sint64() -> Self {
        FfiType(unsafe { &mut low::ffi_type_sint64 })
    }

    pub fn float() -> Self {
        FfiType(unsafe { &mut low::ffi_type_float })
    }

    pub fn double() -> Self {
        FfiType(unsafe { &mut low::ffi_type_double })
    }

    pub fn pointer() -> Self {
        FfiType(unsafe { &mut low::ffi_type_pointer })
    }

    pub fn longdouble() -> Self {
        FfiType(unsafe { &mut low::ffi_type_longdouble })
    }

    pub fn complex_float() -> Self {
        FfiType(unsafe { &mut low::ffi_type_complex_float })
    }

    pub fn complex_double() -> Self {
        FfiType(unsafe { &mut low::ffi_type_complex_double })
    }

    pub fn complex_longdouble() -> Self {
        FfiType(unsafe { &mut low::ffi_type_complex_longdouble })
    }

    pub fn structure(fields: Vec<FfiType>) -> Self {
        println!("FfiType::structure({:?})", fields);
        unsafe {
            FfiType(ffi_type_struct_create(fields))
        }
    }

    pub fn as_raw_ptr(&self) -> *mut low::ffi_type {
        self.0
    }
}

impl FfiTypeArray {
    pub fn new(elements: Vec<FfiType>) -> Self {
        unsafe { FfiTypeArray(ffi_type_array_create(elements)) }
    }

    pub fn len(&self) -> usize {
        unsafe { ffi_type_array_len(self.0) }
    }

    pub fn as_raw_ptr(&self) -> *mut *mut low::ffi_type {
        self.0
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn create_uint64() {
        FfiType::uint64();
    }

    #[test]
    fn create_struct() {
        FfiType::structure(vec![FfiType::sint64(),
                                FfiType::sint64(),
                                FfiType::uint64()]);
    }

}
<commit_msg>added assertions for null malloc return<commit_after>//! Representations of C types and arrays thereof.

use std::{mem, ptr};
use libc;

use c;
use low;

type FfiType_      = *mut low::ffi_type;
type FfiTypeArray_ = *mut FfiType_;
type Owned<T>      = T;

#[derive(Debug)]
pub struct FfiType(FfiType_);

#[derive(Debug)]
pub struct FfiTypeArray(FfiTypeArray_);

/// Computes the length of a raw `FfiTypeArray_` by searching for the
/// null terminator.
unsafe fn ffi_type_array_len(mut array: FfiTypeArray_) -> usize {
    let mut count   = 0;
    while !(*array).is_null() {
        count += 1;
        array = array.offset(1);
    }
    count
}

/// Creates an empty `FfiTypeArray_` with null terminator.
unsafe fn ffi_type_array_create_empty(len: usize) -> Owned<FfiTypeArray_> {
    let array = libc::malloc((len + 1) * mem::size_of::<FfiType_>())
                    as FfiTypeArray_;
    assert!(!array.is_null());
    *array.offset(len as isize) = ptr::null::<low::ffi_type>() as FfiType_;
    array
}

/// Creates a null-terminated array of FfiType_. Takes ownership of
/// the elements.
unsafe fn ffi_type_array_create(elements: Vec<FfiType>)
    -> Owned<FfiTypeArray_>
{
    let size = elements.len();
    let new  = ffi_type_array_create_empty(size);
    for i in 0 .. size {
        *new.offset(i as isize) = elements[i].0;
    }

    for t in elements {
        mem::forget(t);
    }

    println!("ffi_type_array_create(...) = {:?}", new);

    new
}

/// Creates a struct type from a raw array of element types.
unsafe fn ffi_type_struct_create_raw(elements: FfiTypeArray_)
    -> Owned<FfiType_>
{
    let new = libc::malloc(mem::size_of::<low::ffi_type>()) as FfiType_;
    assert!(!new.is_null());

    (*new).size      = 0;
    (*new).alignment = 0;
    (*new).type_     = c::ffi_type_enum::STRUCT as ::libc::c_ushort;
    (*new).elements  = elements;

    println!("ffi_type_struct_create_raw({:?}) = {:?}", elements, new);

    new
}

/// Creates a struct ffi_type with the given elements. Takes ownership
/// of the elements.
unsafe fn ffi_type_struct_create(elements: Vec<FfiType>) -> Owned<FfiType_> {
    println!("ffi_type_array_create({:?})", elements);
    ffi_type_struct_create_raw(ffi_type_array_create(elements))
}

/// Makes a copy of a type array.
unsafe fn ffi_type_array_clone(old: FfiTypeArray_) -> Owned<FfiTypeArray_> {
    let size = ffi_type_array_len(old);
    let new  = ffi_type_array_create_empty(size);

    for i in 0 .. size {
        *new.offset(i as isize) = ffi_type_clone(*old.offset(i as isize));
    }

    new
}

/// Makes a copy of a type.
unsafe fn ffi_type_clone(old: FfiType_) -> Owned<FfiType_> {
    if (*old).type_ == c::ffi_type_enum::STRUCT as u16 {
        ffi_type_struct_create_raw(ffi_type_array_clone((*old).elements))
    } else {
        old
    }
}

/// Destroys an array of FfiType_ and all of its elements.
unsafe fn ffi_type_array_destroy(victim: Owned<FfiTypeArray_>) {
    println!("ffi_type_array_destroy({:?})", victim);
    let mut current = victim;
    while !(*current).is_null() {
        ffi_type_destroy(*current);
        current = current.offset(1);
    }

    libc::free(victim as *mut libc::c_void);
}

/// Destroys an FfiType_ if it was dynamically allocated.
unsafe fn ffi_type_destroy(victim: Owned<FfiType_>) {
    println!("ffi_type_destroy({:?})", victim);
    if (*victim).type_ == c::ffi_type_enum::STRUCT as u16 {
        ffi_type_array_destroy((*victim).elements);
        libc::free(victim as *mut libc::c_void);
    }
}

impl Drop for FfiType {
    fn drop(&mut self) {
        unsafe { ffi_type_destroy(self.0) }
    }
}

impl Drop for FfiTypeArray {
    fn drop(&mut self) {
        unsafe { ffi_type_array_destroy(self.0) }
    }
}

impl Clone for FfiType {
    fn clone(&self) -> Self {
        unsafe { FfiType(ffi_type_clone(self.0)) }
    }
}

impl Clone for FfiTypeArray {
    fn clone(&self) -> Self {
        unsafe { FfiTypeArray(ffi_type_array_clone(self.0)) }
    }
}

impl FfiType {
    pub fn void() -> Self {
        FfiType(unsafe { &mut low::ffi_type_void })
    }

    pub fn uint8() -> Self {
        FfiType(unsafe { &mut low::ffi_type_uint8 })
    }

    pub fn sint8() -> Self {
        FfiType(unsafe { &mut low::ffi_type_sint8 })
    }

    pub fn uint16() -> Self {
        FfiType(unsafe { &mut low::ffi_type_uint16 })
    }

    pub fn sint16() -> Self {
        FfiType(unsafe { &mut low::ffi_type_sint16 })
    }

    pub fn uint32() -> Self {
        FfiType(unsafe { &mut low::ffi_type_uint32 })
    }

    pub fn sint32() -> Self {
        FfiType(unsafe { &mut low::ffi_type_sint32 })
    }

    pub fn uint64() -> Self {
        FfiType(unsafe { &mut low::ffi_type_uint64 })
    }

    pub fn sint64() -> Self {
        FfiType(unsafe { &mut low::ffi_type_sint64 })
    }

    pub fn float() -> Self {
        FfiType(unsafe { &mut low::ffi_type_float })
    }

    pub fn double() -> Self {
        FfiType(unsafe { &mut low::ffi_type_double })
    }

    pub fn pointer() -> Self {
        FfiType(unsafe { &mut low::ffi_type_pointer })
    }

    pub fn longdouble() -> Self {
        FfiType(unsafe { &mut low::ffi_type_longdouble })
    }

    pub fn complex_float() -> Self {
        FfiType(unsafe { &mut low::ffi_type_complex_float })
    }

    pub fn complex_double() -> Self {
        FfiType(unsafe { &mut low::ffi_type_complex_double })
    }

    pub fn complex_longdouble() -> Self {
        FfiType(unsafe { &mut low::ffi_type_complex_longdouble })
    }

    pub fn structure(fields: Vec<FfiType>) -> Self {
        println!("FfiType::structure({:?})", fields);
        unsafe {
            FfiType(ffi_type_struct_create(fields))
        }
    }

    pub fn as_raw_ptr(&self) -> *mut low::ffi_type {
        self.0
    }
}

impl FfiTypeArray {
    pub fn new(elements: Vec<FfiType>) -> Self {
        unsafe { FfiTypeArray(ffi_type_array_create(elements)) }
    }

    pub fn len(&self) -> usize {
        unsafe { ffi_type_array_len(self.0) }
    }

    pub fn as_raw_ptr(&self) -> *mut *mut low::ffi_type {
        self.0
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn create_uint64() {
        FfiType::uint64();
    }

    #[test]
    fn create_struct() {
        FfiType::structure(vec![FfiType::sint64(),
                                FfiType::sint64(),
                                FfiType::uint64()]);
    }

}
<|endoftext|>


<commit_before>extern crate find_folder;

use ::screen;
use ::screen::Screen;
use ::events;
use ::object;

use piston_window;
use piston_window::Transformed;

use gfx_device_gl;

pub struct Game {
    window: piston_window::PistonWindow,
    screens: Vec<Box<screen::Screen>>,
    events: events::Events,
    player: object::Object,
}

// TODO: Remove
fn load_sprite(window: &piston_window::PistonWindow, name: &str) -> piston_window::Texture<gfx_device_gl::Resources> {
    // TODO: Create and use default sprite in case of failure during loading?
    let assets = find_folder::Search::ParentsThenKids(3, 3).for_folder("assets").unwrap();
    let sprite = assets.join(name);
    piston_window::Texture::from_path(&mut *window.factory.borrow_mut(), &sprite, piston_window::Flip::None, &piston_window::TextureSettings::new()).unwrap()
}

impl Game {
    pub fn new() -> Game {
        let window: piston_window::PistonWindow = piston_window::WindowSettings::new("rrthozopsi", [600, 600]).exit_on_esc(true).build().unwrap();
        let sprite = load_sprite(&window, "skeleton.png");
        Game {
            window: window,
            screens: Vec::new(),
            events: events::Events::new(),
            player: object::Object::new(Some(sprite)),
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let mut screen = self.screens.last().unwrap();

        // TODO: Remove clone?
        for window in &mut self.window {
            match window.event {
                Some(Event::Update(args)) => { screen.on_update(&args); }
                Some(Event::Render(args)) => { screen.on_draw(&args, &window); }
                Some(Event::Input(input)) => { screen.on_input(&input); }
                _ => {}
            }
        }
    }

    pub fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        if self.events.is_up()   { self.player.mov(0.0, -150.0 * args.dt); }
        if self.events.is_down() { self.player.mov(0.0, 150.0 * args.dt); }
        if self.events.is_left() { self.player.mov(-150.0 * args.dt, 0.0); }
        if self.events.is_right() { self.player.mov(150.0 * args.dt, 0.0); }
    }

    pub fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);

            let center = context.transform.trans((args.width / 2) as f64, (args.height / 2) as f64);
            self.player.render(graphics, &center);
        });
    }

    pub fn on_input(&mut self, input: &piston_window::Input) {
        self.events.process_input(&input);
    }
}
<commit_msg>Build fix (last_mut instead of last)<commit_after>extern crate find_folder;

use ::screen;
use ::screen::Screen;
use ::events;
use ::object;

use piston_window;
use piston_window::Transformed;

use gfx_device_gl;

pub struct Game {
    window: piston_window::PistonWindow,
    screens: Vec<Box<screen::Screen>>,
    events: events::Events,
    player: object::Object,
}

// TODO: Remove
fn load_sprite(window: &piston_window::PistonWindow, name: &str) -> piston_window::Texture<gfx_device_gl::Resources> {
    // TODO: Create and use default sprite in case of failure during loading?
    let assets = find_folder::Search::ParentsThenKids(3, 3).for_folder("assets").unwrap();
    let sprite = assets.join(name);
    piston_window::Texture::from_path(&mut *window.factory.borrow_mut(), &sprite, piston_window::Flip::None, &piston_window::TextureSettings::new()).unwrap()
}

impl Game {
    pub fn new() -> Game {
        let window: piston_window::PistonWindow = piston_window::WindowSettings::new("rrthozopsi", [600, 600]).exit_on_esc(true).build().unwrap();
        let sprite = load_sprite(&window, "skeleton.png");
        Game {
            window: window,
            screens: Vec::new(),
            events: events::Events::new(),
            player: object::Object::new(Some(sprite)),
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let mut screen = self.screens.last_mut().unwrap();

        // TODO: Remove clone?
        for window in &mut self.window {
            match window.event {
                Some(Event::Update(args)) => { screen.on_update(&args); }
                Some(Event::Render(args)) => { screen.on_draw(&args, &window); }
                Some(Event::Input(input)) => { screen.on_input(&input); }
                _ => {}
            }
        }
    }

    pub fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        if self.events.is_up()   { self.player.mov(0.0, -150.0 * args.dt); }
        if self.events.is_down() { self.player.mov(0.0, 150.0 * args.dt); }
        if self.events.is_left() { self.player.mov(-150.0 * args.dt, 0.0); }
        if self.events.is_right() { self.player.mov(150.0 * args.dt, 0.0); }
    }

    pub fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);

            let center = context.transform.trans((args.width / 2) as f64, (args.height / 2) as f64);
            self.player.render(graphics, &center);
        });
    }

    pub fn on_input(&mut self, input: &piston_window::Input) {
        self.events.process_input(&input);
    }
}
<|endoftext|>


<commit_before>//! # generator
//!
//! Rust generator implementation
//!

use std::mem;
use std::thread;
use std::any::Any;
use std::boxed::FnBox;
use std::marker::PhantomData;

use yield_::yield_now;
use generator::Generator;
use rt::{Error, Context, ContextStack};
use reg_context::Context as RegContext;
// use stack_size::{get_stack_size, set_stack_size};

// default stack size is 1k * sizeof(usize)
pub const DEFAULT_STACK_SIZE: usize = 1024;

/// Generator helper
pub struct Gn<A> {
    dummy: PhantomData<A>,
}

impl <A: Any> Gn<A> {
    /// create a new generator with default stack size
    pub fn new<'a, T: Any, F>(f: F) -> Box<Generator<A, Output = T> + 'a>
        where F: FnOnce() -> T + 'a
    {
        Self::new_opt(f, DEFAULT_STACK_SIZE)
    }

    /// create a new generator with specified stack size
    pub fn new_opt<'a, T: Any, F>(f: F, size: usize) -> Box<Generator<A, Output = T> + 'a>
        where F: FnOnce() -> T + 'a
    {
        let mut g = Box::new(GeneratorImpl::<A, T, F>::new_opt(f, size));

        g.context.para = &mut g.para as &mut Any;
        g.context.ret = &mut g.ret as &mut Any;

        unsafe {
            let ptr = Box::into_raw(g);

            let start: Box<FnBox()> = Box::new(move || {
                // g.ret = Some((g.f.take().unwrap())());
                let f = (*ptr).f.take().unwrap();
                (*ptr).ret = Some(f());
            });

            let stk = &mut (*ptr).context.stack;
            let reg = &mut (*ptr).context.regs;
            reg.init_with(gen_init,
                          ptr as usize,
                          Box::into_raw(Box::new(start)) as *mut usize,
                          stk.end());
            Box::from_raw(ptr)
        }
    }
}

/// GeneratorImpl
struct GeneratorImpl<A: Any, T: Any, F>
    where F: FnOnce() -> T
{
    context: Context,
    // save the input
    para: Option<A>,
    // save the output
    ret: Option<T>,
    // boxed functor
    f: Option<F>,
}

impl<'a, A: Any, T: Any, F> GeneratorImpl<A, T, F>
    where F: FnOnce() -> T + 'a
{
    /// create a new generator with default stack size
    fn new_opt(f: F, size: usize) -> Self {
        GeneratorImpl {
            para: None,
            ret: None,
            f: Some(f),
            context: Context::new(size),
        }
    }

    /// resume the generator
    fn resume_gen(&mut self) {
        let env = ContextStack::current();
        let cur = &mut env.top().regs;
        let ctx = &mut self.context as *mut Context;
        let to = unsafe { &mut (*ctx).regs };
        // save current generator context on stack
        env.push(ctx);
        // switch context
        RegContext::swap(cur, to);

        // check the panic status
        // this would propagate the panic until root context
        let err = self.context.err;
        if err.is_some() {
            panic!(err.unwrap());
        }
    }

    #[inline]
    fn is_started(&self) -> bool {
        // when the f is consumed we think it's running
        self.f.is_none()
    }
}

impl<A: Any, T: Any, F> Drop for GeneratorImpl<A, T, F>
    where F: FnOnce() -> T
{
    fn drop(&mut self) {
        // when the thread is already panic, do nothing
        if thread::panicking() {
            return;
        }

        let mut i = 0;
        while !self.is_done() {
            if i > 2 {
                self.cancel();
                break;
            }
            self.raw_send(None);
            i += 1;
        }

        let (total_stack, used_stack) = self.stack_usage();
        if used_stack < total_stack {
            // here we should record the stack in the class
            // next time will just use
            // set_stack_size::<F>(used_stack);
        } else {
            error!("stack overflow detected!");
            panic!(Error::StackErr);
        }
    }
}

impl<A: Any, T: Any, F> Generator<A> for GeneratorImpl<A, T, F>
    where F: FnOnce() -> T
{
    type Output = T;

    fn raw_send(&mut self, para: Option<A>) -> Option<T> {
        if self.is_started() && self.context._ref != 0 {
            return None;
        }

        // this is the passed in value of the send primitive
        // the yield part would read out this value in the next round
        // use the replace is would drop the old value
        mem::replace(&mut self.para, para);

        // every time we call the function, increase the ref count
        // yiled will decrease it and return will not
        self.context._ref += 1;
        self.resume_gen();

        self.ret.take()
    }

    fn cancel(&mut self) {
        // consume the fun if it's not started
        if !self.is_started() {
            self.f.take();
            self.context._ref = 1;
        } else {
            // tell the func to panic
            // so that we can stop the inner func
            self.context._ref = 2;
            self.resume_gen();
        }
    }

    fn is_done(&self) -> bool {
        self.is_started() && self.context._ref != 0
    }

    fn stack_usage(&self) -> (usize, usize) {
        (self.context.stack.size(),
         self.context.stack.get_used_size())
    }
}

fn gen_init(_: usize, f: *mut usize) -> ! {
    {
        let f = f as usize;
        let clo = move || {
            let func: Box<Box<FnBox()>> = unsafe { Box::from_raw(f as *mut Box<FnBox()>) };
            func();
        };

        // we can't panic inside the generator context
        // need to propagate the panic to the main thread
        if let Err(cause) = thread::catch_panic(clo) {
            if cause.downcast_ref::<Error>().is_some() {
                match cause.downcast_ref::<Error>().unwrap() {
                    &Error::Cancel => {}
                    err => {
                        let ctx = ContextStack::current().top();
                        ctx.err = Some(*err);
                    }
                }
            } else {
                error!("Panicked inside: {:?}", cause.downcast::<&str>());
            }
        }
        // drop the clo here
    }

    yield_now();

    unreachable!("Should never comeback");
}
<commit_msg>add init for gen impl<commit_after>//! # generator
//!
//! Rust generator implementation
//!

use std::mem;
use std::thread;
use std::any::Any;
use std::boxed::FnBox;
use std::marker::PhantomData;

use yield_::yield_now;
use generator::Generator;
use rt::{Error, Context, ContextStack};
use reg_context::Context as RegContext;
// use stack_size::{get_stack_size, set_stack_size};

// default stack size is 1k * sizeof(usize)
pub const DEFAULT_STACK_SIZE: usize = 1024;

/// Generator helper
pub struct Gn<A> {
    dummy: PhantomData<A>,
}

impl <A: Any> Gn<A> {
    /// create a new generator with default stack size
    pub fn new<'a, T: Any, F>(f: F) -> Box<Generator<A, Output = T> + 'a>
        where F: FnOnce() -> T + 'a
    {
        Self::new_opt(f, DEFAULT_STACK_SIZE)
    }

    /// create a new generator with specified stack size
    pub fn new_opt<'a, T: Any, F>(f: F, size: usize) -> Box<Generator<A, Output = T> + 'a>
        where F: FnOnce() -> T + 'a
    {
        let g = Box::new(GeneratorImpl::<A, T, F>::new(f, size));
        g.init()
    }
}

/// GeneratorImpl
struct GeneratorImpl<A: Any, T: Any, F>
    where F: FnOnce() -> T
{
    context: Context,
    // save the input
    para: Option<A>,
    // save the output
    ret: Option<T>,
    // boxed functor
    f: Option<F>,
}

impl<'a, A: Any, T: Any, F> GeneratorImpl<A, T, F>
    where F: FnOnce() -> T + 'a
{
    /// create a new generator with default stack size
    fn new(f: F, size: usize) -> Self {
        GeneratorImpl {
            para: None,
            ret: None,
            f: Some(f),
            context: Context::new(size),
        }
    }

    fn init(mut self: Box<Self>) -> Box<Self> {
        self.context.para = &mut self.para as &mut Any;
        self.context.ret = &mut self.ret as &mut Any;

        unsafe {
            let ptr = Box::into_raw(self);

            let start: Box<FnBox()> = Box::new(move || {
                let f = (*ptr).f.take().unwrap();
                (*ptr).ret = Some(f());
            });

            let stk = &mut (*ptr).context.stack;
            let reg = &mut (*ptr).context.regs;
            reg.init_with(gen_init,
                          ptr as usize,
                          Box::into_raw(Box::new(start)) as *mut usize,
                          stk.end());
            Box::from_raw(ptr)
        }
    }

    /// resume the generator
    fn resume_gen(&mut self) {
        let env = ContextStack::current();
        let cur = &mut env.top().regs;
        let ctx = &mut self.context as *mut Context;
        let to = unsafe { &mut (*ctx).regs };
        // save current generator context on stack
        env.push(ctx);
        // switch context
        RegContext::swap(cur, to);

        // check the panic status
        // this would propagate the panic until root context
        let err = self.context.err;
        if err.is_some() {
            panic!(err.unwrap());
        }
    }

    #[inline]
    fn is_started(&self) -> bool {
        // when the f is consumed we think it's running
        self.f.is_none()
    }
}

impl<A: Any, T: Any, F> Drop for GeneratorImpl<A, T, F>
    where F: FnOnce() -> T
{
    fn drop(&mut self) {
        // when the thread is already panic, do nothing
        if thread::panicking() {
            return;
        }

        let mut i = 0;
        while !self.is_done() {
            if i > 2 {
                self.cancel();
                break;
            }
            self.raw_send(None);
            i += 1;
        }

        let (total_stack, used_stack) = self.stack_usage();
        if used_stack < total_stack {
            // here we should record the stack in the class
            // next time will just use
            // set_stack_size::<F>(used_stack);
        } else {
            error!("stack overflow detected!");
            panic!(Error::StackErr);
        }
    }
}

impl<A: Any, T: Any, F> Generator<A> for GeneratorImpl<A, T, F>
    where F: FnOnce() -> T
{
    type Output = T;

    fn raw_send(&mut self, para: Option<A>) -> Option<T> {
        if self.is_started() && self.context._ref != 0 {
            return None;
        }

        // this is the passed in value of the send primitive
        // the yield part would read out this value in the next round
        // use the replace is would drop the old value
        mem::replace(&mut self.para, para);

        // every time we call the function, increase the ref count
        // yiled will decrease it and return will not
        self.context._ref += 1;
        self.resume_gen();

        self.ret.take()
    }

    fn cancel(&mut self) {
        // consume the fun if it's not started
        if !self.is_started() {
            self.f.take();
            self.context._ref = 1;
        } else {
            // tell the func to panic
            // so that we can stop the inner func
            self.context._ref = 2;
            self.resume_gen();
        }
    }

    fn is_done(&self) -> bool {
        self.is_started() && self.context._ref != 0
    }

    fn stack_usage(&self) -> (usize, usize) {
        (self.context.stack.size(),
         self.context.stack.get_used_size())
    }
}

fn gen_init(_: usize, f: *mut usize) -> ! {
    {
        let f = f as usize;
        let clo = move || {
            let func: Box<Box<FnBox()>> = unsafe { Box::from_raw(f as *mut Box<FnBox()>) };
            func();
        };

        // we can't panic inside the generator context
        // need to propagate the panic to the main thread
        if let Err(cause) = thread::catch_panic(clo) {
            if cause.downcast_ref::<Error>().is_some() {
                match cause.downcast_ref::<Error>().unwrap() {
                    &Error::Cancel => {}
                    err => {
                        let ctx = ContextStack::current().top();
                        ctx.err = Some(*err);
                    }
                }
            } else {
                error!("Panicked inside: {:?}", cause.downcast::<&str>());
            }
        }
        // drop the clo here
    }

    yield_now();

    unreachable!("Should never comeback");
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::os::unix::io::AsRawFd;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::thread::sleep;

use crate::gpio::{Result, Mode, Level, Trigger, PullUpDown, GPIO_OFFSET_GPLEV, GPIO_OFFSET_GPFSEL, GPIO_OFFSET_GPPUDCLK, GPIO_OFFSET_GPPUD, GPIO_OFFSET_GPCLR, GPIO_OFFSET_GPSET, mem::GpioMem, interrupt::{AsyncInterrupt, EventLoop}};

#[derive(Debug)]
pub struct Pin {
    pin: u8,
    event_loop: Arc<Mutex<EventLoop>>,
    gpio_mem: Arc<Mutex<GpioMem>>,
    gpio_cdev: Arc<Mutex<File>>,
}

impl Pin {
    pub(crate) fn new(pin: u8, event_loop: Arc<Mutex<EventLoop>>, gpio_mem: Arc<Mutex<GpioMem>>, gpio_cdev: Arc<Mutex<File>>) -> Pin {
        Pin { pin, event_loop, gpio_mem, gpio_cdev }
    }

    pub fn as_input(&mut self) -> InputPin {
        InputPin::new(self)
    }

    pub fn as_output(&mut self) -> OutputPin {
        OutputPin::new(self, Mode::Output)
    }

    pub fn as_output_with_mode(&mut self, mode: Mode) -> OutputPin {
        OutputPin::new(self, mode)
    }

    pub(crate) fn set_mode(&mut self, mode: Mode) {
        let reg_addr: usize = GPIO_OFFSET_GPFSEL + (self.pin / 10) as usize;

        let reg_value = (*self.gpio_mem.lock().unwrap()).read(reg_addr);
        (*self.gpio_mem.lock().unwrap()).write(
            reg_addr,
            (reg_value & !(0b111 << ((self.pin % 10) * 3)))
                | ((mode as u32 & 0b111) << ((self.pin % 10) * 3)),
        );

    }

    /// Returns the current GPIO pin mode.
    pub fn mode(&self) -> Mode {
        let reg_addr: usize = GPIO_OFFSET_GPFSEL + (self.pin / 10) as usize;
        let reg_value = (*self.gpio_mem.lock().unwrap()).read(reg_addr);
        let mode_value = ((reg_value >> ((self.pin % 10) * 3)) & 0b111) as u8;

        mode_value.into()
    }

    /// Configures the built-in GPIO pull-up/pull-down resistors.
    pub fn set_pullupdown(&self, pud: PullUpDown) -> Result<()> {
        let gpio_mem = &*self.gpio_mem.lock().unwrap();

        // Set the control signal in GPPUD, while leaving the other 30
        // bits unchanged.
        let reg_value = gpio_mem.read(GPIO_OFFSET_GPPUD);
        gpio_mem.write(
            GPIO_OFFSET_GPPUD,
            (reg_value & !0b11) | ((pud as u32) & 0b11),
        );

        // Set-up time for the control signal.
        sleep(Duration::new(0, 20000)); // >= 20µs

        // Select the first GPPUDCLK register for the first 32 pins, and
        // the second register for the remaining pins.
        let reg_addr: usize = GPIO_OFFSET_GPPUDCLK + (self.pin / 32) as usize;

        // Clock the control signal into the selected pin.
        gpio_mem.write(reg_addr, 1 << (self.pin % 32));

        // Hold time for the control signal.
        sleep(Duration::new(0, 20000)); // >= 20µs

        // Remove the control signal and clock.
        let reg_value = gpio_mem.read(GPIO_OFFSET_GPPUD);
        gpio_mem.write(GPIO_OFFSET_GPPUD, reg_value & !0b11);
        gpio_mem.write(reg_addr, 0 << (self.pin % 32));

        Ok(())
    }
}

#[derive(Debug)]
pub struct InputPin<'a> {
    pin: &'a mut Pin,
    prev_mode: Option<Mode>,
    sync_interrupt: Option<EventLoop>,
    async_interrupt: Option<AsyncInterrupt>,
}

impl<'a> InputPin<'a> {
    pub(crate) fn new(pin: &'a mut Pin) -> InputPin<'a> {
        let prev_mode = pin.mode();

        let prev_mode = if prev_mode == Mode::Input {
            None
        } else {
            pin.set_mode(Mode::Input);
            Some(prev_mode)
        };

        InputPin { pin, prev_mode, sync_interrupt: None, async_interrupt: None }
    }

    pub fn read(&self) -> Level {
        let reg_addr: usize = GPIO_OFFSET_GPLEV + (self.pin.pin / 32) as usize;
        let reg_value = (*self.pin.gpio_mem.lock().unwrap()).read(reg_addr);

        if (reg_value & (1 << (self.pin.pin % 32))) > 0 {
            Level::High
        } else {
            Level::Low
        }
    }

    /// Configures a synchronous interrupt trigger.
    ///
    /// After configuring a synchronous interrupt trigger, you can use
    /// [`poll_interrupt`] to wait for a trigger event.
    ///
    /// `set_interrupt` will remove any previously configured
    /// (a)synchronous interrupt triggers for the same pin.
    ///
    /// [`poll_interrupt`]: #method.poll_interrupt
    pub fn set_interrupt(&mut self, trigger: Trigger) -> Result<()> {
        self.clear_async_interrupt()?;

        // Each pin can only be configured for a single trigger type
        (*self.pin.event_loop.lock().unwrap()).set_interrupt(self.pin.pin, trigger)
    }

    /// Removes a previously configured synchronous interrupt trigger.
    pub fn clear_interrupt(&mut self) -> Result<()> {
        (*self.pin.event_loop.lock().unwrap()).clear_interrupt(self.pin.pin)
    }

    /// Blocks until an interrupt is triggered on the specified pin, or a timeout occurs.
    ///
    /// `poll_interrupt` only works for pins that have been configured for synchronous interrupts using
    /// [`set_interrupt`]. Asynchronous interrupt triggers are automatically polled on a separate thread.
    ///
    /// Setting `reset` to `false` causes `poll_interrupt` to return immediately if the interrupt
    /// has been triggered since the previous call to [`set_interrupt`] or `poll_interrupt`.
    /// Setting `reset` to `true` clears any cached trigger events for the pin.
    ///
    /// The `timeout` duration indicates how long the call to `poll_interrupt` will block while waiting
    /// for interrupt trigger events, after which an `Ok(None))` is returned.
    /// `timeout` can be set to `None` to wait indefinitely.
    ///
    /// [`set_interrupt`]: #method.set_interrupt
    pub fn poll_interrupt(&mut self, reset: bool, timeout: Option<Duration>) -> Result<Option<Level>> {
        let opt = (*self.pin.event_loop.lock().unwrap()).poll(&[self.pin.pin], reset, timeout)?;

        if let Some(trigger) = opt {
            Ok(Some(trigger.1))
        } else {
            Ok(None)
        }
    }

    /// Configures an asynchronous interrupt trigger, which will execute the callback on a
    /// separate thread when the interrupt is triggered.
    ///
    /// The callback closure or function pointer is called with a single [`Level`] argument.
    ///
    /// `set_async_interrupt` will remove any previously configured
    /// (a)synchronous interrupt triggers for the same pin.
    ///
    /// [`Level`]: enum.Level.html
    pub fn set_async_interrupt<C>(&mut self, trigger: Trigger, callback: C) -> Result<()>
    where
        C: FnMut(Level) + Send + 'static,
    {
        self.clear_interrupt()?;
        self.clear_async_interrupt()?;

        self.async_interrupt = Some(AsyncInterrupt::new(
            (*self.pin.gpio_cdev.lock().unwrap()).as_raw_fd(),
            self.pin.pin,
            trigger,
            callback,
        )?);

        Ok(())
    }

    pub(crate) fn clear_async_interrupt(&mut self) -> Result<()> {
        if let Some(mut interrupt) = self.async_interrupt.take() {
            interrupt.stop()?;
        }

        Ok(())
    }
}

impl<'a> Drop for InputPin<'a> {
    fn drop(&mut self) {
        let _ = self.clear_async_interrupt();

        if let Some(prev_mode) = self.prev_mode {
            self.pin.set_mode(prev_mode)
        }
    }
}

#[derive(Debug)]
pub struct OutputPin<'a> {
    pin: &'a mut Pin,
    mode: Mode,
    prev_mode: Option<Mode>,
}

impl<'a> OutputPin<'a> {
    pub(crate) fn new(pin: &'a mut Pin, mode: Mode) -> OutputPin<'a> {
        let prev_mode = pin.mode();

        let prev_mode = if prev_mode == mode {
            None
        } else {
            pin.set_mode(mode);
            Some(prev_mode)
        };

        OutputPin { pin, mode, prev_mode }
    }

    pub fn set_low(&mut self) {
        self.write(Level::Low)
    }

    pub fn set_high(&mut self) {
        self.write(Level::High)
    }

    pub fn write(&mut self, level: Level) {
        let reg_addr: usize = match level {
            Level::Low => GPIO_OFFSET_GPCLR + (self.pin.pin / 32) as usize,
            Level::High => GPIO_OFFSET_GPSET + (self.pin.pin / 32) as usize,
        };

        (*self.pin.gpio_mem.lock().unwrap()).write(reg_addr, 1 << (self.pin.pin % 32));
    }
}

impl<'a> Drop for OutputPin<'a> {
  fn drop(&mut self) {
    if let Some(prev_mode) = self.prev_mode {
      self.pin.set_mode(prev_mode)
    }
  }
}
<commit_msg>Remove unused field.<commit_after>use std::fs::File;
use std::os::unix::io::AsRawFd;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::thread::sleep;

use crate::gpio::{Result, Mode, Level, Trigger, PullUpDown, GPIO_OFFSET_GPLEV, GPIO_OFFSET_GPFSEL, GPIO_OFFSET_GPPUDCLK, GPIO_OFFSET_GPPUD, GPIO_OFFSET_GPCLR, GPIO_OFFSET_GPSET, mem::GpioMem, interrupt::{AsyncInterrupt, EventLoop}};

#[derive(Debug)]
pub struct Pin {
    pin: u8,
    event_loop: Arc<Mutex<EventLoop>>,
    gpio_mem: Arc<Mutex<GpioMem>>,
    gpio_cdev: Arc<Mutex<File>>,
}

impl Pin {
    pub(crate) fn new(pin: u8, event_loop: Arc<Mutex<EventLoop>>, gpio_mem: Arc<Mutex<GpioMem>>, gpio_cdev: Arc<Mutex<File>>) -> Pin {
        Pin { pin, event_loop, gpio_mem, gpio_cdev }
    }

    pub fn as_input(&mut self) -> InputPin {
        InputPin::new(self)
    }

    pub fn as_output(&mut self) -> OutputPin {
        OutputPin::new(self, Mode::Output)
    }

    pub fn as_output_with_mode(&mut self, mode: Mode) -> OutputPin {
        OutputPin::new(self, mode)
    }

    pub(crate) fn set_mode(&mut self, mode: Mode) {
        let reg_addr: usize = GPIO_OFFSET_GPFSEL + (self.pin / 10) as usize;

        let reg_value = (*self.gpio_mem.lock().unwrap()).read(reg_addr);
        (*self.gpio_mem.lock().unwrap()).write(
            reg_addr,
            (reg_value & !(0b111 << ((self.pin % 10) * 3)))
                | ((mode as u32 & 0b111) << ((self.pin % 10) * 3)),
        );

    }

    /// Returns the current GPIO pin mode.
    pub fn mode(&self) -> Mode {
        let reg_addr: usize = GPIO_OFFSET_GPFSEL + (self.pin / 10) as usize;
        let reg_value = (*self.gpio_mem.lock().unwrap()).read(reg_addr);
        let mode_value = ((reg_value >> ((self.pin % 10) * 3)) & 0b111) as u8;

        mode_value.into()
    }

    /// Configures the built-in GPIO pull-up/pull-down resistors.
    pub fn set_pullupdown(&self, pud: PullUpDown) -> Result<()> {
        let gpio_mem = &*self.gpio_mem.lock().unwrap();

        // Set the control signal in GPPUD, while leaving the other 30
        // bits unchanged.
        let reg_value = gpio_mem.read(GPIO_OFFSET_GPPUD);
        gpio_mem.write(
            GPIO_OFFSET_GPPUD,
            (reg_value & !0b11) | ((pud as u32) & 0b11),
        );

        // Set-up time for the control signal.
        sleep(Duration::new(0, 20000)); // >= 20µs

        // Select the first GPPUDCLK register for the first 32 pins, and
        // the second register for the remaining pins.
        let reg_addr: usize = GPIO_OFFSET_GPPUDCLK + (self.pin / 32) as usize;

        // Clock the control signal into the selected pin.
        gpio_mem.write(reg_addr, 1 << (self.pin % 32));

        // Hold time for the control signal.
        sleep(Duration::new(0, 20000)); // >= 20µs

        // Remove the control signal and clock.
        let reg_value = gpio_mem.read(GPIO_OFFSET_GPPUD);
        gpio_mem.write(GPIO_OFFSET_GPPUD, reg_value & !0b11);
        gpio_mem.write(reg_addr, 0 << (self.pin % 32));

        Ok(())
    }
}

#[derive(Debug)]
pub struct InputPin<'a> {
    pin: &'a mut Pin,
    prev_mode: Option<Mode>,
    async_interrupt: Option<AsyncInterrupt>,
}

impl<'a> InputPin<'a> {
    pub(crate) fn new(pin: &'a mut Pin) -> InputPin<'a> {
        let prev_mode = pin.mode();

        let prev_mode = if prev_mode == Mode::Input {
            None
        } else {
            pin.set_mode(Mode::Input);
            Some(prev_mode)
        };

        InputPin { pin, prev_mode, async_interrupt: None }
    }

    pub fn read(&self) -> Level {
        let reg_addr: usize = GPIO_OFFSET_GPLEV + (self.pin.pin / 32) as usize;
        let reg_value = (*self.pin.gpio_mem.lock().unwrap()).read(reg_addr);

        if (reg_value & (1 << (self.pin.pin % 32))) > 0 {
            Level::High
        } else {
            Level::Low
        }
    }

    /// Configures a synchronous interrupt trigger.
    ///
    /// After configuring a synchronous interrupt trigger, you can use
    /// [`poll_interrupt`] to wait for a trigger event.
    ///
    /// `set_interrupt` will remove any previously configured
    /// (a)synchronous interrupt triggers for the same pin.
    ///
    /// [`poll_interrupt`]: #method.poll_interrupt
    pub fn set_interrupt(&mut self, trigger: Trigger) -> Result<()> {
        self.clear_async_interrupt()?;

        // Each pin can only be configured for a single trigger type
        (*self.pin.event_loop.lock().unwrap()).set_interrupt(self.pin.pin, trigger)
    }

    /// Removes a previously configured synchronous interrupt trigger.
    pub fn clear_interrupt(&mut self) -> Result<()> {
        (*self.pin.event_loop.lock().unwrap()).clear_interrupt(self.pin.pin)
    }

    /// Blocks until an interrupt is triggered on the specified pin, or a timeout occurs.
    ///
    /// `poll_interrupt` only works for pins that have been configured for synchronous interrupts using
    /// [`set_interrupt`]. Asynchronous interrupt triggers are automatically polled on a separate thread.
    ///
    /// Setting `reset` to `false` causes `poll_interrupt` to return immediately if the interrupt
    /// has been triggered since the previous call to [`set_interrupt`] or `poll_interrupt`.
    /// Setting `reset` to `true` clears any cached trigger events for the pin.
    ///
    /// The `timeout` duration indicates how long the call to `poll_interrupt` will block while waiting
    /// for interrupt trigger events, after which an `Ok(None))` is returned.
    /// `timeout` can be set to `None` to wait indefinitely.
    ///
    /// [`set_interrupt`]: #method.set_interrupt
    pub fn poll_interrupt(&mut self, reset: bool, timeout: Option<Duration>) -> Result<Option<Level>> {
        let opt = (*self.pin.event_loop.lock().unwrap()).poll(&[self.pin.pin], reset, timeout)?;

        if let Some(trigger) = opt {
            Ok(Some(trigger.1))
        } else {
            Ok(None)
        }
    }

    /// Configures an asynchronous interrupt trigger, which will execute the callback on a
    /// separate thread when the interrupt is triggered.
    ///
    /// The callback closure or function pointer is called with a single [`Level`] argument.
    ///
    /// `set_async_interrupt` will remove any previously configured
    /// (a)synchronous interrupt triggers for the same pin.
    ///
    /// [`Level`]: enum.Level.html
    pub fn set_async_interrupt<C>(&mut self, trigger: Trigger, callback: C) -> Result<()>
    where
        C: FnMut(Level) + Send + 'static,
    {
        self.clear_interrupt()?;
        self.clear_async_interrupt()?;

        self.async_interrupt = Some(AsyncInterrupt::new(
            (*self.pin.gpio_cdev.lock().unwrap()).as_raw_fd(),
            self.pin.pin,
            trigger,
            callback,
        )?);

        Ok(())
    }

    pub(crate) fn clear_async_interrupt(&mut self) -> Result<()> {
        if let Some(mut interrupt) = self.async_interrupt.take() {
            interrupt.stop()?;
        }

        Ok(())
    }
}

impl<'a> Drop for InputPin<'a> {
    fn drop(&mut self) {
        let _ = self.clear_async_interrupt();

        if let Some(prev_mode) = self.prev_mode {
            self.pin.set_mode(prev_mode)
        }
    }
}

#[derive(Debug)]
pub struct OutputPin<'a> {
    pin: &'a mut Pin,
    mode: Mode,
    prev_mode: Option<Mode>,
}

impl<'a> OutputPin<'a> {
    pub(crate) fn new(pin: &'a mut Pin, mode: Mode) -> OutputPin<'a> {
        let prev_mode = pin.mode();

        let prev_mode = if prev_mode == mode {
            None
        } else {
            pin.set_mode(mode);
            Some(prev_mode)
        };

        OutputPin { pin, mode, prev_mode }
    }

    pub fn set_low(&mut self) {
        self.write(Level::Low)
    }

    pub fn set_high(&mut self) {
        self.write(Level::High)
    }

    pub fn write(&mut self, level: Level) {
        let reg_addr: usize = match level {
            Level::Low => GPIO_OFFSET_GPCLR + (self.pin.pin / 32) as usize,
            Level::High => GPIO_OFFSET_GPSET + (self.pin.pin / 32) as usize,
        };

        (*self.pin.gpio_mem.lock().unwrap()).write(reg_addr, 1 << (self.pin.pin % 32));
    }
}

impl<'a> Drop for OutputPin<'a> {
  fn drop(&mut self) {
    if let Some(prev_mode) = self.prev_mode {
      self.pin.set_mode(prev_mode)
    }
  }
}
<|endoftext|>


<commit_before>use ops;
use std::cmp::Ordering;
use std::collections::hash_map::{Entry, HashMap};
use std::mem;
use tensor::Tensor;

fn get_sorted_between_nodes<'a>(ys: &[&'a Tensor], xs: &[&'a Tensor]) -> Vec<TensorWrapper<'a>>
{
    let marked = mark_backward_path(ys, xs);
    let mut between = marked
        .into_iter()
        .filter_map(|(k, v)| if v && !k.is_source() {
            Some(k.wrapped())
        } else {
            None
        })
        .collect::<Vec<TensorWrapper>>();
    between.sort_unstable(); // topological sort
    between
}

#[test]
fn test_sorted_between_nodes()
{
    use std::rc::Rc;
    // dummy graph
    // y = 3 * x1 * x1 + 5 * x2 + x3;
    let ref x1 = ::placeholder(&[]);
    let ref x2 = ::placeholder(&[]);
    let ref x3 = ::placeholder(&[]);
    let ref a = 3 * x1; // rank 1
    let ref b = a * x1; // rank 2
    let ref c = 5 * x2; // rank 1
    let ref d = b + c; // rank 3
    let ref y = d + x3; // rank 4
    let sorted_between: Vec<TensorWrapper> = get_sorted_between_nodes(&[y], &[x1, x2]);
    let sorted_between: Vec<&Tensor> = sorted_between.iter().map(|a| a.tensor).collect();

    assert!(sorted_between.contains(&a));
    assert!(sorted_between.contains(&b));
    assert!(sorted_between.contains(&c));
    assert!(sorted_between.contains(&d));
    assert!(sorted_between.contains(&y));
    assert_eq!(sorted_between.len(), 5);

    // Order test
    assert!(sorted_between[..2].contains(&a));
    assert!(sorted_between[..2].contains(&c));
    assert!(Rc::ptr_eq(sorted_between[2], b));
    assert!(Rc::ptr_eq(sorted_between[3], d));
    assert!(Rc::ptr_eq(sorted_between[4], y));
}

use std::fmt;

impl fmt::Debug for Tensor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        write!(f, "{}", self.op.name())
    }
}

/// Returns symbolic gradient tensors.
///
/// This computes partial derivatives of `ys` with `xs` and returns the
/// gradients. This is achieved by building the subgraph between `ys` and
/// `xs` in reverse order from user's graph definition.
/// `known_gys` are already known gradients of `ys`'s outputs.
///
/// NOTE: Nodes that do not contribute to the gradient won't be included to avoid
/// unnecessary computation.
pub fn symbolic_gradients(
    ys: &[&Tensor],
    xs: &[&Tensor],
    known_gys: &[Option<&Tensor>],
) -> Vec<Tensor>
{
    assert_eq!(
        ys.len(),
        known_gys.len(),
        "`ys.len()` must match `gys.len()`"
    );

    // Prepare gradient store
    let mut computed_gys: HashMap<&Tensor, Vec<Tensor>> = HashMap::new();

    // Store default grads
    for (y, known_gy) in ys.iter().zip(known_gys) {
        let gy = known_gy.map(|k| k.clone()).unwrap_or_else(
            || ops::scalar(1.),
        );
        computed_gys.insert(y, vec![gy]);
    }

    // "Reverse order" iteration
    for y in get_sorted_between_nodes(ys, xs).iter().rev() {
        // Get y's input nodes
        let xs_ref = y.tensor.inputs.iter().map(|a| a).collect::<Vec<_>>();

        // Get gxs by calling `Op::grad`
        let gxs = {
            let gys = computed_gys.get_mut(&y.tensor).expect(&format!(
                "Couldn't get `{}`'s grad (probably a bug)",
                y.tensor
            ));
            accumulate_grads(gys);
            y.tensor.op.grad(&gys[0], xs_ref.as_slice(), y.tensor)
        };

        // Check correctness of y's `grad` implementation
        debug_assert_eq!(
            xs_ref.len(),
            gxs.len(),
            "`{}.grad` must return {} gxs",
            y.tensor,
            xs_ref.len()
        );

        // Register computed gxs
        for (gx, x) in gxs.into_iter().zip(xs_ref) {
            if let Some(gx_) = gx {
                // Store gx in `computed_gys[x]`
                match computed_gys.entry(x) {
                    Entry::Occupied(mut grad_buf) => grad_buf.get_mut().push(gx_),
                    Entry::Vacant(grad_buf) => {
                        grad_buf.insert(vec![gx_]);
                    }
                }
            }
        }
    }

    // Aggregate and return xs's gradients
    xs.iter()
        .map(|x| {
            let mut gxs = computed_gys.remove(x).expect(
                "Input tensor(s) not differentiable.",
            );
            accumulate_grads(&mut gxs);
            gxs.remove(0)
        })
        .collect::<Vec<Tensor>>()
}

fn mark_backward_path<'a>(ys: &[&'a Tensor], xs: &[&'a Tensor]) -> HashMap<&'a Tensor, bool>
{
    fn rec<'a>(target: &'a Tensor, vars: &[&'a Tensor], memo: &mut HashMap<&'a Tensor, bool>)
    {
        if memo.contains_key(target) {
            return;
        }

        let mut contrib = false;

        if !target.op.stop_gradient() {
            if vars.contains(&target) {
                contrib = true; // need not recursion.
            } else {
                for x in target.inputs.iter() {
                    // recurse
                    rec(x, vars, memo);
                    // unwrap is always safe
                    contrib |= *memo.get(x).unwrap();
                }
            }
        }
        memo.insert(target, contrib);
    }

    let mut memo = HashMap::new();
    for y in ys.into_iter() {
        rec(y, xs, &mut memo);
    }
    memo
}

impl<'a> Ord for TensorWrapper<'a> {
    /// Compares the ranks in topological ordering
    fn cmp(&self, other: &Self) -> Ordering
    {
        self.tensor.top_rank.cmp(&other.tensor.top_rank)
    }
}

impl<'a> PartialOrd for TensorWrapper<'a> {
    /// Compares the ranks in topological ordering
    fn partial_cmp(&self, other: &Self) -> Option<Ordering>
    {
        Some(self.tensor.top_rank.cmp(&other.tensor.top_rank))
    }
}

impl<'a> Eq for TensorWrapper<'a> {}

impl<'a> PartialEq for TensorWrapper<'a> {
    fn eq(&self, other: &TensorWrapper<'a>) -> bool
    {
        self.tensor.eq(&other.tensor)
    }
}

impl Tensor {
    #[inline]
    fn wrapped(&self) -> TensorWrapper
    {
        let ret = TensorWrapper { tensor: self };
        ret
    }
}

#[inline]
fn accumulate_grads(grads: &mut Vec<Tensor>)
{
    if grads.len() >= 2 {
        let acc = {
            let refs = grads.iter().map(|a| a).collect::<Vec<_>>();
            ops::add_n(refs.as_slice())
        };
        mem::swap(&mut vec![acc], grads);
    }
}

/// Module private.
struct TensorWrapper<'a> {
    tensor: &'a Tensor,
}
<commit_msg>Avoid recursion in mark_gradient_path fn<commit_after>use ops;
use std::cmp::Ordering;
use std::collections::binary_heap::BinaryHeap;
use std::fmt;
use std::mem;
use std::rc::Rc;
use tensor::Tensor;

struct GradInfo<'a> {
    node: &'a Tensor,
    has_gradient: bool,
    grad_called: bool,
    computed_grads: Vec<Tensor>,
    default_grad: Option<&'a Tensor>,
}

impl<'a> GradInfo<'a> {
    #[inline]
    fn new(t: &'a Tensor, has_gradient: bool, default_grad: Option<&'a Tensor>) -> GradInfo<'a>
    {
        GradInfo {
            node: t,
            has_gradient,
            computed_grads: Vec::new(),
            grad_called: false,
            default_grad,
        }
    }
}

impl<'a> fmt::Debug for GradInfo<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        write!(f, "{}", self.node.op.name())
    }
}

impl fmt::Debug for Tensor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        write!(f, "{}", self.op.name())
    }
}

macro_rules! access_grad_info_of {
    ($node:expr, $path:expr) => {
        $path[$node.eval_context.resource_lookup_key.get()]
    };
}

// Marks `has_gradient` if each node is on the gradient propagation path.
// NOTE: Disconnected "parent nodes" are included but their children are not.
fn mark_gradient_path<'a>(ys: &[&'a Tensor], xs: &[&'a Tensor]) -> Vec<GradInfo<'a>>
{
    // Randomly accessible by use of each node's lookup key.
    let mut path: Vec<GradInfo<'a>> = Vec::new();

    // Builds GradInfo while performing DFS.
    // `has_gradient` properties are filled at the same time.
    let mut dfs_stack: Vec<(&Tensor, bool)> = ys.iter().map(|&y| (y, false)).collect();
    while let Some((node, is_parent)) = dfs_stack.pop() {
        if is_parent {
            let mut marker = xs.contains(&node);
            if !marker {
                for x in node.inputs.iter() {
                    marker |= access_grad_info_of!(x, path).has_gradient;
                }
            }
            node.eval_context.resource_lookup_key.set(path.len());
            path.push(GradInfo::new(node, marker, None));
        } else {
            dfs_stack.push((node, true));
            // Push children if needed
            for child in &node.inputs {
                let visited = {
                    let k = child.eval_context.resource_lookup_key.get();
                    k < path.len() && Rc::ptr_eq(child, path[k].node)
                };
                if !visited {
                    if child.is_source() || child.op.stop_gradient() {
                        // Add to result, but don't allow more recursive search
                        child.eval_context.resource_lookup_key.set(path.len());
                        path.push(GradInfo::new(child, xs.contains(&child), None));
                    } else {
                        // Recurse
                        dfs_stack.push((child, false));
                    }
                }
            }
        }
    }
    path
}

#[test]
fn test_gradient_path()
{
    use std::rc::Rc;
    // dummy graph
    // y = 3 * x1 * x1 + 5 * x2 + x3;
    let ref x1 = ::ops::placeholder(&[]);
    let ref x2 = ::ops::placeholder(&[]);
    let ref x3 = ::ops::placeholder(&[]);
    let ref a = 3 * x1; // rank 1
    let ref b = a * x1; // rank 2
    let ref c = 5 * x2; // rank 1
    let ref d = b + c; // rank 3
    let ref y = d + x3; // rank 4
    let path = mark_gradient_path(&[y], &[x1, x2]);
    let path_: Vec<&Tensor> = path.iter().map(|a| a.node).collect();

    assert!(path_.contains(&x1));
    assert!(path_.contains(&x2));
    assert!(path_.contains(&x3));
    assert!(path_.contains(&a));
    assert!(path_.contains(&b));
    assert!(path_.contains(&c));
    assert!(path_.contains(&d));
    assert!(path_.contains(&y));
    assert_eq!(path_.len(), 10); // number of nodes in the grad path

    // Topological ordering test
    let ix1 = path_.iter().position(|x| Rc::ptr_eq(x, x1)).unwrap();
    let ix2 = path_.iter().position(|x| Rc::ptr_eq(x, x2)).unwrap();
    let ix3 = path_.iter().position(|x| Rc::ptr_eq(x, x3)).unwrap();
    let ia = path_.iter().position(|x| Rc::ptr_eq(x, a)).unwrap();
    let ic = path_.iter().position(|x| Rc::ptr_eq(x, c)).unwrap();
    let ib = path_.iter().position(|x| Rc::ptr_eq(x, b)).unwrap();
    let id = path_.iter().position(|x| Rc::ptr_eq(x, d)).unwrap();
    let iy = path_.iter().position(|x| Rc::ptr_eq(x, y)).unwrap();
    assert!(ix1 < ia);
    assert!(ix2 < ic);
    assert!(ix3 < iy);
    assert!(ib < id);
    assert!(id < iy);

    // Ensure continuity of keys
    for (i, node) in path_.iter().enumerate() {
        assert_eq!(i, node.eval_context.resource_lookup_key.get());
    }

    // Connection test
    use std::collections::btree_set::BTreeSet;
    let all = (0..10).collect::<BTreeSet<usize>>();
    let should_be_has_gradient = [ix1, ix2, ia, ic, ib, id, iy]
        .into_iter()
        .cloned()
        .collect::<BTreeSet<usize>>();
    for &id in should_be_has_gradient.iter() {
        if !path[id].has_gradient {
            panic!("{} is not has_gradient", path[id].node.op.name());
        }
    }
    for &id in all.difference(&should_be_has_gradient).into_iter() {
        if path[id].has_gradient {
            panic!("{} should not be has_gradient", path[id].node.op.name());
        }
    }
}

/// Returns symbolic gradient tensors.
///
/// This computes partial derivatives of `ys` with `xs` and returns the
/// gradients. This is achieved by building the subgraph between `ys` and
/// `xs` in reverse order from user's graph definition.
/// `known_gys` are already known gradients of `ys`'s outputs.
///
/// NOTE: Nodes that do not have gradient won't be included in the subgraph avoid
/// unnecessary computation.
pub fn symbolic_gradients(
    ys: &[&Tensor],
    xs: &[&Tensor],
    known_gys: &[Option<&Tensor>],
) -> Vec<Tensor>
{
    assert_eq!(
        ys.len(),
        known_gys.len(),
        "`ys.len()` must match `gys.len()`"
    );

    // Setup gradient path.
    let mut path = mark_gradient_path(ys, xs);

    // Set default grads.
    for (y, gy) in ys.iter().zip(known_gys) {
        let y_info = &mut access_grad_info_of!(y, path);
        if let &Some(gy_) = gy {
            y_info.default_grad = Some(gy_);
        } else {
            y_info.computed_grads.push(ops::scalar(1.));
        }
    }

    // Prepare a heap with given ys.
    let mut heap = ys.into_iter()
        .map(|y| y.wrapped())
        .collect::<BinaryHeap<TensorWrapper>>();

    // Backprop.
    while let Some(y) = heap.pop() {
        let xs_ = y.tensor.inputs.iter().map(|a| a).collect::<Vec<&Tensor>>();
        let gxs = {
            let info = &mut access_grad_info_of!(y.tensor, path);
            let gy = if let Some(def) = info.default_grad {
                def
            } else {
                let gys: &mut Vec<_> = &mut info.computed_grads;
                accumulate_grads(gys);
                &gys[0]
            };
            // Call Op::grad
            let gxs = y.tensor.op.grad(gy, xs_.as_slice(), y.tensor);
            // Validate y::op::grad implementation
            debug_assert_eq!(
                xs_.len(),
                gxs.len(),
                "{}::grad returned {} gxs",
                y.tensor,
                gxs.len()
            );
            gxs
        };
        // Register computed gradients
        for (gx, x) in gxs.into_iter().zip(xs_) {
            let x_info = &mut access_grad_info_of!(x, path);
            if x_info.has_gradient {
                if let Some(gx_) = gx {
                    x_info.computed_grads.push(gx_);
                    // update heap
                    if !x.is_source() && !x_info.grad_called {
                        x_info.grad_called = true;
                        heap.push(x.wrapped());
                    }
                }
            }
        }
    }

    // Aggregate and return xs's gradients
    xs.iter()
        .map(|x| {
            let xk = x.eval_context.resource_lookup_key.get();
            assert!(
                xk < path.len() && Rc::ptr_eq(x, path[xk].node),
                "Not differentiable with given tensor(s)."
            );
            let info = &mut path[xk];
            assert!(
                info.default_grad.is_none(),
                "Can't differentiate with objective itself"
            );
            let gxs = &mut info.computed_grads;
            accumulate_grads(gxs);
            debug_assert_eq!(gxs.len(), 1);
            gxs.remove(0)
        })
        .collect::<Vec<Tensor>>()
}

// Module private.
struct TensorWrapper<'a> {
    tensor: &'a Tensor,
}

impl<'a> Ord for TensorWrapper<'a> {
    // Compares the ranks in topological ordering
    fn cmp(&self, other: &Self) -> Ordering
    {
        self.tensor.top_rank.cmp(&other.tensor.top_rank)
    }
}

impl<'a> PartialOrd for TensorWrapper<'a> {
    // Compares the ranks in topological ordering
    fn partial_cmp(&self, other: &Self) -> Option<Ordering>
    {
        Some(self.tensor.top_rank.cmp(&other.tensor.top_rank))
    }
}

impl<'a> Eq for TensorWrapper<'a> {}

impl<'a> PartialEq for TensorWrapper<'a> {
    fn eq(&self, other: &TensorWrapper<'a>) -> bool
    {
        self.tensor.eq(&other.tensor)
    }
}

impl Tensor {
    #[inline]
    fn wrapped(&self) -> TensorWrapper
    {
        TensorWrapper { tensor: self }
    }
}

#[inline]
fn accumulate_grads(grads: &mut Vec<Tensor>)
{
    if grads.len() > 1 {
        let acc = {
            let refs = grads.iter().map(|a| a).collect::<Vec<_>>();
            ops::add_n(refs.as_slice())
        };
        mem::swap(&mut vec![acc], grads);
    }
}
<|endoftext|>


<commit_before>/// This HTTP client wrapper exists so that if hyper's http client becomes
/// unsupported, putting in a different client only required modifying this one
/// module.
///
extern crate hyper;

use std::option::Option;
use std::collections::HashMap;
use std::convert::From;
use std::result::Result;
use std::io::Read;

struct Response {
    body: Option<String>,
}

// TODO
#[derive(Debug)]
pub enum HttpError {
    Failed
}

impl From<hyper::HttpError> for HttpError {
    fn from(e: hyper::HttpError) -> HttpError {
        HttpError::Failed
    }
}

pub struct Http {
    body: Option<String>,
    headers: HashMap<String, String>
}

impl<'a> Http {
    pub fn new() -> Http {
        Http {
            body: None,
            headers: HashMap::new()
        }
    }

    pub fn body(&mut self, body: &str) -> &mut Http {
        self.body = Some(body.to_string());
        self
    }

    pub fn header(&mut self, header: &str, value: &str) -> &mut Http {
        self.headers.insert(header.to_string(), value.to_string());
        self
    }

    fn build(&self, method: Method, url: &str) -> Result<Response, HttpError> {
        let mut client = hyper::Client::new();
        let s = url.to_string();

        let builder = match method {
            Method::GET => client.get(s.as_ref()),
            Method::PUT => client.put(s.as_ref()),
            Method::POST => client.post(s.as_ref()),
            Method::DELETE => client.delete(s.as_ref())
        };

        // TODO body
        // TODO headers

        let mut hyper_res = builder.send();

        match hyper_res {
            Err(e) => { Err(HttpError::from(e)) },
            Ok(mut r) => {
                let mut body = String::new();
                r.read_to_string(&mut body).unwrap();

                Ok(Response {
                    body: Some(body)
                })
            }
        }
    }

    pub fn get(&mut self, url: &str) -> Result<Response, HttpError> {
        self.build(Method::GET, url)
    }

    pub fn put(&mut self, url: &str) -> Result<Response, HttpError> {
        self.build(Method::PUT, url)
    }

    pub fn post(&mut self, url: &str) -> Result<Response, HttpError> {
        self.build(Method::POST, url)
    }

    pub fn delete(&mut self, url: &str) -> Result<Response, HttpError> {
        self.build(Method::DELETE, url)
    }
}

#[derive(Copy, Clone)]
pub enum Method {
    GET,
    POST,
    PUT,
    DELETE
}

impl Method {
    pub fn to_str(&self) -> &str {
        match *self {
            Method::GET => { "GET" },
            Method::POST => { "POST" },
            Method::PUT => { "PUT" },
            Method::DELETE => { "DELETE" }
        }
    }
}

#[test]
fn request_wrapper_can_fetch() {
    let res = Http::new().get("http://www.google.com").unwrap();
    let body = res.body.unwrap();
    assert!(body.contains("doctype html"));
}
<commit_msg>Support request body in http wrapper<commit_after>/// This HTTP client wrapper exists so that if hyper's http client becomes
/// unsupported, putting in a different client only required modifying this one
/// module.
///
extern crate hyper;

use std::option::Option;
use std::collections::HashMap;
use std::convert::From;
use std::result::Result;
use std::io::Read;

use std::fmt;

struct Response {
    body: Option<String>,
}

use std::fmt::Display;

impl fmt::Display for Response {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s: &str = self.body.as_ref().unwrap().as_ref();
        s.fmt(f)
    }
}

// TODO
#[derive(Debug)]
pub enum HttpError {
    Failed
}

impl From<hyper::HttpError> for HttpError {
    fn from(e: hyper::HttpError) -> HttpError {
        HttpError::Failed
    }
}

pub struct Http {
    body: Option<String>,
    headers: HashMap<String, String>
}

impl<'a> Http {
    pub fn new() -> Http {
        Http {
            body: None,
            headers: HashMap::new()
        }
    }

    pub fn body(&mut self, body: &str) -> &mut Http {
        self.body = Some(body.to_string());
        self
    }

    fn build(&self, method: Method, url: &str) -> Result<Response, HttpError> {
        let mut client = hyper::Client::new();
        let s = url.to_string();

        let mut builder = match method {
            Method::GET => client.get(s.as_ref()),
            Method::PUT => client.put(s.as_ref()),
            Method::POST => client.post(s.as_ref()),
            Method::DELETE => client.delete(s.as_ref())
        };

        // TODO is there a better way to do this?
        builder = if self.body.is_some() {
            let s: &str = (*(self.body.as_ref().unwrap())).as_ref();
            builder.body(s)
        } else {
            builder
        };

        let hyper_res = builder.send();

        match hyper_res {
            Err(e) => { Err(HttpError::from(e)) },
            Ok(mut r) => {
                let mut body = String::new();
                r.read_to_string(&mut body).unwrap();

                Ok(Response {
                    body: Some(body)
                })
            }
        }
    }

    pub fn get(&mut self, url: &str) -> Result<Response, HttpError> {
        self.build(Method::GET, url)
    }

    pub fn put(&mut self, url: &str) -> Result<Response, HttpError> {
        self.build(Method::PUT, url)
    }

    pub fn post(&mut self, url: &str) -> Result<Response, HttpError> {
        self.build(Method::POST, url)
    }

    pub fn delete(&mut self, url: &str) -> Result<Response, HttpError> {
        self.build(Method::DELETE, url)
    }
}

#[derive(Copy, Clone)]
pub enum Method {
    GET,
    POST,
    PUT,
    DELETE
}

impl Method {
    pub fn to_str(&self) -> &str {
        match *self {
            Method::GET => { "GET" },
            Method::POST => { "POST" },
            Method::PUT => { "PUT" },
            Method::DELETE => { "DELETE" }
        }
    }
}

#[test]
fn request_wrapper_can_fetch() {
    let res = Http::new().get("http://www.google.com").unwrap();
    let body = res.body.unwrap();
    assert!(body.contains("doctype html"));
}
<|endoftext|>


<commit_before>use types::PokeType;

mod generated_species_data;
use self::generated_species_data::SPECIES;

#[derive(Debug, Eq, PartialEq, Hash)]
/// Information about a specific Pokemon species.
pub struct SpeciesData {
    id: u16,
    attack: u16,
    defense: u16,
    stamina: u16,
    primary_type: PokeType,
    secondary_type: Option<PokeType>,
}

impl SpeciesData {
    /// Given the id of a species, return its corresponding data. Return `None` if no data is found
    /// for the given id.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::SpeciesData;
    ///
    /// let dragonite = SpeciesData::from_id(149).unwrap();
    /// assert_eq!((263, 201, 182), dragonite.base_stats());
    ///
    /// let no_such_pokemon = SpeciesData::from_id(500);
    /// assert!(no_such_pokemon.is_none());
    /// ```
    pub fn from_id(id: u16) -> Option<&'static SpeciesData> {
        SPECIES.iter().find(|p| p.id() == id)
    }

    /// Return a list of all `SpeciesData`, sorted by id.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::SpeciesData;
    ///
    /// let all_species = SpeciesData::all_species();
    ///
    /// assert_eq!(251, all_species.len());
    /// assert_eq!(1, all_species[0].id());
    /// ```
    pub fn all_species() -> &'static [SpeciesData] {
        SPECIES
    }

    /// This species' id.
    pub fn id(&self) -> u16 {
        self.id
    }

    /// This species' base attack value.
    pub fn attack(&self) -> u16 {
        self.attack
    }

    /// This species's base defense value.
    pub fn defense(&self) -> u16 {
        self.defense
    }

    /// This species' base stamina value.
    pub fn stamina(&self) -> u16 {
        self.stamina
    }

    /// This species' base stats, as an `(attack, defense, stamina)` triple.
    pub fn base_stats(&self) -> (u16, u16, u16) {
        (self.attack, self.defense, self.stamina)
    }

    /// This species' primary `PokeType`.
    pub fn primary_type(&self) -> PokeType {
        self.primary_type
    }

    /// If this species is dual-typed, returns the secondary `PokeType`.
    pub fn secondary_type(&self) -> Option<PokeType> {
        self.secondary_type
    }

    /// Returns `true` if this species has two `PokeType`s.
    pub fn is_dual_type(&self) -> bool {
        self.secondary_type.is_some()
    }
}

#[cfg(test)]
mod tests {
    use types::PokeType;
    use SpeciesData;

    #[test]
    fn pokemon_by_id_test() {
        let bulbasaur = SpeciesData::from_id(1).unwrap();
        assert_eq!((118, 118, 90), bulbasaur.base_stats());

        let sentret = SpeciesData::from_id(161).unwrap();
        assert_eq!((79, 77, 70), sentret.base_stats());

        let lugia = SpeciesData::from_id(249).unwrap();
        assert_eq!((193, 323, 212), lugia.base_stats());

        assert!(SpeciesData::from_id(252).is_none());
    }

    #[test]
    fn poketype() {
        let charizard = SpeciesData::from_id(6).unwrap();
        assert_eq!(PokeType::Fire, charizard.primary_type());
        assert_eq!(Some(PokeType::Flying), charizard.secondary_type());

        let squirtle = SpeciesData::from_id(7).unwrap();
        assert_eq!(PokeType::Water, squirtle.primary_type());
        assert!(squirtle.secondary_type().is_none());
    }

    #[test]
    fn all_pokemon_test() {
        let all_pokemon = SpeciesData::all_species();
        let num_pokemon = 251;

        assert_eq!(num_pokemon, all_pokemon.len());

        for i in 0..num_pokemon {
            assert!(
                all_pokemon[i].id() == (i + 1) as u16,
                format!("Couldn't find pokemon #{}", i)
            );
        }
    }
}
<commit_msg>Implement max_cp and max_cp_at_level<commit_after>use evaluation::Level;
use types::PokeType;

mod generated_species_data;
use self::generated_species_data::SPECIES;

#[derive(Debug, Eq, PartialEq, Hash)]
/// Information about a specific Pokemon species.
pub struct SpeciesData {
    id: u16,
    attack: u16,
    defense: u16,
    stamina: u16,
    primary_type: PokeType,
    secondary_type: Option<PokeType>,
}

impl SpeciesData {
    /// Given the id of a species, return its corresponding data. Return `None` if no data is found
    /// for the given id.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::SpeciesData;
    ///
    /// let dragonite = SpeciesData::from_id(149).unwrap();
    /// assert_eq!((263, 201, 182), dragonite.base_stats());
    ///
    /// let no_such_pokemon = SpeciesData::from_id(500);
    /// assert!(no_such_pokemon.is_none());
    /// ```
    pub fn from_id(id: u16) -> Option<&'static SpeciesData> {
        SPECIES.iter().find(|p| p.id() == id)
    }

    /// Return a list of all `SpeciesData`, sorted by id.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::SpeciesData;
    ///
    /// let all_species = SpeciesData::all_species();
    ///
    /// assert_eq!(251, all_species.len());
    /// assert_eq!(1, all_species[0].id());
    /// ```
    pub fn all_species() -> &'static [SpeciesData] {
        SPECIES
    }

    /// This species' id.
    pub fn id(&self) -> u16 {
        self.id
    }

    /// This species' base attack value.
    pub fn attack(&self) -> u16 {
        self.attack
    }

    /// This species's base defense value.
    pub fn defense(&self) -> u16 {
        self.defense
    }

    /// This species' base stamina value.
    pub fn stamina(&self) -> u16 {
        self.stamina
    }

    /// This species' base stats, as an `(attack, defense, stamina)` triple.
    pub fn base_stats(&self) -> (u16, u16, u16) {
        (self.attack, self.defense, self.stamina)
    }

    /// This species' primary `PokeType`.
    pub fn primary_type(&self) -> PokeType {
        self.primary_type
    }

    /// If this species is dual-typed, returns the secondary `PokeType`.
    pub fn secondary_type(&self) -> Option<PokeType> {
        self.secondary_type
    }

    /// Returns `true` if this species has two `PokeType`s.
    pub fn is_dual_type(&self) -> bool {
        self.secondary_type.is_some()
    }

    /// Returns the highest possible stats for this pokemon (e.g., perfect IVs).
    pub fn perfect_stats(&self) -> (u16, u16, u16) {
        (self.attack() + 15, self.defense() + 15, self.stamina() + 15)
    }

    /// Returns the species' max Combat Power at the given `Level`, assuming perfect IVs.
    pub fn max_cp_at_level(&self, level: Level) -> u16 {
        let (attack, defense, stamina) = self.perfect_stats();

        SpeciesData::calculate_cp(attack, defense, stamina, level)
    }

    /// Returns this species' max Combat Power at level 39, assuming perfect IVs.
    pub fn max_cp(&self) -> u16 {
        let (attack, defense, stamina) = self.perfect_stats();

        SpeciesData::calculate_cp(attack, defense, stamina, Level::max())
    }

    fn calculate_cp(attack: u16, defense: u16, stamina: u16, level: Level) -> u16 {
        let attack_calc = attack as f64;
        let defense_calc = (defense as f64).sqrt();
        let stamina_calc = (stamina as f64).sqrt();

        let cp_multiplier = level.cp_multiplier().powi(2);

        let inner = attack_calc * defense_calc * stamina_calc * cp_multiplier / 10.;

        ::std::cmp::max(10, inner.floor() as u16)
    }
}

#[cfg(test)]
mod tests {
    use evaluation::Level;
    use types::PokeType;
    use SpeciesData;

    #[test]
    fn species_by_id() {
        let bulbasaur = SpeciesData::from_id(1).unwrap();
        assert_eq!((118, 118, 90), bulbasaur.base_stats());

        let sentret = SpeciesData::from_id(161).unwrap();
        assert_eq!((79, 77, 70), sentret.base_stats());

        let lugia = SpeciesData::from_id(249).unwrap();
        assert_eq!((193, 323, 212), lugia.base_stats());

        assert!(SpeciesData::from_id(252).is_none());
    }

    #[test]
    fn poketype() {
        let charizard = SpeciesData::from_id(6).unwrap();
        assert_eq!(PokeType::Fire, charizard.primary_type());
        assert_eq!(Some(PokeType::Flying), charizard.secondary_type());

        let squirtle = SpeciesData::from_id(7).unwrap();
        assert_eq!(PokeType::Water, squirtle.primary_type());
        assert!(squirtle.secondary_type().is_none());
    }

    #[test]
    fn all_species() {
        let all_pokemon = SpeciesData::all_species();
        let num_pokemon = 251;

        assert_eq!(num_pokemon, all_pokemon.len());

        for i in 0..num_pokemon {
            assert!(
                all_pokemon[i].id() == (i + 1) as u16,
                format!("Couldn't find pokemon #{}", i)
            );
        }
    }

    #[test]
    fn max_cp_at_level() {
        let level = Level::new(20.).unwrap();
        let kakuna = SpeciesData::from_id(14).unwrap();

        assert_eq!(224, kakuna.max_cp_at_level(level));
    }

    #[test]
    fn max_cp() {
        let eevee = SpeciesData::from_id(133).unwrap();
        assert_eq!(955, eevee.max_cp());

        let dragonite = SpeciesData::from_id(149).unwrap();
        assert_eq!(3_530, dragonite.max_cp());
    }
}
<|endoftext|>