<commit_before>//! Complex numbers

#![deny(missing_docs, warnings)]

extern crate onezero;
extern crate rand;

use std::fmt;
use std::ops::{Add, Sub, Mul, Div, Neg};
use rand::{Rand, Rng};

use onezero::{One, Zero};

mod ffi;
mod math;

pub mod f32;
pub mod f64;

/// A complex number in Cartesian form.
#[repr(C)]
#[derive(Clone, Copy, PartialEq)]
pub struct Complex<T> {
    /// The real part
    pub re: T,
    /// The imaginary part
    pub im: T,
}

/// Single precision complex number
#[allow(non_camel_case_types)]
pub type c64 = Complex<f32>;
/// Double precision complex number
#[allow(non_camel_case_types)]
pub type c128 = Complex<f64>;

impl<T> Complex<T> {
    /// Create a new complex number
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex {
            im: im,
            re: re,
        }
    }
}

impl<T> Complex<T> where T: Add<Output=T> + Clone + Mul<Output=T> {
    fn norm_sqr(self) -> T {
        self.re.clone() * self.re + self.im.clone() * self.im
    }
}

impl<T> Add<T> for Complex<T> where T: Add<Output=T> + Clone {
    type Output = Complex<T>;

    fn add(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re + rhs,
            im: self.im.clone(),
        }
    }
}

impl<T> Add for Complex<T> where T: Add<Output=T> {
    type Output = Complex<T>;

    fn add(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re + rhs.re,
            im: self.im + rhs.im,
        }
    }
}

/* FIXME(rust-lang/rust#20749)
impl<T> Add<Complex<T>> for T where T: Add<Output=T> + Clone {
    type Output = Complex<T>;

    fn add(self, rhs: Complex<T>) -> Complex<T> {
        rhs + self
    }
}
*/

impl<T> Div<T> for Complex<T> where T: Clone + Div<Output=T> {
    type Output = Complex<T>;

    fn div(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re / rhs.clone(),
            im: self.im / rhs,
        }
    }
}

impl<T> Div for Complex<T> where
    T: Add<Output=T> + Clone + Div<Output=T> + Mul<Output=T> + Sub<Output=T>
{
    type Output = Complex<T>;

    fn div(self, rhs: Complex<T>) -> Complex<T> {
        let den = rhs.clone().norm_sqr();

        Complex {
            re: {
                self.re.clone() * rhs.re.clone() + self.im.clone() * rhs.im.clone()
            } / den.clone(),
            im: (self.im * rhs.re - self.re * rhs.im) / den,
        }
    }
}

/* FIXME(rust-lang/rust#20749)
impl<T> Div<Complex<T>> for T where
    T: Add<Output=T> + Clone + Div<Output=T> + Mul<Output=T> + Neg<Output=T>,
{
    type Output = Complex<T>;

    fn div(self, rhs: Complex<T>) -> Complex<T> {
        let den = rhs.clone().norm_sqr();

        Complex {
            re: (self.clone() * rhs.re) / den.clone(),
            im: -(self * rhs.im) / den,
        }
    }
}
*/

impl<T> Mul<T> for Complex<T> where T: Clone + Mul<Output=T> {
    type Output = Complex<T>;

    fn mul(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re * rhs.clone(),
            im: self.im * rhs,
        }
    }
}

impl<T> Mul for Complex<T> where
    T: Add<Output=T> + Clone + Mul<Output=T> + Sub<Output=T>,
{
    type Output = Complex<T>;

    fn mul(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re.clone() * rhs.re.clone() - self.im.clone() * rhs.im.clone(),
            im: self.re * rhs.im + self.im * rhs.re,
        }
    }
}

/* FIXME(rust-lang/rust#20749)
impl<T> Mul<Complex<T>> for T where T: Clone + Mul<Output=T> {
    type Output = Complex<T>;

    fn mul(self, rhs: Complex<T>) -> Complex<T> {
        rhs * self
    }
}
*/

impl<T> Neg for Complex<T> where T: Neg<Output=T> {
    type Output = Complex<T>;

    fn neg(self) -> Complex<T> {
        Complex {
            re: -self.re,
            im: -self.im,
        }
    }
}

impl<T> One for Complex<T> where T: One + Zero {
    fn one() -> Complex<T> {
        Complex {
            re: One::one(),
            im: Zero::zero(),
        }
    }
}

impl<T> Rand for Complex<T> where T: Rand {
    fn rand<R>(rng: &mut R) -> Complex<T> where R: Rng {
        Complex::new(rng.gen(), rng.gen())
    }
}

impl<T> fmt::Debug for Complex<T> where T: PartialOrd + fmt::Debug + Zero {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{:?}-{:?}i", self.re, self.im)
        } else {
            write!(f, "{:?}+{:?}i", self.re, self.im)
        }
    }
}

impl<T> Sub<T> for Complex<T> where T: Clone + Sub<Output=T> {
    type Output = Complex<T>;

    fn sub(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re - rhs,
            im: self.im.clone(),
        }
    }
}

impl<T> Sub for Complex<T> where T: Sub<Output=T> {
    type Output = Complex<T>;

    fn sub(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re - rhs.re,
            im: self.im - rhs.im,
        }
    }
}

/* FIXME(rust-lang/rust#20749)
impl<T> Sub<Complex<T>> for T where T: Neg<Output=T> + Sub<Output=T> {
    type Output = Complex<T>;

    fn sub(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self - rhs.re,
            im: -rhs.im,
        }
    }
}
*/

impl<T> Zero for Complex<T> where T: Zero {
    fn zero() -> Complex<T> {
        Complex {
            re: Zero::zero(),
            im: Zero::zero(),
        }
    }
}

/// Mathematical operations on complex numbers
// FIXME (AI) `T` should be an associated output type
pub trait Math<T> {
    /// Computes the complex absolute value (also called norm, modulus or magnitude)
    fn abs(self) -> T;

    /// Computes the arc cosine
    fn acos(self) -> Self;

    /// Computes the arc hyperbolic cosine
    fn acosh(self) -> Self;

    /// Computes the argument (also called the phase angle)
    fn arg(self) -> T;

    /// Computes the arc sine
    fn asin(self) -> Self;

    /// Computes the arc hyperbolic sine
    fn asinh(self) -> Self;

    /// Computes the arc tangent
    fn atan(self) -> Self;

    /// Computes the arc hyperbolic tangent
    fn atanh(self) -> Self;

    /// Computes the arc cosine
    fn cos(self) -> Self;

    /// Computes the arc hyperbolic cosine
    fn cosh(self) -> Self;

    /// Computes the complex base-e exponential
    fn exp(self) -> Self;

    /// Returns the imaginary part
    fn imag(self) -> T;

    /// Computes the complex base-e logarithm
    fn log(self) -> Self;

    /// Computes the complex conjugate
    fn conj(self) -> Self;

    /// Computes the complex power
    fn pow(self, Self) -> Self;

    /// Computes the Riemann sphere projection
    fn proj(self) -> Self;

    /// Returns the real part
    fn real(self) -> T;

    /// Computes the arc sine
    fn sin(self) -> Self;

    /// Computes the arc hyperbolic sine
    fn sinh(self) -> Self;

    /// Computes the square root
    fn sqrt(self) -> Self;

    /// Computes the arc tangent
    fn tan(self) -> Self;

    /// Computes the arc hyperbolic tangent
    fn tanh(self) -> Self;
}

#[cfg(test)]
mod test {
    macro_rules! test {
        ($($ty:ident),+) => {$(
            mod $ty {
                use Complex;
                use $ty::I;

                #[test]
                fn constructor() {
                    assert_eq!(Complex::new(3., 4.), I * 4. + 3.)
                }
            })+
         }
    }

    test!(f32, f64);
}
<commit_msg>refactor: fix warnings<commit_after>//! Complex numbers

#![cfg_attr(test, feature(core))]
#![deny(missing_docs)]
#![deny(warnings)]

extern crate onezero;
extern crate rand;

use std::fmt;
use std::ops::{Add, Sub, Mul, Div, Neg};
use rand::{Rand, Rng};

use onezero::{One, Zero};

mod ffi;
mod math;

pub mod f32;
pub mod f64;

/// A complex number in Cartesian form.
#[repr(C)]
#[derive(Clone, Copy, PartialEq)]
pub struct Complex<T> {
    /// The real part
    pub re: T,
    /// The imaginary part
    pub im: T,
}

/// Single precision complex number
#[allow(non_camel_case_types)]
pub type c64 = Complex<f32>;
/// Double precision complex number
#[allow(non_camel_case_types)]
pub type c128 = Complex<f64>;

impl<T> Complex<T> {
    /// Create a new complex number
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex {
            im: im,
            re: re,
        }
    }
}

impl<T> Complex<T> where T: Add<Output=T> + Clone + Mul<Output=T> {
    fn norm_sqr(self) -> T {
        self.re.clone() * self.re + self.im.clone() * self.im
    }
}

impl<T> Add<T> for Complex<T> where T: Add<Output=T> + Clone {
    type Output = Complex<T>;

    fn add(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re + rhs,
            im: self.im.clone(),
        }
    }
}

impl<T> Add for Complex<T> where T: Add<Output=T> {
    type Output = Complex<T>;

    fn add(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re + rhs.re,
            im: self.im + rhs.im,
        }
    }
}

/* FIXME(rust-lang/rust#20749)
impl<T> Add<Complex<T>> for T where T: Add<Output=T> + Clone {
    type Output = Complex<T>;

    fn add(self, rhs: Complex<T>) -> Complex<T> {
        rhs + self
    }
}
*/

impl<T> Div<T> for Complex<T> where T: Clone + Div<Output=T> {
    type Output = Complex<T>;

    fn div(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re / rhs.clone(),
            im: self.im / rhs,
        }
    }
}

impl<T> Div for Complex<T> where
    T: Add<Output=T> + Clone + Div<Output=T> + Mul<Output=T> + Sub<Output=T>
{
    type Output = Complex<T>;

    fn div(self, rhs: Complex<T>) -> Complex<T> {
        let den = rhs.clone().norm_sqr();

        Complex {
            re: {
                self.re.clone() * rhs.re.clone() + self.im.clone() * rhs.im.clone()
            } / den.clone(),
            im: (self.im * rhs.re - self.re * rhs.im) / den,
        }
    }
}

/* FIXME(rust-lang/rust#20749)
impl<T> Div<Complex<T>> for T where
    T: Add<Output=T> + Clone + Div<Output=T> + Mul<Output=T> + Neg<Output=T>,
{
    type Output = Complex<T>;

    fn div(self, rhs: Complex<T>) -> Complex<T> {
        let den = rhs.clone().norm_sqr();

        Complex {
            re: (self.clone() * rhs.re) / den.clone(),
            im: -(self * rhs.im) / den,
        }
    }
}
*/

impl<T> Mul<T> for Complex<T> where T: Clone + Mul<Output=T> {
    type Output = Complex<T>;

    fn mul(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re * rhs.clone(),
            im: self.im * rhs,
        }
    }
}

impl<T> Mul for Complex<T> where
    T: Add<Output=T> + Clone + Mul<Output=T> + Sub<Output=T>,
{
    type Output = Complex<T>;

    fn mul(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re.clone() * rhs.re.clone() - self.im.clone() * rhs.im.clone(),
            im: self.re * rhs.im + self.im * rhs.re,
        }
    }
}

/* FIXME(rust-lang/rust#20749)
impl<T> Mul<Complex<T>> for T where T: Clone + Mul<Output=T> {
    type Output = Complex<T>;

    fn mul(self, rhs: Complex<T>) -> Complex<T> {
        rhs * self
    }
}
*/

impl<T> Neg for Complex<T> where T: Neg<Output=T> {
    type Output = Complex<T>;

    fn neg(self) -> Complex<T> {
        Complex {
            re: -self.re,
            im: -self.im,
        }
    }
}

impl<T> One for Complex<T> where T: One + Zero {
    fn one() -> Complex<T> {
        Complex {
            re: One::one(),
            im: Zero::zero(),
        }
    }
}

impl<T> Rand for Complex<T> where T: Rand {
    fn rand<R>(rng: &mut R) -> Complex<T> where R: Rng {
        Complex::new(rng.gen(), rng.gen())
    }
}

impl<T> fmt::Debug for Complex<T> where T: PartialOrd + fmt::Debug + Zero {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{:?}-{:?}i", self.re, self.im)
        } else {
            write!(f, "{:?}+{:?}i", self.re, self.im)
        }
    }
}

impl<T> Sub<T> for Complex<T> where T: Clone + Sub<Output=T> {
    type Output = Complex<T>;

    fn sub(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re - rhs,
            im: self.im.clone(),
        }
    }
}

impl<T> Sub for Complex<T> where T: Sub<Output=T> {
    type Output = Complex<T>;

    fn sub(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re - rhs.re,
            im: self.im - rhs.im,
        }
    }
}

/* FIXME(rust-lang/rust#20749)
impl<T> Sub<Complex<T>> for T where T: Neg<Output=T> + Sub<Output=T> {
    type Output = Complex<T>;

    fn sub(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self - rhs.re,
            im: -rhs.im,
        }
    }
}
*/

impl<T> Zero for Complex<T> where T: Zero {
    fn zero() -> Complex<T> {
        Complex {
            re: Zero::zero(),
            im: Zero::zero(),
        }
    }
}

/// Mathematical operations on complex numbers
// FIXME (AI) `T` should be an associated output type
pub trait Math<T> {
    /// Computes the complex absolute value (also called norm, modulus or magnitude)
    fn abs(self) -> T;

    /// Computes the arc cosine
    fn acos(self) -> Self;

    /// Computes the arc hyperbolic cosine
    fn acosh(self) -> Self;

    /// Computes the argument (also called the phase angle)
    fn arg(self) -> T;

    /// Computes the arc sine
    fn asin(self) -> Self;

    /// Computes the arc hyperbolic sine
    fn asinh(self) -> Self;

    /// Computes the arc tangent
    fn atan(self) -> Self;

    /// Computes the arc hyperbolic tangent
    fn atanh(self) -> Self;

    /// Computes the arc cosine
    fn cos(self) -> Self;

    /// Computes the arc hyperbolic cosine
    fn cosh(self) -> Self;

    /// Computes the complex base-e exponential
    fn exp(self) -> Self;

    /// Returns the imaginary part
    fn imag(self) -> T;

    /// Computes the complex base-e logarithm
    fn log(self) -> Self;

    /// Computes the complex conjugate
    fn conj(self) -> Self;

    /// Computes the complex power
    fn pow(self, Self) -> Self;

    /// Computes the Riemann sphere projection
    fn proj(self) -> Self;

    /// Returns the real part
    fn real(self) -> T;

    /// Computes the arc sine
    fn sin(self) -> Self;

    /// Computes the arc hyperbolic sine
    fn sinh(self) -> Self;

    /// Computes the square root
    fn sqrt(self) -> Self;

    /// Computes the arc tangent
    fn tan(self) -> Self;

    /// Computes the arc hyperbolic tangent
    fn tanh(self) -> Self;
}

#[cfg(test)]
mod test {
    macro_rules! test {
        ($($ty:ident),+) => {$(
            mod $ty {
                use Complex;
                use $ty::I;

                #[test]
                fn constructor() {
                    assert_eq!(Complex::new(3., 4.), I * 4. + 3.)
                }
            })+
         }
    }

    test!(f32, f64);
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar)]
#![feature(rustc_private)]
#![feature(slice_patterns)]

extern crate rustc_plugin;
extern crate syntax;

use rustc_plugin::Registry;
use syntax::abi::Abi;
use syntax::ast::Expr_::ExprTup;
use syntax::ast::Item_::ItemFn;
use syntax::ast::{Constness, Expr, FnDecl, FunctionRetTy, Generics, Ident, Item_, TokenTree, Unsafety};
use syntax::codemap::{DUMMY_SP, Span, Spanned};
use syntax::ext::base::{DummyResult, ExtCtxt, MacEager, MacResult};
use syntax::ext::build::AstBuilder;
use syntax::parse::PResult;
use syntax::parse::common::seq_sep_trailing_allowed;
use syntax::parse::parser::Parser;
use syntax::parse::token::get_ident_interner;
use syntax::parse::token::keywords::Keyword;
use syntax::parse::token::{DelimToken, Token};
use syntax::ptr::P;
use syntax::util::small_vector::SmallVector;

type ItemInfo = (Ident, Item_);

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("plague", plague_macro);
}

pub fn plague_macro<'cx>(cx: &'cx mut ExtCtxt, span: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
    let mut parser = cx.new_parser_from_tts(tts);

    match parse_plague(&mut parser) {
        Ok((params, ident, item, should_panic)) => {
            match make_plague(cx, &mut parser, params, ident, item, should_panic) {
                Ok(r) => r,
                Err(mut err) => {
                    err.emit();
                    DummyResult::any(span)
                }
            }
        }
        Err(mut err) => {
            err.emit();
            DummyResult::any(span)
        }
    }
}

fn parse_plague<'a>(parser: &mut Parser<'a>) -> PResult<'a, (Spanned<Vec<P<Expr>>>, Ident, Item_, bool)> {
    try!(parser.expect_keyword(Keyword::For));

    let params = try!(parser.parse_seq(
        &Token::OpenDelim(DelimToken::Bracket),
        &Token::CloseDelim(DelimToken::Bracket),
        seq_sep_trailing_allowed(Token::Comma),
        |parser| parser.parse_expr()
    ));

    try!(expect_keyword(parser, "test"));

    let should_panic = try!(parser.eat(&Token::Not));

    let (constness, unsafety, abi) = try!(parser.parse_fn_front_matter());

    // Yep, copy-pasted pieces from libsyntax
    let ident = try!(parser.parse_ident());
    let mut generics = try!(parser.parse_generics());
    let decl = try!(parser.parse_fn_decl(false));
    generics.where_clause = try!(parser.parse_where_clause());
    let body = try!(parser.parse_block());
    let fn_ = ItemFn(decl, unsafety, constness, abi, generics, body);

    Ok((params, ident, fn_, should_panic))
}

fn expect_keyword<'a>(parser: &mut Parser<'a>, kw: &str) -> PResult<'a, ()> {
    match parser.parse_ident() {
        Ok(test_ident) if test_ident.name.as_str() == kw => Ok(()),
        Ok(ident) => {
            Err(parser.fatal(&format!("expected `test`, found `{}`", ident)))
        }
        Err(mut err) => {
            err.cancel();
            Err(parser.fatal(&format!("expected `test`, found `{}`", parser.this_token_to_string())))
        }
    }
}

fn make_plague<'cx, 'a>(
    cx: &'cx mut ExtCtxt,
    parser: &mut Parser<'a>,
    params: Spanned<Vec<P<Expr>>>,
    ident: Ident,
    fn_: Item_,
    should_panic: bool
) -> PResult<'a, Box<MacResult + 'cx>> {
    let unpack_tuple = if let &ItemFn(ref decl, _, _, _, _, _) = &fn_ {
        decl.inputs.len() > 1
    }
    else {
        panic!();
    };

    let interner = get_ident_interner();

    let mut fns = Vec::with_capacity(params.node.len());

    fns.push(cx.item(
        DUMMY_SP, // TODO
        ident,
        Vec::new(),
        fn_
    ));

    let attributes = {
        let make_attr = |name| {
            cx.attribute(DUMMY_SP, cx.meta_word(DUMMY_SP, interner.intern(name).as_str()))
        };

        if should_panic {
            vec![make_attr("test"), make_attr("should_panic")]
        }
        else {
            vec![make_attr("test")]
        }
    };

    let span = params.span;
    for (i, param) in params.node.iter().enumerate() {
        let params = try!(make_params(parser, &param, unpack_tuple));
        let fn_ = make_test_fn(cx, span, ident, params);

        fns.push(cx.item(
            span,
            Ident::new(interner.intern(&format!("{}_{}", ident.name, i)), ident.ctxt),
            attributes.clone(),
            fn_
        ));
    }

    Ok(MacEager::items(SmallVector::many(fns)))
}

fn make_test_fn<'cx>(
    cx: &'cx mut ExtCtxt,
    span: Span,
    ident: Ident,
    params: Vec<P<Expr>>
) -> Item_ {
    let call = cx.expr_call_ident(span, ident, params);
    let block = cx.block_expr(call);

    Item_::ItemFn(
        P(FnDecl { inputs: vec![], output: FunctionRetTy::DefaultReturn(DUMMY_SP), variadic: false }),
        Unsafety::Normal,
        Constness::NotConst,
        Abi::Rust,
        Generics::default(),
        block
    )
}

fn make_params<'a>(
    parser: &mut Parser<'a>,
    params: &P<Expr>,
    unpack_tuple: bool
) -> PResult<'a, Vec<P<Expr>>> {
    if !unpack_tuple {
        Ok(vec![params.clone()])
    }
    else if let ExprTup(ref params) = params.node {
        Ok(params.clone())
    }
    else {
        Err(parser.span_fatal(params.span, "expected tuple, the test function has several arguments"))
    }
}
<commit_msg>Generate correct span for tested function<commit_after>#![feature(plugin_registrar)]
#![feature(rustc_private)]
#![feature(slice_patterns)]

extern crate rustc_plugin;
extern crate syntax;

use rustc_plugin::Registry;
use syntax::abi::Abi;
use syntax::ast::Expr_::ExprTup;
use syntax::ast::Item_::ItemFn;
use syntax::ast::{Constness, Expr, FnDecl, FunctionRetTy, Generics, Ident, Item_, TokenTree, Unsafety};
use syntax::codemap::{DUMMY_SP, Span, Spanned};
use syntax::ext::base::{DummyResult, ExtCtxt, MacEager, MacResult};
use syntax::ext::build::AstBuilder;
use syntax::parse::PResult;
use syntax::parse::common::seq_sep_trailing_allowed;
use syntax::parse::parser::Parser;
use syntax::parse::token::get_ident_interner;
use syntax::parse::token::keywords::Keyword;
use syntax::parse::token::{DelimToken, Token};
use syntax::ptr::P;
use syntax::util::small_vector::SmallVector;

type ItemInfo = (Ident, Item_);

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("plague", plague_macro);
}

pub fn plague_macro<'cx>(cx: &'cx mut ExtCtxt, span: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
    let mut parser = cx.new_parser_from_tts(tts);

    match parse_plague(&mut parser) {
        Ok((params, ident, item, should_panic, fn_span)) => {
            match make_plague(cx, &mut parser, params, ident, item, should_panic, fn_span) {
                Ok(r) => r,
                Err(mut err) => {
                    err.emit();
                    DummyResult::any(span)
                }
            }
        }
        Err(mut err) => {
            err.emit();
            DummyResult::any(span)
        }
    }
}

fn parse_plague<'a>(parser: &mut Parser<'a>) -> PResult<'a, (Spanned<Vec<P<Expr>>>, Ident, Item_, bool, Span)> {
    try!(parser.expect_keyword(Keyword::For));

    let params = try!(parser.parse_seq(
        &Token::OpenDelim(DelimToken::Bracket),
        &Token::CloseDelim(DelimToken::Bracket),
        seq_sep_trailing_allowed(Token::Comma),
        |parser| parser.parse_expr()
    ));

    try!(expect_keyword(parser, "test"));

    let should_panic = try!(parser.eat(&Token::Not));

    let mut span = parser.span;
    let (constness, unsafety, abi) = try!(parser.parse_fn_front_matter());

    // Yep, copy-pasted pieces from libsyntax
    let ident = try!(parser.parse_ident());
    let mut generics = try!(parser.parse_generics());
    let decl = try!(parser.parse_fn_decl(false));
    generics.where_clause = try!(parser.parse_where_clause());
    let body = try!(parser.parse_block());
    let fn_ = ItemFn(decl, unsafety, constness, abi, generics, body);

    span.hi = parser.last_span.hi;

    Ok((params, ident, fn_, should_panic, span))
}

fn expect_keyword<'a>(parser: &mut Parser<'a>, kw: &str) -> PResult<'a, ()> {
    match parser.parse_ident() {
        Ok(test_ident) if test_ident.name.as_str() == kw => Ok(()),
        Ok(ident) => {
            Err(parser.fatal(&format!("expected `test`, found `{}`", ident)))
        }
        Err(mut err) => {
            err.cancel();
            Err(parser.fatal(&format!("expected `test`, found `{}`", parser.this_token_to_string())))
        }
    }
}

fn make_plague<'cx, 'a>(
    cx: &'cx mut ExtCtxt,
    parser: &mut Parser<'a>,
    params: Spanned<Vec<P<Expr>>>,
    ident: Ident,
    fn_: Item_,
    should_panic: bool,
    fn_span: Span
) -> PResult<'a, Box<MacResult + 'cx>> {
    let unpack_tuple = if let &ItemFn(ref decl, _, _, _, _, _) = &fn_ {
        decl.inputs.len() > 1
    }
    else {
        panic!();
    };

    let interner = get_ident_interner();

    let mut fns = Vec::with_capacity(params.node.len());

    fns.push(cx.item( fn_span, ident, Vec::new(), fn_));

    let attributes = {
        let make_attr = |name| {
            cx.attribute(DUMMY_SP, cx.meta_word(DUMMY_SP, interner.intern(name).as_str()))
        };

        if should_panic {
            vec![make_attr("test"), make_attr("should_panic")]
        }
        else {
            vec![make_attr("test")]
        }
    };

    let span = params.span;
    for (i, param) in params.node.iter().enumerate() {
        let params = try!(make_params(parser, &param, unpack_tuple));
        let fn_ = make_test_fn(cx, span, ident, params);

        fns.push(cx.item(
            span,
            Ident::new(interner.intern(&format!("{}_{}", ident.name, i)), ident.ctxt),
            attributes.clone(),
            fn_
        ));
    }

    Ok(MacEager::items(SmallVector::many(fns)))
}

fn make_test_fn<'cx>(
    cx: &'cx mut ExtCtxt,
    span: Span,
    ident: Ident,
    params: Vec<P<Expr>>
) -> Item_ {
    let call = cx.expr_call_ident(span, ident, params);
    let block = cx.block_expr(call);

    Item_::ItemFn(
        P(FnDecl { inputs: vec![], output: FunctionRetTy::DefaultReturn(DUMMY_SP), variadic: false }),
        Unsafety::Normal,
        Constness::NotConst,
        Abi::Rust,
        Generics::default(),
        block
    )
}

fn make_params<'a>(
    parser: &mut Parser<'a>,
    params: &P<Expr>,
    unpack_tuple: bool
) -> PResult<'a, Vec<P<Expr>>> {
    if !unpack_tuple {
        Ok(vec![params.clone()])
    }
    else if let ExprTup(ref params) = params.node {
        Ok(params.clone())
    }
    else {
        Err(parser.span_fatal(params.span, "expected tuple, the test function has several arguments"))
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Library for retrieving and interacting with the [crates.io index].
//!
//! [crates.io index]: https://github.com/rust-lang/crates.io-index
//!
//! ## Examples
//!
//! ```rust
//! extern crate crates_index;
//!
//! let index = crates_index::Index::new("_index");
//! if !index.exists() {
//!    index.retrieve().expect("Could not fetch crates.io index");
//! }
//! for crate_ in index.crates() {
//!    let latest_version = crate_.latest_version();
//!    println!("crate name: {}", latest_version.name());
//!    println!("crate version: {}", latest_version.version());
//! }
//! ```

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::io::{BufRead, BufReader};
use std::iter;
use std::path::{Path, PathBuf};

#[macro_use]
extern crate error_chain;
extern crate git2;
extern crate glob;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde;

error_chain! {
    foreign_links {
        Git(git2::Error);
    }
}

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of a crate published to the index
#[derive(Deserialize, Clone)]
pub struct Version {
    name: String,
    vers: String,
    deps: Vec<Dependency>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

impl Version {
    /// Name of the crate
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Name of this version
    pub fn version(&self) -> &str {
        &self.vers
    }

    /// Dependencies for this version
    pub fn dependencies(&self) -> &[Dependency] {
        &self.deps
    }

    /// Checksum of the package for this version
    pub fn checksum(&self) -> &str {
        &self.cksum
    }

    pub fn features(&self) -> &HashMap<String, Vec<String>> {
        &self.features
    }

    /// Whether this version was [yanked](http://doc.crates.io/crates-io.html#cargo-yank) from the
    /// index
    pub fn is_yanked(&self) -> bool {
        self.yanked
    }
}

/// A single dependency of a specific crate version
#[derive(Deserialize, Clone)]
pub struct Dependency {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>,
}

impl Dependency {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn requirement(&self) -> &str {
        &self.req
    }

    pub fn features(&self) -> &[String] {
        &self.features
    }

    pub fn is_optional(&self) -> bool {
        self.optional
    }

    pub fn has_default_features(&self) -> bool {
        self.default_features
    }

    pub fn target(&self) -> Option<&str> {
        match self.target {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    pub fn kind(&self) -> Option<&str> {
        match self.kind {
            Some(ref s) => Some(s),
            None => None,
        }
    }
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new<P: AsRef<Path>>(path: P) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;
        let path = path.as_ref();

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
#[derive(Debug, Clone, PartialEq)]
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new<P: Into<PathBuf>>(path: P) -> Index {
        Index { path: path.into() }
    }

    /// Determines if a crates.io repository exists at `self.path`
    pub fn exists(&self) -> bool {
        git2::Repository::discover(&self.path)
            .map(|repository| {
                repository
                    .find_remote("origin")
                    .map(|remote| remote.url() == Some(INDEX_GIT_URL))
                    .unwrap_or(false)
            })
            .unwrap_or(false)
    }

    /// Downloads the index to the path specified from the constructor
    pub fn retrieve(&self) -> Result<()> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    /// Assumes the index already exists at `self.path`, and updates it
    pub fn update(&self) -> Result<()> {
        debug_assert!(self.exists());
        let repo = git2::Repository::discover(&self.path)?;
        let mut origin_remote = repo.find_remote("origin")?;
        origin_remote.fetch(&["master"], None, None)?;
        let oid = repo.refname_to_id("refs/remotes/origin/master")?;
        let object = repo.find_object(oid, None).unwrap();
        repo.reset(&object, git2::ResetType::Hard, None)?;
        Ok(())
    }

    /// Downloads the index to the path specified from the constructor
    pub fn retrieve_or_update(&self) -> Result<()> {
        if self.exists() {
            self.update()
        } else {
            self.retrieve()
        }
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| {
                      path.file_name()
                          .and_then(OsStr::to_str)
                          .map(|file_name| file_name.eq_ignore_ascii_case(crate_name))
                          .unwrap_or(false)
                  })
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone()) // TODO: remove this clone
    }

    /// Get the index directory.
    pub fn path(&self) -> &Path {
        &self.path
    }
}

/// A single crate that contains many published versions
pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new<P: AsRef<Path>>(index_path: P) -> Crate {
        let index_path = index_path.as_ref();
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = serde_json::from_str(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate { versions: versions }
    }

    /// Published versions of this crate sorted chronologically by date published
    pub fn versions(&self) -> &[Version] {
        &self.versions
    }

    pub fn earliest_version(&self) -> &Version {
        &self.versions[0]
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }

    pub fn name(&self) -> &str {
        self.latest_version().name()
    }
}

#[cfg(test)]
mod test {
    use std::fs;
    use super::Index;

    static TEST_INDEX_DIR: &'static str = "_test";

    #[test]
    fn test_dependencies() {
        let _ = fs::remove_dir_all(TEST_INDEX_DIR);

        let index = Index::new(TEST_INDEX_DIR);
        index.retrieve().expect("could not fetch crates io index");
        let crate_ = index.crates().nth(0).expect("could not find a crate in the index");
        let version = crate_.latest_version();
        let _ = version.deps;

        let _ = fs::remove_dir_all(TEST_INDEX_DIR);
    }

    #[test]
    fn test_retrieve_or_update() {
        let _ = fs::remove_dir_all(TEST_INDEX_DIR);

        let index = Index::new(TEST_INDEX_DIR);
        index.retrieve_or_update().expect("could not fetch crates io index");
        assert!(index.exists());
        index.retrieve_or_update().expect("could not fetch crates io index");
        assert!(index.exists());

        let _ = fs::remove_dir_all(TEST_INDEX_DIR);
    }

    #[test]
    fn test_exists() {
        let _ = fs::remove_dir_all(TEST_INDEX_DIR);

        let index = Index::new(TEST_INDEX_DIR);
        assert!(!index.exists());
        index.retrieve().unwrap();
        assert!(index.exists());

        let _ = fs::remove_dir_all(TEST_INDEX_DIR);
    }
}
<commit_msg>remove now-unneeded import<commit_after>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Library for retrieving and interacting with the [crates.io index].
//!
//! [crates.io index]: https://github.com/rust-lang/crates.io-index
//!
//! ## Examples
//!
//! ```rust
//! extern crate crates_index;
//!
//! let index = crates_index::Index::new("_index");
//! if !index.exists() {
//!    index.retrieve().expect("Could not fetch crates.io index");
//! }
//! for crate_ in index.crates() {
//!    let latest_version = crate_.latest_version();
//!    println!("crate name: {}", latest_version.name());
//!    println!("crate version: {}", latest_version.version());
//! }
//! ```

use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::io::{BufRead, BufReader};
use std::iter;
use std::path::{Path, PathBuf};

#[macro_use]
extern crate error_chain;
extern crate git2;
extern crate glob;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde;

error_chain! {
    foreign_links {
        Git(git2::Error);
    }
}

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of a crate published to the index
#[derive(Deserialize, Clone)]
pub struct Version {
    name: String,
    vers: String,
    deps: Vec<Dependency>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

impl Version {
    /// Name of the crate
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Name of this version
    pub fn version(&self) -> &str {
        &self.vers
    }

    /// Dependencies for this version
    pub fn dependencies(&self) -> &[Dependency] {
        &self.deps
    }

    /// Checksum of the package for this version
    pub fn checksum(&self) -> &str {
        &self.cksum
    }

    pub fn features(&self) -> &HashMap<String, Vec<String>> {
        &self.features
    }

    /// Whether this version was [yanked](http://doc.crates.io/crates-io.html#cargo-yank) from the
    /// index
    pub fn is_yanked(&self) -> bool {
        self.yanked
    }
}

/// A single dependency of a specific crate version
#[derive(Deserialize, Clone)]
pub struct Dependency {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>,
}

impl Dependency {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn requirement(&self) -> &str {
        &self.req
    }

    pub fn features(&self) -> &[String] {
        &self.features
    }

    pub fn is_optional(&self) -> bool {
        self.optional
    }

    pub fn has_default_features(&self) -> bool {
        self.default_features
    }

    pub fn target(&self) -> Option<&str> {
        match self.target {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    pub fn kind(&self) -> Option<&str> {
        match self.kind {
            Some(ref s) => Some(s),
            None => None,
        }
    }
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new<P: AsRef<Path>>(path: P) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;
        let path = path.as_ref();

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
#[derive(Debug, Clone, PartialEq)]
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new<P: Into<PathBuf>>(path: P) -> Index {
        Index { path: path.into() }
    }

    /// Determines if a crates.io repository exists at `self.path`
    pub fn exists(&self) -> bool {
        git2::Repository::discover(&self.path)
            .map(|repository| {
                repository
                    .find_remote("origin")
                    .map(|remote| remote.url() == Some(INDEX_GIT_URL))
                    .unwrap_or(false)
            })
            .unwrap_or(false)
    }

    /// Downloads the index to the path specified from the constructor
    pub fn retrieve(&self) -> Result<()> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    /// Assumes the index already exists at `self.path`, and updates it
    pub fn update(&self) -> Result<()> {
        debug_assert!(self.exists());
        let repo = git2::Repository::discover(&self.path)?;
        let mut origin_remote = repo.find_remote("origin")?;
        origin_remote.fetch(&["master"], None, None)?;
        let oid = repo.refname_to_id("refs/remotes/origin/master")?;
        let object = repo.find_object(oid, None).unwrap();
        repo.reset(&object, git2::ResetType::Hard, None)?;
        Ok(())
    }

    /// Downloads the index to the path specified from the constructor
    pub fn retrieve_or_update(&self) -> Result<()> {
        if self.exists() {
            self.update()
        } else {
            self.retrieve()
        }
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| {
                      path.file_name()
                          .and_then(OsStr::to_str)
                          .map(|file_name| file_name.eq_ignore_ascii_case(crate_name))
                          .unwrap_or(false)
                  })
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone()) // TODO: remove this clone
    }

    /// Get the index directory.
    pub fn path(&self) -> &Path {
        &self.path
    }
}

/// A single crate that contains many published versions
pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new<P: AsRef<Path>>(index_path: P) -> Crate {
        let index_path = index_path.as_ref();
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = serde_json::from_str(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate { versions: versions }
    }

    /// Published versions of this crate sorted chronologically by date published
    pub fn versions(&self) -> &[Version] {
        &self.versions
    }

    pub fn earliest_version(&self) -> &Version {
        &self.versions[0]
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }

    pub fn name(&self) -> &str {
        self.latest_version().name()
    }
}

#[cfg(test)]
mod test {
    use std::fs;
    use super::Index;

    static TEST_INDEX_DIR: &'static str = "_test";

    #[test]
    fn test_dependencies() {
        let _ = fs::remove_dir_all(TEST_INDEX_DIR);

        let index = Index::new(TEST_INDEX_DIR);
        index.retrieve().expect("could not fetch crates io index");
        let crate_ = index.crates().nth(0).expect("could not find a crate in the index");
        let version = crate_.latest_version();
        let _ = version.deps;

        let _ = fs::remove_dir_all(TEST_INDEX_DIR);
    }

    #[test]
    fn test_retrieve_or_update() {
        let _ = fs::remove_dir_all(TEST_INDEX_DIR);

        let index = Index::new(TEST_INDEX_DIR);
        index.retrieve_or_update().expect("could not fetch crates io index");
        assert!(index.exists());
        index.retrieve_or_update().expect("could not fetch crates io index");
        assert!(index.exists());

        let _ = fs::remove_dir_all(TEST_INDEX_DIR);
    }

    #[test]
    fn test_exists() {
        let _ = fs::remove_dir_all(TEST_INDEX_DIR);

        let index = Index::new(TEST_INDEX_DIR);
        assert!(!index.exists());
        index.retrieve().unwrap();
        assert!(index.exists());

        let _ = fs::remove_dir_all(TEST_INDEX_DIR);
    }
}
<|endoftext|>


<commit_before>//! The `rust-unidecode` library is a Rust port of Sean M. Burke's famous
//! [`Text::Unidecode`](http://search.cpan.org/~sburke/Text-Unidecode-1.23/lib/Text/Unidecode.pm)
//! module for Perl. It transliterates Unicode strings such as "Æneid" into pure
//! ASCII ones such as "AEneid." For a detailed explanation on the rationale
//! behind using such a library, you can refer to both the documentation of the
//! original module and
//! [this article](http://interglacial.com/~sburke/tpj/as_html/tpj22.html)
//! written by Burke in 2001.
//!
//! The data set used to translate the Unicode was ported directly from the
//! `Text::Unidecode` module using a Perl script, so `rust-unidecode` should
//! produce identical output.
//!
//! Examples
//! --------
//! ```ignore
//! extern crate unidecode;
//! use unidecode::unidecode;
//!
//! assert_eq!(unidecode("Æneid"), "AEneid");
//! assert_eq!(unidecode("étude"), "etude");
//! assert_eq!(unidecode("北亰"), "Bei Jing");
//! assert_eq!(unidecode("ᔕᓇᓇ"), "shanana");
//! assert_eq!(unidecode("げんまい茶"), "genmaiCha ");
//! ```

extern crate phf;

static MAPPING: phf::Map<char, &'static str> =
    include!(concat!(env!("OUT_DIR"), "/codegen.rs"));

/// This function takes any Unicode string and returns an ASCII transliteration
/// of that string.
///
/// # Guarantees
///
/// * The `String` returned will be valid ASCII; the decimal representation of
///   every `char` in the string will be between 0 and 127, inclusive.
/// * Every ASCII character (0x0000 - 0x007F) is mapped to itself.
/// * All Unicode characters will translate to a string containing newlines
///   (`"\n"`) or ASCII characters in the range 0x0020 - 0x007E. So for example,
///   no Unicode character will translate to `\u{01}`. The exception is if the
///   ASCII character itself is passed in, in which case it will be mapped to
///   itself. (So `'\u{01}'` will be mapped to `"\u{01}"`.)
///
/// # Warnings
///
/// * As stated, some transliterations do produce `\n` characters.
/// * Some Unicode characters transliterate to an empty string, either on
///   purpose or because `rust-unidecode` does not know about the character.
/// * Some Unicode characters are unknown and transliterate to `"[?]"`.
/// * Many Unicode characters transliterate to multi-character strings. For
///   example, 北 is transliterated as "Bei ".
///
/// These guarantees/warnings are paraphrased from the original
/// `Text::Unidecode` documentation.
pub fn unidecode(s: &str) -> String {
    let mut res = String::new();
    for ch in s.chars() {
        match MAPPING.get(&ch) {
            Some(ascii_str) => res.push_str(ascii_str),
            None => {}
        }
    }
    res
}

/// This function takes a Unicode Scalar Value and returns an ASCII translation.
///
/// The warning and guarantees of unidecode apply to this function as well.
#[inline]
pub fn unidecode_char(ch: char) -> &'static str {
    MAPPING.get(&ch).map(|&s|s).unwrap_or("")
}
<commit_msg>updated unidecode() function to use unidecode_char()<commit_after>//! The `rust-unidecode` library is a Rust port of Sean M. Burke's famous
//! [`Text::Unidecode`](http://search.cpan.org/~sburke/Text-Unidecode-1.23/lib/Text/Unidecode.pm)
//! module for Perl. It transliterates Unicode strings such as "Æneid" into pure
//! ASCII ones such as "AEneid." For a detailed explanation on the rationale
//! behind using such a library, you can refer to both the documentation of the
//! original module and
//! [this article](http://interglacial.com/~sburke/tpj/as_html/tpj22.html)
//! written by Burke in 2001.
//!
//! The data set used to translate the Unicode was ported directly from the
//! `Text::Unidecode` module using a Perl script, so `rust-unidecode` should
//! produce identical output.
//!
//! Examples
//! --------
//! ```ignore
//! extern crate unidecode;
//! use unidecode::unidecode;
//!
//! assert_eq!(unidecode("Æneid"), "AEneid");
//! assert_eq!(unidecode("étude"), "etude");
//! assert_eq!(unidecode("北亰"), "Bei Jing");
//! assert_eq!(unidecode("ᔕᓇᓇ"), "shanana");
//! assert_eq!(unidecode("げんまい茶"), "genmaiCha ");
//! ```

extern crate phf;

static MAPPING: phf::Map<char, &'static str> =
    include!(concat!(env!("OUT_DIR"), "/codegen.rs"));

/// This function takes any Unicode string and returns an ASCII transliteration
/// of that string.
///
/// # Guarantees
///
/// * The `String` returned will be valid ASCII; the decimal representation of
///   every `char` in the string will be between 0 and 127, inclusive.
/// * Every ASCII character (0x0000 - 0x007F) is mapped to itself.
/// * All Unicode characters will translate to a string containing newlines
///   (`"\n"`) or ASCII characters in the range 0x0020 - 0x007E. So for example,
///   no Unicode character will translate to `\u{01}`. The exception is if the
///   ASCII character itself is passed in, in which case it will be mapped to
///   itself. (So `'\u{01}'` will be mapped to `"\u{01}"`.)
///
/// # Warnings
///
/// * As stated, some transliterations do produce `\n` characters.
/// * Some Unicode characters transliterate to an empty string, either on
///   purpose or because `rust-unidecode` does not know about the character.
/// * Some Unicode characters are unknown and transliterate to `"[?]"`.
/// * Many Unicode characters transliterate to multi-character strings. For
///   example, 北 is transliterated as "Bei ".
///
/// These guarantees/warnings are paraphrased from the original
/// `Text::Unidecode` documentation.
pub fn unidecode(s: &str) -> String {
    s.chars().map(|ch| unidecode_char(ch)).collect()
}

/// This function takes a single Unicode character and returns an ASCII
/// transliteration.
///
/// The warnings and guarantees of `unidecode()` apply to this function as well.
#[inline]
pub fn unidecode_char(ch: char) -> &'static str {
    MAPPING.get(&ch).map(|&s| s).unwrap_or("")
}
<|endoftext|>


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

extern crate conduit;
extern crate "conduit-middleware" as conduit_middleware;
extern crate cookie;
extern crate "rustc-serialize" as serialize;
#[cfg(test)] extern crate "conduit-test" as test;

use std::error::Error;
use std::collections::hash_map::Entry;
use conduit::{Request, Response};
use cookie::{CookieJar, Cookie};

pub use session::{RequestSession, SessionMiddleware};

mod session;

pub struct Middleware {
    key: Vec<u8>,
}

impl Middleware {
    pub fn new(key: &[u8]) -> Middleware {
        Middleware { key: key.to_vec() }
    }
}

impl conduit_middleware::Middleware for Middleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        let jar = {
            let headers = req.headers();
            let mut jar = CookieJar::new(self.key.as_slice());
            match headers.find("Cookie") {
                Some(cookies) => {
                    for cookie in cookies.iter() {
                        for cookie in cookie.split(';').map(|s| s.trim()) {
                            match Cookie::parse(cookie) {
                                Ok(c) => jar.add_original(c),
                                Err(..) => {}
                            }
                        }
                    }
                }
                None => {}
            }
            jar
        };
        req.mut_extensions().insert(jar);
        Ok(())
    }

    fn after(&self, req: &mut Request, res: Result<Response, Box<Error+Send>>)
        -> Result<Response, Box<Error+Send>>
    {
        let mut res = try!(res);
        {
            let jar = req.cookies();
            let cookies = match res.headers.entry("Set-Cookie".to_string()) {
                Entry::Occupied(e) => e.into_mut(),
                Entry::Vacant(e) => e.insert(Vec::new()),
            };
            for delta in jar.delta().into_iter() {
                cookies.push(delta.to_string());
            }
        }
        Ok(res)
    }
}

pub trait RequestCookies<'a> {
    fn cookies(self) -> &'a CookieJar<'static>;
}

impl<'a> RequestCookies<'a> for &'a (Request + 'a) {
    fn cookies(self) -> &'a CookieJar<'static> {
        self.extensions().find::<CookieJar<'static>>()
            .expect("Missing cookie jar")
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use std::old_io::{MemReader, IoError};

    use conduit::{Request, Response, Handler, Method};
    use conduit_middleware::MiddlewareBuilder;
    use cookie::Cookie;
    use test::MockRequest;

    use super::{RequestCookies, Middleware};

    #[test]
    fn request_headers() {
        let mut req = MockRequest::new(Method::Post, "/articles");
        req.header("Cookie", "foo=bar");

        let mut app = MiddlewareBuilder::new(test);
        app.add(Middleware::new(b"foo"));
        assert!(app.call(&mut req).is_ok());

        fn test(req: &mut Request) -> Result<Response, IoError> {
            assert!(req.cookies().find("foo").is_some());
            Ok(Response {
                status: (200, "OK"),
                headers: HashMap::new(),
                body: Box::new(MemReader::new(Vec::new())),
            })
        }
    }

    #[test]
    fn set_cookie() {
        let mut req = MockRequest::new(Method::Post, "/articles");
        let mut app = MiddlewareBuilder::new(test);
        app.add(Middleware::new(b"foo"));
        let response = app.call(&mut req).ok().unwrap();
        let v = response.headers["Set-Cookie".to_string()].as_slice();
        assert_eq!(v, ["foo=bar; Path=/".to_string()].as_slice());

        fn test(req: &mut Request) -> Result<Response, IoError> {
            let c = Cookie::new("foo".to_string(), "bar".to_string());
            req.cookies().add(c);
            Ok(Response {
                status: (200, "OK"),
                headers: HashMap::new(),
                body: Box::new(MemReader::new(Vec::new())),
            })
        }
    }
}
<commit_msg>Update to rust master<commit_after>#![feature(collections, core)]
#![cfg_attr(test, feature(io))]
#![cfg_attr(test, deny(warnings))]

extern crate conduit;
extern crate "conduit-middleware" as conduit_middleware;
extern crate cookie;
extern crate "rustc-serialize" as serialize;
#[cfg(test)] extern crate "conduit-test" as test;

use std::error::Error;
use std::collections::hash_map::Entry;
use conduit::{Request, Response};
use cookie::{CookieJar, Cookie};

pub use session::{RequestSession, SessionMiddleware};

mod session;

pub struct Middleware {
    key: Vec<u8>,
}

impl Middleware {
    pub fn new(key: &[u8]) -> Middleware {
        Middleware { key: key.to_vec() }
    }
}

impl conduit_middleware::Middleware for Middleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        let jar = {
            let headers = req.headers();
            let mut jar = CookieJar::new(self.key.as_slice());
            match headers.find("Cookie") {
                Some(cookies) => {
                    for cookie in cookies.iter() {
                        for cookie in cookie.split(';').map(|s| s.trim()) {
                            match Cookie::parse(cookie) {
                                Ok(c) => jar.add_original(c),
                                Err(..) => {}
                            }
                        }
                    }
                }
                None => {}
            }
            jar
        };
        req.mut_extensions().insert(jar);
        Ok(())
    }

    fn after(&self, req: &mut Request, res: Result<Response, Box<Error+Send>>)
        -> Result<Response, Box<Error+Send>>
    {
        let mut res = try!(res);
        {
            let jar = req.cookies();
            let cookies = match res.headers.entry("Set-Cookie".to_string()) {
                Entry::Occupied(e) => e.into_mut(),
                Entry::Vacant(e) => e.insert(Vec::new()),
            };
            for delta in jar.delta().into_iter() {
                cookies.push(delta.to_string());
            }
        }
        Ok(res)
    }
}

pub trait RequestCookies<'a> {
    fn cookies(self) -> &'a CookieJar<'static>;
}

impl<'a> RequestCookies<'a> for &'a (Request + 'a) {
    fn cookies(self) -> &'a CookieJar<'static> {
        self.extensions().find::<CookieJar<'static>>()
            .expect("Missing cookie jar")
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use std::old_io::{MemReader, IoError};

    use conduit::{Request, Response, Handler, Method};
    use conduit_middleware::MiddlewareBuilder;
    use cookie::Cookie;
    use test::MockRequest;

    use super::{RequestCookies, Middleware};

    #[test]
    fn request_headers() {
        let mut req = MockRequest::new(Method::Post, "/articles");
        req.header("Cookie", "foo=bar");

        let mut app = MiddlewareBuilder::new(test);
        app.add(Middleware::new(b"foo"));
        assert!(app.call(&mut req).is_ok());

        fn test(req: &mut Request) -> Result<Response, IoError> {
            assert!(req.cookies().find("foo").is_some());
            Ok(Response {
                status: (200, "OK"),
                headers: HashMap::new(),
                body: Box::new(MemReader::new(Vec::new())),
            })
        }
    }

    #[test]
    fn set_cookie() {
        let mut req = MockRequest::new(Method::Post, "/articles");
        let mut app = MiddlewareBuilder::new(test);
        app.add(Middleware::new(b"foo"));
        let response = app.call(&mut req).ok().unwrap();
        let v = response.headers["Set-Cookie".to_string()].as_slice();
        assert_eq!(v, ["foo=bar; Path=/".to_string()].as_slice());

        fn test(req: &mut Request) -> Result<Response, IoError> {
            let c = Cookie::new("foo".to_string(), "bar".to_string());
            req.cookies().add(c);
            Ok(Response {
                status: (200, "OK"),
                headers: HashMap::new(),
                body: Box::new(MemReader::new(Vec::new())),
            })
        }
    }
}
<|endoftext|>


<commit_before>//! # Functor composition via the Co-Yoneda Lemma
//!
//! ## Functors in Rust
//!
//! Let's implement functors in Rust!
//!
//! Working around the lack of higher-kinded types, our trait for a functor
//! will look something like this:
//!
//! ```
//! pub trait Functor<'a, A, B> {
//!    type Output;
//!    fn fmap<F: Fn(A) -> B + 'a>(self, F) -> Self::Output;
//! }
//! ```
//!
//! This works great as long as we write functions that take specific
//! types which are functors, but it is not possible to write a function
//! operating on a generic functor type and using `fmap` more than once.
//! For example, the following will not compile:
//!
//! ```
//! fn add_and_to_string<'a, F: Functor<'a, i32, String>>(x: F) -> F::Output {
//!    x.fmap(|n: i32| n + 1)
//!     .fmap(|n: i32| n.to_string())
//! }
//! ```
//!
//! While functors in general can be encoded to some extend
//! in Rust's trait system, what we can't encode for a lack of higher-kinded
//! types, is the fact that a functor `Box` maps a function between `A` and `B`
//! to a function between `Box<A>` and `Box<B>`, not between `Box<A>` and `Option<B>`.
//!
//! Especially when looking at functor composition, it is useful to
//! be able to encode this fact, because it allows us to chain
//! multiple calls to `fmap`, knowing that the result is also a functor,
//! and can be `fmap`'ed further.
//!
//! ## The Co-Yoneda Lemma
//!
//! Let's define a data type called `Coyoneda`:
//!
//! ```
//! pub struct Coyoneda<'a, T: Param, B> {
//!     point: T,
//!     morph: Fn(T::Param) -> B + 'a
//! }
//! ```
//!
//! This datatype is a functor, which uses function composition
//! to accumulate the mapping function, without changing the captured
//! `T`. The implementation for `Functor` is trivial:
//!
//! ```
//! impl<'a, T: Param, B, C> Functor<'a, B, C> for Coyoneda<'a, T, B> {
//!     type Output = Coyoneda<'a, T, C>;
//!     fn fmap<F: Fn(B) -> C + 'a>(self, f: F) -> Coyoneda<'a, T, C> {
//!         let g = self.morph;
//!         Coyoneda{point: self.point, morph: move |x| f(g(x))}
//!     }
//! }
//! ```
//!
//! The co-yoneda lemma states that for a covariant functor `f`,
//! this `Coyoneda f` is naturally isomorphic to `f`.
//! Practically speaking, this means that we can lift any `f a` into a `Coyoneda f a`,
//! and given a function `(a -> b) -> f b`, we can retrieve back a `f b` from a `Coyoneda f b`.
//!
//! ## Composing Coyoneda
//!
//! Now here's the catch: Since we have a parameterized datatype that is isomorphic to any functor,
//! we can lift functors into Coyoneda to compose them safely within Rust's type system!
//!
//! For example, let's implement a function that is generic for any functor,
//! by operating on our `Coyoneda` type:
//!
//! ```
//! fn add_and_to_string<T: Param>(y: Coyoneda<T, i32>) -> Coyoneda<T, String> {
//!    y.fmap(|n: i32| n + 1)
//!     .fmap(|n: i32| n.to_string())
//! }
//! ```
//!
//! Given we implemented a functor for `Option`, we can now do the following:
//!
//! ```
//! let y = add_and_to_string(From::from(Some(42)));
//! assert_eq!(y.unwrap(), Some("43".to_string()))
//! ```
//!
//! ... or for `Box`:
//!
//! ```
//! let y = add_and_to_string(From::from(Box::new(42)));
//! assert_eq!(y.unwrap(), Box::new("43".to_string()))
//! ```
//!
//! ... and for every other functor as well. Yay!

mod morphism;

use morphism::Morphism;

pub trait Param { type Param; }

pub trait Functor<'a, A, B>: Param {
    type Output: Param<Param=B>;
    fn fmap<F: Fn(A) -> B + 'a>(self, F) -> Self::Output;
}

pub struct Coyoneda<'a, T: Param, B> {
    point: T,
    morph: Morphism<'a, T::Param, B>
}

pub trait NaturalTransform<T: Param<Param=Self::Param>>: Param {
    fn transform(self) -> T;
}

impl<'a, T: 'a + Param, B: 'a> Coyoneda<'a, T, B> {

    pub fn transform<U: Param, F, G>(self, f: F, g: G) -> Coyoneda<'a, U, B>
        where F: Fn(T) -> U, G: 'a + Fn(U::Param) -> T::Param {
        let Coyoneda{point: t, morph: m} = self;
        Coyoneda{point: f(t), morph: m.head(g)}
    }

    pub fn natural_transform<U: Param<Param=T::Param>>(self) -> Coyoneda<'a, U, B>
        where T: NaturalTransform<U> {
        let Coyoneda{point: t, morph: m} = self;
        Coyoneda{point: t.transform(), morph: m}
    }

    pub fn unwrap(self) -> <T as Functor<'a, <T as Param>::Param, B>>::Output
        where T: Functor<'a, <T as Param>::Param, B>, <T as Param>::Param: 'a {
        let m = self.morph;
        T::fmap(self.point, move |a| { m.run(a) })
    }

}

impl<'a, T: Param, B> Param for Coyoneda<'a, T, B> {
    type Param = B;
}

impl<'a, T: Param, B, C> Functor<'a, B, C> for Coyoneda<'a, T, B> {
    type Output = Coyoneda<'a, T, C>;
    fn fmap<F: Fn(B) -> C + 'a>(self, f: F) -> Coyoneda<'a, T, C> {
        Coyoneda{point: self.point, morph: self.morph.tail(f)}
    }
}

impl<'a, T: Param> From<T> for Coyoneda<'a, T, <T as Param>::Param> {
    fn from(x: T) -> Coyoneda<'a, T, <T as Param>::Param> {
        Coyoneda{point: x, morph: Morphism::new()}
    }
}

impl<A> Param for Box<A> {
    type Param = A;
}

impl<'a, A, B> Functor<'a, A, B> for Box<A> {
    type Output = Box<B>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Box::new(f(*self))
    }
}

impl<A> NaturalTransform<Option<A>> for Box<A> {
    fn transform(self) -> Option<A> {
        Option::Some(*self)
    }
}

impl<A> Param for Option<A> {
    type Param = A;
}

impl<'a, A, B> Functor<'a, A, B> for Option<A> {
    type Output = Option<B>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Option::map(self, f)
    }
}

impl<A, E> Param for Result<A, E> {
    type Param = A;
}

impl<'a, A, B, E> Functor<'a, A, B> for Result<A, E> {
    type Output = Result<B, E>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Result::map(self, f)
    }
}

impl<A, E> NaturalTransform<Option<A>> for Result<A, E> {
    fn transform(self) -> Option<A> {
        match self {
            Ok(a) => Some(a),
            Err(_) => None
        }
    }
}

mod test {
#![cfg(test)]

    use super::*;

    fn add_and_to_string<T: Param>(y: Coyoneda<T, i32>) -> Coyoneda<T, String> {
        y.fmap(|n: i32| n + 1)
         .fmap(|n: i32| n.to_string())
         .fmap(|s| s + "foo")
         .fmap(|s| s + "bar")
    }

    #[test]
    fn fmap_box() {
        let x = Box::new(42);
        let y = add_and_to_string(From::from(x));
        assert_eq!(y.unwrap(), Box::new("43foobar".to_string()))
    }

    #[test]
    fn fmap_option() {
        let x = Some(42);
        let y = add_and_to_string(From::from(x));
        assert_eq!(y.unwrap(), Some("43foobar".to_string()))
    }

    #[test]
    fn fmap_result() {
        let x: Result<i32, ()> = Ok(42);
        let y = add_and_to_string(From::from(x));
        assert_eq!(y.unwrap(), Ok("43foobar".to_string()))
    }

    #[test]
    fn transform() {
        let x = Box::new(42);
        let y = add_and_to_string(From::from(x));
        let z = y.transform(|x| Option::Some(*x as usize), |x| x as i32);
        assert_eq!(z.unwrap(), Some("43foobar".to_string()))
    }

    #[test]
    fn natural_transform_box_to_option() {
        let x = Box::new(42);
        let y = add_and_to_string(From::from(x));
        let z = y.natural_transform();
        assert_eq!(z.unwrap(), Some("43foobar".to_string()))
    }

    #[test]
    fn natural_transform_result_to_option() {
        let x: Result<i32, ()> = Ok(42);
        let y = add_and_to_string(From::from(x));
        let z = y.natural_transform();
        assert_eq!(z.unwrap(), Some("43foobar".to_string()))
    }

}
<commit_msg>change functor<commit_after>//! # Functor composition via the Co-Yoneda Lemma
//!
//! ## Functors in Rust
//!
//! Let's implement functors in Rust!
//!
//! Working around the lack of higher-kinded types, our trait for a functor
//! will look something like this:
//!
//! ```
//! pub trait Param { type Param; }
//! pub trait Functor<'a, B>: Param {
//!     type Output: Param<Param=B>;
//!     fn fmap<F: Fn(Self::Param) -> B + 'a>(self, F) -> Self::Output;
//! }
//! ```
//!
//! This works great as long as we write functions that take specific
//! types which are functors, but it is not possible to write a function
//! operating on a generic functor type and using `fmap` more than once.
//! For example, the following will not compile:
//!
//! ```
//! fn add_and_to_string<'a, F>(x: F) -> <F as Functor<'a, String>>::Output
//!    where F: Param<Param=i32> + Functor<'a, i32> + Functor<'a, String> {
//!    x.fmap(|n: i32| n + 1)
//!     .fmap(|n: i32| n.to_string())
//! }
//! ```
//!
//! While functors in general can be encoded to some extend
//! in Rust's trait system, what we can't encode for a lack of higher-kinded
//! types, is the fact that a functor `Box` maps a function between `A` and `B`
//! to a function between `Box<A>` and `Box<B>`, not between `Box<A>` and `Option<B>`.
//!
//! Especially when looking at functor composition, it is useful to
//! be able to encode this fact, because it allows us to chain
//! multiple calls to `fmap`, knowing that the result is also a functor,
//! and can be `fmap`'ed further.
//!
//! ## The Co-Yoneda Lemma
//!
//! Let's define a data type called `Coyoneda`:
//!
//! ```
//! pub struct Coyoneda<'a, T: Param, B> {
//!     point: T,
//!     morph: Fn(T::Param) -> B + 'a
//! }
//! ```
//!
//! This datatype is a functor, which uses function composition
//! to accumulate the mapping function, without changing the captured
//! `T`. The implementation for `Functor` is trivial:
//!
//! ```
//! impl<'a, T: Param, B, C> Functor<'a, C> for Coyoneda<'a, T, B> {
//!     type Output = Coyoneda<'a, T, C>;
//!     fn fmap<F: Fn(B) -> C + 'a>(self, f: F) -> Coyoneda<'a, T, C> {
//!         let g = self.morph;
//!         Coyoneda{point: self.point, morph: move |x| f(g(x))}
//!     }
//! }
//! ```
//!
//! The co-yoneda lemma states that for a covariant functor `f`,
//! this `Coyoneda f` is naturally isomorphic to `f`.
//! Practically speaking, this means that we can lift any `f a` into a `Coyoneda f a`,
//! and given a function `(a -> b) -> f b`, we can retrieve back a `f b` from a `Coyoneda f b`.
//!
//! ## Composing Coyoneda
//!
//! Now here's the catch: Since we have a parameterized datatype that is isomorphic to any functor,
//! we can lift functors into Coyoneda to compose them safely within Rust's type system!
//!
//! For example, let's implement a function that is generic for any functor,
//! by operating on our `Coyoneda` type:
//!
//! ```
//! fn add_and_to_string<T: Param>(y: Coyoneda<T, i32>) -> Coyoneda<T, String> {
//!    y.fmap(|n: i32| n + 1)
//!     .fmap(|n: i32| n.to_string())
//! }
//! ```
//!
//! Given we implemented a functor for `Option`, we can now do the following:
//!
//! ```
//! let y = add_and_to_string(From::from(Some(42)));
//! assert_eq!(y.unwrap(), Some("43".to_string()))
//! ```
//!
//! ... or for `Box`:
//!
//! ```
//! let y = add_and_to_string(From::from(Box::new(42)));
//! assert_eq!(y.unwrap(), Box::new("43".to_string()))
//! ```
//!
//! ... and for every other functor as well. Yay!

mod morphism;

use morphism::Morphism;

pub trait Param { type Param; }

pub trait Functor<'a, B>: Param {
    type Output: Param<Param=B>;
    fn fmap<F: Fn(Self::Param) -> B + 'a>(self, F) -> Self::Output;
}

pub struct Coyoneda<'a, T: Param, B> {
    point: T,
    morph: Morphism<'a, T::Param, B>
}

pub trait NaturalTransform<T: Param<Param=Self::Param>>: Param {
    fn transform(self) -> T;
}

impl<'a, T: 'a + Param, B: 'a> Coyoneda<'a, T, B> {

    pub fn transform<U: Param, F, G>(self, f: F, g: G) -> Coyoneda<'a, U, B>
        where F: Fn(T) -> U, G: 'a + Fn(U::Param) -> T::Param {
        let Coyoneda{point: t, morph: m} = self;
        Coyoneda{point: f(t), morph: m.head(g)}
    }

    pub fn natural_transform<U: Param<Param=T::Param>>(self) -> Coyoneda<'a, U, B>
        where T: NaturalTransform<U> {
        let Coyoneda{point: t, morph: m} = self;
        Coyoneda{point: t.transform(), morph: m}
    }

    pub fn unwrap(self) -> <T as Functor<'a, B>>::Output
        where T: Functor<'a, B>, <T as Param>::Param: 'a {
        let m = self.morph;
        T::fmap(self.point, move |a| { m.run(a) })
    }

}

impl<'a, T: Param, B> Param for Coyoneda<'a, T, B> {
    type Param = B;
}

impl<'a, T: Param, B, C> Functor<'a, C> for Coyoneda<'a, T, B> {
    type Output = Coyoneda<'a, T, C>;
    fn fmap<F: Fn(B) -> C + 'a>(self, f: F) -> Coyoneda<'a, T, C> {
        Coyoneda{point: self.point, morph: self.morph.tail(f)}
    }
}

impl<'a, T: Param> From<T> for Coyoneda<'a, T, <T as Param>::Param> {
    fn from(x: T) -> Coyoneda<'a, T, <T as Param>::Param> {
        Coyoneda{point: x, morph: Morphism::new()}
    }
}

impl<A> Param for Box<A> {
    type Param = A;
}

impl<'a, A, B> Functor<'a, B> for Box<A> {
    type Output = Box<B>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Box::new(f(*self))
    }
}

impl<A> NaturalTransform<Option<A>> for Box<A> {
    fn transform(self) -> Option<A> {
        Option::Some(*self)
    }
}

impl<A> Param for Option<A> {
    type Param = A;
}

impl<'a, A, B> Functor<'a, B> for Option<A> {
    type Output = Option<B>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Option::map(self, f)
    }
}

impl<A, E> Param for Result<A, E> {
    type Param = A;
}

impl<'a, A, B, E> Functor<'a, B> for Result<A, E> {
    type Output = Result<B, E>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Result::map(self, f)
    }
}

impl<A, E> NaturalTransform<Option<A>> for Result<A, E> {
    fn transform(self) -> Option<A> {
        match self {
            Ok(a) => Some(a),
            Err(_) => None
        }
    }
}

mod test {
#![cfg(test)]

    use super::*;

    fn add_and_to_string<T: Param>(y: Coyoneda<T, i32>) -> Coyoneda<T, String> {
        y.fmap(|n: i32| n + 1)
         .fmap(|n: i32| n.to_string())
         .fmap(|s| s + "foo")
         .fmap(|s| s + "bar")
    }

    #[test]
    fn fmap_box() {
        let x = Box::new(42);
        let y = add_and_to_string(From::from(x));
        assert_eq!(y.unwrap(), Box::new("43foobar".to_string()))
    }

    #[test]
    fn fmap_option() {
        let x = Some(42);
        let y = add_and_to_string(From::from(x));
        assert_eq!(y.unwrap(), Some("43foobar".to_string()))
    }

    #[test]
    fn fmap_result() {
        let x: Result<i32, ()> = Ok(42);
        let y = add_and_to_string(From::from(x));
        assert_eq!(y.unwrap(), Ok("43foobar".to_string()))
    }

    #[test]
    fn transform() {
        let x = Box::new(42);
        let y = add_and_to_string(From::from(x));
        let z = y.transform(|x| Option::Some(*x as usize), |x| x as i32);
        assert_eq!(z.unwrap(), Some("43foobar".to_string()))
    }

    #[test]
    fn natural_transform_box_to_option() {
        let x = Box::new(42);
        let y = add_and_to_string(From::from(x));
        let z = y.natural_transform();
        assert_eq!(z.unwrap(), Some("43foobar".to_string()))
    }

    #[test]
    fn natural_transform_result_to_option() {
        let x: Result<i32, ()> = Ok(42);
        let y = add_and_to_string(From::from(x));
        let z = y.natural_transform();
        assert_eq!(z.unwrap(), Some("43foobar".to_string()))
    }

}
<|endoftext|>


<commit_before>//! SIMD support
//!
//! This crate provides the fundamentals of supporting SIMD in Rust. This crate
//! should compile on all platforms and provide `simd` and `vendor` modules at
//! the top-level. The `simd` module contains *portable vector types* which
//! should work across all platforms and be implemented in the most efficient
//! manner possible for the platform at hand. The `vendor` module contains
//! vendor intrinsics that operate over these SIMD types, typically
//! corresponding to a particular CPU instruction
//!
//! ```rust
//! extern crate stdsimd;
//! use stdsimd::simd::u32x4;
//!
//! fn main() {
//!     let a = u32x4::new(1, 2, 3, 4);
//!     let b = u32x4::splat(10);
//!     assert_eq!(a + b, u32x4::new(11, 12, 13, 14));
//! }
//! ```
//!
//! > **Note**: This crate is *nightly only* at the moment, and requires a
//! > nightly rust toolchain to compile.
//!
//! ## Portability
//!
//! The `simd` module and its types should be portable to all platforms. The
//! runtime characteristics of these types may vary per paltform and per CPU
//! feature enabled, but they should always have the most optimized
//! implementation for the target at hand.
//!
//! The `vendor` module provides no portability guarantees. The `vendor` module
//! is per CPU architecture currently and provides intrinsics corresponding to
//! functions for that particular CPU architecture. Note that the functions
//! provided in this module are intended to correspond to CPU instructions and
//! have no runtime support for whether you CPU actually supports the
//! instruction.
//!
//! CPU target feature detection is done via the `cfg_feature_enabled!` macro at
//! runtime. This macro will detect at runtime whether the specified feature is
//! available or not, returning true or false depending on the current CPU.
//!
//! ```
//! #![feature(cfg_target_feature)]
//!
//! #[macro_use]
//! extern crate stdsimd;
//!
//! fn main() {
//!     if cfg_feature_enabled!("avx2") {
//!         println!("avx2 intrinsics will work");
//!     } else {
//!         println!("avx2 intrinsics will not work, they may generate SIGILL");
//!     }
//! }
//! ```
//!
//! # Status
//!
//! This crate is intended for eventual inclusion into the standard library, but
//! some work and experimentation is needed to get there! First and foremost you
//! can help out by kicking the tires on this crate and seeing if it works for
//! your use case! Next up you can help us fill out the [vendor
//! intrinsics][vendor] to ensure that we've got all the SIMD support necessary.
//!
//! The language support and status of SIMD is also still a little up in the air
//! right now, you may be interested in a few issues along these lines:
//!
//! * [Overal tracking issue for SIMD support](https://github.com/rust-lang/rust/issues/27731)
//! * [`cfg_target_feature` tracking issue](https://github.com/rust-lang/rust/issues/29717)
//! * [SIMD types currently not sound](https://github.com/rust-lang/rust/issues/44367)
//! * [`#[target_feature]` improvements](https://github.com/rust-lang/rust/issues/44839)
//!
//! [vendor]: https://github.com/rust-lang-nursery/stdsimd/issues/40

#![allow(dead_code)]
#![feature(
    const_fn, link_llvm_intrinsics, platform_intrinsics, repr_simd, simd_ffi,
    target_feature, cfg_target_feature, i128_type, asm, const_atomic_usize_new
)]
#![cfg_attr(test, feature(proc_macro))]

#[cfg(test)]
extern crate assert_instr;

/// Platform independent SIMD vector types and operations.
pub mod simd {
    pub use v128::*;
    pub use v256::*;
    pub use v512::*;
    pub use v64::*;
}

/// Platform dependent vendor intrinsics.
pub mod vendor {
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    pub use x86::*;

    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    pub use arm::*;
}

#[macro_use]
mod macros;
mod simd_llvm;
mod v128;
mod v256;
mod v512;
mod v64;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[macro_use]
mod x86;

#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
mod arm;
<commit_msg>Add links to docs<commit_after>//! SIMD support
//!
//! This crate provides the fundamentals of supporting SIMD in Rust. This crate
//! should compile on all platforms and provide `simd` and `vendor` modules at
//! the top-level. The `simd` module contains *portable vector types* which
//! should work across all platforms and be implemented in the most efficient
//! manner possible for the platform at hand. The `vendor` module contains
//! vendor intrinsics that operate over these SIMD types, typically
//! corresponding to a particular CPU instruction
//!
//! ```rust
//! extern crate stdsimd;
//! use stdsimd::simd::u32x4;
//!
//! fn main() {
//!     let a = u32x4::new(1, 2, 3, 4);
//!     let b = u32x4::splat(10);
//!     assert_eq!(a + b, u32x4::new(11, 12, 13, 14));
//! }
//! ```
//!
//! > **Note**: This crate is *nightly only* at the moment, and requires a
//! > nightly rust toolchain to compile.
//!
//! This documentation is only for one particular architecture, you can find
//! others at:
//!
//! * [i686](https://rust-lang-nursery.github.io/stdsimd/i686/stdsimd/)
//! * [x86_64](https://rust-lang-nursery.github.io/stdsimd/x86_64/stdsimd/)
//! * [arm](https://rust-lang-nursery.github.io/stdsimd/arm/stdsimd/)
//! * [aarch64](https://rust-lang-nursery.github.io/stdsimd/aarch64/stdsimd/)
//!
//! ## Portability
//!
//! The `simd` module and its types should be portable to all platforms. The
//! runtime characteristics of these types may vary per paltform and per CPU
//! feature enabled, but they should always have the most optimized
//! implementation for the target at hand.
//!
//! The `vendor` module provides no portability guarantees. The `vendor` module
//! is per CPU architecture currently and provides intrinsics corresponding to
//! functions for that particular CPU architecture. Note that the functions
//! provided in this module are intended to correspond to CPU instructions and
//! have no runtime support for whether you CPU actually supports the
//! instruction.
//!
//! CPU target feature detection is done via the `cfg_feature_enabled!` macro at
//! runtime. This macro will detect at runtime whether the specified feature is
//! available or not, returning true or false depending on the current CPU.
//!
//! ```
//! #![feature(cfg_target_feature)]
//!
//! #[macro_use]
//! extern crate stdsimd;
//!
//! fn main() {
//!     if cfg_feature_enabled!("avx2") {
//!         println!("avx2 intrinsics will work");
//!     } else {
//!         println!("avx2 intrinsics will not work, they may generate SIGILL");
//!     }
//! }
//! ```
//!
//! # Status
//!
//! This crate is intended for eventual inclusion into the standard library, but
//! some work and experimentation is needed to get there! First and foremost you
//! can help out by kicking the tires on this crate and seeing if it works for
//! your use case! Next up you can help us fill out the [vendor
//! intrinsics][vendor] to ensure that we've got all the SIMD support necessary.
//!
//! The language support and status of SIMD is also still a little up in the air
//! right now, you may be interested in a few issues along these lines:
//!
//! * [Overal tracking issue for SIMD support](https://github.com/rust-lang/rust/issues/27731)
//! * [`cfg_target_feature` tracking issue](https://github.com/rust-lang/rust/issues/29717)
//! * [SIMD types currently not sound](https://github.com/rust-lang/rust/issues/44367)
//! * [`#[target_feature]` improvements](https://github.com/rust-lang/rust/issues/44839)
//!
//! [vendor]: https://github.com/rust-lang-nursery/stdsimd/issues/40

#![allow(dead_code)]
#![feature(
    const_fn, link_llvm_intrinsics, platform_intrinsics, repr_simd, simd_ffi,
    target_feature, cfg_target_feature, i128_type, asm, const_atomic_usize_new
)]
#![cfg_attr(test, feature(proc_macro))]

#[cfg(test)]
extern crate assert_instr;

/// Platform independent SIMD vector types and operations.
pub mod simd {
    pub use v128::*;
    pub use v256::*;
    pub use v512::*;
    pub use v64::*;
}

/// Platform dependent vendor intrinsics.
pub mod vendor {
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    pub use x86::*;

    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    pub use arm::*;
}

#[macro_use]
mod macros;
mod simd_llvm;
mod v128;
mod v256;
mod v512;
mod v64;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[macro_use]
mod x86;

#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
mod arm;
<|endoftext|>