<commit_before>extern crate blas;
#[macro_use(s)]
extern crate ndarray;

use ndarray::{Array1,Array2,Data,DataMut,Ix1,Ix2,LinalgScalar};
use ndarray::prelude::*;

pub trait GramSchmidt: Sized + Clone + Default {
    fn compute_into<S1,S2,S3>(a: &ArrayBase<S1, Ix2>, orth: &mut ArrayBase<S2, Ix2>, norm: &mut ArrayBase<S3, Ix1>)
        where S1: Data<Elem = Self>,
              S2: DataMut<Elem = Self>,
              S3: DataMut<Elem = Self>;

    fn compute<S>(a: &ArrayBase<S, Ix2>) -> (Array<Self, Ix2>, Array<Self, Ix1>)
        where S: Data<Elem = Self>
    {
        let mut o = a.to_owned();
        let mut n = Array1::default(a.dim().1);

        Self::compute_into(a, &mut o, &mut n);
        (o, n)
    }
}

pub trait ModifiedGramSchmidt: Sized + Clone + Default {
    fn compute_into<S1,S2,S3>(a: &ArrayBase<S1, Ix2>, orth: &mut ArrayBase<S2, Ix2>, norm: &mut ArrayBase<S3, Ix1>)
        where S1: Data<Elem = Self>,
              S2: DataMut<Elem = Self>,
              S3: DataMut<Elem = Self>;

    fn compute<S>(a: &ArrayBase<S, Ix2>) -> (Array<Self, Ix2>, Array<Self, Ix1>)
        where S: Data<Elem = Self>
    {
        let mut o = a.to_owned();
        let mut n = Array1::default(a.dim().1);

        Self::compute_into(a, &mut o, &mut n);
        (o, n)
    }
}

impl GramSchmidt for f64 {
    fn compute_into<S1,S2,S3>(a: &ArrayBase<S1, Ix2>, orth: &mut ArrayBase<S2, Ix2>, norm: &mut ArrayBase<S3, Ix1>)
        where S1: Data<Elem = Self>,
              S2: DataMut<Elem = Self>,
              S3: DataMut<Elem = Self>
    {
        let n_rows = orth.shape()[0];

        orth.row_mut(0).assign(&a.row(0));

        for i in 0..n_rows {
            let (done, mut todo) = orth.view_mut().split_at(Axis(0), i);
            let ref_vec = a.row(i);

            let mut v = todo.row_mut(0);

            for w in done.inner_iter() {
                let projection = project(&ref_vec, &w);
                v.zip_mut_with(&w, |ev,ew| { *ev -= projection * ew; });
            }

            norm[i] = normalization(v.as_slice().unwrap());
            v /= norm[i];
        }
    }
}

impl ModifiedGramSchmidt for f64 {
    fn compute_into<S1,S2,S3>(a: &ArrayBase<S1, Ix2>, orth: &mut ArrayBase<S2, Ix2>, norm: &mut ArrayBase<S3, Ix1>)
        where S1: Data<Elem = Self>,
              S2: DataMut<Elem = Self>,
              S3: DataMut<Elem = Self>
    {
        let n_rows = orth.shape()[0];

        orth.assign(&a);

        for i in 0..n_rows {
            let (done, mut todo) = orth.view_mut().split_at(Axis(0), i);

            let mut v = todo.row_mut(0);

            for w in done.inner_iter() {
                let projection = project(&v, &w);
                v.zip_mut_with(&w, |ev,ew| { *ev -= projection * ew; });
            }

            norm[i] = normalization(v.as_slice().unwrap());
            v /= norm[i];
        }
    }
}

pub fn orthogonal<S>(a: &ArrayBase<S,Ix2>) -> bool
    where S: Data<Elem=f64>
{
    let b = a.dot(&a.t());
    b.all_close(&Array2::eye(b.shape()[0]), 1e-14)
}

pub fn normalization(v: &[f64]) -> f64 {
    blas::c::dnrm2(v.len() as i32, v, 1)
}

pub fn project<A,S1,S2>(vector: &ArrayBase<S1,Ix1>, onto: &ArrayBase<S2,Ix1>) -> A
    where S1: Data<Elem=A>,
          S2: Data<Elem=A>,
          A: LinalgScalar
{
    vector.dot(onto) / onto.dot(onto)
}

#[cfg(test)]
mod tests {
    use ndarray::{arr1,arr2,Array1,Array2};
    use super::{GramSchmidt,ModifiedGramSchmidt};

    #[test]
    fn normalization() {
        let a = &[1.0,2.0,3.0,4.0,5.0];

        let n_manual = f64::sqrt(1.0 + 4.0 + 9.0 + 16.0 + 25.0);
        let n_calculated = super::normalization(a);

        println!("Norm, manual: {}", n_manual);
        println!("Norm, function: {}", n_calculated);

        assert_eq!(n_manual, n_calculated);
    }

    #[test]
    fn projection() {
        let a = arr1(&[1.0,2.0,3.0,4.0,5.0]);
        let p = super::project(&a,&a);

        println!("Projection: {}", p);
        assert_eq!(p, 1.0);
    }

    #[test]
    fn gram_schmidt() {
        let a = arr2(&[[1.0, 0.0, 0.0, 0.0],
                       [0.0, 1.0, 0.0, 0.0],
                       [0.0, 0.0, 1.0, 0.0],
                       [0.0, 0.0, 0.0, 1.0]]);

        let (a_orth, a_norm) = GramSchmidt::compute(&a);

        let b = arr2(&[[2.0, 0.5, 0.0, 0.0],
                       [0.0, 0.3, 0.0, 0.0],
                       [0.0, 1.0, 0.7, 0.0],
                       [0.0, 0.0, 0.0, 3.0]]);

        let (b_orth, b_norm) = GramSchmidt::compute(&b);

        println!("{:?}", b_orth);
        println!("{:?}", b_norm);

        assert!(super::orthogonal(&a_orth));
        assert!(a_norm.all_close(&Array1::from_elem(4, 1.0), 1e-16));

        assert!(super::orthogonal(&b_orth));
        assert!(b_norm.all_close(&arr1(&[2.0615528128088303, 0.2910427500435996, 0.7, 3.0]), 1e-16));
    }

    #[test]
    fn modified_gram_schmidt() {
        let a = arr2(&[[1.0, 0.0, 0.0, 0.0],
                       [0.0, 1.0, 0.0, 0.0],
                       [0.0, 0.0, 1.0, 0.0],
                       [0.0, 0.0, 0.0, 1.0]]);

        let (a_orth, a_norm) = ModifiedGramSchmidt::compute(&a);

        let b = arr2(&[[2.0, 0.5, 0.0, 0.0],
                       [0.0, 0.3, 0.0, 0.0],
                       [0.0, 1.0, 0.7, 0.0],
                       [0.0, 0.0, 0.0, 3.0]]);

        let (b_orth, b_norm) = ModifiedGramSchmidt::compute(&b);

        assert!(super::orthogonal(&a_orth));
        assert!(a_norm.all_close(&Array1::from_elem(4, 1.0), 1e-16));

        assert!(super::orthogonal(&b_orth));
        assert!(b_norm.all_close(&arr1(&[2.0615528128088303, 0.2910427500435996, 0.7, 3.0]), 1e-16));
    }

    #[test]
    fn modified_gram_schmidt_into() {
        let a = arr2(&[[1.0, 0.0, 0.0, 0.0],
                       [0.0, 1.0, 0.0, 0.0],
                       [0.0, 0.0, 1.0, 0.0],
                       [0.0, 0.0, 0.0, 1.0]]);

        let mut a_o = Array2::default((4,4));
        let mut a_n = Array1::default(4);

        let b = arr2(&[[2.0, 0.5, 0.0, 0.0],
                       [0.0, 0.3, 0.0, 0.0],
                       [0.0, 1.0, 0.7, 0.0],
                       [0.0, 0.0, 0.0, 3.0]]);

        let mut b_o = Array2::default((4,4));
        let mut b_n = Array1::default(4);

        let c = arr2(&[[-4.079764601288893, 4.831491499921403, -2.9560001027996132, -0.02239325297550033, -0.2672544204261703, -0.07718850306444144],
                       [1.2917480323712418, 0.030479388871438983, 0.604549448561548, 0.013409783846041783, 0.037439247530467186, 0.03153579130305008],
                       [-47.584641085515464, 5.501371846864031, 41.39822251681311, -33.69079455346558, 43.13388644338738, 68.7695035292409],
                       [2.5268795799504997, 25.418530275775225, 33.473125141381374, 77.3391516894698, -44.091836957161426, 45.10932299622911],
                       [-20.383209804181938, -19.163209972229616, 0.09795435026201423, -53.296988576627484, -88.482334971421, 16.757575995918756],
                       [62.270964677492124, -75.82678462673792, -0.6889077708993588, 2.2569901796884064, 9.21906803233946, 44.891962279862234]]);

        let mut c_o = Array2::default((6,6));
        let mut c_n = Array1::default(6);

        ModifiedGramSchmidt::compute_into(&a, &mut a_o, &mut a_n);
        ModifiedGramSchmidt::compute_into(&b, &mut b_o, &mut b_n);
        ModifiedGramSchmidt::compute_into(&c, &mut c_o, &mut c_n);

        assert!(super::orthogonal(&a_o));
        assert!(a_n.all_close(&Array1::from_elem(4, 1.0), 1e-16));

        assert!(super::orthogonal(&b_o));
        assert!(b_n.all_close(&arr1(&[2.0615528128088303, 0.2910427500435996, 0.7, 3.0]), 1e-16));

        assert!(super::orthogonal(&c_o));
    }
}
<commit_msg>Add convenience functions<commit_after>extern crate blas;
#[macro_use(s)]
extern crate ndarray;

use ndarray::{Array1,Array2,Data,DataMut,Ix1,Ix2,LinalgScalar};
use ndarray::prelude::*;

pub trait GramSchmidt: Sized + Clone + Default {
    fn compute_into<S1,S2,S3>(a: &ArrayBase<S1, Ix2>, orth: &mut ArrayBase<S2, Ix2>, norm: &mut ArrayBase<S3, Ix1>)
        where S1: Data<Elem = Self>,
              S2: DataMut<Elem = Self>,
              S3: DataMut<Elem = Self>;

    fn compute<S>(a: &ArrayBase<S, Ix2>) -> (Array<Self, Ix2>, Array<Self, Ix1>)
        where S: Data<Elem = Self>
    {
        let mut o = a.to_owned();
        let mut n = Array1::default(a.dim().1);

        Self::compute_into(a, &mut o, &mut n);
        (o, n)
    }
}

pub trait ModifiedGramSchmidt: Sized + Clone + Default {
    fn compute_inplace<S1,S2>(orth: &mut ArrayBase<S1, Ix2>, norm: &mut ArrayBase<S2, Ix1>)
        where S1: DataMut<Elem = Self>,
              S2: DataMut<Elem = Self>;

    fn compute_inplace_no_norm<S1>(a: &mut ArrayBase<S1, Ix2>)
        where S1: DataMut<Elem = Self>;

    fn compute_into<S1,S2,S3>(a: &ArrayBase<S1, Ix2>, orth: &mut ArrayBase<S2, Ix2>, norm: &mut ArrayBase<S3, Ix1>)
        where S1: Data<Elem = Self>,
              S2: DataMut<Elem = Self>,
              S3: DataMut<Elem = Self>,
    {
        orth.assign(&a);
        Self::compute_inplace(orth, norm);
    }

    fn compute<S>(a: &ArrayBase<S, Ix2>) -> (Array<Self, Ix2>, Array<Self, Ix1>)
        where S: Data<Elem = Self>
    {
        let mut o = a.to_owned();
        let mut n = Array1::default(a.dim().1);

        Self::compute_into(a, &mut o, &mut n);
        (o, n)
    }
}

impl GramSchmidt for f64 {
    fn compute_into<S1,S2,S3>(a: &ArrayBase<S1, Ix2>, orth: &mut ArrayBase<S2, Ix2>, norm: &mut ArrayBase<S3, Ix1>)
        where S1: Data<Elem = Self>,
              S2: DataMut<Elem = Self>,
              S3: DataMut<Elem = Self>
    {
        let n_rows = orth.shape()[0];

        orth.row_mut(0).assign(&a.row(0));

        for i in 0..n_rows {
            let (done, mut todo) = orth.view_mut().split_at(Axis(0), i);
            let ref_vec = a.row(i);

            let mut v = todo.row_mut(0);

            for w in done.inner_iter() {
                let projection_factor = project(&ref_vec, &w);
                v.zip_mut_with(&w, |ev,ew| { *ev -= projection_factor * ew; });
            }

            norm[i] = normalization(v.as_slice().unwrap());
            v /= norm[i];
        }
    }
}

impl ModifiedGramSchmidt for f64 {
    fn compute_inplace<S1,S2>(orth: &mut ArrayBase<S1, Ix2>, norm: &mut ArrayBase<S2, Ix1>)
        where S1: DataMut<Elem = Self>,
              S2: DataMut<Elem = Self>,
    {
        let n_rows = orth.shape()[0];

        for i in 0..n_rows {
            let (done, mut todo) = orth.view_mut().split_at(Axis(0), i);

            let mut v = todo.row_mut(0);

            for w in done.inner_iter() {
                // w is already normalized
                // let projection_factor = project(&v, &w);
                let projection_factor = v.dot(&w);
                v.zip_mut_with(&w, |ev,ew| { *ev -= projection_factor * ew; });
            }

            norm[i] = normalization(v.as_slice().unwrap());
            v /= norm[i];
        }
    }

    fn compute_inplace_no_norm<S1>(orth: &mut ArrayBase<S1, Ix2>)
        where S1: DataMut<Elem = Self>,
    {
        let n_rows = orth.shape()[0];

        for i in 0..n_rows {
            let (done, mut todo) = orth.view_mut().split_at(Axis(0), i);

            let mut v = todo.row_mut(0);

            for w in done.inner_iter() {
                // let projection_factor = project(&v, &w);
                let projection_factor = v.dot(&w);
                v.zip_mut_with(&w, |ev,ew| { *ev -= projection_factor * ew; });
            }

            v /= normalization(v.as_slice().unwrap());
        }
    }
}

pub fn orthogonal<S>(a: &ArrayBase<S,Ix2>) -> bool
    where S: Data<Elem=f64>
{
    let b = a.dot(&a.t());
    b.all_close(&Array2::eye(b.shape()[0]), 1e-14)
}

pub fn normalization(v: &[f64]) -> f64 {
    blas::c::dnrm2(v.len() as i32, v, 1)
}

pub fn project<A,S1,S2>(vector: &ArrayBase<S1,Ix1>, onto: &ArrayBase<S2,Ix1>) -> A
    where S1: Data<Elem=A>,
          S2: Data<Elem=A>,
          A: LinalgScalar
{
    vector.dot(onto) / onto.dot(onto)
}

#[cfg(test)]
mod tests {
    use ndarray::{arr1,arr2,Array1,Array2};
    use super::{GramSchmidt,ModifiedGramSchmidt};

    #[test]
    fn normalization() {
        let a = &[1.0,2.0,3.0,4.0,5.0];

        let n_manual = f64::sqrt(1.0 + 4.0 + 9.0 + 16.0 + 25.0);
        let n_calculated = super::normalization(a);

        println!("Norm, manual: {}", n_manual);
        println!("Norm, function: {}", n_calculated);

        assert_eq!(n_manual, n_calculated);
    }

    #[test]
    fn projection() {
        let a = arr1(&[1.0,2.0,3.0,4.0,5.0]);
        let p = super::project(&a,&a);

        println!("Projection: {}", p);
        assert_eq!(p, 1.0);
    }

    #[test]
    fn gram_schmidt() {
        let a = arr2(&[[1.0, 0.0, 0.0, 0.0],
                       [0.0, 1.0, 0.0, 0.0],
                       [0.0, 0.0, 1.0, 0.0],
                       [0.0, 0.0, 0.0, 1.0]]);

        let (a_orth, a_norm) = GramSchmidt::compute(&a);

        let b = arr2(&[[2.0, 0.5, 0.0, 0.0],
                       [0.0, 0.3, 0.0, 0.0],
                       [0.0, 1.0, 0.7, 0.0],
                       [0.0, 0.0, 0.0, 3.0]]);

        let (b_orth, b_norm) = GramSchmidt::compute(&b);

        println!("{:?}", b_orth);
        println!("{:?}", b_norm);

        assert!(super::orthogonal(&a_orth));
        assert!(a_norm.all_close(&Array1::from_elem(4, 1.0), 1e-16));

        assert!(super::orthogonal(&b_orth));
        assert!(b_norm.all_close(&arr1(&[2.0615528128088303, 0.2910427500435996, 0.7, 3.0]), 1e-16));
    }

    #[test]
    fn modified_gram_schmidt() {
        let a = arr2(&[[1.0, 0.0, 0.0, 0.0],
                       [0.0, 1.0, 0.0, 0.0],
                       [0.0, 0.0, 1.0, 0.0],
                       [0.0, 0.0, 0.0, 1.0]]);

        let (a_orth, a_norm) = ModifiedGramSchmidt::compute(&a);

        let b = arr2(&[[2.0, 0.5, 0.0, 0.0],
                       [0.0, 0.3, 0.0, 0.0],
                       [0.0, 1.0, 0.7, 0.0],
                       [0.0, 0.0, 0.0, 3.0]]);

        let (b_orth, b_norm) = ModifiedGramSchmidt::compute(&b);

        assert!(super::orthogonal(&a_orth));
        assert!(a_norm.all_close(&Array1::from_elem(4, 1.0), 1e-16));

        assert!(super::orthogonal(&b_orth));
        assert!(b_norm.all_close(&arr1(&[2.0615528128088303, 0.2910427500435996, 0.7, 3.0]), 1e-16));
    }

    #[test]
    fn modified_gram_schmidt_into() {
        let a = arr2(&[[1.0, 0.0, 0.0, 0.0],
                       [0.0, 1.0, 0.0, 0.0],
                       [0.0, 0.0, 1.0, 0.0],
                       [0.0, 0.0, 0.0, 1.0]]);

        let mut a_o = Array2::default((4,4));
        let mut a_n = Array1::default(4);

        let b = arr2(&[[2.0, 0.5, 0.0, 0.0],
                       [0.0, 0.3, 0.0, 0.0],
                       [0.0, 1.0, 0.7, 0.0],
                       [0.0, 0.0, 0.0, 3.0]]);

        let mut b_o = Array2::default((4,4));
        let mut b_n = Array1::default(4);

        let c = arr2(&[[-4.079764601288893, 4.831491499921403, -2.9560001027996132, -0.02239325297550033, -0.2672544204261703, -0.07718850306444144],
                       [1.2917480323712418, 0.030479388871438983, 0.604549448561548, 0.013409783846041783, 0.037439247530467186, 0.03153579130305008],
                       [-47.584641085515464, 5.501371846864031, 41.39822251681311, -33.69079455346558, 43.13388644338738, 68.7695035292409],
                       [2.5268795799504997, 25.418530275775225, 33.473125141381374, 77.3391516894698, -44.091836957161426, 45.10932299622911],
                       [-20.383209804181938, -19.163209972229616, 0.09795435026201423, -53.296988576627484, -88.482334971421, 16.757575995918756],
                       [62.270964677492124, -75.82678462673792, -0.6889077708993588, 2.2569901796884064, 9.21906803233946, 44.891962279862234]]);

        let mut c_o = Array2::default((6,6));
        let mut c_n = Array1::default(6);

        ModifiedGramSchmidt::compute_into(&a, &mut a_o, &mut a_n);
        ModifiedGramSchmidt::compute_into(&b, &mut b_o, &mut b_n);
        ModifiedGramSchmidt::compute_into(&c, &mut c_o, &mut c_n);

        assert!(super::orthogonal(&a_o));
        assert!(a_n.all_close(&Array1::from_elem(4, 1.0), 1e-16));

        assert!(super::orthogonal(&b_o));
        assert!(b_n.all_close(&arr1(&[2.0615528128088303, 0.2910427500435996, 0.7, 3.0]), 1e-16));

        assert!(super::orthogonal(&c_o));
    }
}
<|endoftext|>


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

//! Operations on ASCII strings and characters

#![feature(macro_rules, globs, default_type_params)]
#![unstable = "unsure about placement and naming"]
#![allow(deprecated)]

//use std::kinds::Sized;
use std::fmt;
use std::mem;
use std::borrow::BorrowFrom;
use std::ascii::AsciiExt;

/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
#[deriving(Clone, PartialEq, PartialOrd, Ord, Eq, Hash, Copy)]
pub struct Ascii { chr: u8 }

impl Ascii {
    /// Converts an ascii character into a `u8`.
    #[inline]
    #[unstable = "recently renamed"]
    pub fn as_byte(&self) -> u8 {
        self.chr
    }

    /// Converts an ascii character into a `char`.
    #[inline]
    #[unstable = "recently renamed"]
    pub fn as_char(&self) -> char {
        self.chr as char
    }

    /// Convert to lowercase.
    #[inline]
    #[stable]
    pub fn to_lowercase(&self) -> Ascii {
        Ascii{chr: self.chr.to_ascii_lowercase()}
    }

    /// Convert to uppercase.
    #[inline]
    #[stable]
    pub fn to_uppercase(&self) -> Ascii {
        Ascii{chr: self.chr.to_ascii_uppercase()}
    }

    // the following methods are like ctype, and the implementation is inspired by musl

    /// Check if the character is a letter (a-z, A-Z)
    #[inline]
    #[stable]
    pub fn is_alphabetic(&self) -> bool {
        (self.chr >= 0x41 && self.chr <= 0x5A) || (self.chr >= 0x61 && self.chr <= 0x7A)
    }

    /// Check if the character is a number (0-9)
    #[inline]
    #[unstable = "may be renamed"]
    pub fn is_digit(&self) -> bool {
        self.chr >= 0x30 && self.chr <= 0x39
    }

    /// Check if the character is a letter or number
    #[inline]
    #[stable]
    pub fn is_alphanumeric(&self) -> bool {
        self.is_alphabetic() || self.is_digit()
    }

    /// Check if the character is a space or horizontal tab
    #[inline]
    #[experimental = "likely to be removed"]
    pub fn is_blank(&self) -> bool {
        self.chr == b' ' || self.chr == b'\t'
    }

    /// Check if the character is a control character
    #[inline]
    #[stable]
    pub fn is_control(&self) -> bool {
        self.chr < 0x20 || self.chr == 0x7F
    }

    /// Checks if the character is printable (except space)
    #[inline]
    #[experimental = "unsure about naming, or whether this is needed"]
    pub fn is_graph(&self) -> bool {
        (self.chr - 0x21) < 0x5E
    }

    /// Checks if the character is printable (including space)
    #[inline]
    #[unstable = "unsure about naming"]
    pub fn is_print(&self) -> bool {
        (self.chr - 0x20) < 0x5F
    }

    /// Checks if the character is alphabetic and lowercase
    #[inline]
    #[stable]
    pub fn is_lowercase(&self) -> bool {
        (self.chr - b'a') < 26
    }

    /// Checks if the character is alphabetic and uppercase
    #[inline]
    #[stable]
    pub fn is_uppercase(&self) -> bool {
        (self.chr - b'A') < 26
    }

    /// Checks if the character is punctuation
    #[inline]
    #[stable]
    pub fn is_punctuation(&self) -> bool {
        self.is_graph() && !self.is_alphanumeric()
    }

    /// Checks if the character is a valid hex digit
    #[inline]
    #[stable]
    pub fn is_hex(&self) -> bool {
        self.is_digit() || ((self.chr | 32u8) - b'a') < 6
    }
}

impl<'a> fmt::Show for Ascii {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (self.chr as char).fmt(f)
    }
}

/// Trait for converting into an ascii type.
#[experimental = "may be replaced by generic conversion traits"]
pub trait AsciiCast<T, U = Self> for Sized?: AsciiExt<U> {
    /// Convert to an ascii type, return None on non-ASCII input.
    #[inline]
    fn to_ascii(&self) -> Option<T> {
        if self.is_ascii() {
            Some(unsafe { self.to_ascii_nocheck() })
        } else {
            None
        }
    }

    /// Convert to an ascii type, not doing any range asserts
    unsafe fn to_ascii_nocheck(&self) -> T;
}

#[experimental = "may be replaced by generic conversion traits"]
impl<'a> AsciiCast<&'a[Ascii], Vec<u8>> for [u8] {
    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] {
        mem::transmute(self)
    }
}

#[experimental = "may be replaced by generic conversion traits"]
impl<'a> AsciiCast<&'a [Ascii], String> for str {
    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] {
        mem::transmute(self)
    }
}

#[experimental = "may be replaced by generic conversion traits"]
impl AsciiCast<Ascii> for u8 {
    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self }
    }
}

#[experimental = "may be replaced by generic conversion traits"]
impl AsciiCast<Ascii> for char {
    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self as u8 }
    }
}

/// Trait for copyless casting to an ascii vector.
#[experimental = "may be replaced by generic conversion traits"]
pub trait OwnedAsciiCast<Sized? T, U = Self>
where T: BorrowFrom<Self> + AsciiExt<U> {
    /// Take ownership and cast to an ascii vector. Return None on non-ASCII input.
    #[inline]
    fn into_ascii(self) -> Option<Vec<Ascii>> {
        if {
            let borrowed: &T = BorrowFrom::borrow_from(&self);
            borrowed.is_ascii()
        } {
            Some(unsafe { self.into_ascii_nocheck() })
        } else {
            None
        }
    }

    /// Take ownership and cast to an ascii vector.
    /// Does not perform validation checks.
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
}

#[experimental = "may be replaced by generic conversion traits"]
impl OwnedAsciiCast<str> for String {
    #[inline]
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
        self.into_bytes().into_ascii_nocheck()
    }
}

#[experimental = "may be replaced by generic conversion traits"]
impl OwnedAsciiCast<[u8]> for Vec<u8> {
    #[inline]
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
        let v = Vec::from_raw_parts(self.as_ptr() as *mut Ascii,
                                    self.len(),
                                    self.capacity());

        // We forget `self` to avoid freeing it at the end of the scope
        // Otherwise, the returned `Vec` would point to freed memory
        mem::forget(self);
        v
    }
}

/// Trait for converting an ascii type to a string. Needed to convert
/// `&[Ascii]` to `&str`.
#[experimental = "may be replaced by generic conversion traits"]
pub trait AsciiStr for Sized? {
    /// Convert to a string.
    fn as_str<'a>(&'a self) -> &'a str;

    /// Convert to bytes.
    fn as_bytes<'a>(&'a self) -> &'a [u8];
}

#[experimental = "may be replaced by generic conversion traits"]
impl AsciiStr for [Ascii] {
    #[inline]
    fn as_str<'a>(&'a self) -> &'a str {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn as_bytes<'a>(&'a self) -> &'a [u8] {
        unsafe { mem::transmute(self) }
    }
}

impl IntoString for Vec<Ascii> {
    #[inline]
    fn into_string(self) -> String {
        unsafe { String::from_utf8_unchecked(self.into_bytes()) }
    }
}

/// Trait to convert to an owned byte vector by consuming self
#[experimental = "may be replaced by generic conversion traits"]
pub trait IntoBytes {
    /// Converts to an owned byte vector by consuming self
    fn into_bytes(self) -> Vec<u8>;
}

#[experimental = "may be replaced by generic conversion traits"]
impl IntoBytes for Vec<Ascii> {
    fn into_bytes(self) -> Vec<u8> {
        unsafe {
            let v = Vec::from_raw_parts(self.as_ptr() as *mut u8,
                                        self.len(),
                                        self.capacity());

            // We forget `self` to avoid freeing it at the end of the scope
            // Otherwise, the returned `Vec` would point to freed memory
            mem::forget(self);
            v
        }
    }
}

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

    macro_rules! v2ascii (
        ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
        (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
    )

    macro_rules! vec2ascii (
        ($($e:expr),*) => ([$(Ascii{chr:$e}),*].to_vec());
    )

    #[test]
    fn test_ascii() {
        assert_eq!(65u8.to_ascii().unwrap().as_byte(), 65u8);
        assert_eq!(65u8.to_ascii().unwrap().as_char(), 'A');
        assert_eq!('A'.to_ascii().unwrap().as_char(), 'A');
        assert_eq!('A'.to_ascii().unwrap().as_byte(), 65u8);

        assert!('0'.to_ascii().unwrap().is_digit());
        assert!('9'.to_ascii().unwrap().is_digit());
        assert!(!'/'.to_ascii().unwrap().is_digit());
        assert!(!':'.to_ascii().unwrap().is_digit());

        assert!((0x1fu8).to_ascii().unwrap().is_control());
        assert!(!' '.to_ascii().unwrap().is_control());
        assert!((0x7fu8).to_ascii().unwrap().is_control());
    }

    #[test]
    fn test_ascii_vec() {
        let test = &[40u8, 32u8, 59u8];
        let b: &[_] = v2ascii!([40, 32, 59]);
        assert_eq!(test.to_ascii().unwrap(), b);
        assert_eq!("( ;".to_ascii().unwrap(), b);
        let v = vec![40u8, 32u8, 59u8];
        assert_eq!(v.as_slice().to_ascii().unwrap(), b);
        assert_eq!("( ;".to_string().as_slice().to_ascii().unwrap(), b);
    }

    #[test]
    fn test_ascii_as_str() {
        let v = v2ascii!([40, 32, 59]);
        assert_eq!(v.as_str(), "( ;");
    }

    #[test]
    fn test_ascii_as_bytes() {
        let v = v2ascii!([40, 32, 59]);
        assert_eq!(v.as_bytes(), b"( ;");
    }

    #[test]
    fn test_ascii_into_string() {
        assert_eq!(vec2ascii![40, 32, 59].into_string(), "( ;".to_string());
        assert_eq!(vec2ascii!(40, 32, 59).into_string(), "( ;".to_string());
    }

    #[test]
    fn test_ascii_to_bytes() {
        assert_eq!(vec2ascii![40, 32, 59].into_bytes(), vec![40u8, 32u8, 59u8]);
    }

    #[test]
    fn test_opt() {
        assert_eq!(65u8.to_ascii(), Some(Ascii { chr: 65u8 }));
        assert_eq!(255u8.to_ascii(), None);

        assert_eq!('A'.to_ascii(), Some(Ascii { chr: 65u8 }));
        assert_eq!('λ'.to_ascii(), None);

        assert_eq!("zoä华".to_ascii(), None);

        let test1 = &[127u8, 128u8, 255u8];
        assert_eq!((test1).to_ascii(), None);

        let v = [40u8, 32u8, 59u8];
        let v2: &[_] = v2ascii!(&[40, 32, 59]);
        assert_eq!(v.to_ascii(), Some(v2));
        let v = [127u8, 128u8, 255u8];
        assert_eq!(v.to_ascii(), None);

        let v = "( ;";
        assert_eq!(v.to_ascii(), Some(v2));
        assert_eq!("zoä华".to_ascii(), None);

        assert_eq!((vec![40u8, 32u8, 59u8]).into_ascii(), Some(vec2ascii![40, 32, 59]));
        assert_eq!((vec![127u8, 128u8, 255u8]).into_ascii(), None);

        assert_eq!(("( ;".to_string()).into_ascii(), Some(vec2ascii![40, 32, 59]));
        assert_eq!(("zoä华".to_string()).into_ascii(), None);
    }

    #[test]
    fn test_to_string() {
        let s = Ascii{ chr: b't' }.to_string();
        assert_eq!(s, "t".to_string());
    }

    #[test]
    fn test_show() {
        let c = Ascii { chr: b't' };
        assert_eq!(format!("{}", c), "t".to_string());
    }
}
<commit_msg>Have to_ascii and into_ascii return Result rather than Option.<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// ignore-lexer-test FIXME #15679

//! Operations on ASCII strings and characters

#![feature(macro_rules, globs, default_type_params)]
#![unstable = "unsure about placement and naming"]
#![allow(deprecated)]

//use std::kinds::Sized;
use std::fmt;
use std::mem;
use std::borrow::BorrowFrom;
use std::ascii::AsciiExt;

/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
#[deriving(Clone, PartialEq, PartialOrd, Ord, Eq, Hash, Copy)]
pub struct Ascii { chr: u8 }

impl Ascii {
    /// Converts an ascii character into a `u8`.
    #[inline]
    #[unstable = "recently renamed"]
    pub fn as_byte(&self) -> u8 {
        self.chr
    }

    /// Converts an ascii character into a `char`.
    #[inline]
    #[unstable = "recently renamed"]
    pub fn as_char(&self) -> char {
        self.chr as char
    }

    /// Convert to lowercase.
    #[inline]
    #[stable]
    pub fn to_lowercase(&self) -> Ascii {
        Ascii{chr: self.chr.to_ascii_lowercase()}
    }

    /// Convert to uppercase.
    #[inline]
    #[stable]
    pub fn to_uppercase(&self) -> Ascii {
        Ascii{chr: self.chr.to_ascii_uppercase()}
    }

    // the following methods are like ctype, and the implementation is inspired by musl

    /// Check if the character is a letter (a-z, A-Z)
    #[inline]
    #[stable]
    pub fn is_alphabetic(&self) -> bool {
        (self.chr >= 0x41 && self.chr <= 0x5A) || (self.chr >= 0x61 && self.chr <= 0x7A)
    }

    /// Check if the character is a number (0-9)
    #[inline]
    #[unstable = "may be renamed"]
    pub fn is_digit(&self) -> bool {
        self.chr >= 0x30 && self.chr <= 0x39
    }

    /// Check if the character is a letter or number
    #[inline]
    #[stable]
    pub fn is_alphanumeric(&self) -> bool {
        self.is_alphabetic() || self.is_digit()
    }

    /// Check if the character is a space or horizontal tab
    #[inline]
    #[experimental = "likely to be removed"]
    pub fn is_blank(&self) -> bool {
        self.chr == b' ' || self.chr == b'\t'
    }

    /// Check if the character is a control character
    #[inline]
    #[stable]
    pub fn is_control(&self) -> bool {
        self.chr < 0x20 || self.chr == 0x7F
    }

    /// Checks if the character is printable (except space)
    #[inline]
    #[experimental = "unsure about naming, or whether this is needed"]
    pub fn is_graph(&self) -> bool {
        (self.chr - 0x21) < 0x5E
    }

    /// Checks if the character is printable (including space)
    #[inline]
    #[unstable = "unsure about naming"]
    pub fn is_print(&self) -> bool {
        (self.chr - 0x20) < 0x5F
    }

    /// Checks if the character is alphabetic and lowercase
    #[inline]
    #[stable]
    pub fn is_lowercase(&self) -> bool {
        (self.chr - b'a') < 26
    }

    /// Checks if the character is alphabetic and uppercase
    #[inline]
    #[stable]
    pub fn is_uppercase(&self) -> bool {
        (self.chr - b'A') < 26
    }

    /// Checks if the character is punctuation
    #[inline]
    #[stable]
    pub fn is_punctuation(&self) -> bool {
        self.is_graph() && !self.is_alphanumeric()
    }

    /// Checks if the character is a valid hex digit
    #[inline]
    #[stable]
    pub fn is_hex(&self) -> bool {
        self.is_digit() || ((self.chr | 32u8) - b'a') < 6
    }
}

impl<'a> fmt::Show for Ascii {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (self.chr as char).fmt(f)
    }
}

/// Trait for converting into an ascii type.
#[experimental = "may be replaced by generic conversion traits"]
pub trait AsciiCast<T, U = Self> for Sized?: AsciiExt<U> {
    /// Convert to an ascii type, return Err(()) on non-ASCII input.
    #[inline]
    fn to_ascii(&self) -> Result<T, ()> {
        if self.is_ascii() {
            Ok(unsafe { self.to_ascii_nocheck() })
        } else {
            Err(())
        }
    }

    /// Convert to an ascii type, not doing any range asserts
    unsafe fn to_ascii_nocheck(&self) -> T;
}

#[experimental = "may be replaced by generic conversion traits"]
impl<'a> AsciiCast<&'a[Ascii], Vec<u8>> for [u8] {
    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] {
        mem::transmute(self)
    }
}

#[experimental = "may be replaced by generic conversion traits"]
impl<'a> AsciiCast<&'a [Ascii], String> for str {
    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] {
        mem::transmute(self)
    }
}

#[experimental = "may be replaced by generic conversion traits"]
impl AsciiCast<Ascii> for u8 {
    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self }
    }
}

#[experimental = "may be replaced by generic conversion traits"]
impl AsciiCast<Ascii> for char {
    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self as u8 }
    }
}

/// Trait for copyless casting to an ascii vector.
#[experimental = "may be replaced by generic conversion traits"]
pub trait OwnedAsciiCast<Sized? T, U = Self>
where T: BorrowFrom<Self> + AsciiExt<U> {
    /// Take ownership and cast to an ascii vector. Return Err(()) on non-ASCII input.
    #[inline]
    fn into_ascii(self) -> Result<Vec<Ascii>, Self> {
        if {
            let borrowed: &T = BorrowFrom::borrow_from(&self);
            borrowed.is_ascii()
        } {
            Ok(unsafe { self.into_ascii_nocheck() })
        } else {
            Err(self)
        }
    }

    /// Take ownership and cast to an ascii vector.
    /// Does not perform validation checks.
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
}

#[experimental = "may be replaced by generic conversion traits"]
impl OwnedAsciiCast<str> for String {
    #[inline]
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
        self.into_bytes().into_ascii_nocheck()
    }
}

#[experimental = "may be replaced by generic conversion traits"]
impl OwnedAsciiCast<[u8]> for Vec<u8> {
    #[inline]
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
        let v = Vec::from_raw_parts(self.as_ptr() as *mut Ascii,
                                    self.len(),
                                    self.capacity());

        // We forget `self` to avoid freeing it at the end of the scope
        // Otherwise, the returned `Vec` would point to freed memory
        mem::forget(self);
        v
    }
}

/// Trait for converting an ascii type to a string. Needed to convert
/// `&[Ascii]` to `&str`.
#[experimental = "may be replaced by generic conversion traits"]
pub trait AsciiStr for Sized? {
    /// Convert to a string.
    fn as_str<'a>(&'a self) -> &'a str;

    /// Convert to bytes.
    fn as_bytes<'a>(&'a self) -> &'a [u8];
}

#[experimental = "may be replaced by generic conversion traits"]
impl AsciiStr for [Ascii] {
    #[inline]
    fn as_str<'a>(&'a self) -> &'a str {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn as_bytes<'a>(&'a self) -> &'a [u8] {
        unsafe { mem::transmute(self) }
    }
}

impl IntoString for Vec<Ascii> {
    #[inline]
    fn into_string(self) -> String {
        unsafe { String::from_utf8_unchecked(self.into_bytes()) }
    }
}

/// Trait to convert to an owned byte vector by consuming self
#[experimental = "may be replaced by generic conversion traits"]
pub trait IntoBytes {
    /// Converts to an owned byte vector by consuming self
    fn into_bytes(self) -> Vec<u8>;
}

#[experimental = "may be replaced by generic conversion traits"]
impl IntoBytes for Vec<Ascii> {
    fn into_bytes(self) -> Vec<u8> {
        unsafe {
            let v = Vec::from_raw_parts(self.as_ptr() as *mut u8,
                                        self.len(),
                                        self.capacity());

            // We forget `self` to avoid freeing it at the end of the scope
            // Otherwise, the returned `Vec` would point to freed memory
            mem::forget(self);
            v
        }
    }
}

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

    macro_rules! v2ascii (
        ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
        (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
    )

    macro_rules! vec2ascii (
        ($($e:expr),*) => ([$(Ascii{chr:$e}),*].to_vec());
    )

    #[test]
    fn test_ascii() {
        assert_eq!(65u8.to_ascii().unwrap().as_byte(), 65u8);
        assert_eq!(65u8.to_ascii().unwrap().as_char(), 'A');
        assert_eq!('A'.to_ascii().unwrap().as_char(), 'A');
        assert_eq!('A'.to_ascii().unwrap().as_byte(), 65u8);

        assert!('0'.to_ascii().unwrap().is_digit());
        assert!('9'.to_ascii().unwrap().is_digit());
        assert!(!'/'.to_ascii().unwrap().is_digit());
        assert!(!':'.to_ascii().unwrap().is_digit());

        assert!(0x1f_u8.to_ascii().unwrap().is_control());
        assert!(!' '.to_ascii().unwrap().is_control());
        assert!(0x7f_u8.to_ascii().unwrap().is_control());
    }

    #[test]
    fn test_ascii_vec() {
        let test = &[40u8, 32u8, 59u8];
        let b: &[_] = v2ascii!([40, 32, 59]);
        assert_eq!(test.to_ascii().unwrap(), b);
        assert_eq!("( ;".to_ascii().unwrap(), b);
        let v = vec![40u8, 32u8, 59u8];
        assert_eq!(v.as_slice().to_ascii().unwrap(), b);
        assert_eq!("( ;".to_string().as_slice().to_ascii().unwrap(), b);
    }

    #[test]
    fn test_ascii_as_str() {
        let v = v2ascii!([40, 32, 59]);
        assert_eq!(v.as_str(), "( ;");
    }

    #[test]
    fn test_ascii_as_bytes() {
        let v = v2ascii!([40, 32, 59]);
        assert_eq!(v.as_bytes(), b"( ;");
    }

    #[test]
    fn test_ascii_into_string() {
        assert_eq!(vec2ascii![40, 32, 59].into_string(), "( ;".to_string());
        assert_eq!(vec2ascii!(40, 32, 59).into_string(), "( ;".to_string());
    }

    #[test]
    fn test_ascii_to_bytes() {
        assert_eq!(vec2ascii![40, 32, 59].into_bytes(), vec![40u8, 32u8, 59u8]);
    }

    #[test]
    fn test_opt() {
        assert_eq!(65u8.to_ascii(), Ok(Ascii { chr: 65u8 }));
        assert_eq!(255u8.to_ascii(), Err(()));

        assert_eq!('A'.to_ascii(), Ok(Ascii { chr: 65u8 }));
        assert_eq!('λ'.to_ascii(), Err(()));

        assert_eq!("zoä华".to_ascii(), Err(()));

        let test1 = &[127u8, 128u8, 255u8];
        assert_eq!(test1.to_ascii(), Err(()));

        let v = [40u8, 32u8, 59u8];
        let v2: &[_] = v2ascii!(&[40, 32, 59]);
        assert_eq!(v.to_ascii(), Ok(v2));
        let v = [127u8, 128u8, 255u8];
        assert_eq!(v.to_ascii(), Err(()));

        let v = "( ;";
        assert_eq!(v.to_ascii(), Ok(v2));
        assert_eq!("zoä华".to_ascii(), Err(()));

        assert_eq!(vec![40u8, 32u8, 59u8].into_ascii(), Ok(vec2ascii![40, 32, 59]));
        assert_eq!(vec![127u8, 128u8, 255u8].into_ascii(), Err(vec![127u8, 128u8, 255u8]));

        assert_eq!("( ;".to_string().into_ascii(), Ok(vec2ascii![40, 32, 59]));
        assert_eq!("zoä华".to_string().into_ascii(), Err("zoä华".to_string()));
    }

    #[test]
    fn test_to_string() {
        let s = Ascii{ chr: b't' }.to_string();
        assert_eq!(s, "t".to_string());
    }

    #[test]
    fn test_show() {
        let c = Ascii { chr: b't' };
        assert_eq!(format!("{}", c), "t".to_string());
    }
}
<|endoftext|>


<commit_before>//! Doc

#![crate_id = "euler#0.1"]
#![deny(missing_doc)]

extern crate core;
extern crate num;
extern crate collections;

pub mod modint;
pub mod fenwick;
pub mod sieve;

<commit_msg>Renamed the crate to algoritmoi.<commit_after>//! Doc

#![crate_id = "algoritmoi#0.1"]
#![deny(missing_doc)]

extern crate core;
extern crate num;
extern crate collections;

pub mod modint;
pub mod fenwick;
pub mod sieve;

<|endoftext|>


<commit_before>//! A simple, thread-safe IRC library.
#![crate_name = "irc"]
#![crate_type = "lib"]
#![unstable]
#![warn(missing_docs)]

#![feature(collections, core, io, str_char, tcp)]
#[cfg(feature = "ctcp")] extern crate time;
#[cfg(feature = "encode")] extern crate encoding;
extern crate rustc_serialize;
#[cfg(feature = "ssl")] extern crate openssl;

pub mod client;
pub mod server;
<commit_msg>Updated to Rust master.<commit_after>//! A simple, thread-safe IRC library.
#![crate_name = "irc"]
#![crate_type = "lib"]
#![unstable]
#![warn(missing_docs)]

#![feature(collections, core, io, slice_patterns, str_char, tcp)]
#[cfg(feature = "ctcp")] extern crate time;
#[cfg(feature = "encode")] extern crate encoding;
extern crate rustc_serialize;
#[cfg(feature = "ssl")] extern crate openssl;

pub mod client;
pub mod server;
<|endoftext|>


<commit_before>#[crate_id = "iron-router"]
#![license = "MIT"]
//#![deny(missing_doc)]
#![deny(unused_result, unused_result, unnecessary_qualification,
        non_camel_case_types, unused_variable, unnecessary_typecast)]
#![feature(phase, macro_export)]

extern crate http;
extern crate iron;
extern crate regex;
#[phase(plugin)] extern crate regex_macros;

pub use router::Router;

mod router;
<commit_msg>(fix) Updated broken attributes and dependencies.<commit_after>#![crate_id = "iron-router"]
#![license = "MIT"]
//#![deny(missing_doc)]
#![deny(unused_result, unused_result, unnecessary_qualification,
        non_camel_case_types, unused_variable, unnecessary_typecast)]
#![feature(phase, globs, macro_rules)]

extern crate http;
extern crate iron;
extern crate regex;
#[phase(plugin, link)] extern crate log;
#[phase(plugin)] extern crate regex_macros;

pub use router::Router;
pub use router::Handler;

mod router;

<|endoftext|>


<commit_before>/*!

# GraphQL

[GraphQL][1] is a data query language developed by Facebook intended to serve
mobile and web application frontends. A server provides a schema, containing
types and fields that applications can query. Queries are hierarchical,
composable, and statically typed. Schemas are introspective, which lets clients
statically verify their queries against a server without actually executing
them.

This library provides data types and traits to expose Rust types in a GraphQL
schema, as well as an optional integration into the [Iron framework][2]. It
tries to keep the number of dynamic operations to a minimum, and give you as the
schema developer the control of the query execution path.

Juniper only depends on `rustc-serialize` by default, making it lightweight and
easy to drop into any project. Through the `iron-handlers` feature, it also
depends on Iron.

## Exposing data types

The `GraphQLType` trait is the primary interface towards application developers.
By deriving this trait, you can expose your types as either objects, enums,
interfaces, unions, or scalars.

However, due to the dynamic nature of GraphQL's type system, deriving this trait
manually is a bit tedious, especially in order to do it in a fully type safe
manner. To help with this task, this library provides a couple of macros; the
most common one being `graphql_object!`. Use this macro to expose your already
existing object types as GraphQL objects:

```rust
#[macro_use] extern crate juniper;
# use std::collections::HashMap;
use juniper::FieldResult;

struct User { id: String, name: String, friend_ids: Vec<String>  }
struct QueryRoot;
struct Database { users: HashMap<String, User> }

// GraphQL objects can access a "context object" during execution. Use this
// object to provide e.g. database access to the field accessors.
//
// In this example, we use the Database struct as our context.
graphql_object!(User: Database |&self| {

    // Expose a simple field as a GraphQL string.
    field id() -> &String {
        &self.id
    }

    field name() -> &String {
        &self.name
    }

    // FieldResult<T> is an alias for Result<T, String> - simply return
    // a string from this method and it will be correctly inserted into
    // the execution response.
    field secret() -> FieldResult<&String> {
        Err("Can't touch this".to_owned())
    }

    // Field accessors can optionally take an "executor" as their first
    // argument. This object can help guide query execution and provides
    // access to the context instance.
    //
    // In this example, the context is used to convert the friend_ids array
    // into actual User objects.
    field friends(&mut executor) -> Vec<&User> {
        self.friend_ids.iter()
            .filter_map(|id| executor.context().users.get(id))
            .collect()
    }
});

// The context object is passed down to all referenced types - all your exposed
// types need to have the same context type.
graphql_object!(QueryRoot: Database |&self| {

    // Arguments work just like they do on functions.
    field user(&mut executor, id: String) -> Option<&User> {
        executor.context().users.get(&id)
    }
});

# fn main() { }
```

Adding per type, field, and argument documentation is possible directly from
this macro. For more in-depth information on how to expose fields and types, see
the [`graphql_object!`][3] macro.

## Integrating with Iron

The most obvious usecase is to expose the GraphQL schema over an HTTP endpoint.
To support this, the library provides an optional and customizable Iron handler.

For example, continuing from the schema created above:

```rust,no_run
extern crate iron;
# #[macro_use] extern crate juniper;
# use std::collections::HashMap;

use iron::prelude::*;
use juniper::iron_handlers::GraphQLHandler;

# use juniper::FieldResult;
#
# struct User { id: String, name: String, friend_ids: Vec<String>  }
# struct QueryRoot;
# struct Database { users: HashMap<String, User> }
#
# graphql_object!(User: Database |&self| {
#     field id() -> FieldResult<&String> {
#         Ok(&self.id)
#     }
#
#     field name() -> FieldResult<&String> {
#         Ok(&self.name)
#     }
#
#     field friends(&mut executor) -> FieldResult<Vec<&User>> {
#         Ok(self.friend_ids.iter()
#             .filter_map(|id| executor.context().users.get(id))
#             .collect())
#     }
# });
#
# graphql_object!(QueryRoot: Database |&self| {
#     field user(&mut executor, id: String) -> FieldResult<Option<&User>> {
#         Ok(executor.context().users.get(&id))
#     }
# });

// This function is executed for every request. Here, we would realistically
// provide a database connection or similar. For this example, we'll be
// creating the database from scratch.
fn context_factory(_: &mut Request) -> Database {
    Database {
        users: vec![
            ( "1000".to_owned(), User {
                id: "1000".to_owned(), name: "Robin".to_owned(),
                friend_ids: vec!["1001".to_owned()] } ),
            ( "1001".to_owned(), User {
                id: "1001".to_owned(), name: "Max".to_owned(),
                friend_ids: vec!["1000".to_owned()] } ),
        ].into_iter().collect()
    }
}

fn main() {
    // GraphQLHandler takes a context factory function, the root object,
    // and the mutation object. If we don't have any mutations to expose, we
    // can use the empty tuple () to indicate absence.
    let graphql_endpoint = GraphQLHandler::new(context_factory, QueryRoot, ());

    // Start serving the schema at the root on port 8080.
    Iron::new(graphql_endpoint).http("localhost:8080").unwrap();
}

```

See the [`iron_handlers`][4] module and the [`GraphQLHandler`][5] documentation
for more information on what request methods are supported. There's also a
built-in [GraphiQL][6] handler included.

[1]: http://graphql.org
[2]: http://ironframework.io
[3]: macro.graphql_object!.html
[4]: iron_handlers/index.html
[5]: iron_handlers/struct.GraphQLHandler.html
[6]: https://github.com/graphql/graphiql

*/

#![cfg_attr(feature="nightly", feature(test))]
#![warn(missing_docs)]

extern crate rustc_serialize;

#[cfg(feature="nightly")] extern crate test;
#[cfg(feature="iron-handlers")] #[macro_use(itry, iexpect)] extern crate iron;
#[cfg(test)] extern crate iron_test;

#[macro_use] mod macros;
mod ast;
pub mod parser;
mod value;
mod types;
mod schema;
pub mod validation;
mod executor;
mod integrations;

#[cfg(all(test, not(feature="expose-test-schema")))] mod tests;
#[cfg(feature="expose-test-schema")] pub mod tests;

#[cfg(test)] mod executor_tests;

use std::collections::HashMap;

use rustc_serialize::json::{ToJson, Json};

use parser::{parse_document_source, ParseError, Spanning, SourcePosition};
use validation::{RuleError, ValidatorContext, visit_all_rules, validate_input_values};
use executor::execute_validated_query;

pub use ast::{ToInputValue, FromInputValue, InputValue, Type, Selection};
pub use value::Value;
pub use types::base::{Arguments, GraphQLType, TypeKind};
pub use executor::{
    Executor, Registry, ExecutionResult, ExecutionError, FieldResult, IntoFieldResult,
};
pub use types::scalars::ID;
pub use schema::model::RootNode;

pub use schema::meta;

#[cfg(feature="iron-handlers")] pub use integrations::iron_handlers;

/// An error that prevented query execution
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub enum GraphQLError<'a> {
    ParseError(Spanning<ParseError<'a>>),
    ValidationError(Vec<RuleError>),
    NoOperationProvided,
    MultipleOperationsProvided,
    UnknownOperationName,
}

/// Execute a query in a provided schema
pub fn execute<'a, CtxT, QueryT, MutationT>(
    document_source: &'a str,
    operation_name: Option<&str>,
    root_node: &RootNode<CtxT, QueryT, MutationT>,
    variables: &HashMap<String, InputValue>,
    context: &CtxT,
)
    -> Result<(Value, Vec<ExecutionError>), GraphQLError<'a>>
    where QueryT: GraphQLType<CtxT>,
          MutationT: GraphQLType<CtxT>,
{
    let document = try!(parse_document_source(document_source));

    {
        let errors = validate_input_values(variables, &document, &root_node.schema);

        if !errors.is_empty() {
            return Err(GraphQLError::ValidationError(errors));
        }
    }

    {
        let mut ctx = ValidatorContext::new(&root_node.schema, &document);
        visit_all_rules(&mut ctx, &document);

        let errors = ctx.into_errors();
        if !errors.is_empty() {
            return Err(GraphQLError::ValidationError(errors));
        }
    }

    execute_validated_query(document, operation_name, root_node, variables, context)
}

impl<'a> From<Spanning<ParseError<'a>>> for GraphQLError<'a> {
    fn from(f: Spanning<ParseError<'a>>) -> GraphQLError<'a> {
        GraphQLError::ParseError(f)
    }
}

impl<'a> ToJson for GraphQLError<'a> {
    fn to_json(&self) -> Json {
        let errs = match *self {
            GraphQLError::ParseError(ref err) => parse_error_to_json(err),
            GraphQLError::ValidationError(ref errs) => errs.to_json(),
            GraphQLError::MultipleOperationsProvided => Json::String(
                "Must provide operation name if query contains multiple operations.".to_owned()),
            GraphQLError::NoOperationProvided => Json::String(
                "Must provide an operation".to_owned()),
            GraphQLError::UnknownOperationName => Json::String(
                "Unknown operation".to_owned()),
        };

        Json::Object(vec![
            ("errors".to_owned(), errs),
        ].into_iter().collect())
    }
}

fn parse_error_to_json(err: &Spanning<ParseError>) -> Json {
    Json::Array(vec![
        Json::Object(vec![
            ("message".to_owned(), format!("{}", err.item).to_json()),
            ("locations".to_owned(), vec![
                Json::Object(vec![
                    ("line".to_owned(), (err.start.line() + 1).to_json()),
                    ("column".to_owned(), (err.start.column() + 1).to_json())
                ].into_iter().collect()),
            ].to_json()),
        ].into_iter().collect()),
    ])
}

impl ToJson for RuleError {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("message".to_owned(), self.message().to_json()),
            ("locations".to_owned(), self.locations().to_json()),
        ].into_iter().collect())
    }
}

impl ToJson for SourcePosition {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("line".to_owned(), (self.line() + 1).to_json()),
            ("column".to_owned(), (self.column() + 1).to_json()),
        ].into_iter().collect())
    }
}

impl ToJson for ExecutionError {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("message".to_owned(), self.message().to_json()),
            ("locations".to_owned(), vec![self.location().clone()].to_json()),
            ("path".to_owned(), self.path().to_json()),
        ].into_iter().collect())
    }
}

#[doc(hidden)]
pub fn to_snake_case(s: &str) -> String {
    let mut dest = String::new();

    for (i, part) in s.split('_').enumerate() {
        if i > 0 && part.len() == 1 {
            dest.push_str(&part.to_uppercase());
        }
        else if i > 0 && part.len() > 1 {
            let first = part.chars().next().unwrap().to_uppercase().collect::<String>();
            let second = &part[1..];

            dest.push_str(&first);
            dest.push_str(second);
        }
        else if i == 0 {
            dest.push_str(part);
        }
    }

    dest
}

#[test]
fn test_to_snake_case() {
    assert_eq!(&to_snake_case("test")[..], "test");
    assert_eq!(&to_snake_case("_test")[..], "Test");
    assert_eq!(&to_snake_case("first_second")[..], "firstSecond");
    assert_eq!(&to_snake_case("first_")[..], "first");
    assert_eq!(&to_snake_case("a_b_c")[..], "aBC");
    assert_eq!(&to_snake_case("a_bc")[..], "aBc");
    assert_eq!(&to_snake_case("a_b")[..], "aB");
    assert_eq!(&to_snake_case("a")[..], "a");
    assert_eq!(&to_snake_case("")[..], "");
}
<commit_msg>Expose RuleError from crate root<commit_after>/*!

# GraphQL

[GraphQL][1] is a data query language developed by Facebook intended to serve
mobile and web application frontends. A server provides a schema, containing
types and fields that applications can query. Queries are hierarchical,
composable, and statically typed. Schemas are introspective, which lets clients
statically verify their queries against a server without actually executing
them.

This library provides data types and traits to expose Rust types in a GraphQL
schema, as well as an optional integration into the [Iron framework][2]. It
tries to keep the number of dynamic operations to a minimum, and give you as the
schema developer the control of the query execution path.

Juniper only depends on `rustc-serialize` by default, making it lightweight and
easy to drop into any project. Through the `iron-handlers` feature, it also
depends on Iron.

## Exposing data types

The `GraphQLType` trait is the primary interface towards application developers.
By deriving this trait, you can expose your types as either objects, enums,
interfaces, unions, or scalars.

However, due to the dynamic nature of GraphQL's type system, deriving this trait
manually is a bit tedious, especially in order to do it in a fully type safe
manner. To help with this task, this library provides a couple of macros; the
most common one being `graphql_object!`. Use this macro to expose your already
existing object types as GraphQL objects:

```rust
#[macro_use] extern crate juniper;
# use std::collections::HashMap;
use juniper::FieldResult;

struct User { id: String, name: String, friend_ids: Vec<String>  }
struct QueryRoot;
struct Database { users: HashMap<String, User> }

// GraphQL objects can access a "context object" during execution. Use this
// object to provide e.g. database access to the field accessors.
//
// In this example, we use the Database struct as our context.
graphql_object!(User: Database |&self| {

    // Expose a simple field as a GraphQL string.
    field id() -> &String {
        &self.id
    }

    field name() -> &String {
        &self.name
    }

    // FieldResult<T> is an alias for Result<T, String> - simply return
    // a string from this method and it will be correctly inserted into
    // the execution response.
    field secret() -> FieldResult<&String> {
        Err("Can't touch this".to_owned())
    }

    // Field accessors can optionally take an "executor" as their first
    // argument. This object can help guide query execution and provides
    // access to the context instance.
    //
    // In this example, the context is used to convert the friend_ids array
    // into actual User objects.
    field friends(&mut executor) -> Vec<&User> {
        self.friend_ids.iter()
            .filter_map(|id| executor.context().users.get(id))
            .collect()
    }
});

// The context object is passed down to all referenced types - all your exposed
// types need to have the same context type.
graphql_object!(QueryRoot: Database |&self| {

    // Arguments work just like they do on functions.
    field user(&mut executor, id: String) -> Option<&User> {
        executor.context().users.get(&id)
    }
});

# fn main() { }
```

Adding per type, field, and argument documentation is possible directly from
this macro. For more in-depth information on how to expose fields and types, see
the [`graphql_object!`][3] macro.

## Integrating with Iron

The most obvious usecase is to expose the GraphQL schema over an HTTP endpoint.
To support this, the library provides an optional and customizable Iron handler.

For example, continuing from the schema created above:

```rust,no_run
extern crate iron;
# #[macro_use] extern crate juniper;
# use std::collections::HashMap;

use iron::prelude::*;
use juniper::iron_handlers::GraphQLHandler;

# use juniper::FieldResult;
#
# struct User { id: String, name: String, friend_ids: Vec<String>  }
# struct QueryRoot;
# struct Database { users: HashMap<String, User> }
#
# graphql_object!(User: Database |&self| {
#     field id() -> FieldResult<&String> {
#         Ok(&self.id)
#     }
#
#     field name() -> FieldResult<&String> {
#         Ok(&self.name)
#     }
#
#     field friends(&mut executor) -> FieldResult<Vec<&User>> {
#         Ok(self.friend_ids.iter()
#             .filter_map(|id| executor.context().users.get(id))
#             .collect())
#     }
# });
#
# graphql_object!(QueryRoot: Database |&self| {
#     field user(&mut executor, id: String) -> FieldResult<Option<&User>> {
#         Ok(executor.context().users.get(&id))
#     }
# });

// This function is executed for every request. Here, we would realistically
// provide a database connection or similar. For this example, we'll be
// creating the database from scratch.
fn context_factory(_: &mut Request) -> Database {
    Database {
        users: vec![
            ( "1000".to_owned(), User {
                id: "1000".to_owned(), name: "Robin".to_owned(),
                friend_ids: vec!["1001".to_owned()] } ),
            ( "1001".to_owned(), User {
                id: "1001".to_owned(), name: "Max".to_owned(),
                friend_ids: vec!["1000".to_owned()] } ),
        ].into_iter().collect()
    }
}

fn main() {
    // GraphQLHandler takes a context factory function, the root object,
    // and the mutation object. If we don't have any mutations to expose, we
    // can use the empty tuple () to indicate absence.
    let graphql_endpoint = GraphQLHandler::new(context_factory, QueryRoot, ());

    // Start serving the schema at the root on port 8080.
    Iron::new(graphql_endpoint).http("localhost:8080").unwrap();
}

```

See the [`iron_handlers`][4] module and the [`GraphQLHandler`][5] documentation
for more information on what request methods are supported. There's also a
built-in [GraphiQL][6] handler included.

[1]: http://graphql.org
[2]: http://ironframework.io
[3]: macro.graphql_object!.html
[4]: iron_handlers/index.html
[5]: iron_handlers/struct.GraphQLHandler.html
[6]: https://github.com/graphql/graphiql

*/

#![cfg_attr(feature="nightly", feature(test))]
#![warn(missing_docs)]

extern crate rustc_serialize;

#[cfg(feature="nightly")] extern crate test;
#[cfg(feature="iron-handlers")] #[macro_use(itry, iexpect)] extern crate iron;
#[cfg(test)] extern crate iron_test;

#[macro_use] mod macros;
mod ast;
pub mod parser;
mod value;
mod types;
mod schema;
mod validation;
mod executor;
mod integrations;

#[cfg(all(test, not(feature="expose-test-schema")))] mod tests;
#[cfg(feature="expose-test-schema")] pub mod tests;

#[cfg(test)] mod executor_tests;

use std::collections::HashMap;

use rustc_serialize::json::{ToJson, Json};

use parser::{parse_document_source, ParseError, Spanning, SourcePosition};
use validation::{ValidatorContext, visit_all_rules, validate_input_values};
use executor::execute_validated_query;

pub use ast::{ToInputValue, FromInputValue, InputValue, Type, Selection};
pub use value::Value;
pub use types::base::{Arguments, GraphQLType, TypeKind};
pub use executor::{
    Executor, Registry, ExecutionResult, ExecutionError, FieldResult, IntoFieldResult,
};
pub use validation::RuleError;
pub use types::scalars::ID;
pub use schema::model::RootNode;

pub use schema::meta;

#[cfg(feature="iron-handlers")] pub use integrations::iron_handlers;

/// An error that prevented query execution
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub enum GraphQLError<'a> {
    ParseError(Spanning<ParseError<'a>>),
    ValidationError(Vec<RuleError>),
    NoOperationProvided,
    MultipleOperationsProvided,
    UnknownOperationName,
}

/// Execute a query in a provided schema
pub fn execute<'a, CtxT, QueryT, MutationT>(
    document_source: &'a str,
    operation_name: Option<&str>,
    root_node: &RootNode<CtxT, QueryT, MutationT>,
    variables: &HashMap<String, InputValue>,
    context: &CtxT,
)
    -> Result<(Value, Vec<ExecutionError>), GraphQLError<'a>>
    where QueryT: GraphQLType<CtxT>,
          MutationT: GraphQLType<CtxT>,
{
    let document = try!(parse_document_source(document_source));

    {
        let errors = validate_input_values(variables, &document, &root_node.schema);

        if !errors.is_empty() {
            return Err(GraphQLError::ValidationError(errors));
        }
    }

    {
        let mut ctx = ValidatorContext::new(&root_node.schema, &document);
        visit_all_rules(&mut ctx, &document);

        let errors = ctx.into_errors();
        if !errors.is_empty() {
            return Err(GraphQLError::ValidationError(errors));
        }
    }

    execute_validated_query(document, operation_name, root_node, variables, context)
}

impl<'a> From<Spanning<ParseError<'a>>> for GraphQLError<'a> {
    fn from(f: Spanning<ParseError<'a>>) -> GraphQLError<'a> {
        GraphQLError::ParseError(f)
    }
}

impl<'a> ToJson for GraphQLError<'a> {
    fn to_json(&self) -> Json {
        let errs = match *self {
            GraphQLError::ParseError(ref err) => parse_error_to_json(err),
            GraphQLError::ValidationError(ref errs) => errs.to_json(),
            GraphQLError::MultipleOperationsProvided => Json::String(
                "Must provide operation name if query contains multiple operations.".to_owned()),
            GraphQLError::NoOperationProvided => Json::String(
                "Must provide an operation".to_owned()),
            GraphQLError::UnknownOperationName => Json::String(
                "Unknown operation".to_owned()),
        };

        Json::Object(vec![
            ("errors".to_owned(), errs),
        ].into_iter().collect())
    }
}

fn parse_error_to_json(err: &Spanning<ParseError>) -> Json {
    Json::Array(vec![
        Json::Object(vec![
            ("message".to_owned(), format!("{}", err.item).to_json()),
            ("locations".to_owned(), vec![
                Json::Object(vec![
                    ("line".to_owned(), (err.start.line() + 1).to_json()),
                    ("column".to_owned(), (err.start.column() + 1).to_json())
                ].into_iter().collect()),
            ].to_json()),
        ].into_iter().collect()),
    ])
}

impl ToJson for RuleError {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("message".to_owned(), self.message().to_json()),
            ("locations".to_owned(), self.locations().to_json()),
        ].into_iter().collect())
    }
}

impl ToJson for SourcePosition {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("line".to_owned(), (self.line() + 1).to_json()),
            ("column".to_owned(), (self.column() + 1).to_json()),
        ].into_iter().collect())
    }
}

impl ToJson for ExecutionError {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("message".to_owned(), self.message().to_json()),
            ("locations".to_owned(), vec![self.location().clone()].to_json()),
            ("path".to_owned(), self.path().to_json()),
        ].into_iter().collect())
    }
}

#[doc(hidden)]
pub fn to_snake_case(s: &str) -> String {
    let mut dest = String::new();

    for (i, part) in s.split('_').enumerate() {
        if i > 0 && part.len() == 1 {
            dest.push_str(&part.to_uppercase());
        }
        else if i > 0 && part.len() > 1 {
            let first = part.chars().next().unwrap().to_uppercase().collect::<String>();
            let second = &part[1..];

            dest.push_str(&first);
            dest.push_str(second);
        }
        else if i == 0 {
            dest.push_str(part);
        }
    }

    dest
}

#[test]
fn test_to_snake_case() {
    assert_eq!(&to_snake_case("test")[..], "test");
    assert_eq!(&to_snake_case("_test")[..], "Test");
    assert_eq!(&to_snake_case("first_second")[..], "firstSecond");
    assert_eq!(&to_snake_case("first_")[..], "first");
    assert_eq!(&to_snake_case("a_b_c")[..], "aBC");
    assert_eq!(&to_snake_case("a_bc")[..], "aBc");
    assert_eq!(&to_snake_case("a_b")[..], "aB");
    assert_eq!(&to_snake_case("a")[..], "a");
    assert_eq!(&to_snake_case("")[..], "");
}
<|endoftext|>


<commit_before>#[macro_use] extern crate bitflags;
extern crate gl as gl_lib;
#[cfg(feature = "cgmath")] extern crate cgmath as cgmath_lib;
#[cfg(feature = "image")] extern crate image as image_lib;

mod ref_into;

#[macro_use] mod macros;
mod context;
mod buffer;
mod shader;
mod program;
mod framebuffer;
mod renderbuffer;
mod texture;
mod texture_units;
mod image_data;
mod vertex_data;
mod vertex_buffer;
mod index_data;
mod uniform_data;
mod types;

#[cfg(feature = "cgmath")] mod cgmath_features;
#[cfg(feature = "image")] mod image_features;

pub use gl_lib as gl;
#[cfg(feature = "cgmath")] pub use cgmath_lib as cgmath;
#[cfg(feature = "image")] pub use image_lib as image;

pub use context::*;
pub use buffer::*;
pub use shader::*;
pub use program::*;
pub use framebuffer::*;
pub use renderbuffer::*;
pub use texture::*;
pub use texture_units::*;
pub use image_data::*;
pub use vertex_data::*;
pub use vertex_buffer::*;
pub use index_data::*;
pub use uniform_data::*;
pub use types::*;

pub mod prelude {
    pub use buffer::{BufferBinding, BufferContext,
                     ArrayBufferContext, ElementArrayBufferContext};
    pub use texture_units::TextureUnit;
    pub use texture::TextureBinding;
}
<commit_msg>Add `VertexBufferContext` and `IndexBufferContext` into the prelude<commit_after>#[macro_use] extern crate bitflags;
extern crate gl as gl_lib;
#[cfg(feature = "cgmath")] extern crate cgmath as cgmath_lib;
#[cfg(feature = "image")] extern crate image as image_lib;

mod ref_into;

#[macro_use] mod macros;
mod context;
mod buffer;
mod shader;
mod program;
mod framebuffer;
mod renderbuffer;
mod texture;
mod texture_units;
mod image_data;
mod vertex_data;
mod vertex_buffer;
mod index_data;
mod uniform_data;
mod types;

#[cfg(feature = "cgmath")] mod cgmath_features;
#[cfg(feature = "image")] mod image_features;

pub use gl_lib as gl;
#[cfg(feature = "cgmath")] pub use cgmath_lib as cgmath;
#[cfg(feature = "image")] pub use image_lib as image;

pub use context::*;
pub use buffer::*;
pub use shader::*;
pub use program::*;
pub use framebuffer::*;
pub use renderbuffer::*;
pub use texture::*;
pub use texture_units::*;
pub use image_data::*;
pub use vertex_data::*;
pub use vertex_buffer::*;
pub use index_data::*;
pub use uniform_data::*;
pub use types::*;

pub mod prelude {
    pub use buffer::{BufferBinding, BufferContext,
                     ArrayBufferContext, ElementArrayBufferContext};
    pub use texture_units::TextureUnit;
    pub use texture::TextureBinding;
    pub use vertex_buffer::{VertexBufferContext, IndexBufferContext};
}
<|endoftext|>


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

// TODO we're going to allocate a whole bunch of temp Strings, is it worth
// keeping some scratch mem for this and running our own StrPool?
// TODO for lint violations of names, emit a refactor script

#[macro_use]
extern crate log;

extern crate syntex_syntax as syntax;
extern crate rustc_serialize;

extern crate strings;

extern crate unicode_segmentation;
extern crate regex;
extern crate diff;
extern crate term;

use syntax::ast;
use syntax::codemap::{mk_sp, Span};
use syntax::diagnostic::{EmitterWriter, Handler};
use syntax::parse::{self, ParseSess};

use std::ops::{Add, Sub};
use std::path::Path;
use std::collections::HashMap;
use std::fmt;
use std::str::FromStr;

use issues::{BadIssueSeeker, Issue};
use filemap::FileMap;
use visitor::FmtVisitor;
use config::Config;

#[macro_use]
mod utils;
pub mod config;
pub mod filemap;
mod visitor;
mod items;
mod missed_spans;
mod lists;
mod types;
mod expr;
mod imports;
mod issues;
mod rewrite;
mod string;
mod comment;
mod modules;
pub mod rustfmt_diff;
mod chains;
mod macros;
mod patterns;

const MIN_STRING: usize = 10;
// When we get scoped annotations, we should have rustfmt::skip.
const SKIP_ANNOTATION: &'static str = "rustfmt_skip";

pub trait Spanned {
    fn span(&self) -> Span;
}

impl Spanned for ast::Expr {
    fn span(&self) -> Span {
        self.span
    }
}

impl Spanned for ast::Pat {
    fn span(&self) -> Span {
        self.span
    }
}

impl Spanned for ast::Ty {
    fn span(&self) -> Span {
        self.span
    }
}

impl Spanned for ast::Arg {
    fn span(&self) -> Span {
        if items::is_named_arg(self) {
            mk_sp(self.pat.span.lo, self.ty.span.hi)
        } else {
            self.ty.span
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct Indent {
    // Width of the block indent, in characters. Must be a multiple of
    // Config::tab_spaces.
    pub block_indent: usize,
    // Alignment in characters.
    pub alignment: usize,
}

impl Indent {
    pub fn new(block_indent: usize, alignment: usize) -> Indent {
        Indent {
            block_indent: block_indent,
            alignment: alignment,
        }
    }

    pub fn empty() -> Indent {
        Indent::new(0, 0)
    }

    pub fn block_indent(mut self, config: &Config) -> Indent {
        self.block_indent += config.tab_spaces;
        self
    }

    pub fn block_unindent(mut self, config: &Config) -> Indent {
        self.block_indent -= config.tab_spaces;
        self
    }

    pub fn width(&self) -> usize {
        self.block_indent + self.alignment
    }

    pub fn to_string(&self, config: &Config) -> String {
        let (num_tabs, num_spaces) = if config.hard_tabs {
            (self.block_indent / config.tab_spaces, self.alignment)
        } else {
            (0, self.block_indent + self.alignment)
        };
        let num_chars = num_tabs + num_spaces;
        let mut indent = String::with_capacity(num_chars);
        for _ in 0..num_tabs {
            indent.push('\t')
        }
        for _ in 0..num_spaces {
            indent.push(' ')
        }
        indent
    }
}

impl Add for Indent {
    type Output = Indent;

    fn add(self, rhs: Indent) -> Indent {
        Indent {
            block_indent: self.block_indent + rhs.block_indent,
            alignment: self.alignment + rhs.alignment,
        }
    }
}

impl Sub for Indent {
    type Output = Indent;

    fn sub(self, rhs: Indent) -> Indent {
        Indent::new(self.block_indent - rhs.block_indent,
                    self.alignment - rhs.alignment)
    }
}

impl Add<usize> for Indent {
    type Output = Indent;

    fn add(self, rhs: usize) -> Indent {
        Indent::new(self.block_indent, self.alignment + rhs)
    }
}

impl Sub<usize> for Indent {
    type Output = Indent;

    fn sub(self, rhs: usize) -> Indent {
        Indent::new(self.block_indent, self.alignment - rhs)
    }
}

#[derive(Copy, Clone)]
pub enum WriteMode {
    // Backsup the original file and overwrites the orignal.
    Replace,
    // Overwrites original file without backup.
    Overwrite,
    // str is the extension of the new file.
    NewFile(&'static str),
    // Write the output to stdout.
    Display,
    // Write the diff to stdout.
    Diff,
    // Return the result as a mapping from filenames to Strings.
    Return,
    // Display how much of the input file was processed
    Coverage,
    // Unfancy stdout
    Plain,
}

impl FromStr for WriteMode {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "replace" => Ok(WriteMode::Replace),
            "display" => Ok(WriteMode::Display),
            "overwrite" => Ok(WriteMode::Overwrite),
            "diff" => Ok(WriteMode::Diff),
            "coverage" => Ok(WriteMode::Coverage),
            "plain" => Ok(WriteMode::Plain),
            _ => Err(()),
        }
    }
}

pub enum ErrorKind {
    // Line has exceeded character limit
    LineOverflow,
    // Line ends in whitespace
    TrailingWhitespace,
    // TO-DO or FIX-ME item without an issue number
    BadIssue(Issue),
}

impl fmt::Display for ErrorKind {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            ErrorKind::LineOverflow => write!(fmt, "line exceeded maximum length"),
            ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"),
            ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue),
        }
    }
}

// Formatting errors that are identified *after* rustfmt has run.
pub struct FormattingError {
    line: u32,
    kind: ErrorKind,
}

impl FormattingError {
    fn msg_prefix(&self) -> &str {
        match self.kind {
            ErrorKind::LineOverflow |
            ErrorKind::TrailingWhitespace => "Rustfmt failed at",
            ErrorKind::BadIssue(_) => "WARNING:",
        }
    }

    fn msg_suffix(&self) -> &str {
        match self.kind {
            ErrorKind::LineOverflow |
            ErrorKind::TrailingWhitespace => "(sorry)",
            ErrorKind::BadIssue(_) => "",
        }
    }
}

pub struct FormatReport {
    // Maps stringified file paths to their associated formatting errors.
    file_error_map: HashMap<String, Vec<FormattingError>>,
}

impl FormatReport {
    pub fn warning_count(&self) -> usize {
        self.file_error_map.iter().map(|(_, ref errors)| errors.len()).fold(0, |acc, x| acc + x)
    }
}

impl fmt::Display for FormatReport {
    // Prints all the formatting errors.
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        for (file, errors) in &self.file_error_map {
            for error in errors {
                try!(write!(fmt,
                            "{} {}:{}: {} {}\n",
                            error.msg_prefix(),
                            file,
                            error.line,
                            error.kind,
                            error.msg_suffix()));
            }
        }
        Ok(())
    }
}

// Formatting which depends on the AST.
fn fmt_ast(krate: &ast::Crate,
           parse_session: &ParseSess,
           main_file: &Path,
           config: &Config,
           mode: WriteMode)
           -> FileMap {
    let mut file_map = FileMap::new();
    for (path, module) in modules::list_files(krate, parse_session.codemap()) {
        if config.skip_children && path.as_path() != main_file {
            continue;
        }
        let path = path.to_str().unwrap();
        if config.verbose {
            println!("Formatting {}", path);
        }
        let mut visitor = FmtVisitor::from_codemap(parse_session, config, Some(mode));
        visitor.format_separate_mod(module);
        file_map.insert(path.to_owned(), visitor.buffer);
    }
    file_map
}

// Formatting done on a char by char or line by line basis.
// TODO(#209) warn on bad license
// TODO(#20) other stuff for parity with make tidy
pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport {
    let mut truncate_todo = Vec::new();
    let mut report = FormatReport { file_error_map: HashMap::new() };

    // Iterate over the chars in the file map.
    for (f, text) in file_map.iter() {
        let mut trims = vec![];
        let mut last_wspace: Option<usize> = None;
        let mut line_len = 0;
        let mut cur_line = 1;
        let mut newline_count = 0;
        let mut errors = vec![];
        let mut issue_seeker = BadIssueSeeker::new(config.report_todo, config.report_fixme);

        for (c, b) in text.chars() {
            if c == '\r' {
                continue;
            }

            // Add warnings for bad todos/ fixmes
            if let Some(issue) = issue_seeker.inspect(c) {
                errors.push(FormattingError {
                    line: cur_line,
                    kind: ErrorKind::BadIssue(issue),
                });
            }

            if c == '\n' {
                // Check for (and record) trailing whitespace.
                if let Some(lw) = last_wspace {
                    trims.push((cur_line, lw, b));
                    line_len -= b - lw;
                }
                // Check for any line width errors we couldn't correct.
                if line_len > config.max_width {
                    errors.push(FormattingError {
                        line: cur_line,
                        kind: ErrorKind::LineOverflow,
                    });
                }
                line_len = 0;
                cur_line += 1;
                newline_count += 1;
                last_wspace = None;
            } else {
                newline_count = 0;
                line_len += 1;
                if c.is_whitespace() {
                    if last_wspace.is_none() {
                        last_wspace = Some(b);
                    }
                } else {
                    last_wspace = None;
                }
            }
        }

        if newline_count > 1 {
            debug!("track truncate: {} {} {}", f, text.len, newline_count);
            truncate_todo.push((f.to_owned(), text.len - newline_count + 1))
        }

        for &(l, _, _) in &trims {
            errors.push(FormattingError {
                line: l,
                kind: ErrorKind::TrailingWhitespace,
            });
        }

        report.file_error_map.insert(f.to_owned(), errors);
    }

    for (f, l) in truncate_todo {
        file_map.get_mut(&f).unwrap().truncate(l);
    }

    report
}

pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap {
    let path = "stdin";
    let mut parse_session = ParseSess::new();
    let krate = parse::parse_crate_from_source_str(path.to_owned(),
                                                   input,
                                                   Vec::new(),
                                                   &parse_session);

    // Suppress error output after parsing.
    let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None));
    parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter);

    // FIXME: we still use a FileMap even though we only have
    // one file, because fmt_lines requires a FileMap
    let mut file_map = FileMap::new();

    // do the actual formatting
    let mut visitor = FmtVisitor::from_codemap(&parse_session, config, Some(mode));
    visitor.format_separate_mod(&krate.module);

    // append final newline
    visitor.buffer.push_str("\n");
    file_map.insert(path.to_owned(), visitor.buffer);

    file_map
}

pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap {
    let mut parse_session = ParseSess::new();
    let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session);

    // Suppress error output after parsing.
    let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None));
    parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter);

    let mut file_map = fmt_ast(&krate, &parse_session, file, config, mode);

    // For some reason, the codemap does not include terminating
    // newlines so we must add one on for each file. This is sad.
    filemap::append_newlines(&mut file_map);

    file_map
}

// args are the arguments passed on the command line, generally passed through
// to the compiler.
// write_mode determines what happens to the result of running rustfmt, see
// WriteMode.
pub fn run(file: &Path, write_mode: WriteMode, config: &Config) {
    let mut result = format(file, config, write_mode);

    print!("{}", fmt_lines(&mut result, config));

    let write_result = filemap::write_all_files(&result, write_mode, config);

    if let Err(msg) = write_result {
        println!("Error writing files: {}", msg);
    }
}

// Similar to run, but takes an input String instead of a file to format
pub fn run_from_stdin(input: String, mode: WriteMode, config: &Config) {
    let mut result = format_string(input, config, mode);
    fmt_lines(&mut result, config);

    let write_result = filemap::write_file(&result["stdin"], "stdin", mode, config);

    if let Err(msg) = write_result {
        panic!("Error writing to stdout: {}", msg);
    }
}
<commit_msg>Fix issue with windows line endings (#717).<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// TODO we're going to allocate a whole bunch of temp Strings, is it worth
// keeping some scratch mem for this and running our own StrPool?
// TODO for lint violations of names, emit a refactor script

#[macro_use]
extern crate log;

extern crate syntex_syntax as syntax;
extern crate rustc_serialize;

extern crate strings;

extern crate unicode_segmentation;
extern crate regex;
extern crate diff;
extern crate term;

use syntax::ast;
use syntax::codemap::{mk_sp, Span};
use syntax::diagnostic::{EmitterWriter, Handler};
use syntax::parse::{self, ParseSess};

use std::ops::{Add, Sub};
use std::path::Path;
use std::collections::HashMap;
use std::fmt;
use std::str::FromStr;

use issues::{BadIssueSeeker, Issue};
use filemap::FileMap;
use visitor::FmtVisitor;
use config::Config;

#[macro_use]
mod utils;
pub mod config;
pub mod filemap;
mod visitor;
mod items;
mod missed_spans;
mod lists;
mod types;
mod expr;
mod imports;
mod issues;
mod rewrite;
mod string;
mod comment;
mod modules;
pub mod rustfmt_diff;
mod chains;
mod macros;
mod patterns;

const MIN_STRING: usize = 10;
// When we get scoped annotations, we should have rustfmt::skip.
const SKIP_ANNOTATION: &'static str = "rustfmt_skip";

pub trait Spanned {
    fn span(&self) -> Span;
}

impl Spanned for ast::Expr {
    fn span(&self) -> Span {
        self.span
    }
}

impl Spanned for ast::Pat {
    fn span(&self) -> Span {
        self.span
    }
}

impl Spanned for ast::Ty {
    fn span(&self) -> Span {
        self.span
    }
}

impl Spanned for ast::Arg {
    fn span(&self) -> Span {
        if items::is_named_arg(self) {
            mk_sp(self.pat.span.lo, self.ty.span.hi)
        } else {
            self.ty.span
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct Indent {
    // Width of the block indent, in characters. Must be a multiple of
    // Config::tab_spaces.
    pub block_indent: usize,
    // Alignment in characters.
    pub alignment: usize,
}

impl Indent {
    pub fn new(block_indent: usize, alignment: usize) -> Indent {
        Indent {
            block_indent: block_indent,
            alignment: alignment,
        }
    }

    pub fn empty() -> Indent {
        Indent::new(0, 0)
    }

    pub fn block_indent(mut self, config: &Config) -> Indent {
        self.block_indent += config.tab_spaces;
        self
    }

    pub fn block_unindent(mut self, config: &Config) -> Indent {
        self.block_indent -= config.tab_spaces;
        self
    }

    pub fn width(&self) -> usize {
        self.block_indent + self.alignment
    }

    pub fn to_string(&self, config: &Config) -> String {
        let (num_tabs, num_spaces) = if config.hard_tabs {
            (self.block_indent / config.tab_spaces, self.alignment)
        } else {
            (0, self.block_indent + self.alignment)
        };
        let num_chars = num_tabs + num_spaces;
        let mut indent = String::with_capacity(num_chars);
        for _ in 0..num_tabs {
            indent.push('\t')
        }
        for _ in 0..num_spaces {
            indent.push(' ')
        }
        indent
    }
}

impl Add for Indent {
    type Output = Indent;

    fn add(self, rhs: Indent) -> Indent {
        Indent {
            block_indent: self.block_indent + rhs.block_indent,
            alignment: self.alignment + rhs.alignment,
        }
    }
}

impl Sub for Indent {
    type Output = Indent;

    fn sub(self, rhs: Indent) -> Indent {
        Indent::new(self.block_indent - rhs.block_indent,
                    self.alignment - rhs.alignment)
    }
}

impl Add<usize> for Indent {
    type Output = Indent;

    fn add(self, rhs: usize) -> Indent {
        Indent::new(self.block_indent, self.alignment + rhs)
    }
}

impl Sub<usize> for Indent {
    type Output = Indent;

    fn sub(self, rhs: usize) -> Indent {
        Indent::new(self.block_indent, self.alignment - rhs)
    }
}

#[derive(Copy, Clone)]
pub enum WriteMode {
    // Backsup the original file and overwrites the orignal.
    Replace,
    // Overwrites original file without backup.
    Overwrite,
    // str is the extension of the new file.
    NewFile(&'static str),
    // Write the output to stdout.
    Display,
    // Write the diff to stdout.
    Diff,
    // Return the result as a mapping from filenames to Strings.
    Return,
    // Display how much of the input file was processed
    Coverage,
    // Unfancy stdout
    Plain,
}

impl FromStr for WriteMode {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "replace" => Ok(WriteMode::Replace),
            "display" => Ok(WriteMode::Display),
            "overwrite" => Ok(WriteMode::Overwrite),
            "diff" => Ok(WriteMode::Diff),
            "coverage" => Ok(WriteMode::Coverage),
            "plain" => Ok(WriteMode::Plain),
            _ => Err(()),
        }
    }
}

pub enum ErrorKind {
    // Line has exceeded character limit
    LineOverflow,
    // Line ends in whitespace
    TrailingWhitespace,
    // TO-DO or FIX-ME item without an issue number
    BadIssue(Issue),
}

impl fmt::Display for ErrorKind {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            ErrorKind::LineOverflow => write!(fmt, "line exceeded maximum length"),
            ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"),
            ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue),
        }
    }
}

// Formatting errors that are identified *after* rustfmt has run.
pub struct FormattingError {
    line: u32,
    kind: ErrorKind,
}

impl FormattingError {
    fn msg_prefix(&self) -> &str {
        match self.kind {
            ErrorKind::LineOverflow |
            ErrorKind::TrailingWhitespace => "Rustfmt failed at",
            ErrorKind::BadIssue(_) => "WARNING:",
        }
    }

    fn msg_suffix(&self) -> &str {
        match self.kind {
            ErrorKind::LineOverflow |
            ErrorKind::TrailingWhitespace => "(sorry)",
            ErrorKind::BadIssue(_) => "",
        }
    }
}

pub struct FormatReport {
    // Maps stringified file paths to their associated formatting errors.
    file_error_map: HashMap<String, Vec<FormattingError>>,
}

impl FormatReport {
    pub fn warning_count(&self) -> usize {
        self.file_error_map.iter().map(|(_, ref errors)| errors.len()).fold(0, |acc, x| acc + x)
    }
}

impl fmt::Display for FormatReport {
    // Prints all the formatting errors.
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        for (file, errors) in &self.file_error_map {
            for error in errors {
                try!(write!(fmt,
                            "{} {}:{}: {} {}\n",
                            error.msg_prefix(),
                            file,
                            error.line,
                            error.kind,
                            error.msg_suffix()));
            }
        }
        Ok(())
    }
}

// Formatting which depends on the AST.
fn fmt_ast(krate: &ast::Crate,
           parse_session: &ParseSess,
           main_file: &Path,
           config: &Config,
           mode: WriteMode)
           -> FileMap {
    let mut file_map = FileMap::new();
    for (path, module) in modules::list_files(krate, parse_session.codemap()) {
        if config.skip_children && path.as_path() != main_file {
            continue;
        }
        let path = path.to_str().unwrap();
        if config.verbose {
            println!("Formatting {}", path);
        }
        let mut visitor = FmtVisitor::from_codemap(parse_session, config, Some(mode));
        visitor.format_separate_mod(module);
        file_map.insert(path.to_owned(), visitor.buffer);
    }
    file_map
}

// Formatting done on a char by char or line by line basis.
// TODO(#209) warn on bad license
// TODO(#20) other stuff for parity with make tidy
pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport {
    let mut truncate_todo = Vec::new();
    let mut report = FormatReport { file_error_map: HashMap::new() };

    // Iterate over the chars in the file map.
    for (f, text) in file_map.iter() {
        let mut trims = vec![];
        let mut last_wspace: Option<usize> = None;
        let mut line_len = 0;
        let mut cur_line = 1;
        let mut newline_count = 0;
        let mut errors = vec![];
        let mut issue_seeker = BadIssueSeeker::new(config.report_todo, config.report_fixme);

        for (c, b) in text.chars() {
            if c == '\r' {
                line_len += c.len_utf8();
                continue;
            }

            // Add warnings for bad todos/ fixmes
            if let Some(issue) = issue_seeker.inspect(c) {
                errors.push(FormattingError {
                    line: cur_line,
                    kind: ErrorKind::BadIssue(issue),
                });
            }

            if c == '\n' {
                // Check for (and record) trailing whitespace.
                if let Some(lw) = last_wspace {
                    trims.push((cur_line, lw, b));
                    line_len -= b - lw;
                }
                // Check for any line width errors we couldn't correct.
                if line_len > config.max_width {
                    errors.push(FormattingError {
                        line: cur_line,
                        kind: ErrorKind::LineOverflow,
                    });
                }
                line_len = 0;
                cur_line += 1;
                newline_count += 1;
                last_wspace = None;
            } else {
                newline_count = 0;
                line_len += c.len_utf8();
                if c.is_whitespace() {
                    if last_wspace.is_none() {
                        last_wspace = Some(b);
                    }
                } else {
                    last_wspace = None;
                }
            }
        }

        if newline_count > 1 {
            debug!("track truncate: {} {} {}", f, text.len, newline_count);
            truncate_todo.push((f.to_owned(), text.len - newline_count + 1))
        }

        for &(l, _, _) in &trims {
            errors.push(FormattingError {
                line: l,
                kind: ErrorKind::TrailingWhitespace,
            });
        }

        report.file_error_map.insert(f.to_owned(), errors);
    }

    for (f, l) in truncate_todo {
        file_map.get_mut(&f).unwrap().truncate(l);
    }

    report
}

pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap {
    let path = "stdin";
    let mut parse_session = ParseSess::new();
    let krate = parse::parse_crate_from_source_str(path.to_owned(),
                                                   input,
                                                   Vec::new(),
                                                   &parse_session);

    // Suppress error output after parsing.
    let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None));
    parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter);

    // FIXME: we still use a FileMap even though we only have
    // one file, because fmt_lines requires a FileMap
    let mut file_map = FileMap::new();

    // do the actual formatting
    let mut visitor = FmtVisitor::from_codemap(&parse_session, config, Some(mode));
    visitor.format_separate_mod(&krate.module);

    // append final newline
    visitor.buffer.push_str("\n");
    file_map.insert(path.to_owned(), visitor.buffer);

    file_map
}

pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap {
    let mut parse_session = ParseSess::new();
    let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session);

    // Suppress error output after parsing.
    let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None));
    parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter);

    let mut file_map = fmt_ast(&krate, &parse_session, file, config, mode);

    // For some reason, the codemap does not include terminating
    // newlines so we must add one on for each file. This is sad.
    filemap::append_newlines(&mut file_map);

    file_map
}

// args are the arguments passed on the command line, generally passed through
// to the compiler.
// write_mode determines what happens to the result of running rustfmt, see
// WriteMode.
pub fn run(file: &Path, write_mode: WriteMode, config: &Config) {
    let mut result = format(file, config, write_mode);

    print!("{}", fmt_lines(&mut result, config));

    let write_result = filemap::write_all_files(&result, write_mode, config);

    if let Err(msg) = write_result {
        println!("Error writing files: {}", msg);
    }
}

// Similar to run, but takes an input String instead of a file to format
pub fn run_from_stdin(input: String, mode: WriteMode, config: &Config) {
    let mut result = format_string(input, config, mode);
    fmt_lines(&mut result, config);

    let write_result = filemap::write_file(&result["stdin"], "stdin", mode, config);

    if let Err(msg) = write_result {
        panic!("Error writing to stdout: {}", msg);
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate uuid;
extern crate chrono;

#[macro_use] mod macros;

pub mod parse;
pub mod method;
pub mod record;
pub mod types;

pub mod mailbox;
pub mod calendar;
pub mod calendar_event;
pub mod contact;
pub mod contact_group;
<commit_msg>Reexport record types<commit_after>extern crate rustc_serialize;
extern crate uuid;
extern crate chrono;

#[macro_use] mod macros;

pub mod parse;
pub mod method;
pub mod record;
pub mod types;

pub use self::mailbox::Mailbox;
pub use self::calendar::Calendar;
pub use self::calendar_event::CalendarEvent;
pub use self::contact::Contact;
pub use self::contact_group::ContactGroup;

pub mod mailbox;
pub mod calendar;
pub mod calendar_event;
pub mod contact;
pub mod contact_group;
<|endoftext|>