<commit_before>use runtime::Error;
use values::Value;
use memory::{RcValue, Memory};

pub static PRIMITIVES: [&'static str; 18] = [
    "*",
    "+",
    "-",
    "/",
    "<",
    "<=",
    "=",
    ">",
    ">=",
    "car",
    "cdr",
    "cons",
    "length",
    "list",
    "list?",
    "not",
    "null?",
    "pair?",
];

pub fn apply(name: &String, args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    match name.as_slice() {
        "*"      => product(args, mem),
        "+"      => plus(args, mem),
        "-"      => minus(args, mem),
        "/"      => division(args, mem),
        "<"      => less_than(args, mem),
        "<="     => less_than_or_equal(args, mem),
        "="      => equals(args, mem),
        ">"      => greater_than(args, mem),
        ">="     => greater_than_or_equal(args, mem),
        "car"    => car(args, mem),
        "cdr"    => cdr(args, mem),
        "cons"   => cons(args, mem),
        "length" => length(args, mem),
        "list"   => list(args, mem),
        "list?"  => list_question_mark(args, mem),
        "not"    => not(args, mem),
        "null?"  => null(args, mem),
        "pair?"  => pair(args, mem),
        _        => Err(Error::PrimitiveFailed(name.to_string()))
    }
}

fn plus(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    let args_ = try!(list_of_integers(args));
    let sum = args_.iter().fold(0, |sum, n| sum + *n);

    Ok(mem.integer(sum))
}

fn minus(args_: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    let args = try!(list_of_integers(args_));

    if args.len() == 0 {
        return Err(Error::BadArity(Some("-".to_string())))
    }

    let head = args.first().unwrap();
    let tail = args.tail();

    if tail.is_empty() {
        return Ok(mem.integer(- *head))
    }

    let tail_sum = tail.iter().fold(0, |sum, n| sum + *n);
    Ok(mem.integer(*head - tail_sum))
}

fn division(args_: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    let args = try!(list_of_integers(args_));

    if args.len() == 0 {
        return Err(Error::BadArity(Some("/".to_string())))
    }

    let head = args.first().unwrap();
    let tail = args.tail();

    if tail.is_empty() {
        return Ok(mem.integer(1 / *head))
    }

    let div = tail.iter().fold(*head, |div, n| div / *n);
    Ok(mem.integer(div))
}

fn product(args_: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    let args = try!(list_of_integers(args_));
    let product = args.iter().fold(1, |product, n| product * *n);

    Ok(mem.integer(product))
}

fn equals(args_: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args_.len() < 2 {
        return Ok(mem.b_true());
    }

    let args = try!(list_of_integers(args_));
    let head = args.first().unwrap();
    let outcome = args.iter().skip(1).all(|n| *n == *head);

    Ok(mem.boolean(outcome))
}

fn less_than(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    ord(args, mem, |a, b| a < b)
}

fn less_than_or_equal(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    ord(args, mem, |a, b| a <= b)
}

fn greater_than(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    ord(args, mem, |a, b| a > b)
}

fn greater_than_or_equal(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    ord(args, mem, |a, b| a >= b)
}

fn not(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("not".to_string())))
    }

    let outcome = match **args.first().unwrap() {
        Value::Bool(false) => true,
        _                  => false,
    };

    Ok(mem.boolean(outcome))
}

fn list(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    Ok(mem.list(args))
}

fn length(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("length".to_string())));
    }

    match *args[0] {
        Value::List(ref list) =>
            Ok(mem.integer(list.len() as i64)),
        ref value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn pair(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("pair?".to_string())));
    }

    let outcome = if let Value::List(ref list) = *args[0] {
        !list.is_empty()
    } else if let Value::DottedList(ref _list, ref _el) = *args[0] {
        true
    } else {
        false
    };

    Ok(mem.boolean(outcome))
}

fn cons(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 2 {
        return Err(Error::BadArity(Some("cons".to_string())));
    }

    let mut list: Vec<RcValue> = Vec::new();
    list.push(args[0].clone());

    if let Value::List(ref l) = *args[1] {
        for item in l.iter() {
            list.push(mem.store(item.clone()));
        }

        Ok(mem.list(list))
    } else {
        Ok(mem.dotted_list(list, (*args[1]).clone()))
    }
}

fn car(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("car".to_string())));
    }

    match *args[0] {
        Value::List(ref l) if !l.is_empty() =>
            Ok(mem.store(l.first().unwrap().clone())),
        Value::DottedList(ref l, ref _t) =>
            Ok(mem.store(l.first().unwrap().clone())),
        ref value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn cdr(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("cdr".to_string())));
    }

    match *args[0] {
        Value::List(ref l) if !l.is_empty() =>
            match l.tail() {
                tail if tail.is_empty() =>
                    Ok(mem.empty_list()),
                tail => {
                    let mut list = Vec::with_capacity(tail.len());

                    for item in tail.iter() {
                        list.push(mem.store(item.clone()));
                    }

                    Ok(mem.list(list))
                }
            },
        Value::DottedList(ref _l, ref t) =>
            Ok(mem.store(*t.clone())),
        ref value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn null(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("null?".to_string())));
    }

    let outcome = *args[0] == *mem.empty_list();
    Ok(mem.boolean(outcome))
}

fn list_question_mark(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("list?".to_string())));
    }

    let out = if let Value::List(ref _l) = *args[0] {
        true
    } else {
        false
    };

    Ok(mem.boolean(out))
}

fn list_of_integers(list: Vec<RcValue>) -> Result<Vec<i64>, Error> {
    let mut integers = Vec::with_capacity(list.len());

    for val in list.into_iter() {
        match *val {
            Value::Integer(n) =>
                integers.push(n),
            ref value =>
                return Err(Error::WrongArgumentType(value.clone())),
        }
    }

    Ok(integers)
}

fn ord(args_: Vec<RcValue>, mem: &mut Memory, cmp: |i64, i64| -> bool) -> Result<RcValue, Error> {
    if args_.len() < 2 {
        return Ok(mem.b_true())
    }

    let args = try!(list_of_integers(args_));
    let outcome = range(0, args.len() - 1).all(|i|
        cmp(args[i], args[i + 1u])
    );

    return Ok(mem.boolean(outcome))
}
<commit_msg>Refactored primitives a bit.<commit_after>use runtime::Error;
use values::Value;
use memory::{RcValue, Memory};

pub static PRIMITIVES: [&'static str; 18] = [
    "*",
    "+",
    "-",
    "/",
    "<",
    "<=",
    "=",
    ">",
    ">=",
    "car",
    "cdr",
    "cons",
    "length",
    "list",
    "list?",
    "not",
    "null?",
    "pair?",
];

pub fn apply(name: &String, args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    match name.as_slice() {
        "*"      => product(args, mem),
        "+"      => plus(args, mem),
        "-"      => minus(args, mem),
        "/"      => division(args, mem),
        "<"      => less_than(args, mem),
        "<="     => less_than_or_equal(args, mem),
        "="      => equals(args, mem),
        ">"      => greater_than(args, mem),
        ">="     => greater_than_or_equal(args, mem),
        "car"    => car(args, mem),
        "cdr"    => cdr(args, mem),
        "cons"   => cons(args, mem),
        "length" => length(args, mem),
        "list"   => list(args, mem),
        "list?"  => list_question_mark(args, mem),
        "not"    => not(args, mem),
        "null?"  => null(args, mem),
        "pair?"  => pair(args, mem),
        _        => Err(Error::PrimitiveFailed(name.to_string()))
    }
}

fn plus(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    let integers = try!(list_of_integers(args));
    let sum = integers.into_iter().fold(0, |sum, n| sum + n);
    Ok(mem.integer(sum))
}

fn minus(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() == 0 {
        return Err(Error::BadArity(Some("-".to_string())))
    }

    let integers = try!(list_of_integers(args));
    let first = integers[0];

    if integers.len() == 1 {
        Ok(mem.integer(-first))
    } else {
        let sum_of_the_rest = integers.into_iter().skip(1).fold(0, |sum, n| sum + n);
        Ok(mem.integer(first - sum_of_the_rest))
    }
}

fn division(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() == 0 {
        return Err(Error::BadArity(Some("/".to_string())))
    }

    let integers = try!(list_of_integers(args));
    let first = integers[0];

    if integers.len() == 1 {
        Ok(mem.integer(1 / first))
    } else {
        let div = integers.into_iter().skip(1).fold(first, |div, n| div / n);
        Ok(mem.integer(div))
    }
}

fn product(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    let integers = try!(list_of_integers(args));
    let product = integers.into_iter().fold(1, |product, n| product * n);
    Ok(mem.integer(product))
}

fn equals(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() < 2 {
        return Ok(mem.b_true());
    }

    let integers = try!(list_of_integers(args));
    let first = integers[0];

    let equality = integers.into_iter().skip(1).all(|n| n == first);
    Ok(mem.boolean(equality))
}

fn less_than(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    ord(args, mem, |a, b| a < b)
}

fn less_than_or_equal(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    ord(args, mem, |a, b| a <= b)
}

fn greater_than(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    ord(args, mem, |a, b| a > b)
}

fn greater_than_or_equal(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    ord(args, mem, |a, b| a >= b)
}

fn not(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("not".to_string())))
    }

    Ok(mem.boolean(args[0] == mem.b_false()))
}

fn list(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    Ok(mem.list(args))
}

fn length(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("length".to_string())));
    }

    match *args[0] {
        Value::List(ref list) =>
            Ok(mem.integer(list.len() as i64)),
        ref value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn pair(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("pair?".to_string())));
    }

    let outcome = match *args[0] {
        Value::List(ref list) =>
            !list.is_empty(),
        Value::DottedList(ref _list, ref _el) =>
            true,
        _ =>
            false,
    };

    Ok(mem.boolean(outcome))
}

fn cons(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 2 {
        return Err(Error::BadArity(Some("cons".to_string())));
    }

    let mut list: Vec<RcValue> = Vec::new();
    list.push(args[0].clone());

    if let Value::List(ref l) = *args[1] {
        for item in l.iter() {
            list.push(mem.store(item.clone()));
        }

        Ok(mem.list(list))
    } else {
        Ok(mem.dotted_list(list, (*args[1]).clone()))
    }
}

fn car(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("car".to_string())));
    }

    match *args[0] {
        Value::List(ref l) if !l.is_empty() =>
            Ok(mem.store(l.first().unwrap().clone())),
        Value::DottedList(ref l, ref _t) =>
            Ok(mem.store(l.first().unwrap().clone())),
        ref value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn cdr(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("cdr".to_string())));
    }

    match *args[0] {
        Value::List(ref l) if !l.is_empty() =>
            match l.tail() {
                tail if tail.is_empty() =>
                    Ok(mem.empty_list()),
                tail => {
                    let mut list = Vec::with_capacity(tail.len());

                    for item in tail.iter() {
                        list.push(mem.store(item.clone()));
                    }

                    Ok(mem.list(list))
                }
            },
        Value::DottedList(ref _l, ref t) =>
            Ok(mem.store(*t.clone())),
        ref value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn null(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("null?".to_string())));
    }

    Ok(mem.boolean(args[0] == mem.empty_list()))
}

fn list_question_mark(args: Vec<RcValue>, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("list?".to_string())));
    }

    let outcome = if let Value::List(ref _l) = *args[0] {
        true
    } else {
        false
    };

    Ok(mem.boolean(outcome))
}

fn list_of_integers(list: Vec<RcValue>) -> Result<Vec<i64>, Error> {
    let mut integers = Vec::with_capacity(list.len());

    for val in list.into_iter() {
        match *val {
            Value::Integer(n) =>
                integers.push(n),
            ref value =>
                return Err(Error::WrongArgumentType(value.clone())),
        }
    }

    Ok(integers)
}

fn ord(args: Vec<RcValue>, mem: &mut Memory, cmp: |i64, i64| -> bool) -> Result<RcValue, Error> {
    if args.len() < 2 {
        return Ok(mem.b_true())
    }

    let integers = try!(list_of_integers(args));
    let outcome = range(0u, integers.len() - 1).all(|i|
        cmp(integers[i], integers[i + 1])
    );

    return Ok(mem.boolean(outcome))
}
<|endoftext|>


<commit_before>extern crate google_maps_services;
extern crate dotenv;

use dotenv::dotenv;
use google_maps_services::distance_matrix::DistanceMatrixRequest;
use google_maps_services::request_structs::LatLng;
use google_maps_services::types::TravelMode;
use std::env;

#[test]
fn address_minimum() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();

    let request = DistanceMatrixRequest::new(origin, destination, api_key);

    let result = request.send();

    assert_eq!(result.status, "OK");
}

#[test]
fn address_travel_mode() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();
    let travel_mode = TravelMode::Transit;

    let mut request = DistanceMatrixRequest::new(origin, destination, api_key);
    {
        request.set_travel_mode(travel_mode);
    }

    let result = request.send();

    assert_eq!(result.status, "OK");
}
<commit_msg>Initial commit and a note to self<commit_after>extern crate google_maps_services;
extern crate dotenv;

use dotenv::dotenv;
use google_maps_services::distance_matrix::DistanceMatrixRequest;
use google_maps_services::request_structs::LatLng;
use google_maps_services::types::TravelMode;
use std::env;

#[test]
fn address_minimum() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();

    let request = DistanceMatrixRequest::new(origin, destination, api_key);

    let result = request.send();

    assert_eq!(result.status, "OK");
}

#[test]
fn address_travel_mode() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();
    let travel_mode = TravelMode::Transit;

    let mut request = DistanceMatrixRequest::new(origin, destination, api_key);
    // Is there a better way to do this? This'd be a hack for someone using this...
    {
        request.set_travel_mode(travel_mode);
    }

    let result = request.send();

    assert_eq!(result.status, "OK");
}
<|endoftext|>


<commit_before>use std::sync::atomic::{fence, AtomicBool, AtomicIsize, AtomicU64, Ordering::*};

fn main() {
    atomic_bool();
    atomic_isize();
    atomic_u64();
    atomic_fences();
}

fn atomic_bool() {
    static mut ATOMIC: AtomicBool = AtomicBool::new(false);

    unsafe {
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.store(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_or(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_and(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.fetch_nand(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_xor(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
    }
}

fn atomic_isize() {
    static ATOMIC: AtomicIsize = AtomicIsize::new(0);

    // Make sure trans can emit all the intrinsics correctly
    assert_eq!(ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed), Ok(0));
    assert_eq!(ATOMIC.compare_exchange(0, 2, Acquire, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange(0, 1, Release, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange(1, 0, AcqRel, Relaxed), Ok(1));
    ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst).ok();

    ATOMIC.store(0, SeqCst);

    assert_eq!(ATOMIC.compare_exchange_weak(0, 1, Relaxed, Relaxed), Ok(0));
    assert_eq!(ATOMIC.compare_exchange_weak(0, 2, Acquire, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange_weak(1, 0, AcqRel, Relaxed), Ok(1));
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok();
}

fn atomic_u64() {
    static ATOMIC: AtomicU64 = AtomicU64::new(0);

    ATOMIC.store(1, SeqCst);
    assert_eq!(ATOMIC.compare_exchange(0, 0x100, AcqRel, Acquire), Err(1));
    assert_eq!(
        ATOMIC.compare_exchange_weak(1, 0x100, AcqRel, Acquire),
        Ok(1)
    );
    assert_eq!(ATOMIC.load(Relaxed), 0x100);
}

fn atomic_fences() {
    fence(SeqCst);
    fence(Release);
    fence(Acquire);
}
<commit_msg>also test AcqRel fence<commit_after>use std::sync::atomic::{fence, AtomicBool, AtomicIsize, AtomicU64, Ordering::*};

fn main() {
    atomic_bool();
    atomic_isize();
    atomic_u64();
    atomic_fences();
}

fn atomic_bool() {
    static mut ATOMIC: AtomicBool = AtomicBool::new(false);

    unsafe {
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.store(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_or(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_and(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.fetch_nand(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_xor(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
    }
}

fn atomic_isize() {
    static ATOMIC: AtomicIsize = AtomicIsize::new(0);

    // Make sure trans can emit all the intrinsics correctly
    assert_eq!(ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed), Ok(0));
    assert_eq!(ATOMIC.compare_exchange(0, 2, Acquire, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange(0, 1, Release, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange(1, 0, AcqRel, Relaxed), Ok(1));
    ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst).ok();

    ATOMIC.store(0, SeqCst);

    assert_eq!(ATOMIC.compare_exchange_weak(0, 1, Relaxed, Relaxed), Ok(0));
    assert_eq!(ATOMIC.compare_exchange_weak(0, 2, Acquire, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed), Err(1));
    assert_eq!(ATOMIC.compare_exchange_weak(1, 0, AcqRel, Relaxed), Ok(1));
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok();
}

fn atomic_u64() {
    static ATOMIC: AtomicU64 = AtomicU64::new(0);

    ATOMIC.store(1, SeqCst);
    assert_eq!(ATOMIC.compare_exchange(0, 0x100, AcqRel, Acquire), Err(1));
    assert_eq!(
        ATOMIC.compare_exchange_weak(1, 0x100, AcqRel, Acquire),
        Ok(1)
    );
    assert_eq!(ATOMIC.load(Relaxed), 0x100);
}

fn atomic_fences() {
    fence(SeqCst);
    fence(Release);
    fence(Acquire);
    fence(AcqRel);
}
<|endoftext|>


<commit_before>use std::env;

use support::registry::Package;
use support::{basic_bin_manifest, basic_manifest, git, main_file, project};

#[test]
fn cargo_clean_simple() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .build();

    p.cargo("build").run();
    assert!(p.build_dir().is_dir());

    p.cargo("clean").run();
    assert!(!p.build_dir().is_dir());
}

#[test]
fn different_dir() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .file("src/bar/a.rs", "")
        .build();

    p.cargo("build").run();
    assert!(p.build_dir().is_dir());

    p.cargo("clean")
        .cwd(&p.root().join("src"))
        .with_stdout("")
        .run();
    assert!(!p.build_dir().is_dir());
}

#[test]
fn clean_multiple_packages() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.d1]
                path = "d1"
            [dependencies.d2]
                path = "d2"

            [[bin]]
                name = "foo"
        "#,
        ).file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .file("d1/Cargo.toml", &basic_bin_manifest("d1"))
        .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
        .file("d2/Cargo.toml", &basic_bin_manifest("d2"))
        .file("d2/src/main.rs", "fn main() { println!(\"d2\"); }")
        .build();

    p.cargo("build -p d1 -p d2 -p foo").run();

    let d1_path = &p
        .build_dir()
        .join("debug")
        .join(format!("d1{}", env::consts::EXE_SUFFIX));
    let d2_path = &p
        .build_dir()
        .join("debug")
        .join(format!("d2{}", env::consts::EXE_SUFFIX));

    assert!(p.bin("foo").is_file());
    assert!(d1_path.is_file());
    assert!(d2_path.is_file());

    p.cargo("clean -p d1 -p d2")
        .cwd(&p.root().join("src"))
        .with_stdout("")
        .run();
    assert!(p.bin("foo").is_file());
    assert!(!d1_path.is_file());
    assert!(!d2_path.is_file());
}

#[test]
fn clean_release() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            a = { path = "a" }
        "#,
        ).file("src/main.rs", "fn main() {}")
        .file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
        .file("a/src/lib.rs", "")
        .build();

    p.cargo("build --release").run();

    p.cargo("clean -p foo").run();
    p.cargo("build --release").with_stdout("").run();

    p.cargo("clean -p foo --release").run();
    p.cargo("build --release")
        .with_stderr(
            "\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] release [optimized] target(s) in [..]
",
        ).run();

    p.cargo("clean").arg("--release").run();
    assert!(!p.build_dir().join("release").is_dir());
}

#[test]
fn clean_doc() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            a = { path = "a" }
        "#,
        ).file("src/main.rs", "fn main() {}")
        .file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
        .file("a/src/lib.rs", "")
        .build();

    p.cargo("doc").run();

    let doc_path = &p.build_dir().join("doc");

    assert!(doc_path.is_dir());

    p.cargo("clean --doc").run();

    assert!(!doc_path.is_dir());
    assert!(p.build_dir().is_dir());
}

#[test]
fn build_script() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
            build = "build.rs"
        "#,
        ).file("src/main.rs", "fn main() {}")
        .file(
            "build.rs",
            r#"
            use std::path::PathBuf;
            use std::env;

            fn main() {
                let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
                if env::var("FIRST").is_ok() {
                    std::fs::File::create(out.join("out")).unwrap();
                } else {
                    assert!(!std::fs::metadata(out.join("out")).is_ok());
                }
            }
        "#,
        ).file("a/src/lib.rs", "")
        .build();

    p.cargo("build").env("FIRST", "1").run();
    p.cargo("clean -p foo").run();
    p.cargo("build -v")
        .with_stderr(
            "\
[COMPILING] foo v0.0.1 ([..])
[RUNNING] `rustc [..] build.rs [..]`
[RUNNING] `[..]build-script-build`
[RUNNING] `rustc [..] src/main.rs [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        ).run();
}

#[test]
fn clean_git() {
    let git = git::new("dep", |project| {
        project
            .file("Cargo.toml", &basic_manifest("dep", "0.5.0"))
            .file("src/lib.rs", "")
    }).unwrap();

    let p = project()
        .file(
            "Cargo.toml",
            &format!(
                r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            dep = {{ git = '{}' }}
        "#,
                git.url()
            ),
        ).file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build").run();
    p.cargo("clean -p dep").with_stdout("").run();
    p.cargo("build").run();
}

#[test]
fn registry() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            bar = "0.1"
        "#,
        ).file("src/main.rs", "fn main() {}")
        .build();

    Package::new("bar", "0.1.0").publish();

    p.cargo("build").run();
    p.cargo("clean -p bar").with_stdout("").run();
    p.cargo("build").run();
}

#[test]
fn clean_verbose() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
        [package]
        name = "foo"
        version = "0.0.1"

        [dependencies]
        bar = "0.1"
    "#,
        ).file("src/main.rs", "fn main() {}")
        .build();

    Package::new("bar", "0.1.0").publish();

    p.cargo("build").run();
    p.cargo("clean -p bar --verbose")
        .with_stderr(
            "\
[REMOVING] [..]
[REMOVING] [..]
",
        ).run();
    p.cargo("build").run();
}
<commit_msg>assert for non-release artifacts<commit_after>use std::env;

use support::registry::Package;
use support::{basic_bin_manifest, basic_manifest, git, main_file, project};

#[test]
fn cargo_clean_simple() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .build();

    p.cargo("build").run();
    assert!(p.build_dir().is_dir());

    p.cargo("clean").run();
    assert!(!p.build_dir().is_dir());
}

#[test]
fn different_dir() {
    let p = project()
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .file("src/bar/a.rs", "")
        .build();

    p.cargo("build").run();
    assert!(p.build_dir().is_dir());

    p.cargo("clean")
        .cwd(&p.root().join("src"))
        .with_stdout("")
        .run();
    assert!(!p.build_dir().is_dir());
}

#[test]
fn clean_multiple_packages() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.d1]
                path = "d1"
            [dependencies.d2]
                path = "d2"

            [[bin]]
                name = "foo"
        "#,
        ).file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .file("d1/Cargo.toml", &basic_bin_manifest("d1"))
        .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
        .file("d2/Cargo.toml", &basic_bin_manifest("d2"))
        .file("d2/src/main.rs", "fn main() { println!(\"d2\"); }")
        .build();

    p.cargo("build -p d1 -p d2 -p foo").run();

    let d1_path = &p
        .build_dir()
        .join("debug")
        .join(format!("d1{}", env::consts::EXE_SUFFIX));
    let d2_path = &p
        .build_dir()
        .join("debug")
        .join(format!("d2{}", env::consts::EXE_SUFFIX));

    assert!(p.bin("foo").is_file());
    assert!(d1_path.is_file());
    assert!(d2_path.is_file());

    p.cargo("clean -p d1 -p d2")
        .cwd(&p.root().join("src"))
        .with_stdout("")
        .run();
    assert!(p.bin("foo").is_file());
    assert!(!d1_path.is_file());
    assert!(!d2_path.is_file());
}

#[test]
fn clean_release() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            a = { path = "a" }
        "#,
        ).file("src/main.rs", "fn main() {}")
        .file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
        .file("a/src/lib.rs", "")
        .build();

    p.cargo("build --release").run();

    p.cargo("clean -p foo").run();
    p.cargo("build --release").with_stdout("").run();

    p.cargo("clean -p foo --release").run();
    p.cargo("build --release")
        .with_stderr(
            "\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] release [optimized] target(s) in [..]
",
        ).run();

    p.cargo("build").run();

    p.cargo("clean").arg("--release").run();
    assert!(p.build_dir().is_dir());
    assert!(p.build_dir().join("debug").is_dir());
    assert!(!p.build_dir().join("release").is_dir());
}

#[test]
fn clean_doc() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            a = { path = "a" }
        "#,
        ).file("src/main.rs", "fn main() {}")
        .file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
        .file("a/src/lib.rs", "")
        .build();

    p.cargo("doc").run();

    let doc_path = &p.build_dir().join("doc");

    assert!(doc_path.is_dir());

    p.cargo("clean --doc").run();

    assert!(!doc_path.is_dir());
    assert!(p.build_dir().is_dir());
}

#[test]
fn build_script() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
            build = "build.rs"
        "#,
        ).file("src/main.rs", "fn main() {}")
        .file(
            "build.rs",
            r#"
            use std::path::PathBuf;
            use std::env;

            fn main() {
                let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
                if env::var("FIRST").is_ok() {
                    std::fs::File::create(out.join("out")).unwrap();
                } else {
                    assert!(!std::fs::metadata(out.join("out")).is_ok());
                }
            }
        "#,
        ).file("a/src/lib.rs", "")
        .build();

    p.cargo("build").env("FIRST", "1").run();
    p.cargo("clean -p foo").run();
    p.cargo("build -v")
        .with_stderr(
            "\
[COMPILING] foo v0.0.1 ([..])
[RUNNING] `rustc [..] build.rs [..]`
[RUNNING] `[..]build-script-build`
[RUNNING] `rustc [..] src/main.rs [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        ).run();
}

#[test]
fn clean_git() {
    let git = git::new("dep", |project| {
        project
            .file("Cargo.toml", &basic_manifest("dep", "0.5.0"))
            .file("src/lib.rs", "")
    }).unwrap();

    let p = project()
        .file(
            "Cargo.toml",
            &format!(
                r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            dep = {{ git = '{}' }}
        "#,
                git.url()
            ),
        ).file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build").run();
    p.cargo("clean -p dep").with_stdout("").run();
    p.cargo("build").run();
}

#[test]
fn registry() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            bar = "0.1"
        "#,
        ).file("src/main.rs", "fn main() {}")
        .build();

    Package::new("bar", "0.1.0").publish();

    p.cargo("build").run();
    p.cargo("clean -p bar").with_stdout("").run();
    p.cargo("build").run();
}

#[test]
fn clean_verbose() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
        [package]
        name = "foo"
        version = "0.0.1"

        [dependencies]
        bar = "0.1"
    "#,
        ).file("src/main.rs", "fn main() {}")
        .build();

    Package::new("bar", "0.1.0").publish();

    p.cargo("build").run();
    p.cargo("clean -p bar --verbose")
        .with_stderr(
            "\
[REMOVING] [..]
[REMOVING] [..]
",
        ).run();
    p.cargo("build").run();
}
<|endoftext|>


<commit_before>
use {Field, Borrowed, Value};
use vecmath::{rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d, Rectangle};
use {RectangleColorContext};

/// A rectangle context.
pub struct RectangleContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
}

impl<'a> Transform2d<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> RectangleContext<'a> {
    /// Creates a RectangleColorContext.
    #[inline(always)]
    pub fn rgba(&'a self, r: f64, g: f64, b: f64, a: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
            rect: Borrowed(self.rect.get()),
        }
    }
}

#[test]
fn test_rgba() {
    use {Context};

    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 100.0);
    let e = d.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(e.color.get()[0], 1.0);
}

<commit_msg>Made RectangleContext implement AddColor<commit_after>
use {Field, Borrowed, Value};
use vecmath::{rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d, Rectangle};
use {RectangleColorContext};
use {AddColor};

/// A rectangle context.
pub struct RectangleContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
}

impl<'a> Transform2d<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> AddColor<'a, RectangleColorContext<'a>> for RectangleContext<'a> {
    /// Creates a RectangleColorContext.
    #[inline(always)]
    fn rgba(&'a self, r: f64, g: f64, b: f64, a: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
            rect: Borrowed(self.rect.get()),
        }
    }
}

#[test]
fn test_rgba() {
    use {Context};

    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 100.0);
    let e = d.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(e.color.get()[0], 1.0);
}

<|endoftext|>


<commit_before>use std::{
    cell::{Ref, RefMut},
    fmt,
};

use actix_http::{
    body::{BoxBody, EitherBody, MessageBody},
    header::HeaderMap,
    Extensions, Response, ResponseHead, StatusCode,
};

#[cfg(feature = "cookies")]
use {
    actix_http::{
        error::HttpError,
        header::{self, HeaderValue},
    },
    cookie::Cookie,
};

use crate::{error::Error, HttpRequest, HttpResponseBuilder, Responder};

/// An outgoing response.
pub struct HttpResponse<B = BoxBody> {
    res: Response<B>,
    error: Option<Error>,
}

impl HttpResponse<BoxBody> {
    /// Constructs a response.
    #[inline]
    pub fn new(status: StatusCode) -> Self {
        Self {
            res: Response::new(status),
            error: None,
        }
    }

    /// Constructs a response builder with specific HTTP status.
    #[inline]
    pub fn build(status: StatusCode) -> HttpResponseBuilder {
        HttpResponseBuilder::new(status)
    }

    /// Create an error response.
    #[inline]
    pub fn from_error(error: impl Into<Error>) -> Self {
        let error = error.into();
        let mut response = error.as_response_error().error_response();
        response.error = Some(error);
        response
    }
}

impl<B> HttpResponse<B> {
    /// Constructs a response with body
    #[inline]
    pub fn with_body(status: StatusCode, body: B) -> Self {
        Self {
            res: Response::with_body(status, body),
            error: None,
        }
    }

    /// Returns a reference to response head.
    #[inline]
    pub fn head(&self) -> &ResponseHead {
        self.res.head()
    }

    /// Returns a mutable reference to response head.
    #[inline]
    pub fn head_mut(&mut self) -> &mut ResponseHead {
        self.res.head_mut()
    }

    /// The source `error` for this response
    #[inline]
    pub fn error(&self) -> Option<&Error> {
        self.error.as_ref()
    }

    /// Get the response status code
    #[inline]
    pub fn status(&self) -> StatusCode {
        self.res.status()
    }

    /// Set the `StatusCode` for this response
    #[inline]
    pub fn status_mut(&mut self) -> &mut StatusCode {
        self.res.status_mut()
    }

    /// Get the headers from the response
    #[inline]
    pub fn headers(&self) -> &HeaderMap {
        self.res.headers()
    }

    /// Get a mutable reference to the headers
    #[inline]
    pub fn headers_mut(&mut self) -> &mut HeaderMap {
        self.res.headers_mut()
    }

    /// Get an iterator for the cookies set by this response.
    #[cfg(feature = "cookies")]
    pub fn cookies(&self) -> CookieIter<'_> {
        CookieIter {
            iter: self.headers().get_all(header::SET_COOKIE),
        }
    }

    /// Add a cookie to this response.
    ///
    /// # Errors
    /// Returns an error if the cookie results in a malformed `Set-Cookie` header.
    #[cfg(feature = "cookies")]
    pub fn add_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
        HeaderValue::from_str(&cookie.to_string())
            .map(|cookie| self.headers_mut().append(header::SET_COOKIE, cookie))
            .map_err(Into::into)
    }

    /// Add a "removal" cookie to the response that matches attributes of given cookie.
    ///
    /// This will cause browsers/clients to remove stored cookies with this name.
    ///
    /// The `Set-Cookie` header added to the response will have:
    /// - name matching given cookie;
    /// - domain matching given cookie;
    /// - path matching given cookie;
    /// - an empty value;
    /// - a max-age of `0`;
    /// - an expiration date far in the past.
    ///
    /// If the cookie you're trying to remove has an explicit path or domain set, those attributes
    /// will need to be included in the cookie passed in here.
    ///
    /// # Errors
    /// Returns an error if the given name results in a malformed `Set-Cookie` header.
    #[cfg(feature = "cookies")]
    pub fn add_removal_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
        let mut removal_cookie = cookie.to_owned();
        removal_cookie.make_removal();

        HeaderValue::from_str(&removal_cookie.to_string())
            .map(|cookie| self.headers_mut().append(header::SET_COOKIE, cookie))
            .map_err(Into::into)
    }

    /// Remove all cookies with the given name from this response.
    ///
    /// Returns the number of cookies removed.
    ///
    /// This method can _not_ cause a browser/client to delete any of its stored cookies. Its only
    /// purpose is to delete cookies that were added to this response using [`add_cookie`]
    /// and [`add_removal_cookie`]. Use [`add_removal_cookie`] to send a "removal" cookie.
    ///
    /// [`add_cookie`]: Self::add_cookie
    /// [`add_removal_cookie`]: Self::add_removal_cookie
    #[cfg(feature = "cookies")]
    pub fn del_cookie(&mut self, name: &str) -> usize {
        let headers = self.headers_mut();

        let vals: Vec<HeaderValue> = headers
            .get_all(header::SET_COOKIE)
            .map(|v| v.to_owned())
            .collect();

        headers.remove(header::SET_COOKIE);

        let mut count: usize = 0;

        for v in vals {
            if let Ok(s) = v.to_str() {
                if let Ok(c) = Cookie::parse_encoded(s) {
                    if c.name() == name {
                        count += 1;
                        continue;
                    }
                }
            }

            // put set-cookie header head back if it does not validate
            headers.append(header::SET_COOKIE, v);
        }

        count
    }

    /// Connection upgrade status
    #[inline]
    pub fn upgrade(&self) -> bool {
        self.res.upgrade()
    }

    /// Keep-alive status for this connection
    pub fn keep_alive(&self) -> bool {
        self.res.keep_alive()
    }

    /// Returns reference to the response-local data/extensions container.
    #[inline]
    pub fn extensions(&self) -> Ref<'_, Extensions> {
        self.res.extensions()
    }

    /// Returns reference to the response-local data/extensions container.
    #[inline]
    pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
        self.res.extensions_mut()
    }

    /// Returns a reference to this response's body.
    #[inline]
    pub fn body(&self) -> &B {
        self.res.body()
    }

    /// Sets new body.
    pub fn set_body<B2>(self, body: B2) -> HttpResponse<B2> {
        HttpResponse {
            res: self.res.set_body(body),
            error: self.error,
        }
    }

    /// Returns split head and body.
    ///
    /// # Implementation Notes
    /// Due to internal performance optimizations, the first element of the returned tuple is an
    /// `HttpResponse` as well but only contains the head of the response this was called on.
    pub fn into_parts(self) -> (HttpResponse<()>, B) {
        let (head, body) = self.res.into_parts();

        (
            HttpResponse {
                res: head,
                error: None,
            },
            body,
        )
    }

    /// Drops body and returns new response.
    pub fn drop_body(self) -> HttpResponse<()> {
        HttpResponse {
            res: self.res.drop_body(),
            error: None,
        }
    }

    /// Map the current body type to another using a closure, returning a new response.
    ///
    /// Closure receives the response head and the current body type.
    pub fn map_body<F, B2>(self, f: F) -> HttpResponse<B2>
    where
        F: FnOnce(&mut ResponseHead, B) -> B2,
    {
        HttpResponse {
            res: self.res.map_body(f),
            error: self.error,
        }
    }

    /// Map the current body type `B` to `EitherBody::Left(B)`.
    ///
    /// Useful for middleware which can generate their own responses.
    #[inline]
    pub fn map_into_left_body<R>(self) -> HttpResponse<EitherBody<B, R>> {
        self.map_body(|_, body| EitherBody::left(body))
    }

    /// Map the current body type `B` to `EitherBody::Right(B)`.
    ///
    /// Useful for middleware which can generate their own responses.
    #[inline]
    pub fn map_into_right_body<L>(self) -> HttpResponse<EitherBody<L, B>> {
        self.map_body(|_, body| EitherBody::right(body))
    }

    /// Map the current body to a type-erased `BoxBody`.
    #[inline]
    pub fn map_into_boxed_body(self) -> HttpResponse<BoxBody>
    where
        B: MessageBody + 'static,
    {
        self.map_body(|_, body| body.boxed())
    }

    /// Returns the response body, dropping all other parts.
    pub fn into_body(self) -> B {
        self.res.into_body()
    }
}

impl<B> fmt::Debug for HttpResponse<B>
where
    B: MessageBody,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("HttpResponse")
            .field("error", &self.error)
            .field("res", &self.res)
            .finish()
    }
}

impl<B> From<Response<B>> for HttpResponse<B> {
    fn from(res: Response<B>) -> Self {
        HttpResponse { res, error: None }
    }
}

impl From<Error> for HttpResponse {
    fn from(err: Error) -> Self {
        HttpResponse::from_error(err)
    }
}

impl<B> From<HttpResponse<B>> for Response<B> {
    fn from(res: HttpResponse<B>) -> Self {
        // this impl will always be called as part of dispatcher

        // TODO: expose cause somewhere?
        // if let Some(err) = res.error {
        //     return Response::from_error(err);
        // }

        res.res
    }
}

// Rationale for cfg(test): this impl causes false positives on a clippy lint (async_yields_async)
// when returning an HttpResponse from an async function/closure and it's not very useful outside of
// tests anyway.
#[cfg(test)]
mod response_fut_impl {
    use std::{
        future::Future,
        mem,
        pin::Pin,
        task::{Context, Poll},
    };

    use super::*;

    // Future is only implemented for BoxBody payload type because it's the most useful for making
    // simple handlers without async blocks. Making it generic over all MessageBody types requires a
    // future impl on Response which would cause it's body field to be, undesirably, Option<B>.
    //
    // This impl is not particularly efficient due to the Response construction and should probably
    // not be invoked if performance is important. Prefer an async fn/block in such cases.
    impl Future for HttpResponse<BoxBody> {
        type Output = Result<Response<BoxBody>, Error>;

        fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
            if let Some(err) = self.error.take() {
                return Poll::Ready(Err(err));
            }

            Poll::Ready(Ok(mem::replace(
                &mut self.res,
                Response::new(StatusCode::default()),
            )))
        }
    }
}

impl<B> Responder for HttpResponse<B>
where
    B: MessageBody + 'static,
{
    type Body = B;

    #[inline]
    fn respond_to(self, _: &HttpRequest) -> HttpResponse<Self::Body> {
        self
    }
}

#[cfg(feature = "cookies")]
pub struct CookieIter<'a> {
    iter: std::slice::Iter<'a, HeaderValue>,
}

#[cfg(feature = "cookies")]
impl<'a> Iterator for CookieIter<'a> {
    type Item = Cookie<'a>;

    #[inline]
    fn next(&mut self) -> Option<Cookie<'a>> {
        for v in self.iter.by_ref() {
            if let Ok(c) = Cookie::parse_encoded(v.to_str().ok()?) {
                return Some(c);
            }
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use static_assertions::assert_impl_all;

    use super::*;
    use crate::http::header::{HeaderValue, COOKIE};

    assert_impl_all!(HttpResponse: Responder);
    assert_impl_all!(HttpResponse<String>: Responder);
    assert_impl_all!(HttpResponse<&'static str>: Responder);
    assert_impl_all!(HttpResponse<crate::body::None>: Responder);

    #[test]
    fn test_debug() {
        let resp = HttpResponse::Ok()
            .append_header((COOKIE, HeaderValue::from_static("cookie1=value1; ")))
            .append_header((COOKIE, HeaderValue::from_static("cookie2=value2; ")))
            .finish();
        let dbg = format!("{:?}", resp);
        assert!(dbg.contains("HttpResponse"));
    }
}

#[cfg(test)]
#[cfg(feature = "cookies")]
mod cookie_tests {
    use super::*;

    #[test]
    fn removal_cookies() {
        let mut res = HttpResponse::Ok().finish();
        let cookie = Cookie::new("foo", "");
        res.add_removal_cookie(&cookie).unwrap();
        let set_cookie_hdr = res.headers().get(header::SET_COOKIE).unwrap();
        assert_eq!(
            &set_cookie_hdr.as_bytes()[..25],
            &b"foo=; Max-Age=0; Expires="[..],
            "unexpected set-cookie value: {:?}",
            set_cookie_hdr.to_str()
        );
    }
}
<commit_msg>propagate response error in all necessary places<commit_after>use std::{
    cell::{Ref, RefMut},
    fmt,
};

use actix_http::{
    body::{BoxBody, EitherBody, MessageBody},
    header::HeaderMap,
    Extensions, Response, ResponseHead, StatusCode,
};

#[cfg(feature = "cookies")]
use {
    actix_http::{
        error::HttpError,
        header::{self, HeaderValue},
    },
    cookie::Cookie,
};

use crate::{error::Error, HttpRequest, HttpResponseBuilder, Responder};

/// An outgoing response.
pub struct HttpResponse<B = BoxBody> {
    res: Response<B>,
    error: Option<Error>,
}

impl HttpResponse<BoxBody> {
    /// Constructs a response.
    #[inline]
    pub fn new(status: StatusCode) -> Self {
        Self {
            res: Response::new(status),
            error: None,
        }
    }

    /// Constructs a response builder with specific HTTP status.
    #[inline]
    pub fn build(status: StatusCode) -> HttpResponseBuilder {
        HttpResponseBuilder::new(status)
    }

    /// Create an error response.
    #[inline]
    pub fn from_error(error: impl Into<Error>) -> Self {
        let error = error.into();
        let mut response = error.as_response_error().error_response();
        response.error = Some(error);
        response
    }
}

impl<B> HttpResponse<B> {
    /// Constructs a response with body
    #[inline]
    pub fn with_body(status: StatusCode, body: B) -> Self {
        Self {
            res: Response::with_body(status, body),
            error: None,
        }
    }

    /// Returns a reference to response head.
    #[inline]
    pub fn head(&self) -> &ResponseHead {
        self.res.head()
    }

    /// Returns a mutable reference to response head.
    #[inline]
    pub fn head_mut(&mut self) -> &mut ResponseHead {
        self.res.head_mut()
    }

    /// The source `error` for this response
    #[inline]
    pub fn error(&self) -> Option<&Error> {
        self.error.as_ref()
    }

    /// Get the response status code
    #[inline]
    pub fn status(&self) -> StatusCode {
        self.res.status()
    }

    /// Set the `StatusCode` for this response
    #[inline]
    pub fn status_mut(&mut self) -> &mut StatusCode {
        self.res.status_mut()
    }

    /// Get the headers from the response
    #[inline]
    pub fn headers(&self) -> &HeaderMap {
        self.res.headers()
    }

    /// Get a mutable reference to the headers
    #[inline]
    pub fn headers_mut(&mut self) -> &mut HeaderMap {
        self.res.headers_mut()
    }

    /// Get an iterator for the cookies set by this response.
    #[cfg(feature = "cookies")]
    pub fn cookies(&self) -> CookieIter<'_> {
        CookieIter {
            iter: self.headers().get_all(header::SET_COOKIE),
        }
    }

    /// Add a cookie to this response.
    ///
    /// # Errors
    /// Returns an error if the cookie results in a malformed `Set-Cookie` header.
    #[cfg(feature = "cookies")]
    pub fn add_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
        HeaderValue::from_str(&cookie.to_string())
            .map(|cookie| self.headers_mut().append(header::SET_COOKIE, cookie))
            .map_err(Into::into)
    }

    /// Add a "removal" cookie to the response that matches attributes of given cookie.
    ///
    /// This will cause browsers/clients to remove stored cookies with this name.
    ///
    /// The `Set-Cookie` header added to the response will have:
    /// - name matching given cookie;
    /// - domain matching given cookie;
    /// - path matching given cookie;
    /// - an empty value;
    /// - a max-age of `0`;
    /// - an expiration date far in the past.
    ///
    /// If the cookie you're trying to remove has an explicit path or domain set, those attributes
    /// will need to be included in the cookie passed in here.
    ///
    /// # Errors
    /// Returns an error if the given name results in a malformed `Set-Cookie` header.
    #[cfg(feature = "cookies")]
    pub fn add_removal_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
        let mut removal_cookie = cookie.to_owned();
        removal_cookie.make_removal();

        HeaderValue::from_str(&removal_cookie.to_string())
            .map(|cookie| self.headers_mut().append(header::SET_COOKIE, cookie))
            .map_err(Into::into)
    }

    /// Remove all cookies with the given name from this response.
    ///
    /// Returns the number of cookies removed.
    ///
    /// This method can _not_ cause a browser/client to delete any of its stored cookies. Its only
    /// purpose is to delete cookies that were added to this response using [`add_cookie`]
    /// and [`add_removal_cookie`]. Use [`add_removal_cookie`] to send a "removal" cookie.
    ///
    /// [`add_cookie`]: Self::add_cookie
    /// [`add_removal_cookie`]: Self::add_removal_cookie
    #[cfg(feature = "cookies")]
    pub fn del_cookie(&mut self, name: &str) -> usize {
        let headers = self.headers_mut();

        let vals: Vec<HeaderValue> = headers
            .get_all(header::SET_COOKIE)
            .map(|v| v.to_owned())
            .collect();

        headers.remove(header::SET_COOKIE);

        let mut count: usize = 0;

        for v in vals {
            if let Ok(s) = v.to_str() {
                if let Ok(c) = Cookie::parse_encoded(s) {
                    if c.name() == name {
                        count += 1;
                        continue;
                    }
                }
            }

            // put set-cookie header head back if it does not validate
            headers.append(header::SET_COOKIE, v);
        }

        count
    }

    /// Connection upgrade status
    #[inline]
    pub fn upgrade(&self) -> bool {
        self.res.upgrade()
    }

    /// Keep-alive status for this connection
    pub fn keep_alive(&self) -> bool {
        self.res.keep_alive()
    }

    /// Returns reference to the response-local data/extensions container.
    #[inline]
    pub fn extensions(&self) -> Ref<'_, Extensions> {
        self.res.extensions()
    }

    /// Returns reference to the response-local data/extensions container.
    #[inline]
    pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
        self.res.extensions_mut()
    }

    /// Returns a reference to this response's body.
    #[inline]
    pub fn body(&self) -> &B {
        self.res.body()
    }

    /// Sets new body.
    pub fn set_body<B2>(self, body: B2) -> HttpResponse<B2> {
        HttpResponse {
            res: self.res.set_body(body),
            error: self.error,
        }
    }

    /// Returns split head and body.
    ///
    /// # Implementation Notes
    /// Due to internal performance optimizations, the first element of the returned tuple is an
    /// `HttpResponse` as well but only contains the head of the response this was called on.
    pub fn into_parts(self) -> (HttpResponse<()>, B) {
        let (head, body) = self.res.into_parts();

        (
            HttpResponse {
                res: head,
                error: self.error,
            },
            body,
        )
    }

    /// Drops body and returns new response.
    pub fn drop_body(self) -> HttpResponse<()> {
        HttpResponse {
            res: self.res.drop_body(),
            error: self.error,
        }
    }

    /// Map the current body type to another using a closure, returning a new response.
    ///
    /// Closure receives the response head and the current body type.
    pub fn map_body<F, B2>(self, f: F) -> HttpResponse<B2>
    where
        F: FnOnce(&mut ResponseHead, B) -> B2,
    {
        HttpResponse {
            res: self.res.map_body(f),
            error: self.error,
        }
    }

    /// Map the current body type `B` to `EitherBody::Left(B)`.
    ///
    /// Useful for middleware which can generate their own responses.
    #[inline]
    pub fn map_into_left_body<R>(self) -> HttpResponse<EitherBody<B, R>> {
        self.map_body(|_, body| EitherBody::left(body))
    }

    /// Map the current body type `B` to `EitherBody::Right(B)`.
    ///
    /// Useful for middleware which can generate their own responses.
    #[inline]
    pub fn map_into_right_body<L>(self) -> HttpResponse<EitherBody<L, B>> {
        self.map_body(|_, body| EitherBody::right(body))
    }

    /// Map the current body to a type-erased `BoxBody`.
    #[inline]
    pub fn map_into_boxed_body(self) -> HttpResponse<BoxBody>
    where
        B: MessageBody + 'static,
    {
        self.map_body(|_, body| body.boxed())
    }

    /// Returns the response body, dropping all other parts.
    pub fn into_body(self) -> B {
        self.res.into_body()
    }
}

impl<B> fmt::Debug for HttpResponse<B>
where
    B: MessageBody,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("HttpResponse")
            .field("error", &self.error)
            .field("res", &self.res)
            .finish()
    }
}

impl<B> From<Response<B>> for HttpResponse<B> {
    fn from(res: Response<B>) -> Self {
        HttpResponse { res, error: None }
    }
}

impl From<Error> for HttpResponse {
    fn from(err: Error) -> Self {
        HttpResponse::from_error(err)
    }
}

impl<B> From<HttpResponse<B>> for Response<B> {
    fn from(res: HttpResponse<B>) -> Self {
        // this impl will always be called as part of dispatcher

        // TODO: expose cause somewhere?
        // if let Some(err) = res.error {
        //     return Response::from_error(err);
        // }

        res.res
    }
}

// Rationale for cfg(test): this impl causes false positives on a clippy lint (async_yields_async)
// when returning an HttpResponse from an async function/closure and it's not very useful outside of
// tests anyway.
#[cfg(test)]
mod response_fut_impl {
    use std::{
        future::Future,
        mem,
        pin::Pin,
        task::{Context, Poll},
    };

    use super::*;

    // Future is only implemented for BoxBody payload type because it's the most useful for making
    // simple handlers without async blocks. Making it generic over all MessageBody types requires a
    // future impl on Response which would cause it's body field to be, undesirably, Option<B>.
    //
    // This impl is not particularly efficient due to the Response construction and should probably
    // not be invoked if performance is important. Prefer an async fn/block in such cases.
    impl Future for HttpResponse<BoxBody> {
        type Output = Result<Response<BoxBody>, Error>;

        fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
            if let Some(err) = self.error.take() {
                return Poll::Ready(Err(err));
            }

            Poll::Ready(Ok(mem::replace(
                &mut self.res,
                Response::new(StatusCode::default()),
            )))
        }
    }
}

impl<B> Responder for HttpResponse<B>
where
    B: MessageBody + 'static,
{
    type Body = B;

    #[inline]
    fn respond_to(self, _: &HttpRequest) -> HttpResponse<Self::Body> {
        self
    }
}

#[cfg(feature = "cookies")]
pub struct CookieIter<'a> {
    iter: std::slice::Iter<'a, HeaderValue>,
}

#[cfg(feature = "cookies")]
impl<'a> Iterator for CookieIter<'a> {
    type Item = Cookie<'a>;

    #[inline]
    fn next(&mut self) -> Option<Cookie<'a>> {
        for v in self.iter.by_ref() {
            if let Ok(c) = Cookie::parse_encoded(v.to_str().ok()?) {
                return Some(c);
            }
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use static_assertions::assert_impl_all;

    use super::*;
    use crate::http::header::{HeaderValue, COOKIE};

    assert_impl_all!(HttpResponse: Responder);
    assert_impl_all!(HttpResponse<String>: Responder);
    assert_impl_all!(HttpResponse<&'static str>: Responder);
    assert_impl_all!(HttpResponse<crate::body::None>: Responder);

    #[test]
    fn test_debug() {
        let resp = HttpResponse::Ok()
            .append_header((COOKIE, HeaderValue::from_static("cookie1=value1; ")))
            .append_header((COOKIE, HeaderValue::from_static("cookie2=value2; ")))
            .finish();
        let dbg = format!("{:?}", resp);
        assert!(dbg.contains("HttpResponse"));
    }
}

#[cfg(test)]
#[cfg(feature = "cookies")]
mod cookie_tests {
    use super::*;

    #[test]
    fn removal_cookies() {
        let mut res = HttpResponse::Ok().finish();
        let cookie = Cookie::new("foo", "");
        res.add_removal_cookie(&cookie).unwrap();
        let set_cookie_hdr = res.headers().get(header::SET_COOKIE).unwrap();
        assert_eq!(
            &set_cookie_hdr.as_bytes()[..25],
            &b"foo=; Max-Age=0; Expires="[..],
            "unexpected set-cookie value: {:?}",
            set_cookie_hdr.to_str()
        );
    }
}
<|endoftext|>


<commit_before>#[doc = "Records the full path to items"];

export mk_pass;

fn mk_pass() -> pass { run }

type ctxt = {
    srv: astsrv::srv,
    mutable path: [str]
};

fn run(srv: astsrv::srv, doc: doc::cratedoc) -> doc::cratedoc {
    let ctxt = {
        srv: srv,
        mutable path: []
    };
    let fold = fold::fold({
        fold_mod: fn~(
            f: fold::fold<ctxt>,
            d: doc::moddoc
        ) -> doc::moddoc {
            fold_mod(f, d)
        }
        with *fold::default_seq_fold(ctxt)
    });
    fold.fold_crate(fold, doc)
}

fn fold_mod(fold: fold::fold<ctxt>, doc: doc::moddoc) -> doc::moddoc {
    let is_topmod = doc.id() == rustc::syntax::ast::crate_node_id;

    if !is_topmod { vec::push(fold.ctxt.path, doc.name()); }
    let doc = fold::default_seq_fold_mod(fold, doc);
    if !is_topmod { vec::pop(fold.ctxt.path); }
    {
        item: {
            path: fold.ctxt.path
            with doc.item
        }
        with doc
    }
}

#[test]
fn should_record_mod_paths() {
    let source = "mod a { mod b { mod c { } } mod d { mod e { } } }";
    let srv = astsrv::mk_srv_from_str(source);
    let doc = extract::from_srv(srv, "");
    let doc = run(srv, doc);
    assert doc.topmod.mods()[0].mods()[0].mods()[0].path() == ["a", "b"];
    assert doc.topmod.mods()[0].mods()[1].mods()[0].path() == ["a", "d"];
}<commit_msg>rustdoc: Find the path to all item types<commit_after>#[doc = "Records the full path to items"];

export mk_pass;

fn mk_pass() -> pass { run }

type ctxt = {
    srv: astsrv::srv,
    mutable path: [str]
};

fn run(srv: astsrv::srv, doc: doc::cratedoc) -> doc::cratedoc {
    let ctxt = {
        srv: srv,
        mutable path: []
    };
    let fold = fold::fold({
        fold_item: fold_item,
        fold_mod: fold_mod
        with *fold::default_seq_fold(ctxt)
    });
    fold.fold_crate(fold, doc)
}

fn fold_item(fold: fold::fold<ctxt>, doc: doc::itemdoc) -> doc::itemdoc {
    {
        path: fold.ctxt.path
        with doc
    }
}

fn fold_mod(fold: fold::fold<ctxt>, doc: doc::moddoc) -> doc::moddoc {
    let is_topmod = doc.id() == rustc::syntax::ast::crate_node_id;

    if !is_topmod { vec::push(fold.ctxt.path, doc.name()); }
    let doc = fold::default_seq_fold_mod(fold, doc);
    if !is_topmod { vec::pop(fold.ctxt.path); }

    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

#[test]
fn should_record_mod_paths() {
    let source = "mod a { mod b { mod c { } } mod d { mod e { } } }";
    let srv = astsrv::mk_srv_from_str(source);
    let doc = extract::from_srv(srv, "");
    let doc = run(srv, doc);
    log(error, doc.topmod.mods()[0].mods()[0].mods()[0].path());
    assert doc.topmod.mods()[0].mods()[0].mods()[0].path() == ["a", "b"];
    assert doc.topmod.mods()[0].mods()[1].mods()[0].path() == ["a", "d"];
}

#[test]
fn should_record_fn_paths() {
    let source = "mod a { fn b() { } }";
    let srv = astsrv::mk_srv_from_str(source);
    let doc = extract::from_srv(srv, "");
    let doc = run(srv, doc);
    assert doc.topmod.mods()[0].fns()[0].path() == ["a"];
}<|endoftext|>


<commit_before>use ansi_term::Style;

use crate::fs::File;
use crate::info::filetype::FileExtensions;

pub trait FileIcon {
    fn icon_file(&self, file: &File<'_>) -> Option<char>;
}

#[derive(Copy, Clone)]
pub enum Icons {
    Audio,
    Image,
    Video,
}

impl Icons {
    pub fn value(self) -> char {
        match self {
            Self::Audio  => '\u{f001}',
            Self::Image  => '\u{f1c5}',
            Self::Video  => '\u{f03d}',
        }
    }
}

pub fn iconify_style<'a>(style: Style) -> Style {
    style.foreground
         .map(Style::from)
         .unwrap_or_default()
}

pub fn icon_for_file(file: &File<'_>) -> char {
    let extensions = Box::new(FileExtensions);

    if file.points_to_directory() {
        '\u{f115}'
    }
    else if let Some(icon) = extensions.icon_file(file) {
        icon
    }
    else if let Some(ext) = file.ext.as_ref() {
        match ext.as_str() {
            "ai"        => '\u{e7b4}',
            "android"   => '\u{e70e}',
            "apple"     => '\u{f179}',
            "avro"      => '\u{e60b}',
            "clj"       => '\u{e768}',
            "coffee"    => '\u{f0f4}',
            "cpp"       => '\u{e61d}',
            "hpp"       => '\u{e61d}',
            "c"         => '\u{e61e}',
            "h"         => '\u{e61e}',
            "cs"        => '\u{f81a}',
            "css"       => '\u{e749}',
            "d"         => '\u{e7af}',
            "dart"      => '\u{e798}',
            "db"        => '\u{f1c0}',
            "diff"      => '\u{f440}',
            "patch"     => '\u{f440}',
            "rtf"       => '\u{f1c2}',
            "doc"       => '\u{f1c2}',
            "docx"      => '\u{f1c2}',
            "odt"       => '\u{f1c2}',
            "ebook"     => '\u{e28b}',
            "env"       => '\u{f462}',
            "epub"      => '\u{e28a}',
            "erl"       => '\u{e7b1}',
            "font"      => '\u{f031}',
            "gform"     => '\u{f298}',
            "git"       => '\u{f1d3}',
            "go"        => '\u{e626}',
            "hs"        => '\u{e777}',
            "htm"       => '\u{f13b}',
            "html"      => '\u{f13b}',
            "xhtml"     => '\u{f13b}',
            "iml"       => '\u{e7b5}',
            "java"      => '\u{e204}',
            "js"        => '\u{e74e}',
            "mjs"       => '\u{e74e}',
            "json"      => '\u{e60b}',
            "jsx"       => '\u{e7ba}',
            "vue"       => '\u{fd42}',
            "node"      => '\u{f898}',
            "less"      => '\u{e758}',
            "log"       => '\u{f18d}',
            "lua"       => '\u{e620}',
            "md"        => '\u{f48a}',
            "markdown"  => '\u{f48a}',
            "mustache"  => '\u{e60f}',
            "npmignore" => '\u{e71e}',
            "pdf"       => '\u{f1c1}',
            "djvu"      => '\u{f02d}',
            "mobi"      => '\u{f02d}',
            "php"       => '\u{e73d}',
            "pl"        => '\u{e769}',
            "ppt"       => '\u{f1c4}',
            "pptx"      => '\u{f1c4}',
            "odp"       => '\u{f1c4}',
            "psd"       => '\u{e7b8}',
            "py"        => '\u{e606}',
            "r"         => '\u{f25d}',
            "rb"        => '\u{e21e}',
            "ru"        => '\u{e21e}',
            "erb"       => '\u{e21e}',
            "gem"       => '\u{e21e}',
            "rdb"       => '\u{e76d}',
            "rs"        => '\u{e7a8}',
            "rss"       => '\u{f09e}',
            "rubydoc"   => '\u{e73b}',
            "sass"      => '\u{e74b}',
            "stylus"    => '\u{e759}',
            "scala"     => '\u{e737}',
            "shell"     => '\u{f489}',
            "sqlite3"   => '\u{e7c4}',
            "styl"      => '\u{e600}',
            "latex"     => '\u{e600}',
            "tex"       => '\u{e600}',
            "ts"        => '\u{e628}',
            "tsx"       => '\u{e628}',
            "twig"      => '\u{e61c}',
            "txt"       => '\u{f15c}',
            "video"     => '\u{f03d}',
            "vim"       => '\u{e62b}',
            "xml"       => '\u{e619}',
            "yml"       => '\u{f481}',
            "yaml"      => '\u{f481}',
            "rar"       => '\u{f410}',
            "zip"       => '\u{f410}',
            "bz"        => '\u{f410}',
            "bz2"       => '\u{f410}',
            "xz"        => '\u{f410}',
            "taz"       => '\u{f410}',
            "tbz"       => '\u{f410}',
            "tbz2"      => '\u{f410}',
            "tz"        => '\u{f410}',
            "tar"       => '\u{f410}',
            "tzo"       => '\u{f410}',
            "lz"        => '\u{f410}',
            "lzh"       => '\u{f410}',
            "lzma"      => '\u{f410}',
            "lzo"       => '\u{f410}',
            "gz"        => '\u{f410}',
            "deb"       => '\u{e77d}',
            "rpm"       => '\u{e7bb}',
            "exe"       => '\u{e70f}',
            "msi"       => '\u{e70f}',
            "dll"       => '\u{e70f}',
            "cab"       => '\u{e70f}',
            "bat"       => '\u{e70f}',
            "cmd"       => '\u{e70f}',
            "sh"        => '\u{f489}',
            "bash"      => '\u{f489}',
            "zsh"       => '\u{f489}',
            "fish"      => '\u{f489}',
            "csh"       => '\u{f489}',
            "ini"       => '\u{e615}',
            "toml"      => '\u{e615}',
            "cfg"       => '\u{e615}',
            "conf"      => '\u{e615}',
            "apk"       => '\u{e70e}',
            "ttf"       => '\u{f031}',
            "woff"      => '\u{f031}',
            "woff2"     => '\u{f031}',
            "otf"       => '\u{f031}',
            "csv"       => '\u{f1c3}',
            "tsv"       => '\u{f1c3}',
            "xls"       => '\u{f1c3}',
            "xlsx"      => '\u{f1c3}',
            "ods"       => '\u{f1c3}',
            "so"        => '\u{f17c}',
            "sql"       => '\u{f1c0}',
            "jar"       => '\u{e256}',
            "jad"       => '\u{e256}',
            "class"     => '\u{e256}',
            "war"       => '\u{e256}',
            "groovy"    => '\u{e775}',
            "iso"       => '\u{e271}',
            "lock"      => '\u{f023}',
            "swift"     => '\u{e755}',
            "nix"       => '\u{f313}',
            _           => '\u{f016}'
        }
    }
    else {
        '\u{f016}'
    }
}
<commit_msg>Prefer background colour when painting icons<commit_after>use ansi_term::Style;

use crate::fs::File;
use crate::info::filetype::FileExtensions;

pub trait FileIcon {
    fn icon_file(&self, file: &File<'_>) -> Option<char>;
}

#[derive(Copy, Clone)]
pub enum Icons {
    Audio,
    Image,
    Video,
}

impl Icons {
    pub fn value(self) -> char {
        match self {
            Self::Audio  => '\u{f001}',
            Self::Image  => '\u{f1c5}',
            Self::Video  => '\u{f03d}',
        }
    }
}

/// Converts the style used to paint a file name into the style that should be
/// used to paint an icon.
///
/// - The background colour should be preferred to the foreground colour, as
///   if one is set, it’s the more “obvious” colour choice.
/// - If neither is set, just use the default style.
/// - Attributes such as bold or underline should not be used to paint the
///   icon, as they can make it look weird.
pub fn iconify_style<'a>(style: Style) -> Style {
    style.background.or(style.foreground)
         .map(Style::from)
         .unwrap_or_default()
}

pub fn icon_for_file(file: &File<'_>) -> char {
    let extensions = Box::new(FileExtensions);

    if file.points_to_directory() {
        '\u{f115}'
    }
    else if let Some(icon) = extensions.icon_file(file) {
        icon
    }
    else if let Some(ext) = file.ext.as_ref() {
        match ext.as_str() {
            "ai"        => '\u{e7b4}',
            "android"   => '\u{e70e}',
            "apple"     => '\u{f179}',
            "avro"      => '\u{e60b}',
            "clj"       => '\u{e768}',
            "coffee"    => '\u{f0f4}',
            "cpp"       => '\u{e61d}',
            "hpp"       => '\u{e61d}',
            "c"         => '\u{e61e}',
            "h"         => '\u{e61e}',
            "cs"        => '\u{f81a}',
            "css"       => '\u{e749}',
            "d"         => '\u{e7af}',
            "dart"      => '\u{e798}',
            "db"        => '\u{f1c0}',
            "diff"      => '\u{f440}',
            "patch"     => '\u{f440}',
            "rtf"       => '\u{f1c2}',
            "doc"       => '\u{f1c2}',
            "docx"      => '\u{f1c2}',
            "odt"       => '\u{f1c2}',
            "ebook"     => '\u{e28b}',
            "env"       => '\u{f462}',
            "epub"      => '\u{e28a}',
            "erl"       => '\u{e7b1}',
            "font"      => '\u{f031}',
            "gform"     => '\u{f298}',
            "git"       => '\u{f1d3}',
            "go"        => '\u{e626}',
            "hs"        => '\u{e777}',
            "htm"       => '\u{f13b}',
            "html"      => '\u{f13b}',
            "xhtml"     => '\u{f13b}',
            "iml"       => '\u{e7b5}',
            "java"      => '\u{e204}',
            "js"        => '\u{e74e}',
            "mjs"       => '\u{e74e}',
            "json"      => '\u{e60b}',
            "jsx"       => '\u{e7ba}',
            "vue"       => '\u{fd42}',
            "node"      => '\u{f898}',
            "less"      => '\u{e758}',
            "log"       => '\u{f18d}',
            "lua"       => '\u{e620}',
            "md"        => '\u{f48a}',
            "markdown"  => '\u{f48a}',
            "mustache"  => '\u{e60f}',
            "npmignore" => '\u{e71e}',
            "pdf"       => '\u{f1c1}',
            "djvu"      => '\u{f02d}',
            "mobi"      => '\u{f02d}',
            "php"       => '\u{e73d}',
            "pl"        => '\u{e769}',
            "ppt"       => '\u{f1c4}',
            "pptx"      => '\u{f1c4}',
            "odp"       => '\u{f1c4}',
            "psd"       => '\u{e7b8}',
            "py"        => '\u{e606}',
            "r"         => '\u{f25d}',
            "rb"        => '\u{e21e}',
            "ru"        => '\u{e21e}',
            "erb"       => '\u{e21e}',
            "gem"       => '\u{e21e}',
            "rdb"       => '\u{e76d}',
            "rs"        => '\u{e7a8}',
            "rss"       => '\u{f09e}',
            "rubydoc"   => '\u{e73b}',
            "sass"      => '\u{e74b}',
            "stylus"    => '\u{e759}',
            "scala"     => '\u{e737}',
            "shell"     => '\u{f489}',
            "sqlite3"   => '\u{e7c4}',
            "styl"      => '\u{e600}',
            "latex"     => '\u{e600}',
            "tex"       => '\u{e600}',
            "ts"        => '\u{e628}',
            "tsx"       => '\u{e628}',
            "twig"      => '\u{e61c}',
            "txt"       => '\u{f15c}',
            "video"     => '\u{f03d}',
            "vim"       => '\u{e62b}',
            "xml"       => '\u{e619}',
            "yml"       => '\u{f481}',
            "yaml"      => '\u{f481}',
            "rar"       => '\u{f410}',
            "zip"       => '\u{f410}',
            "bz"        => '\u{f410}',
            "bz2"       => '\u{f410}',
            "xz"        => '\u{f410}',
            "taz"       => '\u{f410}',
            "tbz"       => '\u{f410}',
            "tbz2"      => '\u{f410}',
            "tz"        => '\u{f410}',
            "tar"       => '\u{f410}',
            "tzo"       => '\u{f410}',
            "lz"        => '\u{f410}',
            "lzh"       => '\u{f410}',
            "lzma"      => '\u{f410}',
            "lzo"       => '\u{f410}',
            "gz"        => '\u{f410}',
            "deb"       => '\u{e77d}',
            "rpm"       => '\u{e7bb}',
            "exe"       => '\u{e70f}',
            "msi"       => '\u{e70f}',
            "dll"       => '\u{e70f}',
            "cab"       => '\u{e70f}',
            "bat"       => '\u{e70f}',
            "cmd"       => '\u{e70f}',
            "sh"        => '\u{f489}',
            "bash"      => '\u{f489}',
            "zsh"       => '\u{f489}',
            "fish"      => '\u{f489}',
            "csh"       => '\u{f489}',
            "ini"       => '\u{e615}',
            "toml"      => '\u{e615}',
            "cfg"       => '\u{e615}',
            "conf"      => '\u{e615}',
            "apk"       => '\u{e70e}',
            "ttf"       => '\u{f031}',
            "woff"      => '\u{f031}',
            "woff2"     => '\u{f031}',
            "otf"       => '\u{f031}',
            "csv"       => '\u{f1c3}',
            "tsv"       => '\u{f1c3}',
            "xls"       => '\u{f1c3}',
            "xlsx"      => '\u{f1c3}',
            "ods"       => '\u{f1c3}',
            "so"        => '\u{f17c}',
            "sql"       => '\u{f1c0}',
            "jar"       => '\u{e256}',
            "jad"       => '\u{e256}',
            "class"     => '\u{e256}',
            "war"       => '\u{e256}',
            "groovy"    => '\u{e775}',
            "iso"       => '\u{e271}',
            "lock"      => '\u{f023}',
            "swift"     => '\u{e755}',
            "nix"       => '\u{f313}',
            _           => '\u{f016}'
        }
    }
    else {
        '\u{f016}'
    }
}
<|endoftext|>