<commit_before>//! Manipulations and data types that represent polynomial.

#![warn(bad_style)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate num_traits;

use num_traits::{One, Zero};
use std::ops::{Add, Mul, Neg, Sub};
use std::{cmp, fmt};

/// Polynomial expression
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Polynomial<T> {
    data: Vec<T>,
}

impl<T: Zero> Polynomial<T> {
    /// Creates new `Polynomial`.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1, 2, 3]);
    /// assert_eq!("1+2*x+3*x^2", poly.pretty("x"));
    /// ```
    #[inline]
    pub fn new(mut data: Vec<T>) -> Polynomial<T> {
        while let Some(true) = data.last().map(|x| x.is_zero()) {
            let _ = data.pop();
        }
        Polynomial { data: data }
    }
}

impl<T: Zero + One + Clone> Polynomial<T> {
    /// Evaluates the polynomial value.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1, 2, 3]);
    /// assert_eq!(1, poly.eval(0));
    /// assert_eq!(6, poly.eval(1));
    /// assert_eq!(17, poly.eval(2));
    /// ```
    #[inline]
    pub fn eval(&self, x: T) -> T {
        let mut sum: T = Zero::zero();
        let mut x_n: T = One::one();
        for n in self.data.iter() {
            sum = sum + n.clone() * x_n.clone();
            x_n = x_n * x.clone();
        }
        sum
    }
}

impl<T> Polynomial<T> {
    /// Gets the slice of internal data.
    #[inline]
    pub fn data(&self) -> &[T] {
        &self.data
    }
}

impl<T> Polynomial<T>
where
    T: Zero + One + Eq + Neg<Output = T> + Ord + fmt::Display + Clone,
{
    /// Pretty prints the polynomial.
    pub fn pretty(&self, x: &str) -> String {
        if self.is_zero() {
            return "0".to_string();
        }

        let one = One::one();
        let mut s = Vec::new();
        for (i, n) in self.data.iter().enumerate() {
            // output n*x^i / -n*x^i
            if n.is_zero() {
                continue;
            }

            let term = if i.is_zero() {
                n.to_string()
            } else if i == 1 {
                if (*n) == one {
                    x.to_string()
                } else if (*n) == -one.clone() {
                    format!("-{}", x)
                } else {
                    format!("{}*{}", n.to_string(), x)
                }
            } else {
                if (*n) == one {
                    format!("{}^{}", x, i)
                } else if (*n) == -one.clone() {
                    format!("-{}^{}", x, i)
                } else {
                    format!("{}*{}^{}", n.to_string(), x, i)
                }
            };

            if s.len() > 0 && (*n) > Zero::zero() {
                s.push("+".to_string());
            }
            s.push(term);
        }

        s.concat()
    }
}

impl<'a, T> Neg for Polynomial<T>
where
    T: Neg + Zero + Clone,
    <T as Neg>::Output: Zero,
{
    type Output = Polynomial<<T as Neg>::Output>;

    #[inline]
    fn neg(self) -> Polynomial<<T as Neg>::Output> {
        -&self
    }
}

impl<'a, T> Neg for &'a Polynomial<T>
where
    T: Neg + Zero + Clone,
    <T as Neg>::Output: Zero,
{
    type Output = Polynomial<<T as Neg>::Output>;

    #[inline]
    fn neg(self) -> Polynomial<<T as Neg>::Output> {
        Polynomial::new(self.data.iter().map(|x| -x.clone()).collect())
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Polynomial<Rhs>> for Polynomial<Lhs>
        where
            Lhs: Zero + $imp<Rhs> + Clone,
            Rhs: Zero + Clone,
            <Lhs as $imp<Rhs>>::Output: Zero,
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    };
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Polynomial<Rhs>> for &'a Polynomial<Lhs>
        where
            Lhs: Zero + $imp<Rhs> + Clone,
            Rhs: Zero + Clone,
            <Lhs as $imp<Rhs>>::Output: Zero,
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    };
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Polynomial<Rhs>> for Polynomial<Lhs>
        where
            Lhs: Zero + $imp<Rhs> + Clone,
            Rhs: Zero + Clone,
            <Lhs as $imp<Rhs>>::Output: Zero,
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    };
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
where
    Lhs: Zero + Add<Rhs> + Clone,
    Rhs: Zero + Clone,
    <Lhs as Add<Rhs>>::Output: Zero,
{
    type Output = Polynomial<<Lhs as Add<Rhs>>::Output>;

    fn add(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Add<Rhs>>::Output> {
        let max_len = cmp::max(self.data.len(), other.data.len());
        let min_len = cmp::min(self.data.len(), other.data.len());

        let mut sum = Vec::with_capacity(max_len);
        for i in 0..min_len {
            sum.push(self.data[i].clone() + other.data[i].clone());
        }

        if self.data.len() <= other.data.len() {
            for i in min_len..max_len {
                sum.push(num_traits::zero::<Lhs>() + other.data[i].clone());
            }
        } else {
            for i in min_len..max_len {
                sum.push(self.data[i].clone() + num_traits::zero::<Rhs>());
            }
        }

        Polynomial::new(sum)
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
where
    Lhs: Zero + Sub<Rhs> + Clone,
    Rhs: Zero + Clone,
    <Lhs as Sub<Rhs>>::Output: Zero,
{
    type Output = Polynomial<<Lhs as Sub<Rhs>>::Output>;

    fn sub(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Sub<Rhs>>::Output> {
        let min_len = cmp::min(self.data.len(), other.data.len());
        let max_len = cmp::max(self.data.len(), other.data.len());

        let mut sub = Vec::with_capacity(max_len);
        for i in 0..min_len {
            sub.push(self.data[i].clone() - other.data[i].clone());
        }
        if self.data.len() <= other.data.len() {
            for i in min_len..max_len {
                sub.push(num_traits::zero::<Lhs>() - other.data[i].clone())
            }
        } else {
            for i in min_len..max_len {
                sub.push(self.data[i].clone() - num_traits::zero::<Rhs>())
            }
        }
        Polynomial::new(sub)
    }
}

forward_all_binop!(impl Mul, mul);

impl<'a, 'b, Lhs, Rhs> Mul<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
where
    Lhs: Zero + Mul<Rhs> + Clone,
    Rhs: Zero + Clone,
    <Lhs as Mul<Rhs>>::Output: Zero,
{
    type Output = Polynomial<<Lhs as Mul<Rhs>>::Output>;

    fn mul(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Mul<Rhs>>::Output> {
        if self.is_zero() || other.is_zero() {
            return Polynomial::new(vec![]);
        }

        let slen = self.data.len();
        let olen = other.data.len();
        let prod = (0..slen + olen - 1)
            .map(|i| {
                let mut p = num_traits::zero::<<Lhs as Mul<Rhs>>::Output>();
                let kstart = cmp::max(olen, i + 1) - olen;
                let kend = cmp::min(slen, i + 1);
                for k in kstart..kend {
                    p = p + self.data[k].clone() * other.data[i - k].clone();
                }
                p
            })
            .collect();
        Polynomial::new(prod)
    }
}

impl<T: Zero + Clone> Zero for Polynomial<T> {
    #[inline]
    fn zero() -> Polynomial<T> {
        Polynomial { data: vec![] }
    }
    #[inline]
    fn is_zero(&self) -> bool {
        self.data.is_empty()
    }
}

impl<T: Zero + One + Clone> One for Polynomial<T> {
    #[inline]
    fn one() -> Polynomial<T> {
        Polynomial {
            data: vec![One::one()],
        }
    }
}

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

    #[test]
    fn new() {
        fn check(dst: Vec<i32>, src: Vec<i32>) {
            assert_eq!(dst, Polynomial::new(src).data);
        }
        check(vec![1, 2, 3], vec![1, 2, 3]);
        check(vec![1, 2, 3], vec![1, 2, 3, 0, 0]);
        check(vec![], vec![0, 0, 0]);
    }

    #[test]
    fn neg_add_sub() {
        fn check(a: &[i32], b: &[i32], c: &[i32]) {
            fn check_eq(a: &Polynomial<i32>, b: &Polynomial<i32>) {
                assert_eq!(*a, *b);
                assert_eq!(-a, -b);
            }
            fn check_add(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
                check_eq(sum, &(a + b));
                check_eq(sum, &(b + a));
            }
            fn check_sub(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
                check_eq(a, &(sum - b));
                check_eq(b, &(sum - a));
            }

            let a = &Polynomial::new(a.to_vec());
            let b = &Polynomial::new(b.to_vec());
            let c = &Polynomial::new(c.to_vec());
            check_add(c, a, b);
            check_add(&(-c), &(-a), &(-b));
            check_sub(c, a, b);
            check_sub(&(-c), &(-a), &(-b));
        }
        check(&[], &[], &[]);
        check(&[], &[1], &[1]);
        check(&[1], &[1], &[2]);
        check(&[1, 0, 1], &[1], &[2, 0, 1]);
        check(&[1, 0, -1], &[-1, 0, 1], &[]);
    }

    #[test]
    fn mul() {
        fn check(a: &[i32], b: &[i32], c: &[i32]) {
            let a = Polynomial::new(a.to_vec());
            let b = Polynomial::new(b.to_vec());
            let c = Polynomial::new(c.to_vec());
            assert_eq!(c, &a * &b);
            assert_eq!(c, &b * &a);
        }
        check(&[], &[], &[]);
        check(&[0, 0], &[], &[]);
        check(&[0, 0], &[1], &[]);
        check(&[1, 0], &[1], &[1]);
        check(&[1, 0, 1], &[1], &[1, 0, 1]);
        check(&[1, 1], &[1, 1], &[1, 2, 1]);
        check(&[1, 1], &[1, 0, 1], &[1, 1, 1, 1]);
        check(&[0, 0, 1], &[0, 0, 1], &[0, 0, 0, 0, 1]);
    }

    #[test]
    fn eval() {
        fn check<F: Fn(i32) -> i32>(pol: &[i32], f: F) {
            for n in -10..10 {
                assert_eq!(f(n), Polynomial::new(pol.to_vec()).eval(n));
            }
        }
        check(&[], |_x| 0);
        check(&[1], |_x| 1);
        check(&[1, 1], |x| x + 1);
        check(&[0, 1], |x| x);
        check(&[10, -10, 10], |x| 10 * x * x - 10 * x + 10);
    }

    #[test]
    fn pretty() {
        fn check(slice: &[i32], s: &str) {
            assert_eq!(s.to_string(), Polynomial::new(slice.to_vec()).pretty("x"));
        }
        check(&[0], "0");
        check(&[1], "1");
        check(&[1, 1], "1+x");
        check(&[1, 1, 1], "1+x+x^2");
        check(&[2, 2, 2], "2+2*x+2*x^2");
        check(&[0, 0, 0, 1], "x^3");
        check(&[0, 0, 0, -1], "-x^3");
        check(&[-1, 0, 0, -1], "-1-x^3");
        check(&[-1, 1, 0, -1], "-1+x-x^3");
        check(&[-1, 1, -1, -1], "-1+x-x^2-x^3");
    }
}
<commit_msg>Change the algorithm of Polynomial::eval<commit_after>//! Manipulations and data types that represent polynomial.

#![warn(bad_style)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate num_traits;

use num_traits::{One, Zero};
use std::ops::{Add, Mul, Neg, Sub};
use std::{cmp, fmt};

/// Polynomial expression
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Polynomial<T> {
    data: Vec<T>,
}

impl<T: Zero> Polynomial<T> {
    /// Creates new `Polynomial`.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1, 2, 3]);
    /// assert_eq!("1+2*x+3*x^2", poly.pretty("x"));
    /// ```
    #[inline]
    pub fn new(mut data: Vec<T>) -> Polynomial<T> {
        while let Some(true) = data.last().map(|x| x.is_zero()) {
            let _ = data.pop();
        }
        Polynomial { data: data }
    }
}

impl<T: Zero + Mul<Output = T> + Clone> Polynomial<T> {
    /// Evaluates the polynomial value.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1, 2, 3]);
    /// assert_eq!(1, poly.eval(0));
    /// assert_eq!(6, poly.eval(1));
    /// assert_eq!(17, poly.eval(2));
    /// ```
    #[inline]
    pub fn eval(&self, x: T) -> T {
        let mut result: T = Zero::zero();
        for n in self.data.iter().rev() {
            result = n.clone() + result * x.clone();
        }
        result
    }
}

impl<T> Polynomial<T> {
    /// Gets the slice of internal data.
    #[inline]
    pub fn data(&self) -> &[T] {
        &self.data
    }
}

impl<T> Polynomial<T>
where
    T: Zero + One + Eq + Neg<Output = T> + Ord + fmt::Display + Clone,
{
    /// Pretty prints the polynomial.
    pub fn pretty(&self, x: &str) -> String {
        if self.is_zero() {
            return "0".to_string();
        }

        let one = One::one();
        let mut s = Vec::new();
        for (i, n) in self.data.iter().enumerate() {
            // output n*x^i / -n*x^i
            if n.is_zero() {
                continue;
            }

            let term = if i.is_zero() {
                n.to_string()
            } else if i == 1 {
                if (*n) == one {
                    x.to_string()
                } else if (*n) == -one.clone() {
                    format!("-{}", x)
                } else {
                    format!("{}*{}", n.to_string(), x)
                }
            } else {
                if (*n) == one {
                    format!("{}^{}", x, i)
                } else if (*n) == -one.clone() {
                    format!("-{}^{}", x, i)
                } else {
                    format!("{}*{}^{}", n.to_string(), x, i)
                }
            };

            if s.len() > 0 && (*n) > Zero::zero() {
                s.push("+".to_string());
            }
            s.push(term);
        }

        s.concat()
    }
}

impl<'a, T> Neg for Polynomial<T>
where
    T: Neg + Zero + Clone,
    <T as Neg>::Output: Zero,
{
    type Output = Polynomial<<T as Neg>::Output>;

    #[inline]
    fn neg(self) -> Polynomial<<T as Neg>::Output> {
        -&self
    }
}

impl<'a, T> Neg for &'a Polynomial<T>
where
    T: Neg + Zero + Clone,
    <T as Neg>::Output: Zero,
{
    type Output = Polynomial<<T as Neg>::Output>;

    #[inline]
    fn neg(self) -> Polynomial<<T as Neg>::Output> {
        Polynomial::new(self.data.iter().map(|x| -x.clone()).collect())
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Polynomial<Rhs>> for Polynomial<Lhs>
        where
            Lhs: Zero + $imp<Rhs> + Clone,
            Rhs: Zero + Clone,
            <Lhs as $imp<Rhs>>::Output: Zero,
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    };
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Polynomial<Rhs>> for &'a Polynomial<Lhs>
        where
            Lhs: Zero + $imp<Rhs> + Clone,
            Rhs: Zero + Clone,
            <Lhs as $imp<Rhs>>::Output: Zero,
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    };
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Polynomial<Rhs>> for Polynomial<Lhs>
        where
            Lhs: Zero + $imp<Rhs> + Clone,
            Rhs: Zero + Clone,
            <Lhs as $imp<Rhs>>::Output: Zero,
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    };
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
where
    Lhs: Zero + Add<Rhs> + Clone,
    Rhs: Zero + Clone,
    <Lhs as Add<Rhs>>::Output: Zero,
{
    type Output = Polynomial<<Lhs as Add<Rhs>>::Output>;

    fn add(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Add<Rhs>>::Output> {
        let max_len = cmp::max(self.data.len(), other.data.len());
        let min_len = cmp::min(self.data.len(), other.data.len());

        let mut sum = Vec::with_capacity(max_len);
        for i in 0..min_len {
            sum.push(self.data[i].clone() + other.data[i].clone());
        }

        if self.data.len() <= other.data.len() {
            for i in min_len..max_len {
                sum.push(num_traits::zero::<Lhs>() + other.data[i].clone());
            }
        } else {
            for i in min_len..max_len {
                sum.push(self.data[i].clone() + num_traits::zero::<Rhs>());
            }
        }

        Polynomial::new(sum)
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
where
    Lhs: Zero + Sub<Rhs> + Clone,
    Rhs: Zero + Clone,
    <Lhs as Sub<Rhs>>::Output: Zero,
{
    type Output = Polynomial<<Lhs as Sub<Rhs>>::Output>;

    fn sub(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Sub<Rhs>>::Output> {
        let min_len = cmp::min(self.data.len(), other.data.len());
        let max_len = cmp::max(self.data.len(), other.data.len());

        let mut sub = Vec::with_capacity(max_len);
        for i in 0..min_len {
            sub.push(self.data[i].clone() - other.data[i].clone());
        }
        if self.data.len() <= other.data.len() {
            for i in min_len..max_len {
                sub.push(num_traits::zero::<Lhs>() - other.data[i].clone())
            }
        } else {
            for i in min_len..max_len {
                sub.push(self.data[i].clone() - num_traits::zero::<Rhs>())
            }
        }
        Polynomial::new(sub)
    }
}

forward_all_binop!(impl Mul, mul);

impl<'a, 'b, Lhs, Rhs> Mul<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
where
    Lhs: Zero + Mul<Rhs> + Clone,
    Rhs: Zero + Clone,
    <Lhs as Mul<Rhs>>::Output: Zero,
{
    type Output = Polynomial<<Lhs as Mul<Rhs>>::Output>;

    fn mul(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Mul<Rhs>>::Output> {
        if self.is_zero() || other.is_zero() {
            return Polynomial::new(vec![]);
        }

        let slen = self.data.len();
        let olen = other.data.len();
        let prod = (0..slen + olen - 1)
            .map(|i| {
                let mut p = num_traits::zero::<<Lhs as Mul<Rhs>>::Output>();
                let kstart = cmp::max(olen, i + 1) - olen;
                let kend = cmp::min(slen, i + 1);
                for k in kstart..kend {
                    p = p + self.data[k].clone() * other.data[i - k].clone();
                }
                p
            })
            .collect();
        Polynomial::new(prod)
    }
}

impl<T: Zero + Clone> Zero for Polynomial<T> {
    #[inline]
    fn zero() -> Polynomial<T> {
        Polynomial { data: vec![] }
    }
    #[inline]
    fn is_zero(&self) -> bool {
        self.data.is_empty()
    }
}

impl<T: Zero + One + Clone> One for Polynomial<T> {
    #[inline]
    fn one() -> Polynomial<T> {
        Polynomial {
            data: vec![One::one()],
        }
    }
}

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

    #[test]
    fn new() {
        fn check(dst: Vec<i32>, src: Vec<i32>) {
            assert_eq!(dst, Polynomial::new(src).data);
        }
        check(vec![1, 2, 3], vec![1, 2, 3]);
        check(vec![1, 2, 3], vec![1, 2, 3, 0, 0]);
        check(vec![], vec![0, 0, 0]);
    }

    #[test]
    fn neg_add_sub() {
        fn check(a: &[i32], b: &[i32], c: &[i32]) {
            fn check_eq(a: &Polynomial<i32>, b: &Polynomial<i32>) {
                assert_eq!(*a, *b);
                assert_eq!(-a, -b);
            }
            fn check_add(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
                check_eq(sum, &(a + b));
                check_eq(sum, &(b + a));
            }
            fn check_sub(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
                check_eq(a, &(sum - b));
                check_eq(b, &(sum - a));
            }

            let a = &Polynomial::new(a.to_vec());
            let b = &Polynomial::new(b.to_vec());
            let c = &Polynomial::new(c.to_vec());
            check_add(c, a, b);
            check_add(&(-c), &(-a), &(-b));
            check_sub(c, a, b);
            check_sub(&(-c), &(-a), &(-b));
        }
        check(&[], &[], &[]);
        check(&[], &[1], &[1]);
        check(&[1], &[1], &[2]);
        check(&[1, 0, 1], &[1], &[2, 0, 1]);
        check(&[1, 0, -1], &[-1, 0, 1], &[]);
    }

    #[test]
    fn mul() {
        fn check(a: &[i32], b: &[i32], c: &[i32]) {
            let a = Polynomial::new(a.to_vec());
            let b = Polynomial::new(b.to_vec());
            let c = Polynomial::new(c.to_vec());
            assert_eq!(c, &a * &b);
            assert_eq!(c, &b * &a);
        }
        check(&[], &[], &[]);
        check(&[0, 0], &[], &[]);
        check(&[0, 0], &[1], &[]);
        check(&[1, 0], &[1], &[1]);
        check(&[1, 0, 1], &[1], &[1, 0, 1]);
        check(&[1, 1], &[1, 1], &[1, 2, 1]);
        check(&[1, 1], &[1, 0, 1], &[1, 1, 1, 1]);
        check(&[0, 0, 1], &[0, 0, 1], &[0, 0, 0, 0, 1]);
    }

    #[test]
    fn eval() {
        fn check<F: Fn(i32) -> i32>(pol: &[i32], f: F) {
            for n in -10..10 {
                assert_eq!(f(n), Polynomial::new(pol.to_vec()).eval(n));
            }
        }
        check(&[], |_x| 0);
        check(&[1], |_x| 1);
        check(&[1, 1], |x| x + 1);
        check(&[0, 1], |x| x);
        check(&[10, -10, 10], |x| 10 * x * x - 10 * x + 10);
    }

    #[test]
    fn pretty() {
        fn check(slice: &[i32], s: &str) {
            assert_eq!(s.to_string(), Polynomial::new(slice.to_vec()).pretty("x"));
        }
        check(&[0], "0");
        check(&[1], "1");
        check(&[1, 1], "1+x");
        check(&[1, 1, 1], "1+x+x^2");
        check(&[2, 2, 2], "2+2*x+2*x^2");
        check(&[0, 0, 0, 1], "x^3");
        check(&[0, 0, 0, -1], "-x^3");
        check(&[-1, 0, 0, -1], "-1-x^3");
        check(&[-1, 1, 0, -1], "-1+x-x^3");
        check(&[-1, 1, -1, -1], "-1+x-x^2-x^3");
    }
}
<|endoftext|>


<commit_before>#![feature(move_from, map_in_place, iter_arith)]

extern crate rand;

pub mod union_find;

pub mod stacks_and_queues;
pub mod elementary_sorts;

pub mod mergesort;
pub mod quicksort;

pub mod convex_hull;

pub mod priority_queues;

pub mod symbol_tables;

pub mod balanced_search_trees;
pub mod geometric_search;

pub mod hash_tables;
pub mod searching_application;
<commit_msg>fix compile error under nightly<commit_after>#![feature(move_from, map_in_place, iter_arith, associated_type_defaults)]

extern crate rand;

pub mod union_find;

pub mod stacks_and_queues;
pub mod elementary_sorts;

pub mod mergesort;
pub mod quicksort;

pub mod convex_hull;

pub mod priority_queues;

pub mod symbol_tables;

pub mod balanced_search_trees;
pub mod geometric_search;

pub mod hash_tables;
pub mod searching_application;
<|endoftext|>


<commit_before>//! This library provides [`anyhow::Error`][Error], a trait object based error
//! type for easy idiomatic error handling in Rust applications.
//!
//!

//!
//! # Details
//!
//! - Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as
//!   the return type of any fallible function.
//!
//!   Within the function, use `?` to easily propagate any error that implements
//!   the `std::error::Error` trait.
//!
//!   ```
//!   # pub trait Deserialize {}
//!   #
//!   # mod serde_json {
//!   #     use super::Deserialize;
//!   #     use std::io;
//!   #
//!   #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # struct ClusterMap;
//!   #
//!   # impl Deserialize for ClusterMap {}
//!   #
//!   use anyhow::Result;
//!
//!   fn get_cluster_info() -> Result<ClusterMap> {
//!       let config = std::fs::read_to_string("cluster.json")?;
//!       let map: ClusterMap = serde_json::from_str(&config)?;
//!       Ok(map)
//!   }
//!   #
//!   # fn main() {}
//!   ```
//!
//! - Attach context to help the person troubleshooting the error understand
//!   where things went wrong. A low-level error like "No such file or
//!   directory" can be annoying to debug without more context about what higher
//!   level step the application was in the middle of.
//!
//!   ```
//!   # struct It;
//!   #
//!   # impl It {
//!   #     fn detach(&self) -> Result<()> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   use anyhow::{Context, Result};
//!
//!   fn main() -> Result<()> {
//!       # return Ok(());
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # let it = It;
//!       # let path = "./path/to/instrs.jsox";
//!       #
//!       it.detach().context("failed to detach the important thing")?;
//!
//!       let content = std::fs::read(path)
//!           .with_context(|| format!("failed to read instrs from {}", path))?;
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # Ok(())
//!   }
//!   ```
//!
//!   ```console
//!   Error: failed to read instrs from ./path/to/instrs.jsox
//!
//!   caused by:
//!       0: No such file or directory (os error 2)
//!   ```
//!
//! - Downcasting is supported and can be by value, by shared reference, or by
//!   mutable reference as needed.
//!
//!   ```
//!   # use anyhow::anyhow;
//!   # use std::fmt::{self, Display};
//!   # use std::task::Poll;
//!   #
//!   # #[derive(Debug)]
//!   # enum DataStoreError {
//!   #     Censored(()),
//!   # }
//!   #
//!   # impl Display for DataStoreError {
//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # impl std::error::Error for DataStoreError {}
//!   #
//!   # const REDACTED_CONTENT: () = ();
//!   #
//!   # let error = anyhow!("...");
//!   # let root_cause = &error;
//!   #
//!   # let ret =
//!   // If the error was caused by redaction, then return a
//!   // tombstone instead of the content.
//!   match root_cause.downcast_ref::<DataStoreError>() {
//!       Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
//!       None => Err(error),
//!   }
//!   # ;
//!   ```
//!
//! - A backtrace is captured and printed with the error if the underlying error
//!   type does not already provide its own. In order to see backtraces, the
//!   `RUST_LIB_BACKTRACE=1` environment variable must be defined.
//!
//! - Anyhow works with any error type that has an impl of `std::error::Error`,
//!   including ones defined in your crate. We do not bundle a `derive(Error)`
//!   macro but you can write the impls yourself or use a standalone macro like
//!   [err-derive].
//!
//!   [err-derive]: https://crates.io/crates/err-derive
//!
//!   ```
//!   # const IGNORE: &str = stringify! {
//!   #[derive(Error, Debug)]
//!   pub enum FormatError {
//!       #[error(display = "invalid header (expected {:?}, got {:?})", expected, found)]
//!       InvalidHeader {
//!           expected: String,
//!           found: String,
//!       },
//!       #[error(display = "missing attribute: {}", _0)]
//!       MissingAttribute(String),
//!   }
//!   # };
//!   ```
//!
//! - One-off error messages can be constructed using the `anyhow!` macro, which
//!   supports string interpolation and produces an `anyhow::Error`.
//!
//!   ```
//!   # use anyhow::{anyhow, Result};
//!   #
//!   # fn demo() -> Result<()> {
//!   #     let missing = "...";
//!   return Err(anyhow!("missing attribute: {}", missing));
//!   #     Ok(())
//!   # }
//!   ```
//!
//!

//!
//! # Acknowledgements
//!
//! The implementation of the `anyhow::Error` type is forked from
//! `fehler::Exception` ([https://github.com/withoutboats/fehler][fehler]). This
//! library just exposes it under the more standard `Error` / `Result`
//! terminology rather than the `throw!` / `#[throws]` / `Exception` language of
//! exceptions.
//!
//! [fehler]: https://github.com/withoutboats/fehler

#![cfg_attr(backtrace, feature(backtrace))]

mod context;
mod error;

#[cfg(not(feature = "std"))]
compile_error!("no_std support is not implemented yet");

pub use crate::context::Context;
pub use crate::error::{Chain, Error};

/// `Result<T, Error>`
pub type Result<T> = std::result::Result<T, Error>;

/// Return early with an error.
///
/// This macro is equivalent to `return Err(From::from($err))`.
#[macro_export]
macro_rules! bail {
    ($err:expr) => {
        return std::result::Result::Err(std::convert::From::from($err));
    };
    ($err:expr,) => {
        $crate::bail!($err);
    };
}

/// Construct an ad-hoc error from a string.
///
/// This evaluates to an `Error`. It can take either just a string, or a format
/// string with arguments. It also can take any custom type which implements
/// `Debug` and `Display`.
#[macro_export]
macro_rules! anyhow {
    ($msg:expr) => {
        $crate::private::new_adhoc($msg)
    };
    ($msg:expr,) => {
        $crate::anyhow!($msg)
    };
    ($fmt:expr, $($arg:tt)*) => {
        $crate::private::new_adhoc(format!($fmt, $($arg)*))
    };
}

// Not public API.
#[doc(hidden)]
pub mod private {
    use crate::Error;
    use std::fmt::{Debug, Display};

    #[cfg(backtrace)]
    use std::backtrace::Backtrace;

    pub fn new_adhoc<M>(message: M) -> Error
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        #[cfg(backtrace)]
        let backtrace = Some(Backtrace::capture());

        #[cfg(not(backtrace))]
        let backtrace = None;

        Error::new_adhoc(message, backtrace)
    }
}
<commit_msg>Simplify handling of trailing commas<commit_after>//! This library provides [`anyhow::Error`][Error], a trait object based error
//! type for easy idiomatic error handling in Rust applications.
//!
//!

//!
//! # Details
//!
//! - Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as
//!   the return type of any fallible function.
//!
//!   Within the function, use `?` to easily propagate any error that implements
//!   the `std::error::Error` trait.
//!
//!   ```
//!   # pub trait Deserialize {}
//!   #
//!   # mod serde_json {
//!   #     use super::Deserialize;
//!   #     use std::io;
//!   #
//!   #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # struct ClusterMap;
//!   #
//!   # impl Deserialize for ClusterMap {}
//!   #
//!   use anyhow::Result;
//!
//!   fn get_cluster_info() -> Result<ClusterMap> {
//!       let config = std::fs::read_to_string("cluster.json")?;
//!       let map: ClusterMap = serde_json::from_str(&config)?;
//!       Ok(map)
//!   }
//!   #
//!   # fn main() {}
//!   ```
//!
//! - Attach context to help the person troubleshooting the error understand
//!   where things went wrong. A low-level error like "No such file or
//!   directory" can be annoying to debug without more context about what higher
//!   level step the application was in the middle of.
//!
//!   ```
//!   # struct It;
//!   #
//!   # impl It {
//!   #     fn detach(&self) -> Result<()> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   use anyhow::{Context, Result};
//!
//!   fn main() -> Result<()> {
//!       # return Ok(());
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # let it = It;
//!       # let path = "./path/to/instrs.jsox";
//!       #
//!       it.detach().context("failed to detach the important thing")?;
//!
//!       let content = std::fs::read(path)
//!           .with_context(|| format!("failed to read instrs from {}", path))?;
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # Ok(())
//!   }
//!   ```
//!
//!   ```console
//!   Error: failed to read instrs from ./path/to/instrs.jsox
//!
//!   caused by:
//!       0: No such file or directory (os error 2)
//!   ```
//!
//! - Downcasting is supported and can be by value, by shared reference, or by
//!   mutable reference as needed.
//!
//!   ```
//!   # use anyhow::anyhow;
//!   # use std::fmt::{self, Display};
//!   # use std::task::Poll;
//!   #
//!   # #[derive(Debug)]
//!   # enum DataStoreError {
//!   #     Censored(()),
//!   # }
//!   #
//!   # impl Display for DataStoreError {
//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # impl std::error::Error for DataStoreError {}
//!   #
//!   # const REDACTED_CONTENT: () = ();
//!   #
//!   # let error = anyhow!("...");
//!   # let root_cause = &error;
//!   #
//!   # let ret =
//!   // If the error was caused by redaction, then return a
//!   // tombstone instead of the content.
//!   match root_cause.downcast_ref::<DataStoreError>() {
//!       Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
//!       None => Err(error),
//!   }
//!   # ;
//!   ```
//!
//! - A backtrace is captured and printed with the error if the underlying error
//!   type does not already provide its own. In order to see backtraces, the
//!   `RUST_LIB_BACKTRACE=1` environment variable must be defined.
//!
//! - Anyhow works with any error type that has an impl of `std::error::Error`,
//!   including ones defined in your crate. We do not bundle a `derive(Error)`
//!   macro but you can write the impls yourself or use a standalone macro like
//!   [err-derive].
//!
//!   [err-derive]: https://crates.io/crates/err-derive
//!
//!   ```
//!   # const IGNORE: &str = stringify! {
//!   #[derive(Error, Debug)]
//!   pub enum FormatError {
//!       #[error(display = "invalid header (expected {:?}, got {:?})", expected, found)]
//!       InvalidHeader {
//!           expected: String,
//!           found: String,
//!       },
//!       #[error(display = "missing attribute: {}", _0)]
//!       MissingAttribute(String),
//!   }
//!   # };
//!   ```
//!
//! - One-off error messages can be constructed using the `anyhow!` macro, which
//!   supports string interpolation and produces an `anyhow::Error`.
//!
//!   ```
//!   # use anyhow::{anyhow, Result};
//!   #
//!   # fn demo() -> Result<()> {
//!   #     let missing = "...";
//!   return Err(anyhow!("missing attribute: {}", missing));
//!   #     Ok(())
//!   # }
//!   ```
//!
//!

//!
//! # Acknowledgements
//!
//! The implementation of the `anyhow::Error` type is forked from
//! `fehler::Exception` ([https://github.com/withoutboats/fehler][fehler]). This
//! library just exposes it under the more standard `Error` / `Result`
//! terminology rather than the `throw!` / `#[throws]` / `Exception` language of
//! exceptions.
//!
//! [fehler]: https://github.com/withoutboats/fehler

#![cfg_attr(backtrace, feature(backtrace))]

mod context;
mod error;

#[cfg(not(feature = "std"))]
compile_error!("no_std support is not implemented yet");

pub use crate::context::Context;
pub use crate::error::{Chain, Error};

/// `Result<T, Error>`
pub type Result<T> = std::result::Result<T, Error>;

/// Return early with an error.
///
/// This macro is equivalent to `return Err(From::from($err))`.
#[macro_export]
macro_rules! bail {
    ($err:expr $(,)?) => {
        return std::result::Result::Err(std::convert::From::from($err));
    };
}

/// Construct an ad-hoc error from a string.
///
/// This evaluates to an `Error`. It can take either just a string, or a format
/// string with arguments. It also can take any custom type which implements
/// `Debug` and `Display`.
#[macro_export]
macro_rules! anyhow {
    ($msg:expr $(,)?) => {
        $crate::private::new_adhoc($msg)
    };
    ($fmt:expr, $($arg:tt)*) => {
        $crate::private::new_adhoc(format!($fmt, $($arg)*))
    };
}

// Not public API.
#[doc(hidden)]
pub mod private {
    use crate::Error;
    use std::fmt::{Debug, Display};

    #[cfg(backtrace)]
    use std::backtrace::Backtrace;

    pub fn new_adhoc<M>(message: M) -> Error
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        #[cfg(backtrace)]
        let backtrace = Some(Backtrace::capture());

        #[cfg(not(backtrace))]
        let backtrace = None;

        Error::new_adhoc(message, backtrace)
    }
}
<|endoftext|>


<commit_before>//! Generate Rust bindings for C and C++ libraries.
//!
//! Provide a C/C++ header file, receive Rust FFI code to call into C/C++
//! functions and use types defined in the header.
//!
//! See the [Builder](./struct.Builder.html) struct for usage.

#![crate_name = "bindgen"]
#![crate_type = "dylib"]

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

#![deny(missing_docs)]
#![deny(warnings)]

// We internally use the deprecated BindgenOptions all over the place. Once we
// remove its `pub` declaration, we can un-deprecate it and remove this pragma.
#![allow(deprecated)]

// To avoid rather annoying warnings when matching with CXCursor_xxx as a
// constant.
#![allow(non_upper_case_globals)]

#[macro_use]
extern crate cfg_if;
extern crate syntex_syntax as syntax;
extern crate aster;
extern crate quasi;
extern crate clang_sys;
extern crate libc;
extern crate regex;
#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;

// A macro to declare an internal module for which we *must* provide
// documentation for. If we are building with the "_docs" feature, then the
// module is declared public, and our `#![deny(missing_docs)]` pragma applies to
// it. This feature is used in CI, so we won't let anything slip by
// undocumented. Normal builds, however, will leave the module private, so that
// we don't expose internals to library consumers.
macro_rules! doc_mod {
    ($m:ident, $doc_mod_name:ident) => {
        cfg_if! {
            if #[cfg(feature = "_docs")] {
                pub mod $doc_mod_name {
                    //! Autogenerated documentation module.
                    pub use super::$m::*;
                }
            } else {
            }
        }
    };
}

mod clangll;
mod clang;
mod ir;
mod parse;
mod regex_set;

doc_mod!(clang, clang_docs);
doc_mod!(ir, ir_docs);
doc_mod!(parse, parse_docs);
doc_mod!(regex_set, regex_set_docs);

mod codegen {
    include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
}

use std::borrow::Borrow;
use std::io::{self, Write};
use std::fs::OpenOptions;
use std::path::Path;
use std::collections::HashSet;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::print::pprust;
use syntax::print::pp::eof;
use syntax::ptr::P;

use ir::context::BindgenContext;
use ir::item::{Item, ItemId};
use parse::{ClangItemParser, ParseError};
use regex_set::RegexSet;

/// Configure and generate Rust bindings for a C/C++ header.
///
/// This is the main entry point to the library.
///
/// ```ignore
/// use bindgen::builder;
///
/// // Configure and generate bindings.
/// let bindings = try!(builder().header("path/to/input/header")
///                              .whitelisted_type("SomeCoolClass")
///                              .whitelisted_function("do_some_cool_thing")
///                              .generate());
///
/// // Write the generated bindings to an output file.
/// try!(bindings.write_to_file("path/to/output.rs"));
/// ```
#[derive(Debug,Default)]
pub struct Builder {
    options: BindgenOptions,
}

/// Construct a new [`Builder`](./struct.Builder.html).
pub fn builder() -> Builder {
    Default::default()
}

impl Builder {
    /// Set the input C/C++ header.
    pub fn header<T: Into<String>>(self, header: T) -> Builder {
        self.clang_arg(header)
    }

    /// Hide the given type from the generated bindings.
    pub fn hide_type<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.hidden_types.insert(arg.into());
        self
    }

    /// Treat the given type as opaque in the generated bindings.
    pub fn opaque_type<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.opaque_types.insert(arg.into());
        self
    }

    /// Whitelist the given type so that it (and all types that it transitively
    /// refers to) appears in the generated bindings.
    pub fn whitelisted_type<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_types.insert(&arg);
        self
    }

    /// Whitelist the given function so that it (and all types that it
    /// transitively refers to) appears in the generated bindings.
    pub fn whitelisted_function<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_functions.insert(&arg);
        self
    }

    /// Whitelist the given variable so that it (and all types that it
    /// transitively refers to) appears in the generated bindings.
    pub fn whitelisted_var<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_vars.insert(&arg);
        self
    }

    /// Add a string to prepend to the generated bindings. The string is passed
    /// through without any modification.
    pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.raw_lines.push(arg.into());
        self
    }

    /// Add an argument to be passed straight through to clang.
    pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.clang_args.push(arg.into());
        self
    }

    /// Make the generated bindings link the given shared library.
    pub fn link<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Default));
        self
    }

    /// Make the generated bindings link the given static library.
    pub fn link_static<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Static));
        self
    }

    /// Make the generated bindings link the given framework.
    pub fn link_framework<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Framework));
        self
    }

    /// Emit bindings for builtin definitions (for example `__builtin_va_list`)
    /// in the generated Rust.
    pub fn emit_builtins(mut self) -> Builder {
        self.options.builtins = true;
        self
    }

    /// Avoid generating any unstable Rust in the generated bindings.
    pub fn no_unstable_rust(mut self) -> Builder {
        self.options.unstable_rust = false;
        self
    }

    /// Generate the Rust bindings using the options built up thus far.
    pub fn generate(self) -> Result<Bindings, ()> {
        Bindings::generate(self.options, None)
    }
}

/// Configuration options for generated bindings.
///
/// Deprecated: use a `Builder` instead.
#[derive(Debug)]
#[deprecated]
pub struct BindgenOptions {
    /// The set of types that have been blacklisted and should not appear
    /// anywhere in the generated code.
    pub hidden_types: HashSet<String>,

    /// The set of types that should be treated as opaque structures in the
    /// generated code.
    pub opaque_types: HashSet<String>,

    /// The set of types that we should have bindings for in the generated
    /// code.
    ///
    /// This includes all types transitively reachable from any type in this
    /// set. One might think of whitelisted types/vars/functions as GC roots,
    /// and the generated Rust code as including everything that gets marked.
    pub whitelisted_types: RegexSet,

    /// Whitelisted functions. See docs for `whitelisted_types` for more.
    pub whitelisted_functions: RegexSet,

    /// Whitelisted variables. See docs for `whitelisted_types` for more.
    pub whitelisted_vars: RegexSet,

    /// Whether we should generate builtins or not.
    pub builtins: bool,

    /// The set of libraries we should link in the generated Rust code.
    pub links: Vec<(String, LinkType)>,

    /// True if we should dump the Clang AST for debugging purposes.
    pub emit_ast: bool,

    /// True if we should ignore functions and only generate bindings for
    /// structures, types, and methods.
    pub ignore_functions: bool,

    /// True if we should avoid generating bindings for methods, and instead
    /// just generate code for structures and types.
    pub ignore_methods: bool,

    /// True if we should emulate C++ namespaces with Rust modules in the
    /// generated bindings.
    pub enable_cxx_namespaces: bool,

    /// True if we shold derive Debug trait implementations for C/C++ structures
    /// and types.
    pub derive_debug: bool,

    /// True if we can use unstable Rust code in the bindings, false if we
    /// cannot.
    pub unstable_rust: bool,

    /// True if we should generate constant names that are **directly** under
    /// namespaces.
    pub namespaced_constants: bool,

    /// True if we should use MSVC name mangling rules.
    pub msvc_mangling: bool,

    /// The set of raw lines to prepend to the generated Rust code.
    pub raw_lines: Vec<String>,

    /// The set of arguments to pass straight through to Clang.
    pub clang_args: Vec<String>,
}

impl Default for BindgenOptions {
    fn default() -> BindgenOptions {
        BindgenOptions {
            hidden_types: Default::default(),
            opaque_types: Default::default(),
            whitelisted_types: Default::default(),
            whitelisted_functions: Default::default(),
            whitelisted_vars: Default::default(),
            builtins: false,
            links: vec![],
            emit_ast: false,
            ignore_functions: false,
            ignore_methods: false,
            derive_debug: true,
            enable_cxx_namespaces: false,
            unstable_rust: true,
            namespaced_constants: true,
            msvc_mangling: false,
            raw_lines: vec![],
            clang_args: vec![],
        }
    }
}

/// The linking type to use with a given library.
///
/// TODO: #104: This is ignored at the moment, but shouldn't be.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum LinkType {
    /// Use shared library linking. This is the default.
    Default,
    /// Use static linking.
    Static,
    /// The library is an OSX framework.
    Framework
}

/// Generated Rust bindings.
#[derive(Debug, Clone)]
pub struct Bindings {
    module: ast::Mod,
    raw_lines: Vec<String>,
}

impl Bindings {
    /// Generate bindings for the given options.
    ///
    /// Deprecated - use a `Builder` instead
    #[deprecated]
    pub fn generate(options: BindgenOptions, span: Option<Span>) -> Result<Bindings, ()> {
        let span = span.unwrap_or(DUMMY_SP);

        let mut context = BindgenContext::new(options);
        parse(&mut context);

        let module = ast::Mod {
            inner: span,
            items: codegen::codegen(&mut context),
        };

        Ok(Bindings {
            module: module,
            raw_lines: context.options().raw_lines.clone(),
        })
    }

    /// Convert these bindings into a Rust AST.
    pub fn into_ast(self) -> Vec<P<ast::Item>> {
        self.module.items
    }

    /// Convert these bindings into source text (with raw lines prepended).
    pub fn to_string(&self) -> String {
        let mut mod_str = vec![];
        {
            let ref_writer = Box::new(mod_str.by_ref()) as Box<Write>;
            self.write(ref_writer).expect("Could not write bindings to string");
        }
        String::from_utf8(mod_str).unwrap()
    }

    /// Write these bindings as source text to a file.
    pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
        let file = try!(OpenOptions::new().write(true).truncate(true).create(true).open(path));
        self.write(Box::new(file))
    }

    /// Write these bindings as source text to the given `Write`able.
    // https://github.com/Manishearth/rust-clippy/issues/740
    #[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
    pub fn write<'a>(&self, mut writer: Box<Write + 'a>) -> io::Result<()> {
        try!(writer.write("/* automatically generated by rust-bindgen */\n\n".as_bytes()));

        for line in self.raw_lines.iter() {
            try!(writer.write(line.as_bytes()));
            try!(writer.write("\n".as_bytes()));
        }
        if !self.raw_lines.is_empty() {
            try!(writer.write("\n".as_bytes()));
        }

        let mut ps = pprust::rust_printer(writer);
        try!(ps.print_mod(&self.module, &[]));
        try!(ps.print_remaining_comments());
        try!(eof(&mut ps.s));
        ps.s.out.flush()
    }
}

/// Determines whether the given cursor is in any of the files matched by the
/// options.
fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
    let (file, _, _, _) = cursor.location().location();

    match file.name() {
        None => ctx.options().builtins,
        Some(..) => true,
    }
}

/// Parse one `Item` from the Clang cursor.
pub fn parse_one(ctx: &mut BindgenContext,
                 cursor: clang::Cursor,
                 parent: Option<ItemId>,
                 children: &mut Vec<ItemId>) -> clangll::Enum_CXVisitorResult {
    if !filter_builtins(ctx, &cursor) {
        return CXChildVisit_Continue
    }

    use clangll::CXChildVisit_Continue;
    match Item::parse(cursor, parent, ctx) {
        Ok(id) => children.push(id),
        Err(ParseError::Continue) => {},
        Err(ParseError::Recurse) => {
            cursor.visit(|child, _| parse_one(ctx, *child, parent, children));
        }
    }
    CXChildVisit_Continue
}

/// Parse the Clang AST into our `Item` internal representation.
fn parse(context: &mut BindgenContext) {
    use clang::Diagnostic;
    use clangll::*;

    for d in context.translation_unit().diags().iter() {
        let msg = d.format(Diagnostic::default_opts());
        let is_err = d.severity() >= CXDiagnostic_Error;
        println!("{}, err: {}", msg, is_err);
    }

    let cursor = context.translation_unit().cursor();
    if context.options().emit_ast {
        cursor.visit(|cur, _| clang::ast_dump(cur, 0));
    }

    let root = context.root_module();
    context.with_module(root, |context, children| {
        cursor.visit(|cursor, _| parse_one(context, *cursor, None, children))
    });

    assert!(context.current_module() == context.root_module(),
            "How did this happen?");
}
<commit_msg>Let rustfmt find the codegen module.<commit_after>//! Generate Rust bindings for C and C++ libraries.
//!
//! Provide a C/C++ header file, receive Rust FFI code to call into C/C++
//! functions and use types defined in the header.
//!
//! See the [Builder](./struct.Builder.html) struct for usage.

#![crate_name = "bindgen"]
#![crate_type = "dylib"]

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

#![deny(missing_docs)]
#![deny(warnings)]

// We internally use the deprecated BindgenOptions all over the place. Once we
// remove its `pub` declaration, we can un-deprecate it and remove this pragma.
#![allow(deprecated)]

// To avoid rather annoying warnings when matching with CXCursor_xxx as a
// constant.
#![allow(non_upper_case_globals)]

#[macro_use]
extern crate cfg_if;
extern crate syntex_syntax as syntax;
extern crate aster;
extern crate quasi;
extern crate clang_sys;
extern crate libc;
extern crate regex;
#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;

// A macro to declare an internal module for which we *must* provide
// documentation for. If we are building with the "_docs" feature, then the
// module is declared public, and our `#![deny(missing_docs)]` pragma applies to
// it. This feature is used in CI, so we won't let anything slip by
// undocumented. Normal builds, however, will leave the module private, so that
// we don't expose internals to library consumers.
macro_rules! doc_mod {
    ($m:ident, $doc_mod_name:ident) => {
        cfg_if! {
            if #[cfg(feature = "_docs")] {
                pub mod $doc_mod_name {
                    //! Autogenerated documentation module.
                    pub use super::$m::*;
                }
            } else {
            }
        }
    };
}

mod clangll;
mod clang;
mod ir;
mod parse;
mod regex_set;

#[cfg(rustfmt)]
mod codegen;

doc_mod!(clang, clang_docs);
doc_mod!(ir, ir_docs);
doc_mod!(parse, parse_docs);
doc_mod!(regex_set, regex_set_docs);

mod codegen {
    include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
}

use std::borrow::Borrow;
use std::io::{self, Write};
use std::fs::OpenOptions;
use std::path::Path;
use std::collections::HashSet;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::print::pprust;
use syntax::print::pp::eof;
use syntax::ptr::P;

use ir::context::BindgenContext;
use ir::item::{Item, ItemId};
use parse::{ClangItemParser, ParseError};
use regex_set::RegexSet;

/// Configure and generate Rust bindings for a C/C++ header.
///
/// This is the main entry point to the library.
///
/// ```ignore
/// use bindgen::builder;
///
/// // Configure and generate bindings.
/// let bindings = try!(builder().header("path/to/input/header")
///                              .whitelisted_type("SomeCoolClass")
///                              .whitelisted_function("do_some_cool_thing")
///                              .generate());
///
/// // Write the generated bindings to an output file.
/// try!(bindings.write_to_file("path/to/output.rs"));
/// ```
#[derive(Debug,Default)]
pub struct Builder {
    options: BindgenOptions,
}

/// Construct a new [`Builder`](./struct.Builder.html).
pub fn builder() -> Builder {
    Default::default()
}

impl Builder {
    /// Set the input C/C++ header.
    pub fn header<T: Into<String>>(self, header: T) -> Builder {
        self.clang_arg(header)
    }

    /// Hide the given type from the generated bindings.
    pub fn hide_type<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.hidden_types.insert(arg.into());
        self
    }

    /// Treat the given type as opaque in the generated bindings.
    pub fn opaque_type<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.opaque_types.insert(arg.into());
        self
    }

    /// Whitelist the given type so that it (and all types that it transitively
    /// refers to) appears in the generated bindings.
    pub fn whitelisted_type<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_types.insert(&arg);
        self
    }

    /// Whitelist the given function so that it (and all types that it
    /// transitively refers to) appears in the generated bindings.
    pub fn whitelisted_function<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_functions.insert(&arg);
        self
    }

    /// Whitelist the given variable so that it (and all types that it
    /// transitively refers to) appears in the generated bindings.
    pub fn whitelisted_var<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_vars.insert(&arg);
        self
    }

    /// Add a string to prepend to the generated bindings. The string is passed
    /// through without any modification.
    pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.raw_lines.push(arg.into());
        self
    }

    /// Add an argument to be passed straight through to clang.
    pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.clang_args.push(arg.into());
        self
    }

    /// Make the generated bindings link the given shared library.
    pub fn link<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Default));
        self
    }

    /// Make the generated bindings link the given static library.
    pub fn link_static<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Static));
        self
    }

    /// Make the generated bindings link the given framework.
    pub fn link_framework<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Framework));
        self
    }

    /// Emit bindings for builtin definitions (for example `__builtin_va_list`)
    /// in the generated Rust.
    pub fn emit_builtins(mut self) -> Builder {
        self.options.builtins = true;
        self
    }

    /// Avoid generating any unstable Rust in the generated bindings.
    pub fn no_unstable_rust(mut self) -> Builder {
        self.options.unstable_rust = false;
        self
    }

    /// Generate the Rust bindings using the options built up thus far.
    pub fn generate(self) -> Result<Bindings, ()> {
        Bindings::generate(self.options, None)
    }
}

/// Configuration options for generated bindings.
///
/// Deprecated: use a `Builder` instead.
#[derive(Debug)]
#[deprecated]
pub struct BindgenOptions {
    /// The set of types that have been blacklisted and should not appear
    /// anywhere in the generated code.
    pub hidden_types: HashSet<String>,

    /// The set of types that should be treated as opaque structures in the
    /// generated code.
    pub opaque_types: HashSet<String>,

    /// The set of types that we should have bindings for in the generated
    /// code.
    ///
    /// This includes all types transitively reachable from any type in this
    /// set. One might think of whitelisted types/vars/functions as GC roots,
    /// and the generated Rust code as including everything that gets marked.
    pub whitelisted_types: RegexSet,

    /// Whitelisted functions. See docs for `whitelisted_types` for more.
    pub whitelisted_functions: RegexSet,

    /// Whitelisted variables. See docs for `whitelisted_types` for more.
    pub whitelisted_vars: RegexSet,

    /// Whether we should generate builtins or not.
    pub builtins: bool,

    /// The set of libraries we should link in the generated Rust code.
    pub links: Vec<(String, LinkType)>,

    /// True if we should dump the Clang AST for debugging purposes.
    pub emit_ast: bool,

    /// True if we should ignore functions and only generate bindings for
    /// structures, types, and methods.
    pub ignore_functions: bool,

    /// True if we should avoid generating bindings for methods, and instead
    /// just generate code for structures and types.
    pub ignore_methods: bool,

    /// True if we should emulate C++ namespaces with Rust modules in the
    /// generated bindings.
    pub enable_cxx_namespaces: bool,

    /// True if we shold derive Debug trait implementations for C/C++ structures
    /// and types.
    pub derive_debug: bool,

    /// True if we can use unstable Rust code in the bindings, false if we
    /// cannot.
    pub unstable_rust: bool,

    /// True if we should generate constant names that are **directly** under
    /// namespaces.
    pub namespaced_constants: bool,

    /// True if we should use MSVC name mangling rules.
    pub msvc_mangling: bool,

    /// The set of raw lines to prepend to the generated Rust code.
    pub raw_lines: Vec<String>,

    /// The set of arguments to pass straight through to Clang.
    pub clang_args: Vec<String>,
}

impl Default for BindgenOptions {
    fn default() -> BindgenOptions {
        BindgenOptions {
            hidden_types: Default::default(),
            opaque_types: Default::default(),
            whitelisted_types: Default::default(),
            whitelisted_functions: Default::default(),
            whitelisted_vars: Default::default(),
            builtins: false,
            links: vec![],
            emit_ast: false,
            ignore_functions: false,
            ignore_methods: false,
            derive_debug: true,
            enable_cxx_namespaces: false,
            unstable_rust: true,
            namespaced_constants: true,
            msvc_mangling: false,
            raw_lines: vec![],
            clang_args: vec![],
        }
    }
}

/// The linking type to use with a given library.
///
/// TODO: #104: This is ignored at the moment, but shouldn't be.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum LinkType {
    /// Use shared library linking. This is the default.
    Default,
    /// Use static linking.
    Static,
    /// The library is an OSX framework.
    Framework
}

/// Generated Rust bindings.
#[derive(Debug, Clone)]
pub struct Bindings {
    module: ast::Mod,
    raw_lines: Vec<String>,
}

impl Bindings {
    /// Generate bindings for the given options.
    ///
    /// Deprecated - use a `Builder` instead
    #[deprecated]
    pub fn generate(options: BindgenOptions, span: Option<Span>) -> Result<Bindings, ()> {
        let span = span.unwrap_or(DUMMY_SP);

        let mut context = BindgenContext::new(options);
        parse(&mut context);

        let module = ast::Mod {
            inner: span,
            items: codegen::codegen(&mut context),
        };

        Ok(Bindings {
            module: module,
            raw_lines: context.options().raw_lines.clone(),
        })
    }

    /// Convert these bindings into a Rust AST.
    pub fn into_ast(self) -> Vec<P<ast::Item>> {
        self.module.items
    }

    /// Convert these bindings into source text (with raw lines prepended).
    pub fn to_string(&self) -> String {
        let mut mod_str = vec![];
        {
            let ref_writer = Box::new(mod_str.by_ref()) as Box<Write>;
            self.write(ref_writer).expect("Could not write bindings to string");
        }
        String::from_utf8(mod_str).unwrap()
    }

    /// Write these bindings as source text to a file.
    pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
        let file = try!(OpenOptions::new().write(true).truncate(true).create(true).open(path));
        self.write(Box::new(file))
    }

    /// Write these bindings as source text to the given `Write`able.
    // https://github.com/Manishearth/rust-clippy/issues/740
    #[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
    pub fn write<'a>(&self, mut writer: Box<Write + 'a>) -> io::Result<()> {
        try!(writer.write("/* automatically generated by rust-bindgen */\n\n".as_bytes()));

        for line in self.raw_lines.iter() {
            try!(writer.write(line.as_bytes()));
            try!(writer.write("\n".as_bytes()));
        }
        if !self.raw_lines.is_empty() {
            try!(writer.write("\n".as_bytes()));
        }

        let mut ps = pprust::rust_printer(writer);
        try!(ps.print_mod(&self.module, &[]));
        try!(ps.print_remaining_comments());
        try!(eof(&mut ps.s));
        ps.s.out.flush()
    }
}

/// Determines whether the given cursor is in any of the files matched by the
/// options.
fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
    let (file, _, _, _) = cursor.location().location();

    match file.name() {
        None => ctx.options().builtins,
        Some(..) => true,
    }
}

/// Parse one `Item` from the Clang cursor.
pub fn parse_one(ctx: &mut BindgenContext,
                 cursor: clang::Cursor,
                 parent: Option<ItemId>,
                 children: &mut Vec<ItemId>) -> clangll::Enum_CXVisitorResult {
    if !filter_builtins(ctx, &cursor) {
        return CXChildVisit_Continue
    }

    use clangll::CXChildVisit_Continue;
    match Item::parse(cursor, parent, ctx) {
        Ok(id) => children.push(id),
        Err(ParseError::Continue) => {},
        Err(ParseError::Recurse) => {
            cursor.visit(|child, _| parse_one(ctx, *child, parent, children));
        }
    }
    CXChildVisit_Continue
}

/// Parse the Clang AST into our `Item` internal representation.
fn parse(context: &mut BindgenContext) {
    use clang::Diagnostic;
    use clangll::*;

    for d in context.translation_unit().diags().iter() {
        let msg = d.format(Diagnostic::default_opts());
        let is_err = d.severity() >= CXDiagnostic_Error;
        println!("{}, err: {}", msg, is_err);
    }

    let cursor = context.translation_unit().cursor();
    if context.options().emit_ast {
        cursor.visit(|cur, _| clang::ast_dump(cur, 0));
    }

    let root = context.root_module();
    context.with_module(root, |context, children| {
        cursor.visit(|cursor, _| parse_one(context, *cursor, None, children))
    });

    assert!(context.current_module() == context.root_module(),
            "How did this happen?");
}
<|endoftext|>


<commit_before>#![feature(io, path, core, fs_time)]
#![cfg_attr(test, deny(warnings))]

extern crate conduit;
extern crate "conduit-mime-types" as mime;
extern crate time;
#[cfg(test)] extern crate tempdir;

use std::collections::HashMap;
use std::error::Error;
use std::io;
use std::io::prelude::*;
use std::path::{PathBuf, AsPath};
use std::fs::File;
use conduit::{Request, Response, Handler};

pub struct Static {
    path: PathBuf,
    types: mime::Types
}

impl Static {
    pub fn new<P: AsPath + ?Sized>(path: &P) -> Static {
        Static {
            path: path.as_path().to_path_buf(),
            types: mime::Types::new()
                .ok().expect("Couldn't load mime-types")
        }
    }
}

impl Handler for Static {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Error+Send>> {
        let request_path = &request.path()[1..];
        if request_path.contains("..") { return Ok(not_found()) }

        let path = self.path.join(request_path);
        let mime = self.types.mime_for_path(&path);
        let file = match File::open(&path) {
            Ok(f) => f,
            Err(..) => return Ok(not_found()),
        };
        let data = try!(file.metadata().map_err(|e| Box::new(e) as Box<Error+Send>));
        if data.is_dir() {
            return Ok(not_found())
        }
        let ts = time::Timespec {
            sec: (data.modified() as i64) / 1000,
            nsec: (((data.modified() as u32) % 1000) as i32) * 1000000
        };
        let tm = time::at(ts).to_utc();

        let mut headers = HashMap::new();
        headers.insert("Content-Type".to_string(), vec![mime.to_string()]);
        headers.insert("Content-Length".to_string(),
                       vec![data.len().to_string()]);
        headers.insert("Last-Modified".to_string(),
                       vec![tm.strftime("%a, %d %b %Y %T GMT").unwrap()
                              .to_string()]);

        Ok(Response {
            status: (200, "OK"),
            headers: headers,
            body: Box::new(file),
        })
    }
}

fn not_found() -> Response {
    Response {
        status: (404, "Not Found"),
        headers: HashMap::new(),
        body: Box::new(io::empty()),
    }
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as test;

    use std::fs::{self, File};
    use std::io::prelude::*;
    use tempdir::TempDir;

    use conduit::{Handler, Method};
    use Static;

    #[test]
    fn test_static() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        let handler = Static::new(root.clone());
        File::create(&root.join("Cargo.toml")).unwrap()
             .write_all(b"[package]").unwrap();
        let mut req = test::MockRequest::new(Method::Get, "/Cargo.toml");
        let mut res = handler.call(&mut req).ok().expect("No response");
        let mut body = String::new();
        res.body.read_to_string(&mut body).unwrap();
        assert_eq!(body, "[package]");
        assert_eq!(res.headers.get("Content-Type"),
                   Some(&vec!("text/plain".to_string())));
        assert_eq!(res.headers.get("Content-Length"),
                   Some(&vec!["9".to_string()]));
    }

    #[test]
    fn test_mime_types() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        fs::create_dir(&root.join("src")).unwrap();
        File::create(&root.join("src/fixture.css")).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/src/fixture.css");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.headers.get("Content-Type"),
                   Some(&vec!("text/css".to_string())));
        assert_eq!(res.headers.get("Content-Length"),
                   Some(&vec!["0".to_string()]));
    }

    #[test]
    fn test_missing() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/nope");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.0, 404);
    }

    #[test]
    fn test_dir() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        fs::create_dir(&root.join("foo")).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/foo");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.0, 404);
    }

    #[test]
    fn last_modified() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        File::create(&root.join("test")).unwrap();
        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/test");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.0, 200);
        assert!(res.headers.get("Last-Modified").is_some());
    }
}
<commit_msg>Update to rust master<commit_after>#![feature(core, fs_time, std_misc)]
#![cfg_attr(test, deny(warnings))]

extern crate conduit;
extern crate "conduit-mime-types" as mime;
extern crate time;
#[cfg(test)] extern crate tempdir;

use std::collections::HashMap;
use std::error::Error;
use std::io;
use std::io::prelude::*;
use std::path::{PathBuf, AsPath};
use std::fs::File;
use conduit::{Request, Response, Handler};

pub struct Static {
    path: PathBuf,
    types: mime::Types
}

impl Static {
    pub fn new<P: AsPath + ?Sized>(path: &P) -> Static {
        Static {
            path: path.as_path().to_path_buf(),
            types: mime::Types::new()
                .ok().expect("Couldn't load mime-types")
        }
    }
}

impl Handler for Static {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Error+Send>> {
        let request_path = &request.path()[1..];
        if request_path.contains("..") { return Ok(not_found()) }

        let path = self.path.join(request_path);
        let mime = self.types.mime_for_path(&path);
        let file = match File::open(&path) {
            Ok(f) => f,
            Err(..) => return Ok(not_found()),
        };
        let data = try!(file.metadata().map_err(|e| Box::new(e) as Box<Error+Send>));
        if data.is_dir() {
            return Ok(not_found())
        }
        let ts = time::Timespec {
            sec: (data.modified() as i64) / 1000,
            nsec: (((data.modified() as u32) % 1000) as i32) * 1000000
        };
        let tm = time::at(ts).to_utc();

        let mut headers = HashMap::new();
        headers.insert("Content-Type".to_string(), vec![mime.to_string()]);
        headers.insert("Content-Length".to_string(),
                       vec![data.len().to_string()]);
        headers.insert("Last-Modified".to_string(),
                       vec![tm.strftime("%a, %d %b %Y %T GMT").unwrap()
                              .to_string()]);

        Ok(Response {
            status: (200, "OK"),
            headers: headers,
            body: Box::new(file),
        })
    }
}

fn not_found() -> Response {
    Response {
        status: (404, "Not Found"),
        headers: HashMap::new(),
        body: Box::new(io::empty()),
    }
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as test;

    use std::fs::{self, File};
    use std::io::prelude::*;
    use tempdir::TempDir;

    use conduit::{Handler, Method};
    use Static;

    #[test]
    fn test_static() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        let handler = Static::new(root.clone());
        File::create(&root.join("Cargo.toml")).unwrap()
             .write_all(b"[package]").unwrap();
        let mut req = test::MockRequest::new(Method::Get, "/Cargo.toml");
        let mut res = handler.call(&mut req).ok().expect("No response");
        let mut body = String::new();
        res.body.read_to_string(&mut body).unwrap();
        assert_eq!(body, "[package]");
        assert_eq!(res.headers.get("Content-Type"),
                   Some(&vec!("text/plain".to_string())));
        assert_eq!(res.headers.get("Content-Length"),
                   Some(&vec!["9".to_string()]));
    }

    #[test]
    fn test_mime_types() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        fs::create_dir(&root.join("src")).unwrap();
        File::create(&root.join("src/fixture.css")).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/src/fixture.css");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.headers.get("Content-Type"),
                   Some(&vec!("text/css".to_string())));
        assert_eq!(res.headers.get("Content-Length"),
                   Some(&vec!["0".to_string()]));
    }

    #[test]
    fn test_missing() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/nope");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.0, 404);
    }

    #[test]
    fn test_dir() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        fs::create_dir(&root.join("foo")).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/foo");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.0, 404);
    }

    #[test]
    fn last_modified() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        File::create(&root.join("test")).unwrap();
        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/test");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.0, 200);
        assert!(res.headers.get("Last-Modified").is_some());
    }
}
<|endoftext|>


<commit_before>#![crate_name = "knuckle"]
#![crate_type = "lib"]
#![license = "MIT"]

#![feature(globs)]
//#![deny(missing_doc)]

//! `knuckle` is an opinionated Rust language interface to the
//! already opinionated NaCl project.
//!
//! Specifically, knuckle uses `tweetnacl`, a minimal implementation
//! of NaCl that's implemented as a standalone C file. Theoretically, the
//! backend could be trivially switched to either full NaCl or the
//! derivative `libsodium` project.
//!
//! It provides several useful abstractions around NaCl's primitives,
//! but also exposes direct bindings to the C library (via the `bindings`
//! module).
//!
//! ## Primitives
//!
//! The following cryptographic primitives are used with this library.
//!
//! Module        | Primitive
//! ------------- | -------------
//! cryptobox     | Curve25519/Salsa20/Poly1305
//! hash          | SHA-512
//! secretbox     | Salsa20/Poly1305
//! sign          | Ed25519
//! stream        | Salsa20

extern crate libc;

pub use bindings::*;

/// Exposes direct Rust bindings to the C NaCl interface.
#[allow(dead_code)]
#[stable]
pub mod bindings;

/// Provides authenticated asymmetric key cryptography operations.
#[stable]
pub mod cryptobox;

/// Simple interface to strong cryptographic hash function.
#[stable]
pub mod hash;

/// Provides authenticated symmetric key cryptography operations.
#[stable]
pub mod secretbox;

/// Provides simple interface to generate and validate digital signatures.
pub mod sign;

/// Exposes the crypto_stream functionality of NaCl. (Not yet written)
pub mod stream;

/// Useful common functions for this library.
pub mod util;
<commit_msg>License annotation no longer exists.<commit_after>#![crate_name = "knuckle"]
#![crate_type = "lib"]

#![feature(globs)]
//#![deny(missing_doc)]

//! `knuckle` is an opinionated Rust language interface to the
//! already opinionated NaCl project.
//!
//! Specifically, knuckle uses `tweetnacl`, a minimal implementation
//! of NaCl that's implemented as a standalone C file. Theoretically, the
//! backend could be trivially switched to either full NaCl or the
//! derivative `libsodium` project.
//!
//! It provides several useful abstractions around NaCl's primitives,
//! but also exposes direct bindings to the C library (via the `bindings`
//! module).
//!
//! ## Primitives
//!
//! The following cryptographic primitives are used with this library.
//!
//! Module        | Primitive
//! ------------- | -------------
//! cryptobox     | Curve25519/Salsa20/Poly1305
//! hash          | SHA-512
//! secretbox     | Salsa20/Poly1305
//! sign          | Ed25519
//! stream        | Salsa20

extern crate libc;

pub use bindings::*;

/// Exposes direct Rust bindings to the C NaCl interface.
#[allow(dead_code)]
#[stable]
pub mod bindings;

/// Provides authenticated asymmetric key cryptography operations.
#[stable]
pub mod cryptobox;

/// Simple interface to strong cryptographic hash function.
#[stable]
pub mod hash;

/// Provides authenticated symmetric key cryptography operations.
#[stable]
pub mod secretbox;

/// Provides simple interface to generate and validate digital signatures.
pub mod sign;

/// Exposes the crypto_stream functionality of NaCl. (Not yet written)
pub mod stream;

/// Useful common functions for this library.
pub mod util;
<|endoftext|>


<commit_before>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    0
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum BotOrOutput {
    Bot,
    Output,
}

#[derive(PartialEq, Debug)]
pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
    low: Option<usize>,
    low_bot_or_output: Option<BotOrOutput>,
    high: Option<usize>,
    high_bot_or_output: Option<BotOrOutput>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
            low: None, high: None,
            low_bot_or_output: None,
            high_bot_or_output: None,
        }
    }

    pub fn has_two_chips(&self) -> bool {
        match (self.chip1, self.chip2) {
            (Some(_), Some(_)) => true,
            _ => false,
        }
    }

    pub fn receive_chip(&mut self, chip: usize)
           -> Vec<(usize, BotOrOutput, usize)> {
        if self.chip1.is_none() {
            self.chip1 = Some(chip);
            vec![]
        } else if self.chip2.is_none() {
            self.chip2 = Some(chip);
            if let (Some(lo), Some(hi)) = (self.low, self.high) {
                let return_commands = if self.chip1 < self.chip2 {
                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                    ]
                } else {
                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                    ]
                };
                self.chip1 = None;
                self.chip2 = None;
                self.low = None;
                self.high = None;
                self.low_bot_or_output = None;
                self.high_bot_or_output = None;
                return_commands
            } else {
                vec![]
            }
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn receive_command(&mut self, low_bot_or_output: &str, low: usize,
                                      high_bot_or_output: &str, high: usize) {
        self.low = Some(low);
        if low_bot_or_output == "bot" {
            self.low_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.low_bot_or_output = Some(BotOrOutput::Output);
        }
        self.high = Some(high);
        if high_bot_or_output == "bot" {
            self.high_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.high_bot_or_output = Some(BotOrOutput::Output);
        }
    }
}

pub struct BotRouter {
    bots: HashMap<usize, Bot>,
    output_bins: HashMap<usize, Vec<usize>>,
}

impl BotRouter {
    pub fn exec_command(&mut self, input: &str) {
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        let return_commands = self.bots
                                  .entry(bot_key)
                                  .or_insert(Bot::new(bot_key))
                                  .receive_chip(value);
        for &(key, bot_or_output, chip_value) in return_commands.iter() {
            match bot_or_output {
                BotOrOutput::Bot => self.value_to_bot(key, chip_value),
                BotOrOutput::Output => self.value_to_output(key, chip_value),
            }
        }
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        self.output_bins.entry(output_key).or_insert(Vec::new()).push(value);
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                          low_bot_or_output: &str, low_key: usize,
                          high_bot_or_output: &str, high_key: usize) {
        let bot = self.bots.entry(bot_key).or_insert(Bot::new(bot_key));
        bot.receive_command(
            low_bot_or_output,
            low_key,
            high_bot_or_output,
            high_key
        );
    }
}

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

    #[test]
    fn new_bot_does_not_have_two_chips() {
        let bot = Bot::new(0);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_a_chip_still_not_two() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_two_chips() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        bot.receive_chip(4);
        assert!(bot.has_two_chips());
    }

    #[test]
    fn router_can_give_values() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            Some(5)
        );
    }

    #[test]
    fn router_can_give_commands_that_get_stored() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        assert_eq!(
            br.bots.get(&2).unwrap().low,
            Some(1)
        );
        assert_eq!(
            br.bots.get(&2).unwrap().high,
            Some(0)
        );
    }

    #[test]
    fn router_adds_two_values_so_commands_get_executed() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            None
        );
        assert_eq!(
            br.bots.get(&2).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&1).unwrap().chip1,
            Some(2)
        );
        assert_eq!(
            br.bots.get(&1).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&0).unwrap().chip1,
            Some(5)
        );
        assert_eq!(
            br.bots.get(&0).unwrap().chip2,
            None
        );
    }

    #[test]
    fn test_sample() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.output_bins.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.output_bins.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.output_bins.get(&2),
            Some(&vec![3])
        )
    }
}
<commit_msg>Panic if we find the bot we're looking for<commit_after>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    0
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum BotOrOutput {
    Bot,
    Output,
}

#[derive(PartialEq, Debug)]
pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
    low: Option<usize>,
    low_bot_or_output: Option<BotOrOutput>,
    high: Option<usize>,
    high_bot_or_output: Option<BotOrOutput>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
            low: None, high: None,
            low_bot_or_output: None,
            high_bot_or_output: None,
        }
    }

    pub fn has_two_chips(&self) -> bool {
        match (self.chip1, self.chip2) {
            (Some(_), Some(_)) => true,
            _ => false,
        }
    }

    pub fn receive_chip(&mut self, chip: usize)
           -> Vec<(usize, BotOrOutput, usize)> {
        if self.chip1.is_none() {
            self.chip1 = Some(chip);
            vec![]
        } else if self.chip2.is_none() {
            self.chip2 = Some(chip);
            if let (Some(lo), Some(hi)) = (self.low, self.high) {
                let return_commands = if self.chip1 < self.chip2 {
                    if self.chip1 == Some(17) && self.chip2 == Some(61) {
                        panic!("The bot you are looking for is {}", self.key);
                    }

                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                    ]
                } else {
                    if self.chip2 == Some(17) && self.chip1 == Some(61) {
                        panic!("The bot you are looking for is {}", self.key);
                    }

                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                    ]
                };
                self.chip1 = None;
                self.chip2 = None;
                self.low = None;
                self.high = None;
                self.low_bot_or_output = None;
                self.high_bot_or_output = None;
                return_commands
            } else {
                vec![]
            }
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn receive_command(&mut self, low_bot_or_output: &str, low: usize,
                                      high_bot_or_output: &str, high: usize) {
        self.low = Some(low);
        if low_bot_or_output == "bot" {
            self.low_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.low_bot_or_output = Some(BotOrOutput::Output);
        }
        self.high = Some(high);
        if high_bot_or_output == "bot" {
            self.high_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.high_bot_or_output = Some(BotOrOutput::Output);
        }
    }
}

pub struct BotRouter {
    bots: HashMap<usize, Bot>,
    output_bins: HashMap<usize, Vec<usize>>,
}

impl BotRouter {
    pub fn exec_command(&mut self, input: &str) {
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        let return_commands = self.bots
                                  .entry(bot_key)
                                  .or_insert(Bot::new(bot_key))
                                  .receive_chip(value);
        for &(key, bot_or_output, chip_value) in return_commands.iter() {
            match bot_or_output {
                BotOrOutput::Bot => self.value_to_bot(key, chip_value),
                BotOrOutput::Output => self.value_to_output(key, chip_value),
            }
        }
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        self.output_bins.entry(output_key).or_insert(Vec::new()).push(value);
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                          low_bot_or_output: &str, low_key: usize,
                          high_bot_or_output: &str, high_key: usize) {
        let bot = self.bots.entry(bot_key).or_insert(Bot::new(bot_key));
        bot.receive_command(
            low_bot_or_output,
            low_key,
            high_bot_or_output,
            high_key
        );
    }
}

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

    #[test]
    fn new_bot_does_not_have_two_chips() {
        let bot = Bot::new(0);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_a_chip_still_not_two() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_two_chips() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        bot.receive_chip(4);
        assert!(bot.has_two_chips());
    }

    #[test]
    fn router_can_give_values() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            Some(5)
        );
    }

    #[test]
    fn router_can_give_commands_that_get_stored() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        assert_eq!(
            br.bots.get(&2).unwrap().low,
            Some(1)
        );
        assert_eq!(
            br.bots.get(&2).unwrap().high,
            Some(0)
        );
    }

    #[test]
    fn router_adds_two_values_so_commands_get_executed() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            None
        );
        assert_eq!(
            br.bots.get(&2).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&1).unwrap().chip1,
            Some(2)
        );
        assert_eq!(
            br.bots.get(&1).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&0).unwrap().chip1,
            Some(5)
        );
        assert_eq!(
            br.bots.get(&0).unwrap().chip2,
            None
        );
    }

    #[test]
    fn test_sample() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.output_bins.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.output_bins.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.output_bins.get(&2),
            Some(&vec![3])
        )
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(test, deny(missing_docs, warnings))]
#![forbid(unused_variables)]

/// An owned sequence of Unicode scalar values, equivalent to `String`.
pub struct UString(Vec<char>);

/// A Unicode string slice, equivalent to `&str`.
pub struct UStr<'a>(&'a [char]);
<commit_msg>Fix UStr implementation<commit_after>#![cfg_attr(test, deny(missing_docs, warnings))]
#![forbid(unused_variables)]

/// An owned sequence of Unicode scalar values, equivalent to `String`.
pub struct UString(Vec<char>);

/// A Unicode string slice, equivalent to `str`.
pub struct UStr([char]);
<|endoftext|>


<commit_before>include!(concat!(env!("OUT_DIR"), "/perl_defs.rs"));
<commit_msg>Add a test.<commit_after>include!(concat!(env!("OUT_DIR"), "/perl_defs.rs"));

#[test]
fn test_svttype() {
    use consts::*;
    /* These relations are documented in perlguts */
    assert!(consts::SVt_PVIV < SVt_PVAV);
    assert!(consts::SVt_PVMG < SVt_PVAV);
}
<|endoftext|>