<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The `bool` module contains useful code to help work with boolean values.

A quick summary:

## Trait implementations for `bool`

Implementations of the following traits:

* `FromStr`
* `Ord`
* `TotalOrd`
* `Eq`

## Various functions to compare `bool`s

All of the standard comparison functions one would expect: `and`, `eq`, `or`,
and more.

Also, a few conversion functions: `to_bit` and `to_str`.

Finally, some inquries into the nature of truth: `is_true` and `is_false`.

*/

#[cfg(not(test))]
use cmp::{Eq, Ord, TotalOrd, Ordering};
use option::{None, Option, Some};
use from_str::FromStr;

/**
* Negation of a boolean value.
*
* # Examples
* ~~~
* rusti> core::bool::not(true)
* false
* ~~~
* rusti> core::bool::not(false)
* true
* ~~~
*/
pub fn not(v: bool) -> bool { !v }

/**
* Conjunction of two boolean values.
*
* # Examples
* ~~~
* rusti> core::bool::and(true, false)
* false
* ~~~
* rusti> core::bool::and(true, true)
* true
* ~~~
*/
pub fn and(a: bool, b: bool) -> bool { a && b }

/**
* Disjunction of two boolean values.
*
* # Examples
* ~~~
* rusti> core::bool::or(true, false)
* true
* ~~~
* rusti> core::bool::or(false, false)
* false
* ~~~
*/
pub fn or(a: bool, b: bool) -> bool { a || b }

/**
* An 'exclusive or' of two boolean values.
*
* 'exclusive or' is identical to `or(and(a, not(b)), and(not(a), b))`.
*
* # Examples
* ~~~
* rusti> core::bool::xor(true, false)
* true
* ~~~
* rusti> core::bool::xor(true, true)
* false
* ~~~
*/
pub fn xor(a: bool, b: bool) -> bool { (a && !b) || (!a && b) }

/**
* Implication between two boolean values.
*
* Implication is often phrased as 'if a then b.'
*
* 'if a then b' is equivalent to `!a || b`.
*
* # Examples
* ~~~
* rusti> core::bool::implies(true, true)
* true
* ~~~
* rusti> core::bool::implies(true, false)
* false
* ~~~
*/
pub fn implies(a: bool, b: bool) -> bool { !a || b }

/**
* Equality between two boolean values.
*
* Two booleans are equal if they have the same value.
*
* # Examples
* ~~~
* rusti> core::bool::eq(false, true)
* false
* ~~~
* rusti> core::bool::eq(false, false)
* true
* ~~~
*/
pub fn eq(a: bool, b: bool) -> bool { a == b }

/**
* Non-equality between two boolean values.
*
* Two booleans are not equal if they have different values.
*
* # Examples
* ~~~
* rusti> core::bool::ne(false, true)
* true
* ~~~
* rusti> core::bool::ne(false, false)
* false
* ~~~
*/
pub fn ne(a: bool, b: bool) -> bool { a != b }

/**
* Is a given boolean value true?
*
* # Examples
* ~~~
* rusti> core::bool::is_true(true)
* true
* ~~~
* rusti> core::bool::is_true(false)
* false
* ~~~
*/
pub fn is_true(v: bool) -> bool { v }

/**
* Is a given boolean value false?
*
* # Examples
* ~~~
* rusti> core::bool::is_false(false)
* true
* ~~~
* rusti> core::bool::is_false(true)
* false
* ~~~
*/
pub fn is_false(v: bool) -> bool { !v }

/**
* Parse a `bool` from a `str`.
*
* Yields an `Option<bool>`, because `str` may or may not actually be parseable.
*
* # Examples
* ~~~
* rusti> FromStr::from_str::<bool>("true")
* Some(true)
* ~~~
* rusti> FromStr::from_str::<bool>("false")
* Some(false)
* ~~~
* rusti> FromStr::from_str::<bool>("not even a boolean")
* None
* ~~~
*/
impl FromStr for bool {
    fn from_str(s: &str) -> Option<bool> {
        match s {
            "true"  => Some(true),
            "false" => Some(false),
            _       => None,
        }
    }
}

/**
* Convert a `bool` to a `str`.
*
* # Examples
* ~~~
* rusti> std::bool::to_str(true)
* "true"
* ~~~
* rusti> std::bool::to_str(false)
* "false"
* ~~~
*/
pub fn to_str(v: bool) -> ~str { if v { ~"true" } else { ~"false" } }

/**
* Iterates over all truth values, passing them to the given block.
*
* There are no guarantees about the order values will be given.
*
* # Examples
* ~~~
* do core::bool::all_values |x: bool| {
*     println(core::bool::to_str(x));
* }
* ~~~
*/
pub fn all_values(blk: &fn(v: bool)) {
    blk(true);
    blk(false);
}

/**
* Convert a `bool` to a `u8`.
*
* # Examples
* ~~~
* rusti> std::bool::to_bit(true)
* 1
* ~~~
* rusti> std::bool::to_bit(false)
* 0
* ~~~
*/
#[inline(always)]
pub fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } }

#[cfg(not(test))]
impl Ord for bool {
    #[inline(always)]
    fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) }
    #[inline(always)]
    fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) }
    #[inline(always)]
    fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) }
    #[inline(always)]
    fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) }
}

#[cfg(not(test))]
impl TotalOrd for bool {
    #[inline(always)]
    fn cmp(&self, other: &bool) -> Ordering { to_bit(*self).cmp(&to_bit(*other)) }
}

#[cfg(not(test))]
impl Eq for bool {
    #[inline(always)]
    fn eq(&self, other: &bool) -> bool { (*self) == (*other) }
    #[inline(always)]
    fn ne(&self, other: &bool) -> bool { (*self) != (*other) }
}

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

    #[test]
    fn test_bool_from_str() {
        do all_values |v| {
            assert!(Some(v) == FromStr::from_str(to_str(v)))
        }
    }

    #[test]
    fn test_bool_to_str() {
        assert_eq!(to_str(false), ~"false");
        assert_eq!(to_str(true), ~"true");
    }

    #[test]
    fn test_bool_to_bit() {
        do all_values |v| {
            assert_eq!(to_bit(v), if is_true(v) { 1u8 } else { 0u8 });
        }
    }

    #[test]
    fn test_bool_ord() {
        assert!(true > false);
        assert!(!(false > true));

        assert!(false < true);
        assert!(!(true < false));

        assert!(false <= false);
        assert!(false >= false);
        assert!(true <= true);
        assert!(true >= true);

        assert!(false <= true);
        assert!(!(false >= true));
        assert!(true >= false);
        assert!(!(true <= false));
    }

    #[test]
    fn test_bool_totalord() {
        assert_eq!(true.cmp(&true), Equal);
        assert_eq!(false.cmp(&false), Equal);
        assert_eq!(true.cmp(&false), Greater);
        assert_eq!(false.cmp(&true), Less);
    }
}
<commit_msg>auto merge of #6763 : steveklabnik/rust/core_to_std, r=thestinger<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The `bool` module contains useful code to help work with boolean values.

A quick summary:

## Trait implementations for `bool`

Implementations of the following traits:

* `FromStr`
* `Ord`
* `TotalOrd`
* `Eq`

## Various functions to compare `bool`s

All of the standard comparison functions one would expect: `and`, `eq`, `or`,
and more.

Also, a few conversion functions: `to_bit` and `to_str`.

Finally, some inquries into the nature of truth: `is_true` and `is_false`.

*/

#[cfg(not(test))]
use cmp::{Eq, Ord, TotalOrd, Ordering};
use option::{None, Option, Some};
use from_str::FromStr;

/**
* Negation of a boolean value.
*
* # Examples
* ~~~
* rusti> std::bool::not(true)
* false
* ~~~
* rusti> std::bool::not(false)
* true
* ~~~
*/
pub fn not(v: bool) -> bool { !v }

/**
* Conjunction of two boolean values.
*
* # Examples
* ~~~
* rusti> std::bool::and(true, false)
* false
* ~~~
* rusti> std::bool::and(true, true)
* true
* ~~~
*/
pub fn and(a: bool, b: bool) -> bool { a && b }

/**
* Disjunction of two boolean values.
*
* # Examples
* ~~~
* rusti> std::bool::or(true, false)
* true
* ~~~
* rusti> std::bool::or(false, false)
* false
* ~~~
*/
pub fn or(a: bool, b: bool) -> bool { a || b }

/**
* An 'exclusive or' of two boolean values.
*
* 'exclusive or' is identical to `or(and(a, not(b)), and(not(a), b))`.
*
* # Examples
* ~~~
* rusti> std::bool::xor(true, false)
* true
* ~~~
* rusti> std::bool::xor(true, true)
* false
* ~~~
*/
pub fn xor(a: bool, b: bool) -> bool { (a && !b) || (!a && b) }

/**
* Implication between two boolean values.
*
* Implication is often phrased as 'if a then b.'
*
* 'if a then b' is equivalent to `!a || b`.
*
* # Examples
* ~~~
* rusti> std::bool::implies(true, true)
* true
* ~~~
* rusti> std::bool::implies(true, false)
* false
* ~~~
*/
pub fn implies(a: bool, b: bool) -> bool { !a || b }

/**
* Equality between two boolean values.
*
* Two booleans are equal if they have the same value.
*
* # Examples
* ~~~
* rusti> std::bool::eq(false, true)
* false
* ~~~
* rusti> std::bool::eq(false, false)
* true
* ~~~
*/
pub fn eq(a: bool, b: bool) -> bool { a == b }

/**
* Non-equality between two boolean values.
*
* Two booleans are not equal if they have different values.
*
* # Examples
* ~~~
* rusti> std::bool::ne(false, true)
* true
* ~~~
* rusti> std::bool::ne(false, false)
* false
* ~~~
*/
pub fn ne(a: bool, b: bool) -> bool { a != b }

/**
* Is a given boolean value true?
*
* # Examples
* ~~~
* rusti> std::bool::is_true(true)
* true
* ~~~
* rusti> std::bool::is_true(false)
* false
* ~~~
*/
pub fn is_true(v: bool) -> bool { v }

/**
* Is a given boolean value false?
*
* # Examples
* ~~~
* rusti> std::bool::is_false(false)
* true
* ~~~
* rusti> std::bool::is_false(true)
* false
* ~~~
*/
pub fn is_false(v: bool) -> bool { !v }

/**
* Parse a `bool` from a `str`.
*
* Yields an `Option<bool>`, because `str` may or may not actually be parseable.
*
* # Examples
* ~~~
* rusti> FromStr::from_str::<bool>("true")
* Some(true)
* ~~~
* rusti> FromStr::from_str::<bool>("false")
* Some(false)
* ~~~
* rusti> FromStr::from_str::<bool>("not even a boolean")
* None
* ~~~
*/
impl FromStr for bool {
    fn from_str(s: &str) -> Option<bool> {
        match s {
            "true"  => Some(true),
            "false" => Some(false),
            _       => None,
        }
    }
}

/**
* Convert a `bool` to a `str`.
*
* # Examples
* ~~~
* rusti> std::bool::to_str(true)
* "true"
* ~~~
* rusti> std::bool::to_str(false)
* "false"
* ~~~
*/
pub fn to_str(v: bool) -> ~str { if v { ~"true" } else { ~"false" } }

/**
* Iterates over all truth values, passing them to the given block.
*
* There are no guarantees about the order values will be given.
*
* # Examples
* ~~~
* do std::bool::all_values |x: bool| {
*     println(std::bool::to_str(x));
* }
* ~~~
*/
pub fn all_values(blk: &fn(v: bool)) {
    blk(true);
    blk(false);
}

/**
* Convert a `bool` to a `u8`.
*
* # Examples
* ~~~
* rusti> std::bool::to_bit(true)
* 1
* ~~~
* rusti> std::bool::to_bit(false)
* 0
* ~~~
*/
#[inline(always)]
pub fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } }

#[cfg(not(test))]
impl Ord for bool {
    #[inline(always)]
    fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) }
    #[inline(always)]
    fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) }
    #[inline(always)]
    fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) }
    #[inline(always)]
    fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) }
}

#[cfg(not(test))]
impl TotalOrd for bool {
    #[inline(always)]
    fn cmp(&self, other: &bool) -> Ordering { to_bit(*self).cmp(&to_bit(*other)) }
}

#[cfg(not(test))]
impl Eq for bool {
    #[inline(always)]
    fn eq(&self, other: &bool) -> bool { (*self) == (*other) }
    #[inline(always)]
    fn ne(&self, other: &bool) -> bool { (*self) != (*other) }
}

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

    #[test]
    fn test_bool_from_str() {
        do all_values |v| {
            assert!(Some(v) == FromStr::from_str(to_str(v)))
        }
    }

    #[test]
    fn test_bool_to_str() {
        assert_eq!(to_str(false), ~"false");
        assert_eq!(to_str(true), ~"true");
    }

    #[test]
    fn test_bool_to_bit() {
        do all_values |v| {
            assert_eq!(to_bit(v), if is_true(v) { 1u8 } else { 0u8 });
        }
    }

    #[test]
    fn test_bool_ord() {
        assert!(true > false);
        assert!(!(false > true));

        assert!(false < true);
        assert!(!(true < false));

        assert!(false <= false);
        assert!(false >= false);
        assert!(true <= true);
        assert!(true >= true);

        assert!(false <= true);
        assert!(!(false >= true));
        assert!(true >= false);
        assert!(!(true <= false));
    }

    #[test]
    fn test_bool_totalord() {
        assert_eq!(true.cmp(&true), Equal);
        assert_eq!(false.cmp(&false), Equal);
        assert_eq!(true.cmp(&false), Greater);
        assert_eq!(false.cmp(&true), Less);
    }
}
<|endoftext|>


<commit_before>/// A representation of a 3-by-3 matrix
pub struct Matrix {
    elements: [f32, ..9]
}

impl Matrix {

    /// Constructs a new matrix given 9 elements in column major order.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let m = Matrix::new(&elems);
    ///
    /// assert!((m[0], m[3], m[6]) == (1.0, 4.0, 7.0))
    /// assert!((m[1], m[4], m[7]) == (2.0, 5.0, 8.0))
    /// assert!((m[2], m[5], m[8]) == (3.0, 6.0, 9.0))
    /// ```
    pub fn new(elements: &[f32, ..9]) -> Matrix {
        Matrix{ elements: *elements }
    }

    /// Constructs a new matrix given 3 elements in the matrix diagonal.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let m = Matrix::diag(1.0, 2.0, 3.0);
    ///
    /// assert!((m[0], m[3], m[6]) == (1.0, 0.0, 0.0))
    /// assert!((m[1], m[4], m[7]) == (0.0, 2.0, 0.0))
    /// assert!((m[2], m[5], m[8]) == (0.0, 0.0, 3.0))
    /// ```
    pub fn diag(x: f32, y: f32, z: f32) -> Matrix {
        Matrix{ elements: [
              x, 0.0, 0.0,
            0.0,   y, 0.0,
            0.0, 0.0,   z
        ] }
    }

    /// Takes an element from the matrix
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let m = Matrix::diag(4.0, 5.0, 2.0);
    ///
    /// assert!((m.get(0, 0), m.get(0, 1), m.get(0, 2)) == (4.0, 0.0, 0.0))
    /// assert!((m.get(1, 0), m.get(1, 1), m.get(1, 2)) == (0.0, 5.0, 0.0))
    /// assert!((m.get(2, 0), m.get(2, 1), m.get(2, 2)) == (0.0, 0.0, 2.0))
    /// ```
    #[inline(always)]
    pub fn get(&self, row: uint, col: uint) -> f32 {
        self.elements[3*col + row]
    }
}

/// Implement the index operator.
impl Index<uint, f32> for Matrix {
    /// Obtain the elements in the Matrix in column major order.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let m = Matrix::new(&elems);
    ///
    /// assert!((m[0], m[3], m[6]) == (1.0, 4.0, 7.0))
    /// assert!((m[1], m[4], m[7]) == (2.0, 5.0, 8.0))
    /// assert!((m[2], m[5], m[8]) == (3.0, 6.0, 9.0))
    /// ```
    #[inline(always)]
    fn index<'a>(&'a self, index: &uint) -> &'a f32 {
        &self.elements[*index]
    }
}

/// Implement the mutable index operator.
impl IndexMut<uint, f32> for Matrix {
    /// Obtains a mutable reference to the element in the Matrix in column
    /// major order.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let mut m = Matrix::new(&elems);
    ///
    /// m[0] = 11.0;
    /// m[4] = 12.0;
    /// m[8] = 13.0;
    ///
    /// assert!((m[0], m[3], m[6]) == (11.0, 4.0, 7.0))
    /// assert!((m[1], m[4], m[7]) == (2.0, 12.0, 8.0))
    /// assert!((m[2], m[5], m[8]) == (3.0, 6.0, 13.0))
    /// ```
    #[inline(always)]
    fn index_mut<'a>(&'a mut self, index: &uint) -> &'a mut f32 {
        &mut self.elements[*index]
    }
}

/// Implement the unary negation operator.
impl Neg<Matrix> for Matrix {
    /// Applies the negation operator to each element in the matrix.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let m = -Matrix::new(&elems);
    ///
    /// assert!((m[0], m[3], m[6]) == (-1.0, -4.0, -7.0))
    /// assert!((m[1], m[4], m[7]) == (-2.0, -5.0, -8.0))
    /// assert!((m[2], m[5], m[8]) == (-3.0, -6.0, -9.0))
    /// ```
    fn neg(&self) -> Matrix {
        let elems: [f32, ..9] = [
            -self[0], -self[1], -self[2],
            -self[3], -self[4], -self[5],
            -self[6], -self[7], -self[8],
        ];
        Matrix{ elements: elems }
    }
}

/// Implement the addition operator between Matrices.
impl Add<Matrix, Matrix> for Matrix {
    /// Calculates the sum of two matrices.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let a = Matrix::new(&elems);
    /// let b = Matrix::diag(3.0, 2.0, 1.0);
    ///
    /// let m = a + b;
    ///
    /// assert!((m[0], m[3], m[6]) == (4.0, 4.0, 7.0))
    /// assert!((m[1], m[4], m[7]) == (2.0, 7.0, 8.0))
    /// assert!((m[2], m[5], m[8]) == (3.0, 6.0, 10.0))
    /// ```
    fn add(&self, other: &Matrix) -> Matrix {
        let elems: [f32, ..9] = [
            self[0] + other[0], self[1] + other[1], self[2] + other[2],
            self[3] + other[3], self[4] + other[4], self[5] + other[5],
            self[6] + other[6], self[7] + other[7], self[8] + other[8],
        ];
        Matrix{ elements: elems }
    }
}

/// Implement the subtraction operator between Matrices.
impl Sub<Matrix, Matrix> for Matrix {
    /// Calculates the difference between two vectors.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let a = Matrix::new(&elems);
    /// let b = Matrix::diag(1.0, 2.0, 3.0);
    ///
    /// let m = a - b;
    ///
    /// assert!((m[0], m[3], m[6]) == (0.0, 4.0, 7.0))
    /// assert!((m[1], m[4], m[7]) == (2.0, 3.0, 8.0))
    /// assert!((m[2], m[5], m[8]) == (3.0, 6.0, 6.0))
    /// ```
    fn sub(&self, other: &Matrix) -> Matrix {
        let elems: [f32, ..9] = [
            self[0] - other[0], self[1] - other[1], self[2] - other[2],
            self[3] - other[3], self[4] - other[4], self[5] - other[5],
            self[6] - other[6], self[7] - other[7], self[8] - other[8],
        ];
        Matrix{ elements: elems }
    }
}
//
// /// Implement the multiplication operator between Matrices.
// impl Mul<Matrix, Matrix> for Matrix {
//     /// Calculates the result of applying matrix multiplication between two
//     /// matrices.
//     ///
//     /// ```rust
//     /// # use mithril::math::Matrix;
//     /// let elems_a: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
//     /// let a = Matrix::new(&elems_a);
//     /// let elems_b: [f32, ..9] = [3.0, 2.0, 1.0, 6.0, 5.0, 4.0, 9.0, 8.0, 7.0];
//     /// let b = Matrix::new(&elems_b);
//     ///
//     /// let m = a * b;
//     ///
//     /// assert!((m[0], m[3], m[6]) == (18.0, 54.0, 90.0))
//     /// assert!((m[1], m[4], m[7]) == (24.0, 69.0, 114.0))
//     /// assert!((m[2], m[5], m[8]) == (30.0, 84.0, 138.0))
//     /// ```
//     fn mul(&self, other: &Matrix) -> Matrix {
//         let elems: [f32, ..9] = [
//             self[0]*other[0] + self[3]*other[1] + self[6]*other[2],
//             self[1]*other[0] + self[4]*other[1] + self[7]*other[2],
//             self[2]*other[0] + self[5]*other[1] + self[8]*other[2],
//             self[0]*other[3] + self[3]*other[4] + self[6]*other[5],
//             self[1]*other[3] + self[4]*other[4] + self[7]*other[5],
//             self[2]*other[3] + self[5]*other[4] + self[8]*other[5],
//             self[0]*other[6] + self[3]*other[7] + self[6]*other[8],
//             self[1]*other[6] + self[4]*other[7] + self[7]*other[8],
//             self[2]*other[6] + self[5]*other[7] + self[8]*other[8],
//         ];
//         Matrix{ elements: elems }
//     }
// }
<commit_msg>add substitute for matrix multiplication operator overload<commit_after>/// A representation of a 3-by-3 matrix
pub struct Matrix {
    elements: [f32, ..9]
}

impl Matrix {

    /// Constructs a new matrix given 9 elements in column major order.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let m = Matrix::new(&elems);
    ///
    /// assert!((m[0], m[3], m[6]) == (1.0, 4.0, 7.0))
    /// assert!((m[1], m[4], m[7]) == (2.0, 5.0, 8.0))
    /// assert!((m[2], m[5], m[8]) == (3.0, 6.0, 9.0))
    /// ```
    pub fn new(elements: &[f32, ..9]) -> Matrix {
        Matrix{ elements: *elements }
    }

    /// Constructs a new matrix given 3 elements in the matrix diagonal.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let m = Matrix::diag(1.0, 2.0, 3.0);
    ///
    /// assert!((m[0], m[3], m[6]) == (1.0, 0.0, 0.0))
    /// assert!((m[1], m[4], m[7]) == (0.0, 2.0, 0.0))
    /// assert!((m[2], m[5], m[8]) == (0.0, 0.0, 3.0))
    /// ```
    pub fn diag(x: f32, y: f32, z: f32) -> Matrix {
        Matrix{ elements: [
              x, 0.0, 0.0,
            0.0,   y, 0.0,
            0.0, 0.0,   z
        ] }
    }

    /// Takes an element from the matrix
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let m = Matrix::diag(4.0, 5.0, 2.0);
    ///
    /// assert!((m.get(0, 0), m.get(0, 1), m.get(0, 2)) == (4.0, 0.0, 0.0))
    /// assert!((m.get(1, 0), m.get(1, 1), m.get(1, 2)) == (0.0, 5.0, 0.0))
    /// assert!((m.get(2, 0), m.get(2, 1), m.get(2, 2)) == (0.0, 0.0, 2.0))
    /// ```
    #[inline(always)]
    pub fn get(&self, row: uint, col: uint) -> f32 {
        self.elements[3*col + row]
    }

    /// Calculates the result of applying matrix multiplication between two
    /// matrices. (TEMPORARY UNTIL ASSOCIATED TYPES ARE SUPPORTED IN RUST)
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems_a: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let a = Matrix::new(&elems_a);
    /// let elems_b: [f32, ..9] = [3.0, 2.0, 1.0, 6.0, 5.0, 4.0, 9.0, 8.0, 7.0];
    /// let b = Matrix::new(&elems_b);
    ///
    /// let m = Matrix::mult(&a, &b);
    ///
    /// assert!((m[0], m[3], m[6]) == (18.0, 54.0, 90.0))
    /// assert!((m[1], m[4], m[7]) == (24.0, 69.0, 114.0))
    /// assert!((m[2], m[5], m[8]) == (30.0, 84.0, 138.0))
    /// ```
    pub fn mult(a: &Matrix, b: &Matrix) -> Matrix {
        let elems: [f32, ..9] = [
            a[0]*b[0] + a[3]*b[1] + a[6]*b[2],
            a[1]*b[0] + a[4]*b[1] + a[7]*b[2],
            a[2]*b[0] + a[5]*b[1] + a[8]*b[2],
            a[0]*b[3] + a[3]*b[4] + a[6]*b[5],
            a[1]*b[3] + a[4]*b[4] + a[7]*b[5],
            a[2]*b[3] + a[5]*b[4] + a[8]*b[5],
            a[0]*b[6] + a[3]*b[7] + a[6]*b[8],
            a[1]*b[6] + a[4]*b[7] + a[7]*b[8],
            a[2]*b[6] + a[5]*b[7] + a[8]*b[8],
        ];
        Matrix{ elements: elems }
    }
}

/// Implement the index operator.
impl Index<uint, f32> for Matrix {
    /// Obtain the elements in the Matrix in column major order.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let m = Matrix::new(&elems);
    ///
    /// assert!((m[0], m[3], m[6]) == (1.0, 4.0, 7.0))
    /// assert!((m[1], m[4], m[7]) == (2.0, 5.0, 8.0))
    /// assert!((m[2], m[5], m[8]) == (3.0, 6.0, 9.0))
    /// ```
    #[inline(always)]
    fn index<'a>(&'a self, index: &uint) -> &'a f32 {
        &self.elements[*index]
    }
}

/// Implement the mutable index operator.
impl IndexMut<uint, f32> for Matrix {
    /// Obtains a mutable reference to the element in the Matrix in column
    /// major order.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let mut m = Matrix::new(&elems);
    ///
    /// m[0] = 11.0;
    /// m[4] = 12.0;
    /// m[8] = 13.0;
    ///
    /// assert!((m[0], m[3], m[6]) == (11.0, 4.0, 7.0))
    /// assert!((m[1], m[4], m[7]) == (2.0, 12.0, 8.0))
    /// assert!((m[2], m[5], m[8]) == (3.0, 6.0, 13.0))
    /// ```
    #[inline(always)]
    fn index_mut<'a>(&'a mut self, index: &uint) -> &'a mut f32 {
        &mut self.elements[*index]
    }
}

/// Implement the unary negation operator.
impl Neg<Matrix> for Matrix {
    /// Applies the negation operator to each element in the matrix.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let m = -Matrix::new(&elems);
    ///
    /// assert!((m[0], m[3], m[6]) == (-1.0, -4.0, -7.0))
    /// assert!((m[1], m[4], m[7]) == (-2.0, -5.0, -8.0))
    /// assert!((m[2], m[5], m[8]) == (-3.0, -6.0, -9.0))
    /// ```
    fn neg(&self) -> Matrix {
        let elems: [f32, ..9] = [
            -self[0], -self[1], -self[2],
            -self[3], -self[4], -self[5],
            -self[6], -self[7], -self[8],
        ];
        Matrix{ elements: elems }
    }
}

/// Implement the addition operator between Matrices.
impl Add<Matrix, Matrix> for Matrix {
    /// Calculates the sum of two matrices.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let a = Matrix::new(&elems);
    /// let b = Matrix::diag(3.0, 2.0, 1.0);
    ///
    /// let m = a + b;
    ///
    /// assert!((m[0], m[3], m[6]) == (4.0, 4.0, 7.0))
    /// assert!((m[1], m[4], m[7]) == (2.0, 7.0, 8.0))
    /// assert!((m[2], m[5], m[8]) == (3.0, 6.0, 10.0))
    /// ```
    fn add(&self, other: &Matrix) -> Matrix {
        let elems: [f32, ..9] = [
            self[0] + other[0], self[1] + other[1], self[2] + other[2],
            self[3] + other[3], self[4] + other[4], self[5] + other[5],
            self[6] + other[6], self[7] + other[7], self[8] + other[8],
        ];
        Matrix{ elements: elems }
    }
}

/// Implement the subtraction operator between Matrices.
impl Sub<Matrix, Matrix> for Matrix {
    /// Calculates the difference between two vectors.
    ///
    /// ```rust
    /// # use mithril::math::Matrix;
    /// let elems: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
    /// let a = Matrix::new(&elems);
    /// let b = Matrix::diag(1.0, 2.0, 3.0);
    ///
    /// let m = a - b;
    ///
    /// assert!((m[0], m[3], m[6]) == (0.0, 4.0, 7.0))
    /// assert!((m[1], m[4], m[7]) == (2.0, 3.0, 8.0))
    /// assert!((m[2], m[5], m[8]) == (3.0, 6.0, 6.0))
    /// ```
    fn sub(&self, other: &Matrix) -> Matrix {
        let elems: [f32, ..9] = [
            self[0] - other[0], self[1] - other[1], self[2] - other[2],
            self[3] - other[3], self[4] - other[4], self[5] - other[5],
            self[6] - other[6], self[7] - other[7], self[8] - other[8],
        ];
        Matrix{ elements: elems }
    }
}
//
// /// Implement the multiplication operator between Matrices.
// impl Mul<Matrix, Matrix> for Matrix {
//     /// Calculates the result of applying matrix multiplication between two
//     /// matrices.
//     ///
//     /// ```rust
//     /// # use mithril::math::Matrix;
//     /// let elems_a: [f32, ..9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
//     /// let a = Matrix::new(&elems_a);
//     /// let elems_b: [f32, ..9] = [3.0, 2.0, 1.0, 6.0, 5.0, 4.0, 9.0, 8.0, 7.0];
//     /// let b = Matrix::new(&elems_b);
//     ///
//     /// let m = a * b;
//     ///
//     /// assert!((m[0], m[3], m[6]) == (18.0, 54.0, 90.0))
//     /// assert!((m[1], m[4], m[7]) == (24.0, 69.0, 114.0))
//     /// assert!((m[2], m[5], m[8]) == (30.0, 84.0, 138.0))
//     /// ```
//     fn mul(&self, other: &Matrix) -> Matrix {
//         let elems: [f32, ..9] = [
//             self[0]*other[0] + self[3]*other[1] + self[6]*other[2],
//             self[1]*other[0] + self[4]*other[1] + self[7]*other[2],
//             self[2]*other[0] + self[5]*other[1] + self[8]*other[2],
//             self[0]*other[3] + self[3]*other[4] + self[6]*other[5],
//             self[1]*other[3] + self[4]*other[4] + self[7]*other[5],
//             self[2]*other[3] + self[5]*other[4] + self[8]*other[5],
//             self[0]*other[6] + self[3]*other[7] + self[6]*other[8],
//             self[1]*other[6] + self[4]*other[7] + self[7]*other[8],
//             self[2]*other[6] + self[5]*other[7] + self[8]*other[8],
//         ];
//         Matrix{ elements: elems }
//     }
// }
<|endoftext|>


<commit_before>use cairo;
use cairo_sys;
use glib::translate::*;
use glib_sys;
use libc;
use pango;
use pango_sys;

use color::*;
use error::*;
use node::NodeType;
use node::RsvgNode;
use opacity::*;
use path_builder::RsvgPathBuilder;
use state::RsvgState;

pub enum RsvgDrawingCtx {}

extern "C" {
    fn rsvg_drawing_ctx_get_dpi(
        draw_ctx: *const RsvgDrawingCtx,
        out_dpi_x: *mut f64,
        out_dpi_y: *mut f64,
    );

    fn rsvg_drawing_ctx_get_normalized_font_size(draw_ctx: *const RsvgDrawingCtx) -> f64;

    fn rsvg_drawing_ctx_get_view_box_size(
        draw_ctx: *const RsvgDrawingCtx,
        out_x: *mut f64,
        out_y: *mut f64,
    );

    fn rsvg_drawing_ctx_push_view_box(draw_ctx: *const RsvgDrawingCtx, width: f64, height: f64);

    fn rsvg_drawing_ctx_pop_view_box(draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_drawing_ctx_acquire_node(
        draw_ctx: *const RsvgDrawingCtx,
        url: *const libc::c_char,
    ) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_acquire_node_of_type(
        draw_ctx: *const RsvgDrawingCtx,
        url: *const libc::c_char,
        node_type: NodeType,
    ) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_release_node(draw_ctx: *const RsvgDrawingCtx, node: *mut RsvgNode);

    fn rsvg_drawing_ctx_get_current_state_affine(draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix;

    fn rsvg_drawing_ctx_set_current_state_affine(
        draw_ctx: *const RsvgDrawingCtx,
        affine: *const cairo::Matrix,
    );

    fn rsvg_drawing_ctx_get_pango_context(
        draw_ctx: *const RsvgDrawingCtx,
    ) -> *mut pango_sys::PangoContext;

    fn rsvg_drawing_ctx_add_clipping_rect(
        draw_ctx: *const RsvgDrawingCtx,
        x: f64,
        y: f64,
        w: f64,
        h: f64,
    );

    fn rsvg_drawing_ctx_draw_node_from_stack(
        draw_ctx: *const RsvgDrawingCtx,
        node: *const RsvgNode,
        dominate: i32,
    );

    fn rsvg_current_state(draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState;
    fn rsvg_state_new() -> *mut RsvgState;
    fn rsvg_state_free(state: *mut RsvgState);
    fn rsvg_state_reinit(state: *mut RsvgState);
    fn rsvg_state_reconstruct(state: *mut RsvgState, node: *const RsvgNode);
    fn rsvg_state_is_overflow(state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_has_overflow(state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_get_cond_true(state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_set_cond_true(state: *const RsvgState, cond_true: glib_sys::gboolean);
    fn rsvg_state_get_stop_color(state: *const RsvgState) -> *const ColorSpec;
    fn rsvg_state_get_stop_opacity(state: *const RsvgState) -> *const OpacitySpec;
    fn rsvg_state_get_current_color(state: *const RsvgState) -> u32;

    fn rsvg_state_push(draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_state_pop(draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_state_reinherit_top(
        draw_ctx: *const RsvgDrawingCtx,
        state: *mut RsvgState,
        dominate: libc::c_int,
    );

    fn rsvg_push_discrete_layer(draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_pop_discrete_layer(draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_render_path_builder(draw_ctx: *const RsvgDrawingCtx, builder: *const RsvgPathBuilder);
    fn rsvg_render_surface(
        draw_ctx: *const RsvgDrawingCtx,
        surface: *const cairo_sys::cairo_surface_t,
        x: f64,
        y: f64,
        w: f64,
        h: f64,
    );

    fn rsvg_cairo_get_cairo_context(draw_ctx: *const RsvgDrawingCtx) -> *mut cairo_sys::cairo_t;
    fn rsvg_cairo_set_cairo_context(draw_ctx: *const RsvgDrawingCtx, cr: *const cairo_sys::cairo_t);
}

pub fn get_dpi(draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut dpi_x: f64 = 0.0;
    let mut dpi_y: f64 = 0.0;

    unsafe {
        rsvg_drawing_ctx_get_dpi(draw_ctx, &mut dpi_x, &mut dpi_y);
    }

    (dpi_x, dpi_y)
}

pub fn get_normalized_font_size(draw_ctx: *const RsvgDrawingCtx) -> f64 {
    unsafe { rsvg_drawing_ctx_get_normalized_font_size(draw_ctx) }
}

pub fn get_view_box_size(draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut w: f64 = 0.0;
    let mut h: f64 = 0.0;

    unsafe {
        rsvg_drawing_ctx_get_view_box_size(draw_ctx, &mut w, &mut h);
    }

    (w, h)
}

pub fn push_view_box(draw_ctx: *const RsvgDrawingCtx, width: f64, height: f64) {
    unsafe {
        rsvg_drawing_ctx_push_view_box(draw_ctx, width, height);
    }
}

pub fn pop_view_box(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_drawing_ctx_pop_view_box(draw_ctx);
    }
}

pub fn get_acquired_node(draw_ctx: *const RsvgDrawingCtx, url: &str) -> Option<AcquiredNode> {
    let raw_node = unsafe { rsvg_drawing_ctx_acquire_node(draw_ctx, str::to_glib_none(url).0) };

    if raw_node.is_null() {
        None
    } else {
        Some(AcquiredNode(draw_ctx, raw_node))
    }
}

pub fn get_acquired_node_of_type(
    draw_ctx: *const RsvgDrawingCtx,
    url: &str,
    node_type: NodeType,
) -> Option<AcquiredNode> {
    let raw_node = unsafe {
        rsvg_drawing_ctx_acquire_node_of_type(draw_ctx, str::to_glib_none(url).0, node_type)
    };

    if raw_node.is_null() {
        None
    } else {
        Some(AcquiredNode(draw_ctx, raw_node))
    }
}

pub fn acquire_node(draw_ctx: *const RsvgDrawingCtx, url: &str) -> *mut RsvgNode {
    unsafe { rsvg_drawing_ctx_acquire_node(draw_ctx, str::to_glib_none(url).0) }
}

pub fn acquire_node_of_type(
    draw_ctx: *const RsvgDrawingCtx,
    url: &str,
    node_type: NodeType,
) -> *mut RsvgNode {
    unsafe { rsvg_drawing_ctx_acquire_node_of_type(draw_ctx, str::to_glib_none(url).0, node_type) }
}

pub fn release_node(draw_ctx: *const RsvgDrawingCtx, node: *mut RsvgNode) {
    unsafe {
        rsvg_drawing_ctx_release_node(draw_ctx, node);
    }
}

pub fn state_reinherit_top(draw_ctx: *const RsvgDrawingCtx, state: *mut RsvgState, dominate: i32) {
    unsafe {
        rsvg_state_reinherit_top(draw_ctx, state, dominate);
    }
}

pub fn push_discrete_layer(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_push_discrete_layer(draw_ctx);
    }
}

pub fn pop_discrete_layer(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_pop_discrete_layer(draw_ctx);
    }
}

pub fn render_path_builder(draw_ctx: *const RsvgDrawingCtx, builder: &RsvgPathBuilder) {
    unsafe {
        rsvg_render_path_builder(draw_ctx, builder);
    }
}

pub fn render_surface(
    draw_ctx: *const RsvgDrawingCtx,
    surface: &cairo::ImageSurface,
    x: f64,
    y: f64,
    w: f64,
    h: f64,
) {
    unsafe {
        rsvg_render_surface(draw_ctx, surface.to_raw_none(), x, y, w, h);
    }
}

pub fn get_cairo_context(draw_ctx: *const RsvgDrawingCtx) -> cairo::Context {
    unsafe {
        let raw_cr = rsvg_cairo_get_cairo_context(draw_ctx);

        cairo::Context::from_glib_none(raw_cr)
    }
}

pub fn set_cairo_context(draw_ctx: *const RsvgDrawingCtx, cr: &cairo::Context) {
    unsafe {
        let raw_cr = cr.to_glib_none().0;

        rsvg_cairo_set_cairo_context(draw_ctx, raw_cr);
    }
}

pub fn get_current_state_affine(draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix {
    unsafe { rsvg_drawing_ctx_get_current_state_affine(draw_ctx) }
}

pub fn set_current_state_affine(draw_ctx: *const RsvgDrawingCtx, affine: cairo::Matrix) {
    unsafe {
        rsvg_drawing_ctx_set_current_state_affine(draw_ctx, &affine);
    }
}

pub fn get_pango_context(draw_ctx: *const RsvgDrawingCtx) -> pango::Context {
    unsafe { from_glib_full(rsvg_drawing_ctx_get_pango_context(draw_ctx)) }
}

pub fn add_clipping_rect(draw_ctx: *const RsvgDrawingCtx, x: f64, y: f64, w: f64, h: f64) {
    unsafe {
        rsvg_drawing_ctx_add_clipping_rect(draw_ctx, x, y, w, h);
    }
}

pub fn draw_node_from_stack(draw_ctx: *const RsvgDrawingCtx, node: *const RsvgNode, dominate: i32) {
    unsafe {
        rsvg_drawing_ctx_draw_node_from_stack(draw_ctx, node, dominate);
    }
}

pub fn get_current_state(draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState {
    unsafe { rsvg_current_state(draw_ctx) }
}

pub fn state_new() -> *mut RsvgState {
    unsafe { rsvg_state_new() }
}

pub fn state_free(state: *mut RsvgState) {
    unsafe {
        rsvg_state_free(state);
    }
}

pub fn state_reinit(state: *mut RsvgState) {
    unsafe {
        rsvg_state_reinit(state);
    }
}

pub fn state_reconstruct(state: *mut RsvgState, node: *const RsvgNode) {
    unsafe {
        rsvg_state_reconstruct(state, node);
    }
}

pub fn state_is_overflow(state: *const RsvgState) -> bool {
    unsafe { from_glib(rsvg_state_is_overflow(state)) }
}

pub fn state_has_overflow(state: *const RsvgState) -> bool {
    unsafe { from_glib(rsvg_state_has_overflow(state)) }
}

pub fn state_get_cond_true(state: *const RsvgState) -> bool {
    unsafe { from_glib(rsvg_state_get_cond_true(state)) }
}

pub fn state_set_cond_true(state: *const RsvgState, cond_true: bool) {
    unsafe {
        rsvg_state_set_cond_true(state, cond_true.to_glib());
    }
}

pub fn state_push(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_push(draw_ctx);
    }
}

pub fn state_pop(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_pop(draw_ctx);
    }
}

pub fn state_get_stop_color(state: *const RsvgState) -> Result<Option<Color>, AttributeError> {
    unsafe {
        let spec_ptr = rsvg_state_get_stop_color(state);

        if spec_ptr.is_null() {
            Ok(None)
        } else {
            Color::from_color_spec(&*spec_ptr).map(Some)
        }
    }
}

pub fn state_get_stop_opacity(state: *const RsvgState) -> Result<Option<Opacity>, AttributeError> {
    unsafe {
        let opacity_ptr = rsvg_state_get_stop_opacity(state);

        if opacity_ptr.is_null() {
            Ok(None)
        } else {
            Opacity::from_opacity_spec(&*opacity_ptr).map(Some)
        }
    }
}

pub fn state_get_current_color(state: *const RsvgState) -> Color {
    let argb = unsafe { rsvg_state_get_current_color(state) };

    Color::from(argb)
}

pub struct AcquiredNode(*const RsvgDrawingCtx, *mut RsvgNode);

impl Drop for AcquiredNode {
    fn drop(&mut self) {
        release_node(self.0, self.1);
    }
}

impl AcquiredNode {
    pub fn get(&self) -> RsvgNode {
        unsafe { (*self.1).clone() }
    }
}
<commit_msg>drawing_ctx.rs: Removed unused acquire_node()/acquire_node_of_type()/release_node()<commit_after>use cairo;
use cairo_sys;
use glib::translate::*;
use glib_sys;
use libc;
use pango;
use pango_sys;

use color::*;
use error::*;
use node::NodeType;
use node::RsvgNode;
use opacity::*;
use path_builder::RsvgPathBuilder;
use state::RsvgState;

pub enum RsvgDrawingCtx {}

extern "C" {
    fn rsvg_drawing_ctx_get_dpi(
        draw_ctx: *const RsvgDrawingCtx,
        out_dpi_x: *mut f64,
        out_dpi_y: *mut f64,
    );

    fn rsvg_drawing_ctx_get_normalized_font_size(draw_ctx: *const RsvgDrawingCtx) -> f64;

    fn rsvg_drawing_ctx_get_view_box_size(
        draw_ctx: *const RsvgDrawingCtx,
        out_x: *mut f64,
        out_y: *mut f64,
    );

    fn rsvg_drawing_ctx_push_view_box(draw_ctx: *const RsvgDrawingCtx, width: f64, height: f64);

    fn rsvg_drawing_ctx_pop_view_box(draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_drawing_ctx_acquire_node(
        draw_ctx: *const RsvgDrawingCtx,
        url: *const libc::c_char,
    ) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_acquire_node_of_type(
        draw_ctx: *const RsvgDrawingCtx,
        url: *const libc::c_char,
        node_type: NodeType,
    ) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_release_node(draw_ctx: *const RsvgDrawingCtx, node: *mut RsvgNode);

    fn rsvg_drawing_ctx_get_current_state_affine(draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix;

    fn rsvg_drawing_ctx_set_current_state_affine(
        draw_ctx: *const RsvgDrawingCtx,
        affine: *const cairo::Matrix,
    );

    fn rsvg_drawing_ctx_get_pango_context(
        draw_ctx: *const RsvgDrawingCtx,
    ) -> *mut pango_sys::PangoContext;

    fn rsvg_drawing_ctx_add_clipping_rect(
        draw_ctx: *const RsvgDrawingCtx,
        x: f64,
        y: f64,
        w: f64,
        h: f64,
    );

    fn rsvg_drawing_ctx_draw_node_from_stack(
        draw_ctx: *const RsvgDrawingCtx,
        node: *const RsvgNode,
        dominate: i32,
    );

    fn rsvg_current_state(draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState;
    fn rsvg_state_new() -> *mut RsvgState;
    fn rsvg_state_free(state: *mut RsvgState);
    fn rsvg_state_reinit(state: *mut RsvgState);
    fn rsvg_state_reconstruct(state: *mut RsvgState, node: *const RsvgNode);
    fn rsvg_state_is_overflow(state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_has_overflow(state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_get_cond_true(state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_set_cond_true(state: *const RsvgState, cond_true: glib_sys::gboolean);
    fn rsvg_state_get_stop_color(state: *const RsvgState) -> *const ColorSpec;
    fn rsvg_state_get_stop_opacity(state: *const RsvgState) -> *const OpacitySpec;
    fn rsvg_state_get_current_color(state: *const RsvgState) -> u32;

    fn rsvg_state_push(draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_state_pop(draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_state_reinherit_top(
        draw_ctx: *const RsvgDrawingCtx,
        state: *mut RsvgState,
        dominate: libc::c_int,
    );

    fn rsvg_push_discrete_layer(draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_pop_discrete_layer(draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_render_path_builder(draw_ctx: *const RsvgDrawingCtx, builder: *const RsvgPathBuilder);
    fn rsvg_render_surface(
        draw_ctx: *const RsvgDrawingCtx,
        surface: *const cairo_sys::cairo_surface_t,
        x: f64,
        y: f64,
        w: f64,
        h: f64,
    );

    fn rsvg_cairo_get_cairo_context(draw_ctx: *const RsvgDrawingCtx) -> *mut cairo_sys::cairo_t;
    fn rsvg_cairo_set_cairo_context(draw_ctx: *const RsvgDrawingCtx, cr: *const cairo_sys::cairo_t);
}

pub fn get_dpi(draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut dpi_x: f64 = 0.0;
    let mut dpi_y: f64 = 0.0;

    unsafe {
        rsvg_drawing_ctx_get_dpi(draw_ctx, &mut dpi_x, &mut dpi_y);
    }

    (dpi_x, dpi_y)
}

pub fn get_normalized_font_size(draw_ctx: *const RsvgDrawingCtx) -> f64 {
    unsafe { rsvg_drawing_ctx_get_normalized_font_size(draw_ctx) }
}

pub fn get_view_box_size(draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut w: f64 = 0.0;
    let mut h: f64 = 0.0;

    unsafe {
        rsvg_drawing_ctx_get_view_box_size(draw_ctx, &mut w, &mut h);
    }

    (w, h)
}

pub fn push_view_box(draw_ctx: *const RsvgDrawingCtx, width: f64, height: f64) {
    unsafe {
        rsvg_drawing_ctx_push_view_box(draw_ctx, width, height);
    }
}

pub fn pop_view_box(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_drawing_ctx_pop_view_box(draw_ctx);
    }
}

pub fn get_acquired_node(draw_ctx: *const RsvgDrawingCtx, url: &str) -> Option<AcquiredNode> {
    let raw_node = unsafe { rsvg_drawing_ctx_acquire_node(draw_ctx, str::to_glib_none(url).0) };

    if raw_node.is_null() {
        None
    } else {
        Some(AcquiredNode(draw_ctx, raw_node))
    }
}

pub fn get_acquired_node_of_type(
    draw_ctx: *const RsvgDrawingCtx,
    url: &str,
    node_type: NodeType,
) -> Option<AcquiredNode> {
    let raw_node = unsafe {
        rsvg_drawing_ctx_acquire_node_of_type(draw_ctx, str::to_glib_none(url).0, node_type)
    };

    if raw_node.is_null() {
        None
    } else {
        Some(AcquiredNode(draw_ctx, raw_node))
    }
}

pub fn state_reinherit_top(draw_ctx: *const RsvgDrawingCtx, state: *mut RsvgState, dominate: i32) {
    unsafe {
        rsvg_state_reinherit_top(draw_ctx, state, dominate);
    }
}

pub fn push_discrete_layer(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_push_discrete_layer(draw_ctx);
    }
}

pub fn pop_discrete_layer(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_pop_discrete_layer(draw_ctx);
    }
}

pub fn render_path_builder(draw_ctx: *const RsvgDrawingCtx, builder: &RsvgPathBuilder) {
    unsafe {
        rsvg_render_path_builder(draw_ctx, builder);
    }
}

pub fn render_surface(
    draw_ctx: *const RsvgDrawingCtx,
    surface: &cairo::ImageSurface,
    x: f64,
    y: f64,
    w: f64,
    h: f64,
) {
    unsafe {
        rsvg_render_surface(draw_ctx, surface.to_raw_none(), x, y, w, h);
    }
}

pub fn get_cairo_context(draw_ctx: *const RsvgDrawingCtx) -> cairo::Context {
    unsafe {
        let raw_cr = rsvg_cairo_get_cairo_context(draw_ctx);

        cairo::Context::from_glib_none(raw_cr)
    }
}

pub fn set_cairo_context(draw_ctx: *const RsvgDrawingCtx, cr: &cairo::Context) {
    unsafe {
        let raw_cr = cr.to_glib_none().0;

        rsvg_cairo_set_cairo_context(draw_ctx, raw_cr);
    }
}

pub fn get_current_state_affine(draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix {
    unsafe { rsvg_drawing_ctx_get_current_state_affine(draw_ctx) }
}

pub fn set_current_state_affine(draw_ctx: *const RsvgDrawingCtx, affine: cairo::Matrix) {
    unsafe {
        rsvg_drawing_ctx_set_current_state_affine(draw_ctx, &affine);
    }
}

pub fn get_pango_context(draw_ctx: *const RsvgDrawingCtx) -> pango::Context {
    unsafe { from_glib_full(rsvg_drawing_ctx_get_pango_context(draw_ctx)) }
}

pub fn add_clipping_rect(draw_ctx: *const RsvgDrawingCtx, x: f64, y: f64, w: f64, h: f64) {
    unsafe {
        rsvg_drawing_ctx_add_clipping_rect(draw_ctx, x, y, w, h);
    }
}

pub fn draw_node_from_stack(draw_ctx: *const RsvgDrawingCtx, node: *const RsvgNode, dominate: i32) {
    unsafe {
        rsvg_drawing_ctx_draw_node_from_stack(draw_ctx, node, dominate);
    }
}

pub fn get_current_state(draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState {
    unsafe { rsvg_current_state(draw_ctx) }
}

pub fn state_new() -> *mut RsvgState {
    unsafe { rsvg_state_new() }
}

pub fn state_free(state: *mut RsvgState) {
    unsafe {
        rsvg_state_free(state);
    }
}

pub fn state_reinit(state: *mut RsvgState) {
    unsafe {
        rsvg_state_reinit(state);
    }
}

pub fn state_reconstruct(state: *mut RsvgState, node: *const RsvgNode) {
    unsafe {
        rsvg_state_reconstruct(state, node);
    }
}

pub fn state_is_overflow(state: *const RsvgState) -> bool {
    unsafe { from_glib(rsvg_state_is_overflow(state)) }
}

pub fn state_has_overflow(state: *const RsvgState) -> bool {
    unsafe { from_glib(rsvg_state_has_overflow(state)) }
}

pub fn state_get_cond_true(state: *const RsvgState) -> bool {
    unsafe { from_glib(rsvg_state_get_cond_true(state)) }
}

pub fn state_set_cond_true(state: *const RsvgState, cond_true: bool) {
    unsafe {
        rsvg_state_set_cond_true(state, cond_true.to_glib());
    }
}

pub fn state_push(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_push(draw_ctx);
    }
}

pub fn state_pop(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_pop(draw_ctx);
    }
}

pub fn state_get_stop_color(state: *const RsvgState) -> Result<Option<Color>, AttributeError> {
    unsafe {
        let spec_ptr = rsvg_state_get_stop_color(state);

        if spec_ptr.is_null() {
            Ok(None)
        } else {
            Color::from_color_spec(&*spec_ptr).map(Some)
        }
    }
}

pub fn state_get_stop_opacity(state: *const RsvgState) -> Result<Option<Opacity>, AttributeError> {
    unsafe {
        let opacity_ptr = rsvg_state_get_stop_opacity(state);

        if opacity_ptr.is_null() {
            Ok(None)
        } else {
            Opacity::from_opacity_spec(&*opacity_ptr).map(Some)
        }
    }
}

pub fn state_get_current_color(state: *const RsvgState) -> Color {
    let argb = unsafe { rsvg_state_get_current_color(state) };

    Color::from(argb)
}

pub struct AcquiredNode(*const RsvgDrawingCtx, *mut RsvgNode);

impl Drop for AcquiredNode {
    fn drop(&mut self) {
        unsafe {
            rsvg_drawing_ctx_release_node(self.0, self.1);
        }
    }
}

impl AcquiredNode {
    pub fn get(&self) -> RsvgNode {
        unsafe { (*self.1).clone() }
    }
}
<|endoftext|>


<commit_before>//! Endpoints for account registration and management.

pub mod add_3pid;
pub mod bind_3pid;
pub mod change_password;
pub mod deactivate;
pub mod delete_3pid;
pub mod get_username_availability;
pub mod register;
pub mod request_3pid_management_token_via_email;
pub mod request_3pid_management_token_via_msisdn;
pub mod request_openid_token;
pub mod request_password_change_token_via_email;
pub mod request_password_change_token_via_msisdn;
pub mod request_registration_token_via_email;
pub mod request_registration_token_via_msisdn;
pub mod unbind_3pid;

pub mod whoami;

use ruma_serde::{Outgoing, StringEnum};
use serde::Serialize;

/// Additional authentication information for requestToken endpoints.
#[derive(Clone, Debug, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct IdentityServerInfo<'a> {
    /// The ID server to send the onward request to as a hostname with an
    /// appended colon and port number if the port is not the default.
    pub id_server: &'a str,

    /// Access token previously registered with identity server.
    pub id_access_token: &'a str,
}

impl<'a> IdentityServerInfo<'a> {
    /// Creates a new `IdentityServerInfo` with the given server name and access token.
    pub fn new(id_server: &'a str, id_access_token: &'a str) -> Self {
        Self { id_server, id_access_token }
    }
}

/// Possible values for deleting or unbinding 3PIDs.
#[derive(Clone, Debug, StringEnum)]
#[ruma_enum(rename_all = "kebab-case")]
pub enum ThirdPartyIdRemovalStatus {
    /// Either the homeserver couldn't determine the right identity server to contact, or the
    /// identity server refused the operation.
    NoSupport,

    /// Success.
    Success,

    #[doc(hidden)]
    _Custom(String),
}
<commit_msg>Remove weird newline<commit_after>//! Endpoints for account registration and management.

pub mod add_3pid;
pub mod bind_3pid;
pub mod change_password;
pub mod deactivate;
pub mod delete_3pid;
pub mod get_username_availability;
pub mod register;
pub mod request_3pid_management_token_via_email;
pub mod request_3pid_management_token_via_msisdn;
pub mod request_openid_token;
pub mod request_password_change_token_via_email;
pub mod request_password_change_token_via_msisdn;
pub mod request_registration_token_via_email;
pub mod request_registration_token_via_msisdn;
pub mod unbind_3pid;
pub mod whoami;

use ruma_serde::{Outgoing, StringEnum};
use serde::Serialize;

/// Additional authentication information for requestToken endpoints.
#[derive(Clone, Debug, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct IdentityServerInfo<'a> {
    /// The ID server to send the onward request to as a hostname with an
    /// appended colon and port number if the port is not the default.
    pub id_server: &'a str,

    /// Access token previously registered with identity server.
    pub id_access_token: &'a str,
}

impl<'a> IdentityServerInfo<'a> {
    /// Creates a new `IdentityServerInfo` with the given server name and access token.
    pub fn new(id_server: &'a str, id_access_token: &'a str) -> Self {
        Self { id_server, id_access_token }
    }
}

/// Possible values for deleting or unbinding 3PIDs.
#[derive(Clone, Debug, StringEnum)]
#[ruma_enum(rename_all = "kebab-case")]
pub enum ThirdPartyIdRemovalStatus {
    /// Either the homeserver couldn't determine the right identity server to contact, or the
    /// identity server refused the operation.
    NoSupport,

    /// Success.
    Success,

    #[doc(hidden)]
    _Custom(String),
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! SQL Parser
//!
//! Declares a SQL parser based on sqlparser that handles custom formats that we need.

use sqlparser::{
    ast::{ColumnDef, Statement as SQLStatement, TableConstraint},
    dialect::{keywords::Keyword, GenericDialect},
    parser::{Parser, ParserError},
    tokenizer::{Token, Tokenizer},
};

// Use `Parser::expected` instead, if possible
macro_rules! parser_err {
    ($MSG:expr) => {
        Err(ParserError::ParserError($MSG.to_string()))
    };
}

/// Types of files to parse as DataFrames
#[derive(Debug, Clone)]
pub enum FileType {
    /// Newline-delimited JSON
    NdJson,
    /// Apache Parquet columnar storage
    Parquet,
    /// Comma separated values
    CSV,
}

/// DataFrame Statement's representations.
///
/// Tokens parsed by `DFParser` are converted into these values.
#[derive(Debug, Clone)]
pub enum Statement {
    /// ANSI SQL AST node
    Statement(SQLStatement),
    /// DDL for creating an external table in DataFusion
    CreateExternalTable {
        /// Table name
        name: String,
        /// Optional schema
        columns: Vec<ColumnDef>,
        /// File type (Parquet, NDJSON, CSV)
        file_type: FileType,
        /// CSV Header row?
        has_header: bool,
        /// Path to file
        location: String,
    },
}

/// SQL Parser
pub struct DFParser {
    parser: Parser,
}

impl DFParser {
    /// Parse the specified tokens
    pub fn new(sql: &str) -> Result<Self, ParserError> {
        let dialect = GenericDialect {};
        let mut tokenizer = Tokenizer::new(&dialect, sql);
        let tokens = tokenizer.tokenize()?;
        Ok(DFParser {
            parser: Parser::new(tokens),
        })
    }

    /// Parse a SQL statement and produce a set of statements
    pub fn parse_sql(sql: &str) -> Result<Vec<Statement>, ParserError> {
        let mut tokenizer = Tokenizer::new(&GenericDialect {}, &sql);
        tokenizer.tokenize()?;
        let mut parser = DFParser::new(sql)?;
        let mut stmts = Vec::new();
        let mut expecting_statement_delimiter = false;
        loop {
            // ignore empty statements (between successive statement delimiters)
            while parser.parser.consume_token(&Token::SemiColon) {
                expecting_statement_delimiter = false;
            }

            if parser.parser.peek_token() == Token::EOF {
                break;
            }
            if expecting_statement_delimiter {
                return parser.expected("end of statement", parser.parser.peek_token());
            }

            let statement = parser.parse_statement()?;
            stmts.push(statement);
            expecting_statement_delimiter = true;
        }
        Ok(stmts)
    }

    /// Report unexpected token
    fn expected<T>(&self, expected: &str, found: Token) -> Result<T, ParserError> {
        parser_err!(format!("Expected {}, found: {}", expected, found))
    }

    /// Parse a new expression
    pub fn parse_statement(&mut self) -> Result<Statement, ParserError> {
        match self.parser.peek_token() {
            Token::Word(w) => match w.keyword {
                Keyword::CREATE => {
                    // move one token forward
                    self.parser.next_token();
                    // use custom parsing
                    Ok(self.parse_create()?)
                }
                _ => {
                    // use the native parser
                    Ok(Statement::Statement(self.parser.parse_statement()?))
                }
            },
            _ => {
                // use the native parser
                Ok(Statement::Statement(self.parser.parse_statement()?))
            }
        }
    }

    /// Parse a SQL CREATE statement
    pub fn parse_create(&mut self) -> Result<Statement, ParserError> {
        if self.parser.parse_keyword(Keyword::EXTERNAL) {
            self.parse_create_external_table()
        } else {
            Ok(Statement::Statement(self.parser.parse_create()?))
        }
    }

    // This is a copy of the equivalent implementation in sqlparser.
    fn parse_columns(
        &mut self,
    ) -> Result<(Vec<ColumnDef>, Vec<TableConstraint>), ParserError> {
        let mut columns = vec![];
        let mut constraints = vec![];
        if !self.parser.consume_token(&Token::LParen)
            || self.parser.consume_token(&Token::RParen)
        {
            return Ok((columns, constraints));
        }

        loop {
            if let Some(constraint) = self.parser.parse_optional_table_constraint()? {
                constraints.push(constraint);
            } else if let Token::Word(_) = self.parser.peek_token() {
                let column_def = self.parse_column_def()?;
                columns.push(column_def);
            } else {
                return self.expected(
                    "column name or constraint definition",
                    self.parser.peek_token(),
                );
            }
            let comma = self.parser.consume_token(&Token::Comma);
            if self.parser.consume_token(&Token::RParen) {
                // allow a trailing comma, even though it's not in standard
                break;
            } else if !comma {
                return self.expected(
                    "',' or ')' after column definition",
                    self.parser.peek_token(),
                );
            }
        }

        Ok((columns, constraints))
    }

    fn parse_column_def(&mut self) -> Result<ColumnDef, ParserError> {
        let name = self.parser.parse_identifier()?;
        let data_type = self.parser.parse_data_type()?;
        let collation = if self.parser.parse_keyword(Keyword::COLLATE) {
            Some(self.parser.parse_object_name()?)
        } else {
            None
        };
        let mut options = vec![];
        loop {
            match self.parser.peek_token() {
                Token::EOF | Token::Comma | Token::RParen => break,
                _ => options.push(self.parser.parse_column_option_def()?),
            }
        }
        Ok(ColumnDef {
            name,
            data_type,
            collation,
            options,
        })
    }

    fn parse_create_external_table(&mut self) -> Result<Statement, ParserError> {
        self.parser.expect_keyword(Keyword::TABLE)?;
        let table_name = self.parser.parse_object_name()?;
        let (columns, _) = self.parse_columns()?;
        self.parser
            .expect_keywords(&[Keyword::STORED, Keyword::AS])?;

        // THIS is the main difference: we parse a different file format.
        let file_type = self.parse_file_format()?;

        let has_header = self.parse_csv_has_header();

        self.parser.expect_keyword(Keyword::LOCATION)?;
        let location = self.parser.parse_literal_string()?;

        Ok(Statement::CreateExternalTable {
            name: table_name.to_string(),
            columns,
            file_type,
            has_header,
            location,
        })
    }

    /// Parses the set of valid formats
    fn parse_file_format(&mut self) -> Result<FileType, ParserError> {
        match self.parser.next_token() {
            Token::Word(w) => match &*w.value {
                "PARQUET" => Ok(FileType::Parquet),
                "NDJSON" => Ok(FileType::NdJson),
                "CSV" => Ok(FileType::CSV),
                _ => self.expected("fileformat", Token::Word(w)),
            },
            unexpected => self.expected("fileformat", unexpected),
        }
    }

    fn consume_token(&mut self, expected: &str) -> bool {
        if self.parser.peek_token().to_string() == *expected {
            self.parser.next_token();
            true
        } else {
            false
        }
    }

    fn parse_csv_has_header(&mut self) -> bool {
        self.consume_token("WITH")
            & self.consume_token("HEADER")
            & self.consume_token("ROW")
    }
}
<commit_msg>ARROW-9656: [Rust] [DataFusion] Better error messages for unsupported EXTERNAL TABLE types<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! SQL Parser
//!
//! Declares a SQL parser based on sqlparser that handles custom formats that we need.

use sqlparser::{
    ast::{ColumnDef, Statement as SQLStatement, TableConstraint},
    dialect::{keywords::Keyword, GenericDialect},
    parser::{Parser, ParserError},
    tokenizer::{Token, Tokenizer},
};

// Use `Parser::expected` instead, if possible
macro_rules! parser_err {
    ($MSG:expr) => {
        Err(ParserError::ParserError($MSG.to_string()))
    };
}

/// Types of files to parse as DataFrames
#[derive(Debug, Clone, PartialEq)]
pub enum FileType {
    /// Newline-delimited JSON
    NdJson,
    /// Apache Parquet columnar storage
    Parquet,
    /// Comma separated values
    CSV,
}

/// DataFusion Statement representations.
///
/// Tokens parsed by `DFParser` are converted into these values.
#[derive(Debug, Clone, PartialEq)]
pub enum Statement {
    /// ANSI SQL AST node
    Statement(SQLStatement),
    /// DDL for creating an external table in DataFusion
    CreateExternalTable {
        /// Table name
        name: String,
        /// Optional schema
        columns: Vec<ColumnDef>,
        /// File type (Parquet, NDJSON, CSV)
        file_type: FileType,
        /// CSV Header row?
        has_header: bool,
        /// Path to file
        location: String,
    },
}

/// SQL Parser
pub struct DFParser {
    parser: Parser,
}

impl DFParser {
    /// Parse the specified tokens
    pub fn new(sql: &str) -> Result<Self, ParserError> {
        let dialect = GenericDialect {};
        let mut tokenizer = Tokenizer::new(&dialect, sql);
        let tokens = tokenizer.tokenize()?;
        Ok(DFParser {
            parser: Parser::new(tokens),
        })
    }

    /// Parse a SQL statement and produce a set of statements
    pub fn parse_sql(sql: &str) -> Result<Vec<Statement>, ParserError> {
        let mut tokenizer = Tokenizer::new(&GenericDialect {}, &sql);
        tokenizer.tokenize()?;
        let mut parser = DFParser::new(sql)?;
        let mut stmts = Vec::new();
        let mut expecting_statement_delimiter = false;
        loop {
            // ignore empty statements (between successive statement delimiters)
            while parser.parser.consume_token(&Token::SemiColon) {
                expecting_statement_delimiter = false;
            }

            if parser.parser.peek_token() == Token::EOF {
                break;
            }
            if expecting_statement_delimiter {
                return parser.expected("end of statement", parser.parser.peek_token());
            }

            let statement = parser.parse_statement()?;
            stmts.push(statement);
            expecting_statement_delimiter = true;
        }
        Ok(stmts)
    }

    /// Report unexpected token
    fn expected<T>(&self, expected: &str, found: Token) -> Result<T, ParserError> {
        parser_err!(format!("Expected {}, found: {}", expected, found))
    }

    /// Parse a new expression
    pub fn parse_statement(&mut self) -> Result<Statement, ParserError> {
        match self.parser.peek_token() {
            Token::Word(w) => match w.keyword {
                Keyword::CREATE => {
                    // move one token forward
                    self.parser.next_token();
                    // use custom parsing
                    Ok(self.parse_create()?)
                }
                _ => {
                    // use the native parser
                    Ok(Statement::Statement(self.parser.parse_statement()?))
                }
            },
            _ => {
                // use the native parser
                Ok(Statement::Statement(self.parser.parse_statement()?))
            }
        }
    }

    /// Parse a SQL CREATE statement
    pub fn parse_create(&mut self) -> Result<Statement, ParserError> {
        if self.parser.parse_keyword(Keyword::EXTERNAL) {
            self.parse_create_external_table()
        } else {
            Ok(Statement::Statement(self.parser.parse_create()?))
        }
    }

    // This is a copy of the equivalent implementation in sqlparser.
    fn parse_columns(
        &mut self,
    ) -> Result<(Vec<ColumnDef>, Vec<TableConstraint>), ParserError> {
        let mut columns = vec![];
        let mut constraints = vec![];
        if !self.parser.consume_token(&Token::LParen)
            || self.parser.consume_token(&Token::RParen)
        {
            return Ok((columns, constraints));
        }

        loop {
            if let Some(constraint) = self.parser.parse_optional_table_constraint()? {
                constraints.push(constraint);
            } else if let Token::Word(_) = self.parser.peek_token() {
                let column_def = self.parse_column_def()?;
                columns.push(column_def);
            } else {
                return self.expected(
                    "column name or constraint definition",
                    self.parser.peek_token(),
                );
            }
            let comma = self.parser.consume_token(&Token::Comma);
            if self.parser.consume_token(&Token::RParen) {
                // allow a trailing comma, even though it's not in standard
                break;
            } else if !comma {
                return self.expected(
                    "',' or ')' after column definition",
                    self.parser.peek_token(),
                );
            }
        }

        Ok((columns, constraints))
    }

    fn parse_column_def(&mut self) -> Result<ColumnDef, ParserError> {
        let name = self.parser.parse_identifier()?;
        let data_type = self.parser.parse_data_type()?;
        let collation = if self.parser.parse_keyword(Keyword::COLLATE) {
            Some(self.parser.parse_object_name()?)
        } else {
            None
        };
        let mut options = vec![];
        loop {
            match self.parser.peek_token() {
                Token::EOF | Token::Comma | Token::RParen => break,
                _ => options.push(self.parser.parse_column_option_def()?),
            }
        }
        Ok(ColumnDef {
            name,
            data_type,
            collation,
            options,
        })
    }

    fn parse_create_external_table(&mut self) -> Result<Statement, ParserError> {
        self.parser.expect_keyword(Keyword::TABLE)?;
        let table_name = self.parser.parse_object_name()?;
        let (columns, _) = self.parse_columns()?;
        self.parser
            .expect_keywords(&[Keyword::STORED, Keyword::AS])?;

        // THIS is the main difference: we parse a different file format.
        let file_type = self.parse_file_format()?;

        let has_header = self.parse_csv_has_header();

        self.parser.expect_keyword(Keyword::LOCATION)?;
        let location = self.parser.parse_literal_string()?;

        Ok(Statement::CreateExternalTable {
            name: table_name.to_string(),
            columns,
            file_type,
            has_header,
            location,
        })
    }

    /// Parses the set of valid formats
    fn parse_file_format(&mut self) -> Result<FileType, ParserError> {
        match self.parser.next_token() {
            Token::Word(w) => match &*w.value {
                "PARQUET" => Ok(FileType::Parquet),
                "NDJSON" => Ok(FileType::NdJson),
                "CSV" => Ok(FileType::CSV),
                _ => self.expected("one of PARQUET, NDJSON, or CSV", Token::Word(w)),
            },
            unexpected => self.expected("one of PARQUET, NDJSON, or CSV", unexpected),
        }
    }

    fn consume_token(&mut self, expected: &str) -> bool {
        if self.parser.peek_token().to_string() == *expected {
            self.parser.next_token();
            true
        } else {
            false
        }
    }

    fn parse_csv_has_header(&mut self) -> bool {
        self.consume_token("WITH")
            & self.consume_token("HEADER")
            & self.consume_token("ROW")
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use sqlparser::ast::{DataType, Ident};

    fn expect_parse_ok(sql: &str, expected: Statement) -> Result<(), ParserError> {
        let statements = DFParser::parse_sql(sql)?;
        assert_eq!(
            statements.len(),
            1,
            "Expected to parse exactly one statement"
        );
        assert_eq!(statements[0], expected);
        Ok(())
    }

    /// Parses sql and asserts that the expected error message was found
    fn expect_parse_error(sql: &str, expected_error: &str) -> Result<(), ParserError> {
        match DFParser::parse_sql(sql) {
            Ok(statements) => {
                assert!(
                    false,
                    "Expected parse error for '{}', but was successful: {:?}",
                    sql, statements
                );
            }
            Err(e) => {
                let error_message = e.to_string();
                assert!(
                    error_message.contains(expected_error),
                    "Expected error '{}' not found in actual error '{}'",
                    expected_error,
                    error_message
                );
            }
        }
        Ok(())
    }

    fn make_column_def(name: impl Into<String>, data_type: DataType) -> ColumnDef {
        ColumnDef {
            name: Ident {
                value: name.into(),
                quote_style: None,
            },
            data_type,
            collation: None,
            options: vec![],
        }
    }

    #[test]
    fn create_external_table() -> Result<(), ParserError> {
        // positive case
        let sql = "CREATE EXTERNAL TABLE t(c1 int) STORED AS CSV LOCATION 'foo.csv'";
        let expected = Statement::CreateExternalTable {
            name: "t".into(),
            columns: vec![make_column_def("c1", DataType::Int)],
            file_type: FileType::CSV,
            has_header: false,
            location: "foo.csv".into(),
        };
        expect_parse_ok(sql, expected)?;

        // positive case: it is ok for parquet files not to have columns specified
        let sql = "CREATE EXTERNAL TABLE t STORED AS PARQUET LOCATION 'foo.parquet'";
        let expected = Statement::CreateExternalTable {
            name: "t".into(),
            columns: vec![],
            file_type: FileType::Parquet,
            has_header: false,
            location: "foo.parquet".into(),
        };
        expect_parse_ok(sql, expected)?;

        // Error cases: Invalid type
        let sql =
            "CREATE EXTERNAL TABLE t(c1 int) STORED AS UNKNOWN_TYPE LOCATION 'foo.csv'";
        expect_parse_error(
            sql,
            "Expected one of PARQUET, NDJSON, or CSV, found: UNKNOWN_TYPE",
        )?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>use hand;
use table;
use types;

mod straight_flush;
mod four_of_a_kind;
mod full_house;
mod flush;
mod straight;
mod three_of_a_kind;
mod two_pairs;
mod pair;
mod kickers;

mod utility;

pub struct Calculator {}

impl Calculator {
  pub fn get_highest_combination<'a, 'b>(
    hand: &'b hand::Hand,
    table: &'b table::Table,
  ) -> types::Combination {
    let sorted_cards = utility::get_sorted_cards(&hand.cards[..], &table.cards[..]);

    if let Some(result) = straight_flush::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = four_of_a_kind::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = full_house::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = flush::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = straight::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = three_of_a_kind::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = two_pairs::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = pair::test(sorted_cards.clone()) {
      return result;
    }

    return kickers::test(sorted_cards.clone());
  }
}
<commit_msg>small change<commit_after>use hand;
use table;
use types;

mod straight_flush;
mod four_of_a_kind;
mod full_house;
mod flush;
mod straight;
mod three_of_a_kind;
mod two_pairs;
mod pair;
mod kickers;

mod utility;

pub struct Calculator {}

impl Calculator {
  pub fn get_highest_combination<'a, 'b>(
    hand: &'b hand::Hand,
    table: &'b table::Table,
  ) -> types::Combination {
    let sorted_cards = utility::get_sorted_cards(&hand.cards[..], &table.cards[..]);

    if let Some(result) = straight_flush::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = four_of_a_kind::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = full_house::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = flush::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = straight::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = three_of_a_kind::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = two_pairs::test(sorted_cards.clone()) {
      return result;
    }

    if let Some(result) = pair::test(sorted_cards.clone()) {
      return result;
    }

    return kickers::test(sorted_cards);
  }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Read;
use std::env;
use std::path::{Path,PathBuf};
use racer::util::{path_exists, is_dir};
use std::fs::{read_dir};
use toml;

// otry is 'option try'
macro_rules! otry {
    ($e:expr) => (match $e { Some(e) => e, None => return None })
}

// converts errors into None
macro_rules! otry2 {
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => { error!("ERROR!: {:?} {} {}", e, file!(), line!()); return None } })
}

fn find_src_via_lockfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    let mut file = otry2!(File::open(cargofile));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let lock_table = parser.parse().unwrap();

    debug!("find_src_via_lockfile found lock table {:?}", lock_table);

    let t = match lock_table.get("package") {
        Some(&toml::Value::Array(ref t1)) => t1,
        _ => return None
    };

    for item in t {
        if let &toml::Value::Table(ref t) = item {
            if let Some(&toml::Value::String(ref name)) = t.get("name") {
                if name.replace("-", "_") == kratename {
                    debug!("found matching crate {:?}", t);
                    let version = otry!(getstr(t, "version"));
                    let source = otry!(getstr(t, "source"));

                    if Some("registry") == source.split("+").nth(0) {
                        return get_versioned_cratefile(name, &version);
                    } else if Some("git") == source.split("+").nth(0) {
                        let sha1 = otry!(source.split("#").last());
                        let mut d = otry!(get_cargo_rootdir());
                        d.push("git");
                        d.push("checkouts");
                        d = otry!(find_git_src_dir(d, name, &sha1));
                        d.push("src");
                        d.push("lib.rs");
                        return Some(d);
                    }
                }
            }
        }
    }
    None
}

fn get_cargo_rootdir() -> Option<PathBuf> {
    let mut d = otry!(env::home_dir());
    d.push(".cargo");
    if path_exists(&d) {
        return Some(d);
    }

    // try multirust
    d.pop();
    d.push(".multirust");
    d.push("default");
    if let Ok(mut multirustdefault) = File::open(&d) {
        let mut s = String::new();
        otry2!(multirustdefault.read_to_string(&mut s));
        d.pop();
        d.push("toolchains");
        d.push(s.trim());
        d.push("cargo");
        debug!("get_cargo_rootdir root is {:?}",d);
        Some(d)
    } else {
        None
    }
}

fn get_versioned_cratefile(kratename: &str, version: &str) -> Option<PathBuf> {
    let mut d = otry!(get_cargo_rootdir());
    d.push("registry");
    d.push("src");
    d = otry!(find_cratesio_src_dir(d));
    d.push(kratename.to_string() + "-" + &version);
    d.push("src");

    // First, check for package name at root (src/kratename/lib.rs)
    d.push(kratename.to_string());
    if let Err(_) = File::open(&d) {
        // It doesn't exist, so assume src/lib.rs
        d.pop();
    }
    d.push("lib.rs");
    if let Err(_) = File::open(&d) {
        return None;
    }

    Some(d)
 }

fn find_src_via_tomlfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    // only look for 'path' references here.
    // We find the git and crates.io stuff via the lockfile

    let mut file = otry2!(File::open(cargofile));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let table = otry!(parser.parse());
    let t = match table.get("dependencies") {
        Some(&toml::Value::Table(ref t)) => t,
        _ => return None
    };

    match t.get(kratename) {
        Some(&toml::Value::Table(ref t)) => {
            // local directory
            let relative_path = otry!(getstr(t, "path"));
            return Some(otry!(cargofile.parent())
                        .join(relative_path)
                        .join("src")
                        .join("lib.rs"));
        },
        Some(&toml::Value::String(ref version)) => {
            // versioned crate
            return get_versioned_cratefile(kratename, version);
        }
        _ => return None
    }
}

fn find_cratesio_src_dir(d: PathBuf) -> Option<PathBuf> {
    for entry in otry2!(read_dir(d)) {
        let path = otry2!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with("github.com-") {
                    return Some(path.clone());
                }
            }
        }
    }
    None
}

fn find_git_src_dir(d: PathBuf, name: &str, sha1: &str) -> Option<PathBuf> {
    for entry in otry2!(read_dir(d)) {
        let path = otry2!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with(name) {
                    let mut d = path.clone();

                    // dirname can be the sha1 or master.
                    d.push(sha1);

                    if !is_dir(d.as_path()) {
                        d.pop();
                        d.push("master");
                    }

                    let retval = d.clone();

                    // check that the checkout matches the commit sha1
                    d.push(".git");
                    d.push("refs");
                    d.push("heads");
                    d.push("master");

                    let mut headref = String::new();
                    otry2!(otry2!(File::open(d)).read_to_string(&mut headref));

                    debug!("git headref is {:?}", headref);

                    if headref.ends_with("\n") {
                        headref.pop();
                    }

                    if sha1 == headref {
                        return Some(retval);
                    }
                }
            }
        }
    }
    None
}

fn getstr(t: &toml::Table, k: &str) -> Option<String> {
    match t.get(k) {
        Some(&toml::Value::String(ref s)) => Some(s.clone()),
        _ => None
    }
}

fn find_cargo_tomlfile(currentfile: &Path) -> Option<PathBuf> {
    let mut f = currentfile.to_path_buf();
    f.push("Cargo.toml");
    if path_exists(f.as_path()) {
        return Some(f);
    } else {
        if f.pop() && f.pop() {
            return find_cargo_tomlfile(&f);
        } else {
            None
        }
    }
}

pub fn get_crate_file(kratename: &str, from_path: &Path) -> Option<PathBuf> {
    if let Some(tomlfile) = find_cargo_tomlfile(from_path) {
        // look in the lockfile first, if there is one
        debug!("get_crate_file tomlfile is {:?}", tomlfile);
        let mut lockfile = tomlfile.clone();
        lockfile.pop();
        lockfile.push("Cargo.lock");
        if path_exists(lockfile.as_path()) {
            if let Some(f) = find_src_via_lockfile(kratename, &lockfile) {
                return Some(f);
            }
        }

        // oh, no luck with the lockfile. Try the tomlfile
        return find_src_via_tomlfile(kratename, &tomlfile)
    }
    None
}
<commit_msg>search for hyphen crates in toml<commit_after>use std::fs::File;
use std::io::Read;
use std::env;
use std::path::{Path,PathBuf};
use racer::util::{path_exists, is_dir};
use std::fs::{read_dir};
use toml;

// otry is 'option try'
macro_rules! otry {
    ($e:expr) => (match $e { Some(e) => e, None => return None })
}

// converts errors into None
macro_rules! otry2 {
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => { error!("ERROR!: {:?} {} {}", e, file!(), line!()); return None } })
}

fn find_src_via_lockfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    let mut file = otry2!(File::open(cargofile));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let lock_table = parser.parse().unwrap();

    debug!("find_src_via_lockfile found lock table {:?}", lock_table);

    let t = match lock_table.get("package") {
        Some(&toml::Value::Array(ref t1)) => t1,
        _ => return None
    };

    for item in t {
        if let &toml::Value::Table(ref t) = item {
            if let Some(&toml::Value::String(ref name)) = t.get("name") {
                if name.replace("-", "_") == kratename {
                    debug!("found matching crate {:?}", t);
                    let version = otry!(getstr(t, "version"));
                    let source = otry!(getstr(t, "source"));

                    if Some("registry") == source.split("+").nth(0) {
                        return get_versioned_cratefile(name, &version);
                    } else if Some("git") == source.split("+").nth(0) {
                        let sha1 = otry!(source.split("#").last());
                        let mut d = otry!(get_cargo_rootdir());
                        d.push("git");
                        d.push("checkouts");
                        d = otry!(find_git_src_dir(d, name, &sha1));
                        d.push("src");
                        d.push("lib.rs");
                        return Some(d);
                    }
                }
            }
        }
    }
    None
}

fn get_cargo_rootdir() -> Option<PathBuf> {
    let mut d = otry!(env::home_dir());
    d.push(".cargo");
    if path_exists(&d) {
        return Some(d);
    }

    // try multirust
    d.pop();
    d.push(".multirust");
    d.push("default");
    if let Ok(mut multirustdefault) = File::open(&d) {
        let mut s = String::new();
        otry2!(multirustdefault.read_to_string(&mut s));
        d.pop();
        d.push("toolchains");
        d.push(s.trim());
        d.push("cargo");
        debug!("get_cargo_rootdir root is {:?}",d);
        Some(d)
    } else {
        None
    }
}

fn get_versioned_cratefile(kratename: &str, version: &str) -> Option<PathBuf> {
    let mut d = otry!(get_cargo_rootdir());
    d.push("registry");
    d.push("src");
    d = otry!(find_cratesio_src_dir(d));

    // if version=* then search for the first matching folder
    if version == "*" {
        use std::fs::read_dir;
        let mut start_path = d.clone();
        start_path.push(kratename);
        let start_name = start_path.to_str().unwrap();

        if let Ok(reader) = read_dir(d) {
            if let Some(path) = reader
                                .map(|entry| entry.unwrap().path())
                                .find(|path| path.to_str().unwrap().starts_with(start_name)) {
                d = path.clone();
            } else {
                return None;
            }
        } else { return None; }
    } else {
        d.push(kratename.to_string() + "-" + &version);
    }

    d.push("src");
    debug!("crate path {:?}",d);

    // First, check for package name at root (src/kratename/lib.rs)
    d.push(kratename.to_string());
    if let Err(_) = File::open(&d) {
        // It doesn't exist, so assume src/lib.rs
        d.pop();
    }
    d.push("lib.rs");
    if let Err(_) = File::open(&d) {
        return None;
    }

    Some(d)
 }

fn find_src_via_tomlfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    // only look for 'path' references here.
    // We find the git and crates.io stuff via the lockfile

    let mut file = otry2!(File::open(cargofile));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let table = otry!(parser.parse());
    let t = match table.get("dependencies") {
        Some(&toml::Value::Table(ref t)) => t,
        _ => return None
    };

    let mut name = kratename;
    let value = if kratename.contains('_') {
        t.iter().find(|&(k, _)| k.replace("-", "_") == name).map(|(k,v)| {
            name = k;
            v
        })
    } else {
        t.get(kratename)
    };

    match value {
        Some(&toml::Value::Table(ref t)) => {
            // local directory
            let relative_path = otry!(getstr(t, "path"));
            return Some(otry!(cargofile.parent())
                        .join(relative_path)
                        .join("src")
                        .join("lib.rs"));
        },
        Some(&toml::Value::String(ref version)) => {
            // versioned crate
            return get_versioned_cratefile(name, version);
        }
        _ => return None
    }
}

fn find_cratesio_src_dir(d: PathBuf) -> Option<PathBuf> {
    for entry in otry2!(read_dir(d)) {
        let path = otry2!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with("github.com-") {
                    return Some(path.clone());
                }
            }
        }
    }
    None
}

fn find_git_src_dir(d: PathBuf, name: &str, sha1: &str) -> Option<PathBuf> {
    for entry in otry2!(read_dir(d)) {
        let path = otry2!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with(name) {
                    let mut d = path.clone();

                    // dirname can be the sha1 or master.
                    d.push(sha1);

                    if !is_dir(d.as_path()) {
                        d.pop();
                        d.push("master");
                    }

                    let retval = d.clone();

                    // check that the checkout matches the commit sha1
                    d.push(".git");
                    d.push("refs");
                    d.push("heads");
                    d.push("master");

                    let mut headref = String::new();
                    otry2!(otry2!(File::open(d)).read_to_string(&mut headref));

                    debug!("git headref is {:?}", headref);

                    if headref.ends_with("\n") {
                        headref.pop();
                    }

                    if sha1 == headref {
                        return Some(retval);
                    }
                }
            }
        }
    }
    None
}

fn getstr(t: &toml::Table, k: &str) -> Option<String> {
    match t.get(k) {
        Some(&toml::Value::String(ref s)) => Some(s.clone()),
        _ => None
    }
}

fn find_cargo_tomlfile(currentfile: &Path) -> Option<PathBuf> {
    let mut f = currentfile.to_path_buf();
    f.push("Cargo.toml");
    if path_exists(f.as_path()) {
        return Some(f);
    } else {
        if f.pop() && f.pop() {
            return find_cargo_tomlfile(&f);
        } else {
            None
        }
    }
}

pub fn get_crate_file(kratename: &str, from_path: &Path) -> Option<PathBuf> {
    if let Some(tomlfile) = find_cargo_tomlfile(from_path) {
        // look in the lockfile first, if there is one
        debug!("get_crate_file tomlfile is {:?}", tomlfile);
        let mut lockfile = tomlfile.clone();
        lockfile.pop();
        lockfile.push("Cargo.lock");
        if path_exists(lockfile.as_path()) {
            if let Some(f) = find_src_via_lockfile(kratename, &lockfile) {
                return Some(f);
            }
        }

        // oh, no luck with the lockfile. Try the tomlfile
        return find_src_via_tomlfile(kratename, &tomlfile)
    }
    None
}
<|endoftext|>


<commit_before>/*
 * rustboy/cpu.rs
 *
 * This is the CPU of the GameBoy emulator. A technical specification
 * of the GameBoy can be found here: http://problemkaputt.de/pandocs.htm
 *
 */

// Declarations
// These have Z80 added to the names because eventually ARM7TDMI architecture
// will also be defined here.
struct Z80_Clock;
struct Z80_CPU;
struct Z80_Registers;

struct Z80_Clock {

}

/*
  16bit Hi   Lo   Name/Function
  AF    A    -    Accumulator & Flags
  BC    B    C    BC
  DE    D    E    DE
  HL    H    L    HL
  SP    -    -    Stack Pointer
  PC    -    -    Program Counter/Pointer
*/
struct Z80_Registers {
    // 8-bit registers:
    a: u8,      // acc and flags
    b: u8,      // BC
    c: u8,
    d: u8,      // DE
    e: u8,
    h: u8,      // HL
    l: u8,
    // 16-bit registers:
    af: u16,    // acc and flags
    bc: u16,    // BC
    de: u16,    // DE
    hl: u16,    // HL
    // pointers:
    sp: u16,    // stack pointer
    pc: u16     // program counter / instruction pointer
}

struct Z80_CPU;
<commit_msg>z80 cpu skeleton done<commit_after>/*
 * rustboy/cpu.rs
 *
 * This is the CPU of the GameBoy emulator. A technical specification
 * of the GameBoy can be found here: http://problemkaputt.de/pandocs.htm
 *
 */

// Declarations
// These have Z80 added to the names because eventually ARM7TDMI architecture
// will also be defined here.
struct Z80_Clock;
struct Z80_CPU;
struct Z80_Registers;

// The Z80 keeps two internal clocks, m and t. t is a measure of CPU cycles
// and m is 1/4 of t.
struct Z80_Clock {
    m: u8,
    t: u8
}

/*
  16bit Hi   Lo   Name/Function
  AF    A    -    Accumulator & Flags
  BC    B    C    BC
  DE    D    E    DE
  HL    H    L    HL
  SP    -    -    Stack Pointer
  PC    -    -    Program Counter/Pointer
*/
struct Z80_Registers {
    // 8-bit registers:
    a: u8,      // acc and flags
    b: u8,      // BC
    c: u8,
    d: u8,      // DE
    e: u8,
    h: u8,      // HL
    l: u8,
    // 16-bit registers:
    af: u16,    // acc and flags
    bc: u16,    // BC
    de: u16,    // DE
    hl: u16,    // HL
    // pointers:
    sp: u16,    // stack pointer
    pc: u16     // program counter / instruction pointer
}

struct Z80_CPU {
    clock: Z80_Clock,
    //mem: memory,
    regs: Z80_Registers,
}

impl Z80_CPU {
    pub fn reset(&mut self) {
        // clear 8-bit registers
        self.regs.a = 0;
        self.regs.b = 0;
        self.regs.c = 0;
        self.regs.d = 0;
        self.regs.e = 0;
        self.regs.h = 0;
        self.regs.l = 0;
        // clear 16-bit registers
        self.regs.af = 0;
        self.regs.bc = 0;
        self.regs.de = 0;
        self.regs.hl = 0;
        // clear pointers
        self.regs.sp = 0; // beginning of stack
        self.regs.pc = 0; // back to first instruction

        // reset the clock
        self.clock.m = 0;
        self.clock.t = 0;
    }
}
<|endoftext|>