<commit_before>use std::ascii::AsciiExt;
use std::cmp::*;

extern crate num_cpus;

macro_rules! chars {
    ($str:expr) => (
        &$str.chars().collect::<Vec<char>>()
    );
}

#[derive(PartialEq)]
struct ScoredChoice {
    idx: usize,
    score: f64,
}

impl PartialOrd for ScoredChoice {
    fn partial_cmp(&self, other: &ScoredChoice) -> Option<Ordering> {
        if other.score == self.score {
            // We fall back to an array index comparison in order to guarantee a stable sort;
            // otherwise the matches may be displayed in a nondeterministic order.
            Some(self.idx.cmp(&other.idx))
        } else {
            other.score.partial_cmp(&self.score)
        }
    }
}

#[cfg(nightly)]
pub fn compute_matches<'a>(choices: &[&'a str], query: &str) -> Vec<&'a str> {
    use std::thread;
    use std::sync::mpsc::*;
    let mut join_guards = Vec::new();
    let (tx, rx) = channel();
    let workers = num_cpus::get();
    for current_worker in 0..workers {
        let tx = tx.clone();
        join_guards.push(thread::scoped(move|| {
            let (lower_bound, upper_bound) = get_slice_indices(choices.len(), workers, current_worker);
            for i in lower_bound..upper_bound {
                let score = score(choices[i], query);
                tx.send(ScoredChoice{ idx: i, score: score }).unwrap();
            }
        }));
    }

    let mut ret = Vec::new();
    for _ in 0..choices.len() {
        let scored_choice = rx.recv().unwrap();
        if scored_choice.score > 0_f64 {
            ret.push(scored_choice);
        }
    }

    ret.sort_by(|x, y| x.partial_cmp(y).unwrap());
    ret.iter().map(|x| choices[x.idx]).collect()
}

#[cfg(not(nightly))]
pub fn compute_matches<'a>(choices: &[&'a str], query: &str) -> Vec<&'a str> {
    let mut ret = Vec::new();
    for i in 0..choices.len() {
        let score = score(choices[i], query);
        if score > 0_f64 {
            ret.push(ScoredChoice{ idx: i, score: score });
        }
    }

    ret.sort_by(|x, y| x.partial_cmp(y).unwrap());
    ret.iter().map(|x| choices[x.idx]).collect()
}

fn get_slice_indices(length: usize, workers: usize, idx: usize) -> (usize, usize) {
    let lb = (length as f64 / workers as f64) * idx as f64;
    let ub = (length as f64 / workers as f64) * (idx + 1) as f64;
    (lb as usize, ub as usize)
}

#[test]
fn get_slice_indices_test() {
    assert_eq!(get_slice_indices(100, 1, 0), (0, 100));

    assert_eq!(get_slice_indices(100, 2, 1), (50, 100));
    assert_eq!(get_slice_indices(100, 2, 0), (0, 50));

    assert_eq!(get_slice_indices(100, 3, 0), (0, 33));
    assert_eq!(get_slice_indices(100, 3, 1), (33, 66));
    assert_eq!(get_slice_indices(100, 3, 2), (66, 100));

    assert_eq!(get_slice_indices(100, 4, 0), (0, 25));
    assert_eq!(get_slice_indices(100, 4, 1), (25, 50));
    assert_eq!(get_slice_indices(100, 4, 2), (50, 75));
    assert_eq!(get_slice_indices(100, 4, 3), (75, 100));

    assert_eq!(get_slice_indices(12, 12, 11), (11, 12));
    assert_eq!(get_slice_indices(12, 12, 0), (0, 1));

    assert_eq!(get_slice_indices(1, 2, 0), (0, 0));
    assert_eq!(get_slice_indices(1, 2, 1), (0, 1));
}

fn score(choice: &str, query: &str) -> f64 {
    if query.len() == 0 {
        return 1.0;
    }
    if choice.len() == 0 {
        return 0.0;
    }

    let query = chars!(query);
    let choice = chars!(choice);

    match compute_match_length(choice, query) {
        None => return 0.0,
        Some(match_length) => {
            let score = query.len() as f64 / match_length as f64;
            return score as f64 / choice.len() as f64;
        }
    }
}

// This function is for picking out the matching characters for a given (choice, query) pair for
// rendering purposes. It assumes that the given choice is in fact a match for the given query, and
// will panic if this is not the case.
pub fn visual_score(choice: &str, query: &str) -> Vec<usize> {
    if query.len() == 0 || choice.len() == 0 {
        return Vec::new();
    }
    let query = chars!(query);
    let choice = chars!(choice);

    let (first_idx, _) = get_longest_match(&choice, &query).unwrap();
    get_match_indices(&choice, &query[1..], first_idx).unwrap()
}

fn compute_match_length(string: &[char], query: &[char]) -> Option<usize> {
    get_match_length(get_longest_match(string, query))
}

fn get_longest_match(string: &[char], query: &[char]) -> Option<(usize, usize)> {
    let first_char = query[0];
    let rest = &query[1..];
    let indices = find_char_in_string(string, first_char);

    let mut current_bounds: Option<(usize, usize)> = None;
    let smallest_possible_match = query.len();
    for &i in &indices {
        if let Some(last_index) = find_end_of_match(string, rest, i) {
            let last_bounds = Some((i, last_index));
            let last_match_len = get_match_length(last_bounds).unwrap();
            if current_bounds.is_none() || last_match_len < get_match_length(current_bounds).unwrap() {
                current_bounds = last_bounds;
                if last_match_len == smallest_possible_match {
                    break;
                }
            }
        }
    }
    current_bounds
}

fn get_match_length(bounds: Option<(usize, usize)>) -> Option<usize> {
    if let Some((lb, ub)) = bounds {
        Some(ub - lb + 1)
    } else {
        None
    }
}

fn find_char_in_string(string: &[char], char: char) -> Vec<usize> {
    let mut indices = Vec::new();
    for (i, c) in string.iter().enumerate() {
        if chars_equal(&char, c) {
            indices.push(i);
        }
    }
    return indices;
}

fn find_end_of_match(string: &[char], rest_of_query: &[char], first_index: usize) -> Option<usize> {
    if let Some(indices) = get_match_indices(string, rest_of_query, first_index) {
        Some(indices[indices.len() - 1])
    } else {
        None
    }
}

fn get_match_indices(string: &[char], rest_of_query: &[char], first_index: usize) -> Option<Vec<usize>> {
    let mut ret = Vec::new();
    let mut last_index = first_index + 1;
    ret.push(first_index);
    for c in rest_of_query.iter() {
        let current_substring = &string[last_index..];
        let mut index = None;
        for (i, x) in current_substring.iter().enumerate() {
            if chars_equal(c, x) {
                index = Some(i);
                break;
            }
        }
        if index.is_some() {
            last_index += index.unwrap() + 1;
            ret.push(last_index - 1);
        } else {
            return None;
        }
    }
    Some(ret)
}

fn chars_equal(q: &char, c: &char) -> bool {
    q == c || *q == c.to_ascii_lowercase()
}

#[test]
fn chars_equal_test() {
    assert!(chars_equal(&'a', &'a'));
    assert!(!chars_equal(&'a', &'b'));
    assert!(chars_equal(&'A', &'A'));
    assert!(!chars_equal(&'A', &'a'));
    assert!(chars_equal(&'a', &'A'));
}

#[test]
fn get_match_indices_test() {
    assert_eq!(get_match_indices(chars!("asdf"), chars!("sdf"), 0).unwrap(), vec![0, 1, 2, 3]);
    assert_eq!(get_match_indices(chars!("aoeuasdf"), chars!("sdf"), 4).unwrap(), vec![4, 5, 6, 7]);
    assert_eq!(get_match_indices(chars!(" a s d f"), chars!("sdf"), 1).unwrap(), vec![1, 3, 5, 7]);
}

#[test]
fn find_end_of_match_test() {
    assert_eq!(find_end_of_match(chars!("a"), chars!("a"), 0), None);
    assert_eq!(find_end_of_match(chars!("ba"), chars!("a"), 1), None);
    assert_eq!(find_end_of_match(chars!("aaa"), chars!("aa"), 0), Some(2));
    assert_eq!(find_end_of_match(chars!("aaa"), chars!("b"), 0), None);
    assert_eq!(find_end_of_match(chars!("this is a long match"), chars!("this is a match"), 0), None);
    assert_eq!(find_end_of_match(chars!("this is a long match"), chars!("his is a match"), 0), Some(19));
    assert_eq!(find_end_of_match(chars!("./rust/x86_64-apple-darwin/test/run-pass/process-spawn-with-unicode-params-πЯ音æ∞/child.stage2-x86_64-apple-darwin"), chars!("ust"), 2), Some(5));
}

#[test]
fn unicode_boundary_handling_test() {
    score("./rust/x86_64-apple-darwin/test/run-pass/process-spawn-with-unicode-params-πЯ音æ∞/child.stage2-x86_64-apple-darwin", "he");
}

#[test]
fn basic_scoring() {
    assert_eq!(score("", "a"), 0.0);
    assert_eq!(score("a", ""), 1.0);
    assert_eq!(score("short", "longer"), 0.0);
    assert_eq!(score("a", "b"), 0.0);
    assert_eq!(score("ab", "ac"), 0.0);

    assert!(score("a", "a") > 0.0);
    assert!(score("ab", "a") > 0.0);
    assert!(score("ba", "a") > 0.0);
    assert!(score("bab", "a") > 0.0);
    assert!(score("babababab", "aaaa") > 0.0);

    assert_eq!(score("a", "a"), 1_f64 / "a".len() as f64);
    assert_eq!(score("ab", "ab"), 0.5);
    assert_eq!(score("a long string", "a long string"), 1_f64 / "a long string".len() as f64);
    assert_eq!(score("spec/search_spec.rb", "sear"), 1_f64 / "spec/search_spec.rb".len() as f64);
}

#[test]
fn character_matching() {
    assert!(score("/! symbols $^", "/!$^") > 0.0);

    assert_eq!(score("a", "A"), 0.0);
    assert_eq!(score("A", "a"), 1.0);
    assert_eq!(score("A", "A"), 1.0);

    assert_eq!(score("a", "aa"), 0.0);
}

#[test]
fn match_equality() {
    assert!(score("selecta.gemspec", "asp") > score("algorithm4_spec.rb", "asp"));
    assert!(score("README.md", "em") > score("benchmark.rb", "em"));
    assert!(score("search.rb", "sear") > score("spec/search_spec.rb", "sear"));

    assert!(score("fbb", "fbb") > score("foo bar baz", "fbb"));
    assert!(score("foo", "foo") > score("longer foo", "foo"));
    assert!(score("foo", "foo") > score("foo longer", "foo"));
    assert!(score("1/2/3/4", "1/2/3") > score("1/9/2/3/4", "1/2/3"));

    assert!(score("long 12 long", "12") > score("1 long 2", "12"));

    assert_eq!(score("121padding2", "12"), 1.0 / "121padding2".len() as f64);
    assert_eq!(score("1padding212", "12"), 1.0 / "1padding212".len() as f64);
}
<commit_msg>Suppress dead code warning<commit_after>use std::ascii::AsciiExt;
use std::cmp::*;

extern crate num_cpus;

macro_rules! chars {
    ($str:expr) => (
        &$str.chars().collect::<Vec<char>>()
    );
}

#[derive(PartialEq)]
struct ScoredChoice {
    idx: usize,
    score: f64,
}

impl PartialOrd for ScoredChoice {
    fn partial_cmp(&self, other: &ScoredChoice) -> Option<Ordering> {
        if other.score == self.score {
            // We fall back to an array index comparison in order to guarantee a stable sort;
            // otherwise the matches may be displayed in a nondeterministic order.
            Some(self.idx.cmp(&other.idx))
        } else {
            other.score.partial_cmp(&self.score)
        }
    }
}

#[cfg(nightly)]
pub fn compute_matches<'a>(choices: &[&'a str], query: &str) -> Vec<&'a str> {
    use std::thread;
    use std::sync::mpsc::*;
    let mut join_guards = Vec::new();
    let (tx, rx) = channel();
    let workers = num_cpus::get();
    for current_worker in 0..workers {
        let tx = tx.clone();
        join_guards.push(thread::scoped(move|| {
            let (lower_bound, upper_bound) = get_slice_indices(choices.len(), workers, current_worker);
            for i in lower_bound..upper_bound {
                let score = score(choices[i], query);
                tx.send(ScoredChoice{ idx: i, score: score }).unwrap();
            }
        }));
    }

    let mut ret = Vec::new();
    for _ in 0..choices.len() {
        let scored_choice = rx.recv().unwrap();
        if scored_choice.score > 0_f64 {
            ret.push(scored_choice);
        }
    }

    ret.sort_by(|x, y| x.partial_cmp(y).unwrap());
    ret.iter().map(|x| choices[x.idx]).collect()
}

#[cfg(not(nightly))]
pub fn compute_matches<'a>(choices: &[&'a str], query: &str) -> Vec<&'a str> {
    let mut ret = Vec::new();
    for i in 0..choices.len() {
        let score = score(choices[i], query);
        if score > 0_f64 {
            ret.push(ScoredChoice{ idx: i, score: score });
        }
    }

    ret.sort_by(|x, y| x.partial_cmp(y).unwrap());
    ret.iter().map(|x| choices[x.idx]).collect()
}

#[cfg_attr(not(nightly), allow(dead_code))]
fn get_slice_indices(length: usize, workers: usize, idx: usize) -> (usize, usize) {
    let lb = (length as f64 / workers as f64) * idx as f64;
    let ub = (length as f64 / workers as f64) * (idx + 1) as f64;
    (lb as usize, ub as usize)
}

#[test]
fn get_slice_indices_test() {
    assert_eq!(get_slice_indices(100, 1, 0), (0, 100));

    assert_eq!(get_slice_indices(100, 2, 1), (50, 100));
    assert_eq!(get_slice_indices(100, 2, 0), (0, 50));

    assert_eq!(get_slice_indices(100, 3, 0), (0, 33));
    assert_eq!(get_slice_indices(100, 3, 1), (33, 66));
    assert_eq!(get_slice_indices(100, 3, 2), (66, 100));

    assert_eq!(get_slice_indices(100, 4, 0), (0, 25));
    assert_eq!(get_slice_indices(100, 4, 1), (25, 50));
    assert_eq!(get_slice_indices(100, 4, 2), (50, 75));
    assert_eq!(get_slice_indices(100, 4, 3), (75, 100));

    assert_eq!(get_slice_indices(12, 12, 11), (11, 12));
    assert_eq!(get_slice_indices(12, 12, 0), (0, 1));

    assert_eq!(get_slice_indices(1, 2, 0), (0, 0));
    assert_eq!(get_slice_indices(1, 2, 1), (0, 1));
}

fn score(choice: &str, query: &str) -> f64 {
    if query.len() == 0 {
        return 1.0;
    }
    if choice.len() == 0 {
        return 0.0;
    }

    let query = chars!(query);
    let choice = chars!(choice);

    match compute_match_length(choice, query) {
        None => return 0.0,
        Some(match_length) => {
            let score = query.len() as f64 / match_length as f64;
            return score as f64 / choice.len() as f64;
        }
    }
}

// This function is for picking out the matching characters for a given (choice, query) pair for
// rendering purposes. It assumes that the given choice is in fact a match for the given query, and
// will panic if this is not the case.
pub fn visual_score(choice: &str, query: &str) -> Vec<usize> {
    if query.len() == 0 || choice.len() == 0 {
        return Vec::new();
    }
    let query = chars!(query);
    let choice = chars!(choice);

    let (first_idx, _) = get_longest_match(&choice, &query).unwrap();
    get_match_indices(&choice, &query[1..], first_idx).unwrap()
}

fn compute_match_length(string: &[char], query: &[char]) -> Option<usize> {
    get_match_length(get_longest_match(string, query))
}

fn get_longest_match(string: &[char], query: &[char]) -> Option<(usize, usize)> {
    let first_char = query[0];
    let rest = &query[1..];
    let indices = find_char_in_string(string, first_char);

    let mut current_bounds: Option<(usize, usize)> = None;
    let smallest_possible_match = query.len();
    for &i in &indices {
        if let Some(last_index) = find_end_of_match(string, rest, i) {
            let last_bounds = Some((i, last_index));
            let last_match_len = get_match_length(last_bounds).unwrap();
            if current_bounds.is_none() || last_match_len < get_match_length(current_bounds).unwrap() {
                current_bounds = last_bounds;
                if last_match_len == smallest_possible_match {
                    break;
                }
            }
        }
    }
    current_bounds
}

fn get_match_length(bounds: Option<(usize, usize)>) -> Option<usize> {
    if let Some((lb, ub)) = bounds {
        Some(ub - lb + 1)
    } else {
        None
    }
}

fn find_char_in_string(string: &[char], char: char) -> Vec<usize> {
    let mut indices = Vec::new();
    for (i, c) in string.iter().enumerate() {
        if chars_equal(&char, c) {
            indices.push(i);
        }
    }
    return indices;
}

fn find_end_of_match(string: &[char], rest_of_query: &[char], first_index: usize) -> Option<usize> {
    if let Some(indices) = get_match_indices(string, rest_of_query, first_index) {
        Some(indices[indices.len() - 1])
    } else {
        None
    }
}

fn get_match_indices(string: &[char], rest_of_query: &[char], first_index: usize) -> Option<Vec<usize>> {
    let mut ret = Vec::new();
    let mut last_index = first_index + 1;
    ret.push(first_index);
    for c in rest_of_query.iter() {
        let current_substring = &string[last_index..];
        let mut index = None;
        for (i, x) in current_substring.iter().enumerate() {
            if chars_equal(c, x) {
                index = Some(i);
                break;
            }
        }
        if index.is_some() {
            last_index += index.unwrap() + 1;
            ret.push(last_index - 1);
        } else {
            return None;
        }
    }
    Some(ret)
}

fn chars_equal(q: &char, c: &char) -> bool {
    q == c || *q == c.to_ascii_lowercase()
}

#[test]
fn chars_equal_test() {
    assert!(chars_equal(&'a', &'a'));
    assert!(!chars_equal(&'a', &'b'));
    assert!(chars_equal(&'A', &'A'));
    assert!(!chars_equal(&'A', &'a'));
    assert!(chars_equal(&'a', &'A'));
}

#[test]
fn get_match_indices_test() {
    assert_eq!(get_match_indices(chars!("asdf"), chars!("sdf"), 0).unwrap(), vec![0, 1, 2, 3]);
    assert_eq!(get_match_indices(chars!("aoeuasdf"), chars!("sdf"), 4).unwrap(), vec![4, 5, 6, 7]);
    assert_eq!(get_match_indices(chars!(" a s d f"), chars!("sdf"), 1).unwrap(), vec![1, 3, 5, 7]);
}

#[test]
fn find_end_of_match_test() {
    assert_eq!(find_end_of_match(chars!("a"), chars!("a"), 0), None);
    assert_eq!(find_end_of_match(chars!("ba"), chars!("a"), 1), None);
    assert_eq!(find_end_of_match(chars!("aaa"), chars!("aa"), 0), Some(2));
    assert_eq!(find_end_of_match(chars!("aaa"), chars!("b"), 0), None);
    assert_eq!(find_end_of_match(chars!("this is a long match"), chars!("this is a match"), 0), None);
    assert_eq!(find_end_of_match(chars!("this is a long match"), chars!("his is a match"), 0), Some(19));
    assert_eq!(find_end_of_match(chars!("./rust/x86_64-apple-darwin/test/run-pass/process-spawn-with-unicode-params-πЯ音æ∞/child.stage2-x86_64-apple-darwin"), chars!("ust"), 2), Some(5));
}

#[test]
fn unicode_boundary_handling_test() {
    score("./rust/x86_64-apple-darwin/test/run-pass/process-spawn-with-unicode-params-πЯ音æ∞/child.stage2-x86_64-apple-darwin", "he");
}

#[test]
fn basic_scoring() {
    assert_eq!(score("", "a"), 0.0);
    assert_eq!(score("a", ""), 1.0);
    assert_eq!(score("short", "longer"), 0.0);
    assert_eq!(score("a", "b"), 0.0);
    assert_eq!(score("ab", "ac"), 0.0);

    assert!(score("a", "a") > 0.0);
    assert!(score("ab", "a") > 0.0);
    assert!(score("ba", "a") > 0.0);
    assert!(score("bab", "a") > 0.0);
    assert!(score("babababab", "aaaa") > 0.0);

    assert_eq!(score("a", "a"), 1_f64 / "a".len() as f64);
    assert_eq!(score("ab", "ab"), 0.5);
    assert_eq!(score("a long string", "a long string"), 1_f64 / "a long string".len() as f64);
    assert_eq!(score("spec/search_spec.rb", "sear"), 1_f64 / "spec/search_spec.rb".len() as f64);
}

#[test]
fn character_matching() {
    assert!(score("/! symbols $^", "/!$^") > 0.0);

    assert_eq!(score("a", "A"), 0.0);
    assert_eq!(score("A", "a"), 1.0);
    assert_eq!(score("A", "A"), 1.0);

    assert_eq!(score("a", "aa"), 0.0);
}

#[test]
fn match_equality() {
    assert!(score("selecta.gemspec", "asp") > score("algorithm4_spec.rb", "asp"));
    assert!(score("README.md", "em") > score("benchmark.rb", "em"));
    assert!(score("search.rb", "sear") > score("spec/search_spec.rb", "sear"));

    assert!(score("fbb", "fbb") > score("foo bar baz", "fbb"));
    assert!(score("foo", "foo") > score("longer foo", "foo"));
    assert!(score("foo", "foo") > score("foo longer", "foo"));
    assert!(score("1/2/3/4", "1/2/3") > score("1/9/2/3/4", "1/2/3"));

    assert!(score("long 12 long", "12") > score("1 long 2", "12"));

    assert_eq!(score("121padding2", "12"), 1.0 / "121padding2".len() as f64);
    assert_eq!(score("1padding212", "12"), 1.0 / "1padding212".len() as f64);
}
<|endoftext|>


<commit_before>//! Contains mathematical functions that operate on tensors. These functions are largely modelled
//! after what is available natively in Rust.

use tensor::Tensor;
use Numeric;
use num::traits::Float;

macro_rules! add_impl {
    ($($f:ident)*) => ($(
        pub fn $f<T: Numeric + Float>(x: Tensor<T>) -> Tensor<T> {
            //let mut y = Tensor::zeros(&x.shape());
            let mut y = x;
            for i in 0..y.size() {
                y[i] = y[i].$f();
            }
            y
        }
    )*)
}

add_impl! { ln log10 log2 sin cos tan asin acos atan exp_m1
            ln_1p sinh cosh tanh asinh acosh atanh sqrt }

pub fn log<T: Numeric + Float>(x: Tensor<T>, base: T) -> Tensor<T> {
    let mut y = x;
    for i in 0..y.size() {
        y[i] = y[i].log(base);
    }
    y
}

/*
pub fn gt<T: TensorType>(lhs: &Tensor<T>, rhs: &Tensor<T>) -> Tensor<bool> {
    assert_eq!(lhs.shape(), rhs.shape());
    let mut y = Tensor::empty(&lhs.shape());
    for i in 0..lhs.size() {
        y[i] = lhs[i] > rhs[i];
    }
    y
}
*/
<commit_msg>Removed old commented out code<commit_after>//! Contains mathematical functions that operate on tensors. These functions are largely modelled
//! after what is available natively in Rust.

use tensor::Tensor;
use Numeric;
use num::traits::Float;

macro_rules! add_impl {
    ($($f:ident)*) => ($(
        pub fn $f<T: Numeric + Float>(x: Tensor<T>) -> Tensor<T> {
            //let mut y = Tensor::zeros(&x.shape());
            let mut y = x;
            for i in 0..y.size() {
                y[i] = y[i].$f();
            }
            y
        }
    )*)
}

add_impl! { ln log10 log2 sin cos tan asin acos atan exp_m1
            ln_1p sinh cosh tanh asinh acosh atanh sqrt }

pub fn log<T: Numeric + Float>(x: Tensor<T>, base: T) -> Tensor<T> {
    let mut y = x;
    for i in 0..y.size() {
        y[i] = y[i].log(base);
    }
    y
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

#[crate_id="calculator"];
#[crate_type="bin"];

extern crate capnp;
extern crate extra;
extern crate capnp_rpc = "capnp-rpc";

pub mod calculator_capnp;

pub mod client;
pub mod server;

pub fn main() {
    match std::os::args() {
        [_, ~"client", ..] => client::main(),
        [_, ~"server", ..] => server::main(),
        args => println!("usage: {} [client | server] ADDRESS", args[0]),
    }
}
<commit_msg>owned vector patterns are gone<commit_after>/*
 * Copyright (c) 2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

#[crate_id="calculator"];
#[crate_type="bin"];

extern crate capnp;
extern crate extra;
extern crate capnp_rpc = "capnp-rpc";

pub mod calculator_capnp;

pub mod client;
pub mod server;

pub fn main() {
    let args = std::os::args();
    if args.len() >= 2 {
        match args[1] {
            ~"client" => return client::main(),
            ~"server" => return server::main(),
            _ => (),
        }
    }

    println!("usage: {} [client | server] ADDRESS", args[0]);
}
<|endoftext|>


<commit_before>//! Implementation of a simple uTP client and server.
#![feature(collections,convert,os)]

extern crate utp;

macro_rules! iotry {
    ($e:expr) => (match $e { Ok(v) => v, Err(e) => panic!("{}", e), })
}

fn usage() {
    println!("Usage: utp [-s|-c] <address> <port>");
}

fn main() {
    use utp::UtpStream;
    use std::io::{stdin, stdout, stderr, Read, Write};

    enum Mode {
        Server,
        Client
    }

    let args = std::os::args();
    let mut args = args.iter().map(|arg| &arg[..]);

    // Skip program name
    args.next();

    let mode = match args.next() {
        Some("-s") => Mode::Server,
        Some("-c") => Mode::Client,
        _ => { usage(); return; }
    };

    let addr = match (args.next(), args.next()) {
        (None, None) => String::from_str("127.0.0.1:8080"),
        (Some(ip), Some(port)) => format!("{}:{}", ip, port),
        _ => { usage(); return; }
    };
    let addr: &str = addr.as_ref();

    match mode {
        Mode::Server => {
            let mut stream = iotry!(UtpStream::bind(addr));
            let mut writer = stdout();
            let _ = writeln!(&mut stderr(), "Serving on {}", addr);

            let mut payload = vec![0; 1024 * 1024];
            loop {
                match stream.read(&mut payload) {
                    Ok(0) => break,
                    Ok(read) => iotry!(writer.write(&payload[..read])),
                    Err(e) => panic!("{}", e)
                };
            }
        }
        Mode::Client => {
            let mut stream = iotry!(UtpStream::connect(addr));
            let mut reader = stdin();

            let mut payload = vec![0; 1024 * 1024];
            loop {
                match reader.read(&mut payload) {
                    Ok(0) => break,
                    Ok(read) => iotry!(stream.write(&payload[..read])),
                    Err(e) => {
                        iotry!(stream.close());
                        panic!("{:?}", e);
                    }
                };
            }
            iotry!(stream.close());
        }
    }
}
<commit_msg>Clean up example code in utpcat.<commit_after>//! Implementation of a simple uTP client and server.
extern crate utp;

macro_rules! iotry {
    ($e:expr) => (match $e { Ok(v) => v, Err(e) => panic!("{}", e), })
}

fn usage() {
    println!("Usage: utp [-s|-c] <address> <port>");
}

fn main() {
    use utp::UtpStream;
    use std::io::{stdin, stdout, stderr, Read, Write};

    enum Mode {
        Server,
        Client
    }

    let mut args = std::env::args();

    // Skip program name
    args.next();

    let mode: Mode = match args.next() {
        Some(ref s) if &s[..] == "-s" => Mode::Server,
        Some(ref s) if &s[..] == "-c" => Mode::Client,
        _ => { usage(); return; }
    };

    let addr = match (args.next(), args.next()) {
        (None, None) => "127.0.0.1:8080".to_string(),
        (Some(ip), Some(port)) => format!("{}:{}", ip, port),
        _ => { usage(); return; }
    };
    let addr: &str = &addr;

    match mode {
        Mode::Server => {
            let mut stream = iotry!(UtpStream::bind(addr));
            let mut writer = stdout();
            let _ = writeln!(&mut stderr(), "Serving on {}", addr);

            let mut payload = vec![0; 1024 * 1024];
            loop {
                match stream.read(&mut payload) {
                    Ok(0) => break,
                    Ok(read) => iotry!(writer.write(&payload[..read])),
                    Err(e) => panic!("{}", e)
                };
            }
        }
        Mode::Client => {
            let mut stream = iotry!(UtpStream::connect(addr));
            let mut reader = stdin();

            let mut payload = vec![0; 1024 * 1024];
            loop {
                match reader.read(&mut payload) {
                    Ok(0) => break,
                    Ok(read) => iotry!(stream.write(&payload[..read])),
                    Err(e) => {
                        iotry!(stream.close());
                        panic!("{:?}", e);
                    }
                };
            }
            iotry!(stream.close());
        }
    }
}
<|endoftext|>


<commit_before>//! Actix web diesel example
//!
//! Diesel does not support tokio, so we have to run it in separate threads.
//! Actix supports sync actors by default, so we going to create sync actor that will
//! use diesel. Technically sync actors are worker style actors, multiple of them
//! can run in parallele and process messages from same queue.
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate diesel;
extern crate uuid;
extern crate futures;
extern crate actix;
extern crate actix_web;
extern crate env_logger;

use actix::prelude::*;
use actix_web::*;
use futures::future::{Future, ok};
use diesel::Connection;
use diesel::sqlite::SqliteConnection;
use diesel::prelude::*;

mod models;
mod schema;

struct State {
    db: SyncAddress<DbExecutor>,
}

fn index(req: HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>> {
    let name = &req.match_info()["name"];

    Box::new(
        req.state().db.call_fut(CreatePerson{name: name.to_owned()})
            .and_then(|res| {
                match res {
                    Ok(person) => ok(httpcodes::HTTPOk.build().json(person).unwrap()),
                    Err(_) => ok(httpcodes::HTTPInternalServerError.response())
                }
            })
            .map_err(|e| error::ErrorInternalServerError(e).into()))
}

/// This is db executor actor. We are going to run 3 of them in parallele.
struct DbExecutor(SqliteConnection);

/// This is only message that this actor can handle, but it is easy to extend number of
/// messages.
struct CreatePerson {
    name: String,
}

impl ResponseType for CreatePerson {
    type Item = models::User;
    type Error = Error;
}

impl Actor for DbExecutor {
    type Context = SyncContext<Self>;
}

impl Handler<CreatePerson> for DbExecutor {
    fn handle(&mut self, msg: CreatePerson, _: &mut Self::Context)
              -> Response<Self, CreatePerson>
    {
        use self::schema::users::dsl::*;

        let uuid = format!("{}", uuid::Uuid::new_v4());
        let new_user = models::NewUser {
            id: &uuid,
            name: &msg.name,
        };

        diesel::insert_into(users)
            .values(&new_user)
            .execute(&self.0)
            .expect("Error inserting person");

        let mut items = users
            .filter(id.eq(&uuid))
            .load::<models::User>(&self.0)
            .expect("Error loading person");

        Self::reply(items.pop().unwrap())
    }
}

fn main() {
    ::std::env::set_var("RUST_LOG", "actix_web=info");
    let _ = env_logger::init();
    let sys = actix::System::new("diesel-example");

    // Start db executor actors
    let addr = SyncArbiter::start(3, || {
        DbExecutor(SqliteConnection::establish("test.db").unwrap())
    });

    // Start http server
    HttpServer::new(move || {
        Application::with_state(State{db: addr.clone()})
            // enable logger
            .middleware(middlewares::Logger::default())
            .resource("/{name}", |r| r.method(Method::GET).a(index))})
        .bind("127.0.0.1:8080").unwrap()
        .start().unwrap();

    println!("Started http server: 127.0.0.1:8080");
    let _ = sys.run();
}
<commit_msg>add more comments<commit_after>//! Actix web diesel example
//!
//! Diesel does not support tokio, so we have to run it in separate threads.
//! Actix supports sync actors by default, so we going to create sync actor that will
//! use diesel. Technically sync actors are worker style actors, multiple of them
//! can run in parallele and process messages from same queue.
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate diesel;
extern crate uuid;
extern crate futures;
extern crate actix;
extern crate actix_web;
extern crate env_logger;

use actix::prelude::*;
use actix_web::*;
use futures::future::{Future, ok};
use diesel::Connection;
use diesel::sqlite::SqliteConnection;
use diesel::prelude::*;

mod models;
mod schema;

/// State with DbExecutor address
struct State {
    db: SyncAddress<DbExecutor>,
}

/// Async request handler
fn index(req: HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>> {
    let name = &req.match_info()["name"];

    Box::new(
        req.state().db.call_fut(CreatePerson{name: name.to_owned()})
            .and_then(|res| {
                match res {
                    Ok(person) => ok(httpcodes::HTTPOk.build().json(person).unwrap()),
                    Err(_) => ok(httpcodes::HTTPInternalServerError.response())
                }
            })
            .map_err(|e| error::ErrorInternalServerError(e).into()))
}

/// This is db executor actor. We are going to run 3 of them in parallele.
struct DbExecutor(SqliteConnection);

/// This is only message that this actor can handle, but it is easy to extend number of
/// messages.
struct CreatePerson {
    name: String,
}

impl ResponseType for CreatePerson {
    type Item = models::User;
    type Error = Error;
}

impl Actor for DbExecutor {
    type Context = SyncContext<Self>;
}

impl Handler<CreatePerson> for DbExecutor {
    fn handle(&mut self, msg: CreatePerson, _: &mut Self::Context)
              -> Response<Self, CreatePerson>
    {
        use self::schema::users::dsl::*;

        let uuid = format!("{}", uuid::Uuid::new_v4());
        let new_user = models::NewUser {
            id: &uuid,
            name: &msg.name,
        };

        diesel::insert_into(users)
            .values(&new_user)
            .execute(&self.0)
            .expect("Error inserting person");

        let mut items = users
            .filter(id.eq(&uuid))
            .load::<models::User>(&self.0)
            .expect("Error loading person");

        Self::reply(items.pop().unwrap())
    }
}

fn main() {
    ::std::env::set_var("RUST_LOG", "actix_web=info");
    let _ = env_logger::init();
    let sys = actix::System::new("diesel-example");

    // Start db executor actors
    let addr = SyncArbiter::start(3, || {
        DbExecutor(SqliteConnection::establish("test.db").unwrap())
    });

    // Start http server
    HttpServer::new(move || {
        Application::with_state(State{db: addr.clone()})
            // enable logger
            .middleware(middlewares::Logger::default())
            .resource("/{name}", |r| r.method(Method::GET).a(index))})
        .bind("127.0.0.1:8080").unwrap()
        .start().unwrap();

    println!("Started http server: 127.0.0.1:8080");
    let _ = sys.run();
}
<|endoftext|>


<commit_before>use std::path::*;
use std::string::String;

use case::*;

pub fn split_namespace_name(name: &str) -> (Option<&str>, &str) {
    let mut parts = name.split('.');
    let name = parts.next_back().unwrap();
    let ns = parts.next_back();
    assert!(ns.is_none() || parts.next().is_none());
    (ns, name)
}

pub fn file_name(full_name: &str) -> String {
    let (_, class_name) = split_namespace_name(full_name);
    let mut name = PathBuf::from(class_name.to_snake());
    let added = name.set_extension("rs");
    assert!(added);
    name.to_str().unwrap().into()
}

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

    #[test]
    fn split_no_namespace() {
        let (ns, name) = split_namespace_name("GObject");
        assert_eq!(ns, None);
        assert_eq!(name, "GObject");
    }

    #[test]
    fn split_full_name() {
        assert_eq!(split_namespace_name("Gtk.StatusIcon").1, "StatusIcon");
    }

    #[test]
    fn file_name_works() {
        assert_eq!(file_name("Gtk.StatusIcon"), "status_icon.rs");
    }
}
<commit_msg>Update a split_namespace_name test<commit_after>use std::path::*;
use std::string::String;

use case::*;

pub fn split_namespace_name(name: &str) -> (Option<&str>, &str) {
    let mut parts = name.split('.');
    let name = parts.next_back().unwrap();
    let ns = parts.next_back();
    assert!(ns.is_none() || parts.next().is_none());
    (ns, name)
}

pub fn file_name(full_name: &str) -> String {
    let (_, class_name) = split_namespace_name(full_name);
    let mut name = PathBuf::from(class_name.to_snake());
    let added = name.set_extension("rs");
    assert!(added);
    name.to_str().unwrap().into()
}

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

    #[test]
    fn split_no_namespace() {
        let (ns, name) = split_namespace_name("GObject");
        assert_eq!(ns, None);
        assert_eq!(name, "GObject");
    }

    #[test]
    fn split_full_name() {
        let (ns, name) = split_namespace_name("Gtk.StatusIcon");
        assert_eq!(ns, "Gtk");
        assert_eq!(name, "StatusIcon");
    }

    #[test]
    fn file_name_works() {
        assert_eq!(file_name("Gtk.StatusIcon"), "status_icon.rs");
    }
}
<|endoftext|>


<commit_before>use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::allowed_url::{Fragment, Href};
use crate::aspect_ratio::AspectRatio;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::{CascadedValues, Node};
use crate::parsers::ParseValue;
use crate::property_bag::PropertyBag;
use crate::rect::Rect;
use crate::viewbox::ViewBox;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, Primitive};

/// The `feImage` filter primitive.
pub struct FeImage {
    base: Primitive,
    aspect: AspectRatio,
    href: Option<Href>,
}

impl Default for FeImage {
    /// Constructs a new `FeImage` with empty properties.
    #[inline]
    fn default() -> FeImage {
        FeImage {
            base: Primitive::new::<Self>(),
            aspect: AspectRatio::default(),
            href: None,
        }
    }
}

impl FeImage {
    /// Renders the filter if the source is an existing node.
    fn render_node(
        &self,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes,
        draw_ctx: &mut DrawingCtx,
        bounds: Rect,
        fragment: &Fragment,
    ) -> Result<FilterResult, FilterError> {
        let acquired_drawable = acquired_nodes
            .acquire(fragment)
            .map_err(|_| FilterError::InvalidInput)?;
        let drawable = acquired_drawable.get();

        let node_being_filtered_values = ctx.get_computed_values_from_node_being_filtered();
        let cascaded = CascadedValues::new_from_values(&drawable, node_being_filtered_values);

        let image = draw_ctx.draw_node_to_surface(
            &drawable,
            acquired_nodes,
            &cascaded,
            ctx.paffine(),
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let surface = ctx.source_graphic().paint_image(bounds, &image, None)?;

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface,
                bounds: bounds.into(),
            },
        })
    }

    /// Renders the filter if the source is an external image.
    fn render_external_image(
        &self,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes,
        _draw_ctx: &DrawingCtx,
        bounds: Rect,
        unclipped_bounds: &Rect,
        url: &str,
    ) -> Result<FilterResult, FilterError> {
        // FIXME: translate the error better here
        let image = acquired_nodes
            .lookup_image(url)
            .map_err(|_| FilterError::InvalidInput)?;

        // TODO: this goes through a f64->i32->f64 conversion.
        let rect = self.aspect.compute(
            &ViewBox(Rect::from_size(
                f64::from(image.width()),
                f64::from(image.height()),
            )),
            &unclipped_bounds,
        );

        let surface = ctx
            .source_graphic()
            .paint_image(bounds, &image, Some(rect))?;

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface,
                bounds: bounds.into(),
            },
        })
    }
}

impl SetAttributes for FeImage {
    fn set_attributes(&mut self, pbag: &PropertyBag<'_>) -> ElementResult {
        self.base.set_attributes(pbag)?;

        for (attr, value) in pbag.iter() {
            match attr.expanded() {
                expanded_name!("", "preserveAspectRatio") => self.aspect = attr.parse(value)?,

                // "path" is used by some older Adobe Illustrator versions
                expanded_name!(xlink "href") | expanded_name!("", "path") => {
                    let href = Href::parse(value)
                        .map_err(|e| ValueErrorKind::from(e))
                        .attribute(attr)?;

                    self.href = Some(href);
                }

                _ => (),
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeImage {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let bounds_builder = self.base.get_bounds(ctx, node.parent().as_ref())?;
        let bounds = bounds_builder.into_rect(draw_ctx);

        match self.href.as_ref() {
            Some(Href::PlainUrl(url)) => {
                let unclipped_bounds = bounds_builder.into_rect_without_clipping(draw_ctx);
                self.render_external_image(
                    ctx,
                    acquired_nodes,
                    draw_ctx,
                    bounds,
                    &unclipped_bounds,
                    url,
                )
            }
            Some(Href::WithFragment(ref frag)) => {
                self.render_node(ctx, acquired_nodes, draw_ctx, bounds, frag)
            }
            _ => Err(FilterError::InvalidInput),
        }
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        false
    }
}
<commit_msg>image: fix clippy warning<commit_after>use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::allowed_url::{Fragment, Href};
use crate::aspect_ratio::AspectRatio;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::{CascadedValues, Node};
use crate::parsers::ParseValue;
use crate::property_bag::PropertyBag;
use crate::rect::Rect;
use crate::viewbox::ViewBox;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, Primitive};

/// The `feImage` filter primitive.
pub struct FeImage {
    base: Primitive,
    aspect: AspectRatio,
    href: Option<Href>,
}

impl Default for FeImage {
    /// Constructs a new `FeImage` with empty properties.
    #[inline]
    fn default() -> FeImage {
        FeImage {
            base: Primitive::new::<Self>(),
            aspect: AspectRatio::default(),
            href: None,
        }
    }
}

impl FeImage {
    /// Renders the filter if the source is an existing node.
    fn render_node(
        &self,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes,
        draw_ctx: &mut DrawingCtx,
        bounds: Rect,
        fragment: &Fragment,
    ) -> Result<FilterResult, FilterError> {
        let acquired_drawable = acquired_nodes
            .acquire(fragment)
            .map_err(|_| FilterError::InvalidInput)?;
        let drawable = acquired_drawable.get();

        let node_being_filtered_values = ctx.get_computed_values_from_node_being_filtered();
        let cascaded = CascadedValues::new_from_values(&drawable, node_being_filtered_values);

        let image = draw_ctx.draw_node_to_surface(
            &drawable,
            acquired_nodes,
            &cascaded,
            ctx.paffine(),
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let surface = ctx.source_graphic().paint_image(bounds, &image, None)?;

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface,
                bounds: bounds.into(),
            },
        })
    }

    /// Renders the filter if the source is an external image.
    fn render_external_image(
        &self,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes,
        _draw_ctx: &DrawingCtx,
        bounds: Rect,
        unclipped_bounds: &Rect,
        url: &str,
    ) -> Result<FilterResult, FilterError> {
        // FIXME: translate the error better here
        let image = acquired_nodes
            .lookup_image(url)
            .map_err(|_| FilterError::InvalidInput)?;

        // TODO: this goes through a f64->i32->f64 conversion.
        let rect = self.aspect.compute(
            &ViewBox(Rect::from_size(
                f64::from(image.width()),
                f64::from(image.height()),
            )),
            &unclipped_bounds,
        );

        let surface = ctx
            .source_graphic()
            .paint_image(bounds, &image, Some(rect))?;

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface,
                bounds: bounds.into(),
            },
        })
    }
}

impl SetAttributes for FeImage {
    fn set_attributes(&mut self, pbag: &PropertyBag<'_>) -> ElementResult {
        self.base.set_attributes(pbag)?;

        for (attr, value) in pbag.iter() {
            match attr.expanded() {
                expanded_name!("", "preserveAspectRatio") => self.aspect = attr.parse(value)?,

                // "path" is used by some older Adobe Illustrator versions
                expanded_name!(xlink "href") | expanded_name!("", "path") => {
                    let href = Href::parse(value)
                        .map_err(ValueErrorKind::from)
                        .attribute(attr)?;

                    self.href = Some(href);
                }

                _ => (),
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeImage {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let bounds_builder = self.base.get_bounds(ctx, node.parent().as_ref())?;
        let bounds = bounds_builder.into_rect(draw_ctx);

        match self.href.as_ref() {
            Some(Href::PlainUrl(url)) => {
                let unclipped_bounds = bounds_builder.into_rect_without_clipping(draw_ctx);
                self.render_external_image(
                    ctx,
                    acquired_nodes,
                    draw_ctx,
                    bounds,
                    &unclipped_bounds,
                    url,
                )
            }
            Some(Href::WithFragment(ref frag)) => {
                self.render_node(ctx, acquired_nodes, draw_ctx, bounds, frag)
            }
            _ => Err(FilterError::InvalidInput),
        }
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        false
    }
}
<|endoftext|>


<commit_before>use crate::dep_graph::DepNodeIndex;
use crate::query::plumbing::{QueryLookup, QueryState};
use crate::query::QueryContext;

use arena::TypedArena;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sharded::Sharded;
use rustc_data_structures::sync::WorkerLocal;
use std::default::Default;
use std::hash::Hash;
use std::marker::PhantomData;

pub trait CacheSelector<K, V> {
    type Cache;
}

pub trait QueryStorage: Default {
    type Value;
    type Stored: Clone;

    /// Store a value without putting it in the cache.
    /// This is meant to be used with cycle errors.
    fn store_nocache(&self, value: Self::Value) -> Self::Stored;
}

pub trait QueryCache: QueryStorage {
    type Key: Hash;
    type Sharded: Default;

    /// Checks if the query is already computed and in the cache.
    /// It returns the shard index and a lock guard to the shard,
    /// which will be used if the query is not in the cache and we need
    /// to compute it.
    fn lookup<CTX: QueryContext, R, OnHit, OnMiss>(
        &self,
        state: &QueryState<CTX, Self>,
        key: Self::Key,
        // `on_hit` can be called while holding a lock to the query state shard.
        on_hit: OnHit,
        on_miss: OnMiss,
    ) -> R
    where
        OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R,
        OnMiss: FnOnce(Self::Key, QueryLookup<'_, CTX, Self::Key, Self::Sharded>) -> R;

    fn complete<CTX: QueryContext>(
        &self,
        tcx: CTX,
        lock_sharded_storage: &mut Self::Sharded,
        key: Self::Key,
        value: Self::Value,
        index: DepNodeIndex,
    ) -> Self::Stored;

    fn iter<R, L>(
        &self,
        shards: &Sharded<L>,
        get_shard: impl Fn(&mut L) -> &mut Self::Sharded,
        f: impl for<'a> FnOnce(
            Box<dyn Iterator<Item = (&'a Self::Key, &'a Self::Value, DepNodeIndex)> + 'a>,
        ) -> R,
    ) -> R;
}

pub struct DefaultCacheSelector;

impl<K: Eq + Hash, V: Clone> CacheSelector<K, V> for DefaultCacheSelector {
    type Cache = DefaultCache<K, V>;
}

pub struct DefaultCache<K, V>(PhantomData<(K, V)>);

impl<K, V> Default for DefaultCache<K, V> {
    fn default() -> Self {
        DefaultCache(PhantomData)
    }
}

impl<K: Eq + Hash, V: Clone> QueryStorage for DefaultCache<K, V> {
    type Value = V;
    type Stored = V;

    fn store_nocache(&self, value: Self::Value) -> Self::Stored {
        // We have no dedicated storage
        value
    }
}

impl<K: Eq + Hash, V: Clone> QueryCache for DefaultCache<K, V> {
    type Key = K;
    type Sharded = FxHashMap<K, (V, DepNodeIndex)>;

    #[inline(always)]
    fn lookup<CTX: QueryContext, R, OnHit, OnMiss>(
        &self,
        state: &QueryState<CTX, Self>,
        key: K,
        on_hit: OnHit,
        on_miss: OnMiss,
    ) -> R
    where
        OnHit: FnOnce(&V, DepNodeIndex) -> R,
        OnMiss: FnOnce(K, QueryLookup<'_, CTX, K, Self::Sharded>) -> R,
    {
        let mut lookup = state.get_lookup(&key);
        let lock = &mut *lookup.lock;

        let result = lock.cache.raw_entry().from_key_hashed_nocheck(lookup.key_hash, &key);

        if let Some((_, value)) = result { on_hit(&value.0, value.1) } else { on_miss(key, lookup) }
    }

    #[inline]
    fn complete<CTX: QueryContext>(
        &self,
        _: CTX,
        lock_sharded_storage: &mut Self::Sharded,
        key: K,
        value: V,
        index: DepNodeIndex,
    ) -> Self::Stored {
        lock_sharded_storage.insert(key, (value.clone(), index));
        value
    }

    fn iter<R, L>(
        &self,
        shards: &Sharded<L>,
        get_shard: impl Fn(&mut L) -> &mut Self::Sharded,
        f: impl for<'a> FnOnce(Box<dyn Iterator<Item = (&'a K, &'a V, DepNodeIndex)> + 'a>) -> R,
    ) -> R {
        let mut shards = shards.lock_shards();
        let mut shards: Vec<_> = shards.iter_mut().map(|shard| get_shard(shard)).collect();
        let results = shards.iter_mut().flat_map(|shard| shard.iter()).map(|(k, v)| (k, &v.0, v.1));
        f(Box::new(results))
    }
}

pub struct ArenaCacheSelector<'tcx>(PhantomData<&'tcx ()>);

impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<K, V> for ArenaCacheSelector<'tcx> {
    type Cache = ArenaCache<'tcx, K, V>;
}

pub struct ArenaCache<'tcx, K, V> {
    arena: WorkerLocal<&'tcx TypedArena<(V, DepNodeIndex)>>,
    phantom: PhantomData<K>,
}

impl<'tcx, K, V> Default for ArenaCache<'tcx, K, V> {
    fn default() -> Self {
        ArenaCache {
            arena: WorkerLocal::new(|_| &*Box::leak(Box::new(TypedArena::default()))),
            phantom: PhantomData,
        }
    }
}

impl<'tcx, K: Eq + Hash, V: 'tcx> QueryStorage for ArenaCache<'tcx, K, V> {
    type Value = V;
    type Stored = &'tcx V;

    fn store_nocache(&self, value: Self::Value) -> Self::Stored {
        let value = self.arena.alloc((value, DepNodeIndex::INVALID));
        &value.0
    }
}

impl<'tcx, K: Eq + Hash, V: 'tcx> QueryCache for ArenaCache<'tcx, K, V> {
    type Key = K;
    type Sharded = FxHashMap<K, &'tcx (V, DepNodeIndex)>;

    #[inline(always)]
    fn lookup<CTX: QueryContext, R, OnHit, OnMiss>(
        &self,
        state: &QueryState<CTX, Self>,
        key: K,
        on_hit: OnHit,
        on_miss: OnMiss,
    ) -> R
    where
        OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R,
        OnMiss: FnOnce(K, QueryLookup<'_, CTX, K, Self::Sharded>) -> R,
    {
        let mut lookup = state.get_lookup(&key);
        let lock = &mut *lookup.lock;

        let result = lock.cache.raw_entry().from_key_hashed_nocheck(lookup.key_hash, &key);

        if let Some((_, value)) = result {
            on_hit(&&value.0, value.1)
        } else {
            on_miss(key, lookup)
        }
    }

    #[inline]
    fn complete<CTX: QueryContext>(
        &self,
        _: CTX,
        lock_sharded_storage: &mut Self::Sharded,
        key: K,
        value: V,
        index: DepNodeIndex,
    ) -> Self::Stored {
        let value = self.arena.alloc((value, index));
        lock_sharded_storage.insert(key, value);
        &value.0
    }

    fn iter<R, L>(
        &self,
        shards: &Sharded<L>,
        get_shard: impl Fn(&mut L) -> &mut Self::Sharded,
        f: impl for<'a> FnOnce(Box<dyn Iterator<Item = (&'a K, &'a V, DepNodeIndex)> + 'a>) -> R,
    ) -> R {
        let mut shards = shards.lock_shards();
        let mut shards: Vec<_> = shards.iter_mut().map(|shard| get_shard(shard)).collect();
        let results = shards.iter_mut().flat_map(|shard| shard.iter()).map(|(k, v)| (k, &v.0, v.1));
        f(Box::new(results))
    }
}
<commit_msg>Stop leaking memory.<commit_after>use crate::dep_graph::DepNodeIndex;
use crate::query::plumbing::{QueryLookup, QueryState};
use crate::query::QueryContext;

use arena::TypedArena;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sharded::Sharded;
use rustc_data_structures::sync::WorkerLocal;
use std::default::Default;
use std::hash::Hash;
use std::marker::PhantomData;

pub trait CacheSelector<K, V> {
    type Cache;
}

pub trait QueryStorage: Default {
    type Value;
    type Stored: Clone;

    /// Store a value without putting it in the cache.
    /// This is meant to be used with cycle errors.
    fn store_nocache(&self, value: Self::Value) -> Self::Stored;
}

pub trait QueryCache: QueryStorage {
    type Key: Hash;
    type Sharded: Default;

    /// Checks if the query is already computed and in the cache.
    /// It returns the shard index and a lock guard to the shard,
    /// which will be used if the query is not in the cache and we need
    /// to compute it.
    fn lookup<CTX: QueryContext, R, OnHit, OnMiss>(
        &self,
        state: &QueryState<CTX, Self>,
        key: Self::Key,
        // `on_hit` can be called while holding a lock to the query state shard.
        on_hit: OnHit,
        on_miss: OnMiss,
    ) -> R
    where
        OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R,
        OnMiss: FnOnce(Self::Key, QueryLookup<'_, CTX, Self::Key, Self::Sharded>) -> R;

    fn complete<CTX: QueryContext>(
        &self,
        tcx: CTX,
        lock_sharded_storage: &mut Self::Sharded,
        key: Self::Key,
        value: Self::Value,
        index: DepNodeIndex,
    ) -> Self::Stored;

    fn iter<R, L>(
        &self,
        shards: &Sharded<L>,
        get_shard: impl Fn(&mut L) -> &mut Self::Sharded,
        f: impl for<'a> FnOnce(
            Box<dyn Iterator<Item = (&'a Self::Key, &'a Self::Value, DepNodeIndex)> + 'a>,
        ) -> R,
    ) -> R;
}

pub struct DefaultCacheSelector;

impl<K: Eq + Hash, V: Clone> CacheSelector<K, V> for DefaultCacheSelector {
    type Cache = DefaultCache<K, V>;
}

pub struct DefaultCache<K, V>(PhantomData<(K, V)>);

impl<K, V> Default for DefaultCache<K, V> {
    fn default() -> Self {
        DefaultCache(PhantomData)
    }
}

impl<K: Eq + Hash, V: Clone> QueryStorage for DefaultCache<K, V> {
    type Value = V;
    type Stored = V;

    fn store_nocache(&self, value: Self::Value) -> Self::Stored {
        // We have no dedicated storage
        value
    }
}

impl<K: Eq + Hash, V: Clone> QueryCache for DefaultCache<K, V> {
    type Key = K;
    type Sharded = FxHashMap<K, (V, DepNodeIndex)>;

    #[inline(always)]
    fn lookup<CTX: QueryContext, R, OnHit, OnMiss>(
        &self,
        state: &QueryState<CTX, Self>,
        key: K,
        on_hit: OnHit,
        on_miss: OnMiss,
    ) -> R
    where
        OnHit: FnOnce(&V, DepNodeIndex) -> R,
        OnMiss: FnOnce(K, QueryLookup<'_, CTX, K, Self::Sharded>) -> R,
    {
        let mut lookup = state.get_lookup(&key);
        let lock = &mut *lookup.lock;

        let result = lock.cache.raw_entry().from_key_hashed_nocheck(lookup.key_hash, &key);

        if let Some((_, value)) = result { on_hit(&value.0, value.1) } else { on_miss(key, lookup) }
    }

    #[inline]
    fn complete<CTX: QueryContext>(
        &self,
        _: CTX,
        lock_sharded_storage: &mut Self::Sharded,
        key: K,
        value: V,
        index: DepNodeIndex,
    ) -> Self::Stored {
        lock_sharded_storage.insert(key, (value.clone(), index));
        value
    }

    fn iter<R, L>(
        &self,
        shards: &Sharded<L>,
        get_shard: impl Fn(&mut L) -> &mut Self::Sharded,
        f: impl for<'a> FnOnce(Box<dyn Iterator<Item = (&'a K, &'a V, DepNodeIndex)> + 'a>) -> R,
    ) -> R {
        let mut shards = shards.lock_shards();
        let mut shards: Vec<_> = shards.iter_mut().map(|shard| get_shard(shard)).collect();
        let results = shards.iter_mut().flat_map(|shard| shard.iter()).map(|(k, v)| (k, &v.0, v.1));
        f(Box::new(results))
    }
}

pub struct ArenaCacheSelector<'tcx>(PhantomData<&'tcx ()>);

impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<K, V> for ArenaCacheSelector<'tcx> {
    type Cache = ArenaCache<'tcx, K, V>;
}

pub struct ArenaCache<'tcx, K, V> {
    arena: WorkerLocal<TypedArena<(V, DepNodeIndex)>>,
    phantom: PhantomData<(K, &'tcx V)>,
}

impl<'tcx, K, V> Default for ArenaCache<'tcx, K, V> {
    fn default() -> Self {
        ArenaCache { arena: WorkerLocal::new(|_| TypedArena::default()), phantom: PhantomData }
    }
}

impl<'tcx, K: Eq + Hash, V: 'tcx> QueryStorage for ArenaCache<'tcx, K, V> {
    type Value = V;
    type Stored = &'tcx V;

    fn store_nocache(&self, value: Self::Value) -> Self::Stored {
        let value = self.arena.alloc((value, DepNodeIndex::INVALID));
        let value = unsafe { &*(&value.0 as *const _) };
        &value
    }
}

impl<'tcx, K: Eq + Hash, V: 'tcx> QueryCache for ArenaCache<'tcx, K, V> {
    type Key = K;
    type Sharded = FxHashMap<K, &'tcx (V, DepNodeIndex)>;

    #[inline(always)]
    fn lookup<CTX: QueryContext, R, OnHit, OnMiss>(
        &self,
        state: &QueryState<CTX, Self>,
        key: K,
        on_hit: OnHit,
        on_miss: OnMiss,
    ) -> R
    where
        OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R,
        OnMiss: FnOnce(K, QueryLookup<'_, CTX, K, Self::Sharded>) -> R,
    {
        let mut lookup = state.get_lookup(&key);
        let lock = &mut *lookup.lock;

        let result = lock.cache.raw_entry().from_key_hashed_nocheck(lookup.key_hash, &key);

        if let Some((_, value)) = result {
            on_hit(&&value.0, value.1)
        } else {
            on_miss(key, lookup)
        }
    }

    #[inline]
    fn complete<CTX: QueryContext>(
        &self,
        _: CTX,
        lock_sharded_storage: &mut Self::Sharded,
        key: K,
        value: V,
        index: DepNodeIndex,
    ) -> Self::Stored {
        let value = self.arena.alloc((value, index));
        let value = unsafe { &*(value as *const _) };
        lock_sharded_storage.insert(key, value);
        &value.0
    }

    fn iter<R, L>(
        &self,
        shards: &Sharded<L>,
        get_shard: impl Fn(&mut L) -> &mut Self::Sharded,
        f: impl for<'a> FnOnce(Box<dyn Iterator<Item = (&'a K, &'a V, DepNodeIndex)> + 'a>) -> R,
    ) -> R {
        let mut shards = shards.lock_shards();
        let mut shards: Vec<_> = shards.iter_mut().map(|shard| get_shard(shard)).collect();
        let results = shards.iter_mut().flat_map(|shard| shard.iter()).map(|(k, v)| (k, &v.0, v.1));
        f(Box::new(results))
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
#[phase(plugin)]

extern crate regex_macros;
extern crate regex;
extern crate core;
extern crate getopts;

use std::io::{stdin, stderr, BufferedWriter};
use std::io::stdio::{stdout_raw};
use std::os::{args, set_exit_status};
use std::{uint, str};

use getopts::{getopts, optopt, optflag, usage};

use Alignment::{Left, Right, Centered};

struct DynVec<T> {
    vec: Vec<T>,
    default: T,
}

impl<T: Clone> DynVec<T> {
    fn new(default: T) -> DynVec<T> {
        DynVec { vec: Vec::new(), default: default }
    }

    fn get(&self, i: uint) -> T {
        if i < self.vec.len() {
            self.vec[i].clone()
        } else {
            self.default.clone()
        }
    }

    fn set(&mut self, index: uint, v: T) {
        let l = self.vec.len();
        if index >= l {
            self.vec.grow(index - l + 1u, self.default.clone());
        }
        self.vec[index] = v
    }

    fn push(&mut self, v: T) {
        self.default = v.clone();
        self.vec.push(v);
    }
}

#[deriving(Clone)]
enum Alignment {
    Left,
    Right,
    Centered,
}

struct Opts {
    str_delim: char,
    out_sep:   Vec<u8>,
    until:     uint,
    unicode:   bool,
    align:     DynVec<Alignment>,
    max_width: DynVec<uint>,
}

fn parse_opts() -> Result<Opts, ()> {
    let args = args();
    let prog_name = &args[0];

    let opts = [
        optopt("o", "", "set the output separator", "output separator"),
        optopt("s", "", "set the string delimiter", "string delimiter"),
        optopt("u", "", "set the maximum column", "until"),
        optflag("U", "", "read as UTF8 and use unicode width"),
        optflag("h", "", "print this help menu"),
    ];
    let matches = match getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f);
            set_exit_status(1);
            return Err(());
        }
    };
    if matches.opt_present("h") {
        print!("{}", usage(prog_name.as_slice(), &opts));
        return Err(());
    }
    let unicode = matches.opt_present("U");
    let out_sep = match matches.opt_str("o") {
        Some(s) => s.into_bytes(),
        None => " ".to_string().into_bytes(),
    };
    let str_delim = match matches.opt_str("s") {
        Some(s) => {
            match s.len() {
                0 => 0u8 as char,
                _ => s.as_bytes()[0] as char,
            }
        },
        None => '"',
    };
    let until = match matches.opt_str("u") {
        Some(s) => match s.as_slice().parse() {
            Some(u) => u,
            None => {
                let _ = writeln!(&mut stderr(), "-u argument has to be a number");
                set_exit_status(1);
                return Err(());
            },
        },
        None => uint::MAX,
    };
    let mut align = DynVec::new(Left);
    let mut max_width = DynVec::new(0u);
    if matches.free.len() > 0 {
        let fmt = &matches.free[0];
        let test = regex!(r"(\d*)([<>=])");
        for c in test.captures_iter(fmt.as_slice()) {
            match c.at(1).unwrap() {
                p if p.len() > 0 => max_width.push(p.parse().unwrap()),
                _ => max_width.push(0),
            }
            match c.at(2).unwrap() {
                "<" => align.push(Left),
                ">" => align.push(Right),
                "=" => align.push(Centered),
                _ => unreachable!(),
            }
        }
        max_width.push(0);
    }
    Ok(Opts {
        str_delim: str_delim,
        out_sep: out_sep,
        until: until,
        unicode: unicode,
        align: align,
        max_width: max_width
    })
}

struct Words {
    line: Vec<u8>,
    words: Vec<(uint, uint)>,
}

impl Words {
    fn new(line: Vec<u8>, str_delim: char, until: uint) -> Words {
        let mut words = Vec::new();
        let mut pos = 0;
        loop {
            pos += match line.slice_from(pos).iter().position(|&c|
                                                         !(c as char).is_whitespace()) {
                Some(i) => i,
                None => break,
            };
            if words.len() == until {
                let end = match line.slice_from(pos).iter().position(|&c| c=='\n' as u8) {
                    Some(e) => pos + e,
                    None => line.len(),
                };
                words.push((pos, end));
                break;
            }
            let start = pos;
            let mut esc = false;
            let mut string = false;
            for (i, &c) in line.slice_from(start).iter().enumerate() {
                if !esc && c == str_delim as u8 {
                    string = !string;
                }
                esc = !esc && c == '\\' as u8;
                if c == '\n' as u8 || (!string && (c == ' ' as u8 || c == '\t' as u8)) {
                    pos += i;
                    break;
                }
            }
            words.push((start, pos));
        }
        Words { line: line, words: words }
    }

    fn iter<'a>(&'a self) -> WordIter<'a> {
        WordIter {
            pos: 0,
            line: &self.line,
            words: &self.words,
        }
    }
}

struct WordIter<'a> {
    pos: uint,
    line: &'a Vec<u8>,
    words: &'a Vec<(uint, uint)>,
}

impl<'a> Iterator<&'a [u8]> for WordIter<'a> {
    fn next(&mut self) -> Option<&'a [u8]> {
        if self.pos < self.words.len() {
            let (start, end) = self.words[self.pos];
            self.pos += 1;
            Some(self.line.slice(start, end))
        } else {
            None
        }
    }
}

fn is_indent(c: u8) -> bool {
    c == ' ' as u8 || c == '\t' as u8
}

fn unsafe_byte_unicode_width(s: &[u8]) -> uint {
    unsafe { str::from_utf8_unchecked(s).width(false) }
}

fn read_as_bytes(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        let line = match stdin.read_until('\n' as u8) {
            Ok(l) => l,
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            if word.len() > opts.max_width.get(i) {
                opts.max_width.set(i, word.len());
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn read_as_unicode(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        // Unicode validation up here
        let line = match stdin.read_line() {
            Ok(l) => l.into_bytes(),
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            let width = unsafe_byte_unicode_width(word);
            if width > opts.max_width.get(i) {
                opts.max_width.set(i, width);
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn main() {
    let mut opts = match parse_opts() {
        Ok(o) => o,
        Err(..) => return,
    };

    let (indent, lines) = if opts.unicode {
        read_as_unicode(&mut opts)
    } else {
        read_as_bytes(&mut opts)
    };
    if lines.len() == 0 {
        return;
    }
    let indent = indent.unwrap();
    let padding = {
        let max_max_width = *opts.max_width.vec.iter().max().unwrap_or(&0);
        Vec::from_elem(max_max_width, ' ' as u8)
    };

    let mut stdout = BufferedWriter::new(stdout_raw());
    for line in lines.iter() {
        if line.words.len() > 0 {
            stdout.write(indent.as_slice()).unwrap();
        }
        let mut words = line.iter().enumerate().peekable();
        while let Some((i, word)) = words.next() {
            let pad = opts.max_width.get(i) - if opts.unicode {
                unsafe_byte_unicode_width(word)
            } else {
                word.len()
            };
            match opts.align.get(i) {
                Left => {
                    stdout.write(word).unwrap();
                    if words.peek().is_some() {
                        stdout.write(padding.slice_to(pad)).unwrap();
                    }
                },
                Right => {
                    stdout.write(padding.slice_to(pad)).unwrap();
                    stdout.write(word).unwrap();
                },
                Centered => {
                    stdout.write(padding.slice_to(pad/2)).unwrap();
                    stdout.write(word).unwrap();
                    if words.peek().is_some() {
                        stdout.write(padding.slice_to(pad-pad/2)).unwrap();
                    }
                },
            }
            if words.peek().is_some() {
                stdout.write(opts.out_sep.as_slice()).unwrap();
            }
        }
        stdout.write_str("\n").unwrap();
    }
}
<commit_msg>update syntax<commit_after>#![feature(phase, slicing_syntax)]
#![allow(unused_must_use)]

#[phase(plugin)]
extern crate regex_macros;
extern crate regex;
extern crate core;
extern crate getopts;

use std::io::{stdin, stderr, BufferedWriter};
use std::io::stdio::{stdout_raw};
use std::os::{args, set_exit_status};
use std::{uint, str};

use getopts::{getopts, optopt, optflag, usage};

use Alignment::{Left, Right, Centered};

struct DynVec<T> {
    vec: Vec<T>,
    default: T,
}

impl<T: Clone> DynVec<T> {
    fn new(default: T) -> DynVec<T> {
        DynVec { vec: Vec::new(), default: default }
    }

    fn get(&self, i: uint) -> T {
        if i < self.vec.len() {
            self.vec[i].clone()
        } else {
            self.default.clone()
        }
    }

    fn set(&mut self, index: uint, v: T) {
        let l = self.vec.len();
        if index >= l {
            self.vec.grow(index - l + 1u, self.default.clone());
        }
        self.vec[index] = v
    }

    fn push(&mut self, v: T) {
        self.default = v.clone();
        self.vec.push(v);
    }
}

#[deriving(Clone)]
enum Alignment {
    Left,
    Right,
    Centered,
}

struct Opts {
    str_delim: char,
    out_sep:   Vec<u8>,
    until:     uint,
    unicode:   bool,
    align:     DynVec<Alignment>,
    max_width: DynVec<uint>,
}

fn parse_opts() -> Result<Opts, ()> {
    let args = args();
    let prog_name = &args[0];

    let opts = [
        optopt("o", "", "set the output separator", "output separator"),
        optopt("s", "", "set the string delimiter", "string delimiter"),
        optopt("u", "", "set the maximum column", "until"),
        optflag("U", "", "read as UTF8 and use unicode width"),
        optflag("h", "", "print this help menu"),
    ];
    let matches = match getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f);
            set_exit_status(1);
            return Err(());
        }
    };
    if matches.opt_present("h") {
        print!("{}", usage(prog_name[], &opts));
        return Err(());
    }
    let unicode = matches.opt_present("U");
    let out_sep = match matches.opt_str("o") {
        Some(s) => s.into_bytes(),
        None => " ".to_string().into_bytes(),
    };
    let str_delim = match matches.opt_str("s") {
        Some(s) => {
            match s.len() {
                0 => 0u8 as char,
                _ => s.as_bytes()[0] as char,
            }
        },
        None => '"',
    };
    let until = match matches.opt_str("u") {
        Some(s) => match s.parse() {
            Some(u) => u,
            None => {
                let _ = writeln!(&mut stderr(), "-u argument has to be a number");
                set_exit_status(1);
                return Err(());
            },
        },
        None => uint::MAX,
    };
    let mut align = DynVec::new(Left);
    let mut max_width = DynVec::new(0u);
    if matches.free.len() > 0 {
        let fmt = &matches.free[0];
        let test = regex!(r"(\d*)([<>=])");
        for c in test.captures_iter(fmt[]) {
            match c.at(1).unwrap() {
                p if p.len() > 0 => max_width.push(p.parse().unwrap()),
                _ => max_width.push(0),
            }
            match c.at(2).unwrap() {
                "<" => align.push(Left),
                ">" => align.push(Right),
                "=" => align.push(Centered),
                _ => unreachable!(),
            }
        }
        max_width.push(0);
    }
    Ok(Opts {
        str_delim: str_delim,
        out_sep: out_sep,
        until: until,
        unicode: unicode,
        align: align,
        max_width: max_width
    })
}

struct Words {
    line: Vec<u8>,
    words: Vec<(uint, uint)>,
}

impl Words {
    fn new(line: Vec<u8>, str_delim: char, until: uint) -> Words {
        let mut words = Vec::new();
        let mut pos = 0;
        loop {
            pos += match line[pos..].iter().position(|&c| !(c as char).is_whitespace()) {
                Some(i) => i,
                None => break,
            };
            if words.len() == until {
                let end = match line[pos..].iter().position(|&c| c=='\n' as u8) {
                    Some(e) => pos + e,
                    None => line.len(),
                };
                words.push((pos, end));
                break;
            }
            let start = pos;
            let mut esc = false;
            let mut string = false;
            for (i, &c) in line[start..].iter().enumerate() {
                if !esc && c == str_delim as u8 {
                    string = !string;
                }
                esc = !esc && c == '\\' as u8;
                if c == '\n' as u8 || (!string && (c == ' ' as u8 || c == '\t' as u8)) {
                    pos += i;
                    break;
                }
            }
            words.push((start, pos));
        }
        Words { line: line, words: words }
    }

    fn iter<'a>(&'a self) -> WordIter<'a> {
        WordIter {
            pos: 0,
            line: &self.line,
            words: &self.words,
        }
    }
}

struct WordIter<'a> {
    pos: uint,
    line: &'a Vec<u8>,
    words: &'a Vec<(uint, uint)>,
}

impl<'a> Iterator<&'a [u8]> for WordIter<'a> {
    fn next(&mut self) -> Option<&'a [u8]> {
        if self.pos < self.words.len() {
            let (start, end) = self.words[self.pos];
            self.pos += 1;
            Some(self.line[start..end])
        } else {
            None
        }
    }
}

fn is_indent(c: u8) -> bool {
    c == ' ' as u8 || c == '\t' as u8
}

fn unsafe_byte_unicode_width(s: &[u8]) -> uint {
    unsafe { str::from_utf8_unchecked(s).width(false) }
}

fn read_as_bytes(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        let line = match stdin.read_until('\n' as u8) {
            Ok(l) => l,
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            if word.len() > opts.max_width.get(i) {
                opts.max_width.set(i, word.len());
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn read_as_unicode(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        // Unicode validation up here
        let line = match stdin.read_line() {
            Ok(l) => l.into_bytes(),
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            let width = unsafe_byte_unicode_width(word);
            if width > opts.max_width.get(i) {
                opts.max_width.set(i, width);
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn main() {
    let mut opts = match parse_opts() {
        Ok(o) => o,
        Err(..) => return,
    };

    let (indent, lines) = if opts.unicode {
        read_as_unicode(&mut opts)
    } else {
        read_as_bytes(&mut opts)
    };
    if lines.len() == 0 {
        return;
    }
    let indent = indent.unwrap();
    let padding = {
        let max_max_width = *opts.max_width.vec.iter().max().unwrap_or(&0);
        Vec::from_elem(max_max_width, ' ' as u8)
    };

    let mut stdout = BufferedWriter::new(stdout_raw());
    for line in lines.iter() {
        if line.words.len() > 0 {
            stdout.write(indent[]);
        }
        let mut words = line.iter().enumerate().peekable();
        while let Some((i, word)) = words.next() {
            let pad = opts.max_width.get(i) - if opts.unicode {
                unsafe_byte_unicode_width(word)
            } else {
                word.len()
            };
            match opts.align.get(i) {
                Left => {
                    stdout.write(word);
                    if words.peek().is_some() {
                        stdout.write(padding[0..pad]);
                    }
                },
                Right => {
                    stdout.write(padding[0..pad]);
                    stdout.write(word);
                },
                Centered => {
                    stdout.write(padding[0..pad/2]);
                    stdout.write(word);
                    if words.peek().is_some() {
                        stdout.write(padding[0..pad-pad/2]);
                    }
                },
            }
            if words.peek().is_some() {
                stdout.write(opts.out_sep[]);
            }
        }
        stdout.write_str("\n");
    }
}
<|endoftext|>


<commit_before>extern mod std;

#[test]
fn test_tokenize() {
    assert tokenize( ~"(1 2 3)" ) == ~[~"(", ~"1", ~"2", ~"3", ~")"];
}

#[test]
fn test_tokenize_empty() {
    assert tokenize( ~"" ) == ~[];
}

#[test]
fn test_tokenize_no_spaces() {
    assert tokenize( ~"one" ) == ~[~"one"];
}

#[test]
fn test_pad_parentheses() {
    assert pad_parentheses( ~"(1 2 3)" ) == ~" ( 1 2 3 ) "
}

#[test]
fn test_pad_parentheses_empty() {
    assert pad_parentheses( ~"" ) == ~""
}

#[test]
fn test_pad_parentheses_one() {
    assert pad_parentheses( ~"(" ) == ~" ( ";
    assert pad_parentheses( ~")" ) == ~" ) ";
}

fn pad_parentheses( input:&str ) -> ~str {
    str::replace(str::replace(input, ")", " ) "), "(", " ( ")
}

fn tokenize( input:&str ) -> ~[~str] {
    str::words(pad_parentheses(input))
}

#[test]
fn test_that_atom_can_read_a_symbol() {
    match atom(~"hello") {
        Symbol(~"hello") => (),
            _ => fail
    }
}

#[test]
fn test_that_atom_can_read_an_int() {
    match atom(~"10") {
        Int(10) => (),
            _ => fail
    }
}

#[test]
fn test_that_atom_can_read_a_float() {
    match atom(~"10.1") {
        Float(10.1) => (),
            _ => fail
    }
}

fn atom( input:~str ) -> Expression {
    match int::from_str(input) {
        Some(number) => Int(number),
        None => match float::from_str(input) {
            Some(number) => Float(number),
            None => Symbol(input)
        }
    }
}

#[test]
fn test_that_parse_can_read_an_atom() {
    let atom = parse( ~[~"12"] );
    match atom {
        Int(12) => (),
            _ => fail
    }
}

#[test]
fn test_that_parse_can_read_a_list() {
    let list = parse( ~[ ~"(", ~"1", ~")" ] );
    match list {
        List([Int(1)]) => (),
            _ => fail ~"not a list"
    }
}

#[test]
fn test_that_parse_can_read_a_nested_list() {
    let list = parse( ~[ ~"(", ~"1", ~"(", ~"2", ~")", ~"3", ~")" ] );
    match list {
        List([Int(1), List([Int(2)]), Int(3)]) => (),
        _ => fail
    }
}

fn parse( tokens:~[~str] ) -> Expression {
    fn subexpression( tokens:~[~str] ) -> (Expression, ~[~str]) {
        let token = tokens.head();
        match token {
            ~"(" => {
                let mut accumulator:~[Expression] = ~[];
                let mut remainder = tokens.tail();
                while remainder.len() > 0 && remainder.head() != ~")" {
                    let (expr, new_remainder) = subexpression( remainder );
                    accumulator += [expr];
                    remainder = new_remainder
                }
                (List(accumulator), remainder.tail())
            }
            ~")" => fail,
                _ => (atom(token), tokens.tail())
        }
    }
    let (expression, remainder) = subexpression( tokens );
    expression
}

enum Expression {
    Int(int),
    Float(float),
    Symbol(~str),
    List(~[Expression])
}

fn print_expression( expression:Expression ) {
    fn print_expr( expression:Expression ) {
        match expression {
            Int(number) => { io::print( fmt!("%d", number) ) }
            Float(number) => {
                if number == (number as int) as float {
                    io::print( fmt!("%.1f", number) )
                } else {
                    io::print( fmt!("%f", number) )
                }
            }
            Symbol(string) => { io::print( string ) }
            List(expressions) => {
                io::print("(");
                for expressions.init().each |&expression| {
                    print_expr( expression );
                    io::print(" ");
                }
                print_expr( expressions.last() );
                io::print(")");
            }
        }
    }
    print_expr(expression);
    io::println(~"");
}

fn main() {
    print_expression( parse( tokenize( "(1 2 3 (1 2 3))" ) ) );
    print_expression( parse( tokenize( "((1 2) 3 (1 2 3))" ) ) );
    let blah:Expression = List(~[Int(1), List(~[Float(1.0), Symbol(~"xyz")])]);
    print_expression(blah);
    io::println( "(begin 1 2)" )
}
<commit_msg>Change print_expression into stringify_expression<commit_after>extern mod std;

#[test]
fn test_tokenize() {
    assert tokenize( ~"(1 2 3)" ) == ~[~"(", ~"1", ~"2", ~"3", ~")"];
}

#[test]
fn test_tokenize_empty() {
    assert tokenize( ~"" ) == ~[];
}

#[test]
fn test_tokenize_no_spaces() {
    assert tokenize( ~"one" ) == ~[~"one"];
}

#[test]
fn test_pad_parentheses() {
    assert pad_parentheses( ~"(1 2 3)" ) == ~" ( 1 2 3 ) "
}

#[test]
fn test_pad_parentheses_empty() {
    assert pad_parentheses( ~"" ) == ~""
}

#[test]
fn test_pad_parentheses_one() {
    assert pad_parentheses( ~"(" ) == ~" ( ";
    assert pad_parentheses( ~")" ) == ~" ) ";
}

fn pad_parentheses( input:&str ) -> ~str {
    str::replace(str::replace(input, ")", " ) "), "(", " ( ")
}

fn tokenize( input:&str ) -> ~[~str] {
    str::words(pad_parentheses(input))
}

#[test]
fn test_that_atom_can_read_a_symbol() {
    match atom(~"hello") {
        Symbol(~"hello") => (),
            _ => fail
    }
}

#[test]
fn test_that_atom_can_read_an_int() {
    match atom(~"10") {
        Int(10) => (),
            _ => fail
    }
}

#[test]
fn test_that_atom_can_read_a_float() {
    match atom(~"10.1") {
        Float(10.1) => (),
            _ => fail
    }
}

fn atom( input:~str ) -> Expression {
    match int::from_str(input) {
        Some(number) => Int(number),
        None => match float::from_str(input) {
            Some(number) => Float(number),
            None => Symbol(input)
        }
    }
}

#[test]
fn test_that_parse_can_read_an_atom() {
    let atom = parse( ~[~"12"] );
    match atom {
        Int(12) => (),
            _ => fail
    }
}

#[test]
fn test_that_parse_can_read_a_list() {
    let list = parse( ~[ ~"(", ~"1", ~")" ] );
    match list {
        List([Int(1)]) => (),
            _ => fail ~"not a list"
    }
}

#[test]
fn test_that_parse_can_read_a_nested_list() {
    let list = parse( ~[ ~"(", ~"1", ~"(", ~"2", ~")", ~"3", ~")" ] );
    match list {
        List([Int(1), List([Int(2)]), Int(3)]) => (),
        _ => fail
    }
}

fn parse( tokens:~[~str] ) -> Expression {
    fn subexpression( tokens:~[~str] ) -> (Expression, ~[~str]) {
        let token = tokens.head();
        match token {
            ~"(" => {
                let mut accumulator:~[Expression] = ~[];
                let mut remainder = tokens.tail();
                while remainder.len() > 0 && remainder.head() != ~")" {
                    let (expr, new_remainder) = subexpression( remainder );
                    accumulator += [expr];
                    remainder = new_remainder
                }
                (List(accumulator), remainder.tail())
            }
            ~")" => fail,
                _ => (atom(token), tokens.tail())
        }
    }
    let (expression, remainder) = subexpression( tokens );
    expression
}

enum Expression {
    Int(int),
    Float(float),
    Symbol(~str),
    List(~[Expression])
}

fn stringify_expression( expression:Expression ) -> ~str {
    match expression {
        Int(number) => { fmt!("%d", number) }
        Float(number) => {
            if number == (number as int) as float {
                fmt!("%.1f", number)
            } else {
                fmt!("%f", number)
            }
        }
        Symbol(string) => { string }
        List(expressions) => {
            let strings = expressions.map( | &expr | {stringify_expression(expr)} );
            ~"(" + strings.foldl(~"", |&x, &y| { x + ~" " + y } ).trim() + ~")"
        }
    }
}

fn main() {
    io::println(stringify_expression( parse( tokenize( "(1 2 3 (1 2 3))" ) ) ));
    io::println(stringify_expression( parse( tokenize( "((1 2) 3 (1 2 3))" ) ) ));
    let blah:Expression = List(~[Int(1), List(~[Float(1.0), Symbol(~"xyz")])]);
    io::println(stringify_expression(blah));
    io::println( "(begin 1 2)" )
}
<|endoftext|>