<commit_before>// #![feature(scoped)]
// #![feature(collections)]

extern crate mmap;
extern crate time;
extern crate timely;
extern crate columnar;
extern crate dataflow_join;

extern crate docopt;
use docopt::Docopt;

use std::thread;

use dataflow_join::graph::{GraphTrait, GraphMMap};

use timely::progress::timestamp::RootTimestamp;
use timely::progress::scope::Scope;
use timely::progress::nested::Summary::Local;
use timely::example_static::*;
use timely::communication::*;
use timely::communication::pact::Exchange;

use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

static USAGE: &'static str = "
Usage: pagerank <source> [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      list of host:port for workers
";

fn main () {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    // let workers = if let Ok(threads) = args.get_str("<workers>").parse() { threads }
    //               else { panic!("invalid setting for workers: {}", args.get_str("<workers>")) };
    // println!("starting pagerank dataflow with {:?} worker{}", workers, if workers == 1 { "" } else { "s" });
    let source = args.get_str("<source>").to_owned();

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting pagerank dataflow with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        pagerank_multi(communicators, source);
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        pagerank_multi(ProcessCommunicator::new_vector(workers), source);
    }
    else {
        println!("Initializing ThreadCommunicator");
        pagerank_multi(vec![ThreadCommunicator], source);
    };
}

fn pagerank_multi<C>(communicators: Vec<C>, filename: String)
where C: Communicator+Send {
    let mut guards = Vec::new();
    let workers = communicators.len();
    for communicator in communicators.into_iter() {
        let filename = filename.clone();
        guards.push(thread::Builder::new().name(format!("timely worker {}", communicator.index()))
                                          .spawn(move || pagerank(communicator, filename, workers))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

fn transpose(filename: String, index: usize, peers: usize) -> (Vec<u32>, Vec<(u32, u32)>, Vec<u32>)  {

    let graph = GraphMMap::<u32>::new(&filename);

    let mut edges = Vec::new();
    let mut deg = vec![];

    for node in 0..graph.nodes() {
        if node % peers == index {
            deg.push(graph.edges(node).len() as u32);
            for &b in graph.edges(node) {
                edges.push((b as u32, node as u32));
            }
        }
    }

    println!("slice {} of {} extracted {} edges", index, peers, edges.len());

    edges.sort();

    let mut rev = vec![(0,0);0];
    let mut reversed = vec![];
    for (d, s) in edges.drain_temp() {
        let len = rev.len();
        if (len == 0) || (rev[len-1].0 < d) {
            rev.push((d, 0));
        }

        let len = rev.len();
        rev[len-1].1 += 1;
        reversed.push(s / peers as u32);
    }

    return (deg, rev, reversed);
}

fn pagerank<C>(communicator: C, filename: String, workers: usize)
where C: Communicator {
    let index = communicator.index() as usize;
    let peers = communicator.peers() as usize;

    let mut root = GraphRoot::new(communicator);

    {   // new scope avoids long borrow on root
        let mut builder = root.new_subgraph();

        // establish the beginnings of a loop,
        // 20 iterations, each time around += 1.
        let (helper, stream) = builder.loop_variable::<(u32, f32)>(RootTimestamp::new(20), Local(1));

        let mut start = time::precise_time_s();

        let (deg, rev, edges) = transpose(filename, index, peers);

        println!("sorted {} edges; {}s", edges.len(), time::precise_time_s() - start);
        println!("src: {}, rev: {}, edges: {}", deg.len(), rev.len(), edges.len());
        start = time::precise_time_s();

        let mut src = vec![0.0; deg.len()];

        // from feedback, place an operator that
        // aggregates and broadcasts ranks along edges.
        let ranks = stream.enable(builder).unary_notify(

            Exchange::new(|x: &(u32, f32)| x.0 as u64),     // 1. how data should be exchanged
            format!("PageRank"),                            // 2. a tasteful, descriptive name
            vec![RootTimestamp::new(0)],                    // 3. indicate an initial capability
            move |input, output, iterator| {                // 4. provide the operator logic

                while let Some((iter, _)) = iterator.next() {

                    for node in 0..src.len() {
                        src[node] = 0.15 + 0.85 * src[node] / deg[node] as f32;
                    }

                    let mut index = 0;
                    let mut slice = &edges[..];
                    while index < rev.len() {

                        let mut session = output.session(&iter);

                        for _ in 0..std::cmp::min(100_000, rev.len() - index) {

                            let (dst, deg) = rev[index];

                            let mut accum = 0.0;
                            for &s in &slice[..deg as usize] {
                                accum += src[s as usize];
                            }
                            slice = &slice[deg as usize..];
                            session.give((dst, accum));

                            index += 1;
                        }
                    }

                    for s in &mut src { *s = 0.0; }

                    println!("iteration {:?}: {}s", iter, time::precise_time_s() - start);
                    start = time::precise_time_s();
                }

                while let Some((iter, data)) = input.pull() {
                    iterator.notify_at(&iter);
                    for (node, rank) in data.drain_temp() {
                        src[node as usize / peers] += rank;
                    }
                }
            }
        );

        // let local_index = index as usize % workers;
        // let mut acc = vec![0.0; src.len()];

        ranks
        // .unary_notify(
        //     Exchange::new(move |x: &(u32, f32)| (workers * (index / workers)) as u64 + (x.0 as u64 % workers as u64)),
        //     format!("Aggregation"),
        //     vec![],
        //     move |input, output, iterator| {
        //         while let Some((iter, data)) = input.pull() {
        //             iterator.notify_at(&iter);
        //             for (node, rank) in data.drain_temp() {
        //                 acc[node as usize / workers] += rank;
        //             }
        //         }
        //
        //         while let Some((item, _)) = iterator.next() {
        //
        //             output.give_at(&item, acc.drain_temp().enumerate().filter(|x| x.1 != 0.0)
        //                                      .map(|(u,f)| (((u * workers + local_index) as u32), f)));
        //
        //             for _ in 0..(1 + (nodes/workers)) { acc.push(0.0); }
        //             assert!(acc.len() == (1 + (nodes/workers)));
        //         }
        //     }
        // )
        .connect_loop(helper);
    }

    while root.step() { }
}
<commit_msg>measurement code<commit_after>// #![feature(scoped)]
// #![feature(collections)]

extern crate mmap;
extern crate time;
extern crate timely;
extern crate columnar;
extern crate dataflow_join;

extern crate docopt;
use docopt::Docopt;

use std::thread;
use std::mem;
use std::ptr;

use dataflow_join::graph::{GraphTrait, GraphMMap};

use timely::progress::timestamp::RootTimestamp;
use timely::progress::scope::Scope;
use timely::progress::nested::Summary::Local;
use timely::example_static::*;
use timely::communication::*;
use timely::communication::pact::Exchange;

use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

static USAGE: &'static str = "
Usage: pagerank <source> [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      list of host:port for workers
";

fn main () {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    // let workers = if let Ok(threads) = args.get_str("<workers>").parse() { threads }
    //               else { panic!("invalid setting for workers: {}", args.get_str("<workers>")) };
    // println!("starting pagerank dataflow with {:?} worker{}", workers, if workers == 1 { "" } else { "s" });
    let source = args.get_str("<source>").to_owned();

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting pagerank dataflow with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        pagerank_multi(communicators, source);
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        pagerank_multi(ProcessCommunicator::new_vector(workers), source);
    }
    else {
        println!("Initializing ThreadCommunicator");
        pagerank_multi(vec![ThreadCommunicator], source);
    };
}

fn pagerank_multi<C>(communicators: Vec<C>, filename: String)
where C: Communicator+Send {
    let mut guards = Vec::new();
    let workers = communicators.len();
    for communicator in communicators.into_iter() {
        let filename = filename.clone();
        guards.push(thread::Builder::new().name(format!("timely worker {}", communicator.index()))
                                          .spawn(move || pagerank(communicator, filename, workers))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

fn transpose(filename: String, index: usize, peers: usize) -> (Vec<u32>, Vec<(u32, u32)>, Vec<u32>)  {

    let graph = GraphMMap::<u32>::new(&filename);

    let mut src = vec![];
    let mut dst = vec![];
    let mut deg = vec![];

    for node in 0..graph.nodes() {
        if node % peers == index {
            deg.push(graph.edges(node).len() as u32);
            for &b in graph.edges(node) {
                src.push((node / peers) as u32);
                dst.push(b as u32);
            }
        }
    }

    // println!("slice {} of {} extracted {} edges", index, peers, edges.len());

    qsort_kv(&mut dst[..], &mut src[..]);

    let mut rev = vec![(0,0);0];
    for d in dst.drain_temp() {
        let len = rev.len();
        if (len == 0) || (rev[len-1].0 < d) {
            rev.push((d, 0));
        }

        let len = rev.len();
        rev[len-1].1 += 1;
    }

    return (deg, rev, src);
}

fn pagerank<C>(communicator: C, filename: String, _workers: usize)
where C: Communicator {
    let index = communicator.index() as usize;
    let peers = communicator.peers() as usize;

    let mut root = GraphRoot::new(communicator);

    let mut start = time::precise_time_s();
    let mut going = start;

    {   // new scope avoids long borrow on root
        let mut builder = root.new_subgraph();

        // establish the beginnings of a loop,
        // 20 iterations, each time around += 1.
        let (helper, stream) = builder.loop_variable::<(u32, f32)>(RootTimestamp::new(20), Local(1));

        let (deg, rev, edges) = transpose(filename, index, peers);
        let mut src = vec![0.0; deg.len()];

        // from feedback, place an operator that
        // aggregates and broadcasts ranks along edges.
        let ranks = stream.enable(builder).unary_notify(

            Exchange::new(|x: &(u32, f32)| x.0 as u64),     // 1. how data should be exchanged
            format!("PageRank"),                            // 2. a tasteful, descriptive name
            vec![RootTimestamp::new(0)],                    // 3. indicate an initial capability
            move |input, output, iterator| {                // 4. provide the operator logic

                while let Some((iter, _)) = iterator.next() {

                    if iter.inner == 10 {
                        going = time::precise_time_s();
                    }

                    if iter.inner == 20 {
                        if index == 0 {
                            println!("average over 10 iters: {}", (time::precise_time_s() - going) / 10.0);
                        }
                    }

                    for node in 0..src.len() {
                        src[node] = 0.15 + 0.85 * src[node] / deg[node] as f32;
                    }

                    let mut index = 0;
                    let mut slice = &edges[..];
                    while index < rev.len() {

                        let mut session = output.session(&iter);

                        for _ in 0..std::cmp::min(100_000, rev.len() - index) {

                            let (dst, deg) = rev[index];

                            let mut accum = 0.0;
                            for &s in &slice[..deg as usize] {
                                accum += src[s as usize];
                            }
                            slice = &slice[deg as usize..];
                            session.give((dst, accum));

                            index += 1;
                        }
                    }

                    for s in &mut src { *s = 0.0; }

                    // println!("iteration {:?}: {}s", iter, time::precise_time_s() - start);
                    start = time::precise_time_s();
                }

                while let Some((iter, data)) = input.pull() {
                    iterator.notify_at(&iter);
                    for (node, rank) in data.drain_temp() {
                        src[node as usize / peers] += rank;
                    }
                }
            }
        );

        // let local_index = index as usize % workers;
        // let mut acc = vec![0.0; src.len()];

        ranks
        // .unary_notify(
        //     Exchange::new(move |x: &(u32, f32)| (workers * (index / workers)) as u64 + (x.0 as u64 % workers as u64)),
        //     format!("Aggregation"),
        //     vec![],
        //     move |input, output, iterator| {
        //         while let Some((iter, data)) = input.pull() {
        //             iterator.notify_at(&iter);
        //             for (node, rank) in data.drain_temp() {
        //                 acc[node as usize / workers] += rank;
        //             }
        //         }
        //
        //         while let Some((item, _)) = iterator.next() {
        //
        //             output.give_at(&item, acc.drain_temp().enumerate().filter(|x| x.1 != 0.0)
        //                                      .map(|(u,f)| (((u * workers + local_index) as u32), f)));
        //
        //             for _ in 0..(1 + (nodes/workers)) { acc.push(0.0); }
        //             assert!(acc.len() == (1 + (nodes/workers)));
        //         }
        //     }
        // )
        .connect_loop(helper);
    }

    while root.step() { }

    if index == 0 {
        println!("elapsed: {}", time::precise_time_s() - start);
    }
}

pub fn qsort_kv<K: Ord, V>(keys: &mut [K], vals: &mut [V]) {
    let mut work = vec![(keys, vals)];
    while let Some((ks, vs)) = work.pop() {
        if ks.len() < 16 { isort_kv(ks, vs); }
        else {
            let p = partition_kv(ks, vs);
            let (ks1, ks2) = ks.split_at_mut(p);
            let (vs1, vs2) = vs.split_at_mut(p);
            work.push((&mut ks2[1..], &mut vs2[1..]));
            work.push((ks1, vs1));
        }
    }
}

#[inline(always)]
pub fn partition_kv<K: Ord, V>(keys: &mut [K], vals: &mut [V]) -> usize {

    let pivot = keys.len() / 2;

    let mut lower = 0;
    let mut upper = keys.len() - 1;

    unsafe {
        while lower < upper {
            // NOTE : Pairs are here to insulate against "same key" balance issues
            while lower < upper && (keys.get_unchecked(lower),lower) <= (keys.get_unchecked(pivot),pivot) { lower += 1; }
            while lower < upper && (keys.get_unchecked(pivot),pivot) <= (keys.get_unchecked(upper),upper) { upper -= 1; }
            ptr::swap(keys.get_unchecked_mut(lower), keys.get_unchecked_mut(upper));
            ptr::swap(vals.get_unchecked_mut(lower), vals.get_unchecked_mut(upper));
        }
    }

    // we want to end up with xs[p] near lower.
    if keys[lower] < keys[pivot] && lower < pivot { lower += 1; }
    if keys[lower] > keys[pivot] && lower > pivot { lower -= 1; }
    keys.swap(lower, pivot);
    vals.swap(lower, pivot);
    lower
}

// insertion sort
pub fn isort_kv<K: Ord, V>(keys: &mut [K], vals: &mut [V]) {
    for i in 1..keys.len() {
        let mut j = i;
        unsafe {
            while j > 0 && keys.get_unchecked(j-1) > keys.get_unchecked(i) { j -= 1; }

            // bulk shift the stuff we skipped over
            let mut tmp_k: K = mem::uninitialized();
            ptr::swap(&mut tmp_k, keys.get_unchecked_mut(i));
            ptr::copy(keys.get_unchecked_mut(j), keys.get_unchecked_mut(j+1), i-j);
            ptr::swap(&mut tmp_k, keys.get_unchecked_mut(j));
            mem::forget(tmp_k);

            let mut tmp_v: V = mem::uninitialized();
            ptr::swap(&mut tmp_v, vals.get_unchecked_mut(i));
            ptr::copy(vals.get_unchecked_mut(j), vals.get_unchecked_mut(j+1), i-j);
            ptr::swap(&mut tmp_v, vals.get_unchecked_mut(j));
            mem::forget(tmp_v);
        }
    }
}
<|endoftext|>


<commit_before>extern crate cairo;

#[repr(C)]
pub struct RsvgPathBuilder {
    path_data: Vec<cairo::PathSegment>,
    last_move_to_index: Option<usize>
}

impl RsvgPathBuilder {
    fn move_to (&mut self, x: f64, y: f64) {
        self.path_data.push (cairo::PathSegment::MoveTo ((x, y)));
        self.last_move_to_index = Some (self.path_data.len () - 1);
    }

    fn line_to (&mut self, x: f64, y: f64) {
        self.path_data.push (cairo::PathSegment::LineTo ((x, y)));
    }

    fn curve_to (&mut self, x2: f64, y2: f64, x3: f64, y3: f64, x4: f64, y4: f64) {
        self.path_data.push (cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)));
    }

    fn close_path (&mut self) {
        if let Some (idx) = self.last_move_to_index {
            let segment = self.path_data[idx];

            if let cairo::PathSegment::MoveTo ((x, y)) = segment {
                self.move_to (x, y);
            } else {
                unreachable! ();
            }
        }
    }
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_new () -> *mut RsvgPathBuilder {
    let builder = RsvgPathBuilder {
        path_data: Vec::new (),
        last_move_to_index: None
    };

    let boxed_builder = Box::new (builder);

    Box::into_raw (boxed_builder)
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_destroy (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let _ = Box::from_raw (raw_builder);
}

#[no_mangle]
pub extern fn rsvg_path_builder_move_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder;
    unsafe { builder = &mut (*raw_builder); }

    builder.move_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_line_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder;
    unsafe { builder = &mut (*raw_builder); }

    builder.line_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_curve_to (raw_builder: *mut RsvgPathBuilder,
                                          x2: f64, y2: f64,
                                          x3: f64, y3: f64,
                                          x4: f64, y4: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder;
    unsafe { builder = &mut (*raw_builder); }

    builder.curve_to (x2, y2, x3, y3, x4, y4);
}

#[no_mangle]
pub extern fn rsvg_path_builder_close_path (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder;
    unsafe { builder = &mut (*raw_builder); }

    builder.close_path ();
}
<commit_msg>path_builder.rs: Compress declarations a bit<commit_after>extern crate cairo;

#[repr(C)]
pub struct RsvgPathBuilder {
    path_data: Vec<cairo::PathSegment>,
    last_move_to_index: Option<usize>
}

impl RsvgPathBuilder {
    fn move_to (&mut self, x: f64, y: f64) {
        self.path_data.push (cairo::PathSegment::MoveTo ((x, y)));
        self.last_move_to_index = Some (self.path_data.len () - 1);
    }

    fn line_to (&mut self, x: f64, y: f64) {
        self.path_data.push (cairo::PathSegment::LineTo ((x, y)));
    }

    fn curve_to (&mut self, x2: f64, y2: f64, x3: f64, y3: f64, x4: f64, y4: f64) {
        self.path_data.push (cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)));
    }

    fn close_path (&mut self) {
        if let Some (idx) = self.last_move_to_index {
            let segment = self.path_data[idx];

            if let cairo::PathSegment::MoveTo ((x, y)) = segment {
                self.move_to (x, y);
            } else {
                unreachable! ();
            }
        }
    }
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_new () -> *mut RsvgPathBuilder {
    let builder = RsvgPathBuilder {
        path_data: Vec::new (),
        last_move_to_index: None
    };

    let boxed_builder = Box::new (builder);

    Box::into_raw (boxed_builder)
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_destroy (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let _ = Box::from_raw (raw_builder);
}

#[no_mangle]
pub extern fn rsvg_path_builder_move_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.move_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_line_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.line_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_curve_to (raw_builder: *mut RsvgPathBuilder,
                                          x2: f64, y2: f64,
                                          x3: f64, y3: f64,
                                          x4: f64, y4: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.curve_to (x2, y2, x3, y3, x4, y4);
}

#[no_mangle]
pub extern fn rsvg_path_builder_close_path (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.close_path ();
}
<|endoftext|>


<commit_before>extern crate cairo;
extern crate cairo_sys;

#[repr(C)]
pub struct RsvgPathBuilder {
    path_segments: Vec<cairo::PathSegment>,
    last_move_to_index: Option<usize>
}

impl RsvgPathBuilder {
    fn move_to (&mut self, x: f64, y: f64) {
        self.path_segments.push (cairo::PathSegment::MoveTo ((x, y)));
        self.last_move_to_index = Some (self.path_segments.len () - 1);
    }

    fn line_to (&mut self, x: f64, y: f64) {
        self.path_segments.push (cairo::PathSegment::LineTo ((x, y)));
    }

    fn curve_to (&mut self, x2: f64, y2: f64, x3: f64, y3: f64, x4: f64, y4: f64) {
        self.path_segments.push (cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)));
    }

    fn close_path (&mut self) {
        if let Some (idx) = self.last_move_to_index {
            let segment = self.path_segments[idx];

            if let cairo::PathSegment::MoveTo ((x, y)) = segment {
                self.move_to (x, y);
            } else {
                unreachable! ();
            }
        }
    }

    fn get_path_segments (&mut self) -> &Vec<cairo::PathSegment> {
        &self.path_segments
    }
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_new () -> *mut RsvgPathBuilder {
    let builder = RsvgPathBuilder {
        path_segments: Vec::new (),
        last_move_to_index: None
    };

    let boxed_builder = Box::new (builder);

    Box::into_raw (boxed_builder)
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_destroy (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let _ = Box::from_raw (raw_builder);
}

#[no_mangle]
pub extern fn rsvg_path_builder_move_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.move_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_line_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.line_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_curve_to (raw_builder: *mut RsvgPathBuilder,
                                          x2: f64, y2: f64,
                                          x3: f64, y3: f64,
                                          x4: f64, y4: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.curve_to (x2, y2, x3, y3, x4, y4);
}

#[no_mangle]
pub extern fn rsvg_path_builder_close_path (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.close_path ();
}

#[no_mangle]
pub extern fn rsvg_path_builder_add_to_cairo_context (raw_builder: *mut RsvgPathBuilder, cr: *mut cairo_sys::cairo_t) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    unsafe {
        let path_segments = builder.get_path_segments ();

        for s in path_segments {
            match *s {
                cairo::PathSegment::MoveTo ((x, y)) => {
                    cairo_sys::cairo_move_to (cr, x, y);
                },

                cairo::PathSegment::LineTo ((x, y)) => {
                    cairo_sys::cairo_line_to (cr, x, y);
                },

                cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)) => {
                    cairo_sys::cairo_curve_to (cr, x2, y2, x3, y3, x4, y4);
                },

                cairo::PathSegment::ClosePath => {
                    cairo_sys::cairo_close_path (cr);
                    /* FIXME: we'll get a MoveTo from the path builder.  Do we need to omit it
                     * if Cairo will add a similar Moveto by itself?
                     */
                }
            }
        }
    }
}
<commit_msg>path_builder.rs: Make RsvgPathBuilder's methods public<commit_after>extern crate cairo;
extern crate cairo_sys;

#[repr(C)]
pub struct RsvgPathBuilder {
    path_segments: Vec<cairo::PathSegment>,
    last_move_to_index: Option<usize>
}

impl RsvgPathBuilder {
    pub fn new () -> RsvgPathBuilder {
        let builder = RsvgPathBuilder {
            path_segments: Vec::new (),
            last_move_to_index: None
        };

        builder
    }

    pub fn move_to (&mut self, x: f64, y: f64) {
        self.path_segments.push (cairo::PathSegment::MoveTo ((x, y)));
        self.last_move_to_index = Some (self.path_segments.len () - 1);
    }

    pub fn line_to (&mut self, x: f64, y: f64) {
        self.path_segments.push (cairo::PathSegment::LineTo ((x, y)));
    }

    pub fn curve_to (&mut self, x2: f64, y2: f64, x3: f64, y3: f64, x4: f64, y4: f64) {
        self.path_segments.push (cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)));
    }

    pub fn close_path (&mut self) {
        if let Some (idx) = self.last_move_to_index {
            let segment = self.path_segments[idx];

            if let cairo::PathSegment::MoveTo ((x, y)) = segment {
                self.move_to (x, y);
            } else {
                unreachable! ();
            }
        }
    }

    pub fn get_path_segments (&self) -> &Vec<cairo::PathSegment> {
        &self.path_segments
    }
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_new () -> *mut RsvgPathBuilder {
    let builder = RsvgPathBuilder::new ();

    let boxed_builder = Box::new (builder);

    Box::into_raw (boxed_builder)
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_destroy (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let _ = Box::from_raw (raw_builder);
}

#[no_mangle]
pub extern fn rsvg_path_builder_move_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.move_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_line_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.line_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_curve_to (raw_builder: *mut RsvgPathBuilder,
                                          x2: f64, y2: f64,
                                          x3: f64, y3: f64,
                                          x4: f64, y4: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.curve_to (x2, y2, x3, y3, x4, y4);
}

#[no_mangle]
pub extern fn rsvg_path_builder_close_path (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.close_path ();
}

#[no_mangle]
pub extern fn rsvg_path_builder_add_to_cairo_context (raw_builder: *mut RsvgPathBuilder, cr: *mut cairo_sys::cairo_t) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    unsafe {
        let path_segments = builder.get_path_segments ();

        for s in path_segments {
            match *s {
                cairo::PathSegment::MoveTo ((x, y)) => {
                    cairo_sys::cairo_move_to (cr, x, y);
                },

                cairo::PathSegment::LineTo ((x, y)) => {
                    cairo_sys::cairo_line_to (cr, x, y);
                },

                cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)) => {
                    cairo_sys::cairo_curve_to (cr, x2, y2, x3, y3, x4, y4);
                },

                cairo::PathSegment::ClosePath => {
                    cairo_sys::cairo_close_path (cr);
                    /* FIXME: we'll get a MoveTo from the path builder.  Do we need to omit it
                     * if Cairo will add a similar Moveto by itself?
                     */
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering::Equal;
use std::collections::HashMap;

enum GameResult {
    Win,
    Draw,
    Loss
}

struct TeamResult {
    wins: u32,
    draws: u32,
    losses: u32,
}

impl TeamResult {
    fn new() -> TeamResult {
        TeamResult { wins: 0, draws: 0, losses: 0 }
    }
    fn add_game_result(&mut self, result: GameResult) {
        match result {
            GameResult::Win => self.wins += 1,
            GameResult::Draw => self.draws += 1,
            GameResult::Loss => self.losses += 1,
        }
    }
}

pub fn tally(input: &str) -> String {
    let mut results: HashMap<String, TeamResult> = HashMap::new();
    for line in input.to_string().lines() {
        let parts: Vec<&str> = line.trim_right().split(';').collect();
        if parts.len() != 3 { continue; }
        let team1 = parts[0];
        let team2 = parts[1];
        let outcome = parts[2];
        match outcome {
            "win" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Win);
                add_game_result(&mut results, team2.to_string(), GameResult::Loss);
            },
            "draw" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Draw);
                add_game_result(&mut results, team2.to_string(), GameResult::Draw);
            },
            "loss" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Loss);
                add_game_result(&mut results, team2.to_string(), GameResult::Win);
            },
            _ => () // Ignore bad lines
        }
    }
    write_tally(&results)
}

fn write_tally(results: &HashMap<String, TeamResult>) -> String {
    let mut v: Vec<_> = results.iter().map(|(team, r)| {
        let games = r.wins + r.draws + r.losses;
        let points = r.wins * 3 + r.draws;
        (team, games, r, points)
    }).collect();
    // Sort by points, then games played, in reverse order.
    v.sort_by(|a, b|
              match a.3.cmp(&(b.3)).reverse() {
                  Equal => a.1.cmp(&(b.1)).reverse(),
                  other => other
              });
    let header = format!("{:30} | MP |  W |  D |  L |  P\n", "Team");
    let lines: Vec<_> = v.iter().map(|&(ref team, games, r, points)| {
        format!("{:30} | {:2} | {:2} | {:2} | {:2} | {:2}",
                team, games, r.wins, r.draws, r.losses, points)
    }).collect();
    header + &lines.join("\n")
}

fn add_game_result(results: &mut HashMap<String, TeamResult>, team: String, result: GameResult) {
    results.entry(team).or_insert(TeamResult::new()).add_game_result(result);
}
<commit_msg>tournament: print header without newline if no teams<commit_after>use std::cmp::Ordering::Equal;
use std::collections::HashMap;

enum GameResult {
    Win,
    Draw,
    Loss
}

struct TeamResult {
    wins: u32,
    draws: u32,
    losses: u32,
}

impl TeamResult {
    fn new() -> TeamResult {
        TeamResult { wins: 0, draws: 0, losses: 0 }
    }
    fn add_game_result(&mut self, result: GameResult) {
        match result {
            GameResult::Win => self.wins += 1,
            GameResult::Draw => self.draws += 1,
            GameResult::Loss => self.losses += 1,
        }
    }
}

pub fn tally(input: &str) -> String {
    let mut results: HashMap<String, TeamResult> = HashMap::new();
    for line in input.to_string().lines() {
        let parts: Vec<&str> = line.trim_right().split(';').collect();
        if parts.len() != 3 { continue; }
        let team1 = parts[0];
        let team2 = parts[1];
        let outcome = parts[2];
        match outcome {
            "win" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Win);
                add_game_result(&mut results, team2.to_string(), GameResult::Loss);
            },
            "draw" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Draw);
                add_game_result(&mut results, team2.to_string(), GameResult::Draw);
            },
            "loss" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Loss);
                add_game_result(&mut results, team2.to_string(), GameResult::Win);
            },
            _ => () // Ignore bad lines
        }
    }
    write_tally(&results)
}

fn write_tally(results: &HashMap<String, TeamResult>) -> String {
    let mut v: Vec<_> = results.iter().map(|(team, r)| {
        let games = r.wins + r.draws + r.losses;
        let points = r.wins * 3 + r.draws;
        (team, games, r, points)
    }).collect();
    // Sort by points, then games played, in reverse order.
    v.sort_by(|a, b|
              match a.3.cmp(&(b.3)).reverse() {
                  Equal => a.1.cmp(&(b.1)).reverse(),
                  other => other
              });
    let mut lines = vec![format!("{:30} | MP |  W |  D |  L |  P", "Team")];
    lines.extend(v.iter().map(|&(ref team, games, r, points)| {
        format!("{:30} | {:2} | {:2} | {:2} | {:2} | {:2}",
                team, games, r.wins, r.draws, r.losses, points)
    }));
    lines.join("\n")
}

fn add_game_result(results: &mut HashMap<String, TeamResult>, team: String, result: GameResult) {
    results.entry(team).or_insert(TeamResult::new()).add_game_result(result);
}
<|endoftext|>


<commit_before>/*!

DC (Distance Coding) forward and backward transformation.
Designed to be used on BWT block output for compression.

MTF (Move To Front) encoder/decoder:
Used internally for DC processing.
Can also be used separately on the BWT output as an alternative to DC.

# Links

http://www.data-compression.info/Algorithms/DC/
http://en.wikipedia.org/wiki/Move-to-front_transform

# Example

```rust
use compress::dc;

let bytes = bytes!("abracadabra");
let (alphabet,distances) = dc::encode_simple(bytes);
let decoded = dc::decode_simple(bytes.len(),
                                alphabet.as_slice(),
                                distances.as_slice());
```

# Credit

This is an original implementation.
Thanks to Edgar Binder for inventing DC!

*/

use std::{io, iter, util, vec};

pub type Symbol = u8;
pub type Rank = u8;
pub type Distance = uint;
pub static TotalSymbols: uint = 0x100;

/// MoveToFront encoder/decoder
pub struct MTF {
    /// rank-ordered list of unique Symbols
    symbols: [Symbol, ..TotalSymbols],
}

impl MTF {
    /// create a new zeroed MTF
    pub fn new() -> MTF {
        MTF { symbols: [0, ..TotalSymbols] }
    }

    /// set the order of symbols to be alphabetical
    pub fn reset_alphabetical(&mut self) {
        for (i,sym) in self.symbols.mut_iter().enumerate() {
            *sym = i as Symbol;
        }
    }

    /// encode a symbol into its rank
    pub fn encode(&mut self, sym: Symbol) -> Rank {
        let mut next = self.symbols[0];
        if next == sym {
            return 0
        }
        let mut rank: Rank = 1u8;
        loop {
            util::swap(&mut self.symbols[rank], &mut next);
            if next == sym {
                break;
            }
            rank += 1;
            assert!((rank as uint) < self.symbols.len());
        }
        self.symbols[0] = sym;
        rank
    }

    /// decode a rank into its symbol
    pub fn decode(&mut self, rank: Rank) -> Symbol {
        let sym = self.symbols[rank];
        debug!("\tDecoding rank {} with symbol {}", rank, sym);
        for i in iter::range_inclusive(1,rank).rev() {
            self.symbols[i] = self.symbols[i-1];
        }
        self.symbols[0] = sym;
        sym
    }
}

/// encode a block of bytes 'input'
/// write output distance stream into 'distances'
/// return: unique bytes encountered in the order they appear
/// with the corresponding initial distances
pub fn encode(input: &[Symbol], distances: &mut [Distance], mtf: &mut MTF) -> ~[(Symbol,Distance)] {
    let N = input.len();
    assert_eq!(distances.len(), N);
    let mut last = [N, ..TotalSymbols];
    let mut unique: ~[(Symbol,Distance)] = ~[];
    for (i,&sym) in input.iter().enumerate() {
        distances[i] = N;
        let base = last[sym];
        last[sym] = i;
        debug!("\tProcessing symbol {} at position {}, last known at {}", sym, i, base);
        if base == N {
            let rank = unique.len();
            mtf.symbols[rank] = sym;
            mtf.encode(sym);    //==rank
            // initial distances are not ordered to support re-shuffle
            debug!("\t\tUnique => assigning rank {}, encoding {}", rank, i);
            unique.push((sym,i))
        }else {
            let rank = mtf.encode(sym) as Distance;
            if rank > 0 {
                debug!("\t\tRegular at rank {}, encoding {}", rank, i-base-rank-1);
                assert!(i >= base+rank+1);
                distances[base] = i-base-rank-1;
            }
        }
    }
    for (rank,&sym) in mtf.symbols.slice_to(unique.len()).iter().enumerate() {
        let base = last[sym];
        debug!("\tSweep symbol {} of rank {}, last known at {}, encoding {}", sym, rank, base, N-base-rank-1);
        assert!(N >= base+rank+1);
        distances[base] = N-base-rank-1;
    }
    assert_eq!(input.iter().zip(input.iter().skip(1)).zip(distances.iter()).
        position(|((&a,&b),&d)| d==N && a!=b), None);
    unique
}

/// encode with "batteries included" for quick testing
pub fn encode_simple(input: &[Symbol]) -> (~[Symbol],~[Distance]) {
    let N = input.len();
    if N==0 {
        (~[],~[])
    }else   {
        let mut raw_dist = vec::from_elem(N, 0 as Distance);
        let pairs = encode(input, raw_dist.as_mut_slice(), &mut MTF::new());
        let symbols = pairs.map(|&(sym,_)| sym);
        let init_iter = pairs.iter().map(|&(_,d)| d);
        // chain initial distances with intermediate ones
        let raw_iter = raw_dist.iter().filter_map(|&d| if d!=N {Some(d)} else {None});
        let mut combined = init_iter.chain(raw_iter);
        (symbols,combined.collect())
    }
}

/// Decode a block of distances with a list of initial symbols
pub fn decode(alphabet: Option<&[Symbol]>, output: &mut [Symbol], mtf: &mut MTF,
        fn_dist: |Symbol|->io::IoResult<Distance>) -> io::IoResult<()> {
    let N = output.len();
    let mut next = [N, ..TotalSymbols];
    let E = match alphabet  {
        Some([]) => {
            // alphabet is empty
            assert_eq!(N,0);
            return Ok(())
        },
        Some([sym]) => {
            // there is only one known symbol
            for out in output.mut_iter()    {
                *out = sym;
            }
            return Ok(())
        }
        Some(list) => {
            // given fixed alphabet
            for (rank,&sym) in list.iter().enumerate()   {
                // initial distances are not ordered
                next[sym] = match fn_dist(sym) {
                    Ok(d) => d, // + (rank as Distance)
                    Err(e) => return Err(e)
                };
                mtf.symbols[rank] = sym;
                debug!("\tRegistering symbol {} of rank {} at position {}", sym, rank, next[sym]);
            }
            for rank in range(list.len(),TotalSymbols) {
                mtf.symbols[rank] = 0; //erazing unused symbols
            }
            list.len()
        },
        None => {
            // alphabet is large, total range of symbols is assumed
            for i in range(0,TotalSymbols) {
                next[i] = match fn_dist(i as Symbol) {
                    Ok(d) => d,
                    Err(e) => return Err(e)
                };
                mtf.symbols[i] = i as Symbol;
                debug!("\tRegistering symbol {} at position {}", i, next[i]);
            }
            TotalSymbols
        },
    };
    let mut i = 0u;
    while i<N {
        let sym = mtf.symbols[0];
        let stop = next[mtf.symbols[1]];
        debug!("\tFilling region [{}-{}) with symbol {}", i, stop, sym);
        while i<stop    {
            output[i] = sym;
            i += 1;
        }
        let future = match fn_dist(sym) {
            Ok(d) => stop + d,
            Err(e) => return Err(e)
        };
        debug!("\t\tLooking for future position {}", future);
        let mut rank = 1u;
        while rank < E && future+rank > next[mtf.symbols[rank]] {
            mtf.symbols[rank-1] = mtf.symbols[rank];
            rank += 1;
        }
        if rank<E {
            debug!("\t\tFound sym {} of rank {} at position {}", mtf.symbols[rank],
                rank, next[mtf.symbols[rank]]);
        }else {
            debug!("\t\tNot found");
        }
        mtf.symbols[rank-1] = sym;
        debug!("\t\tAssigning future pos {} for symbol {}", future+rank-1, sym);
        next[sym] = future+rank-1;
    }
    assert_eq!(next.iter().position(|&d| d<N || d>=N+E), None);
    assert_eq!(i, N);
    Ok(())
}

/// decode with "batteries included" for quick testing
pub fn decode_simple(N: uint, alphabet: &[Symbol], distances: &[Distance]) -> ~[Symbol] {
    let mut output = vec::from_elem(N, 0 as Symbol);
    let mut di = 0u;
    decode(Some(alphabet), output.as_mut_slice(), &mut MTF::new(), |_sym| {
        di += 1;
        if di > distances.len() {
            Err(io::standard_error(io::EndOfFile))
        }else {
            Ok(distances[di-1])
        }
    }).unwrap();
    output
}

#[cfg(test)]
mod test {
    //use extra::test;
    use super::{MTF, encode_simple, decode_simple};

    fn roundtrip_dc(bytes: &[u8]) {
        info!("Roundtrip DC of size {}", bytes.len());
        let (alphabet,distances) = encode_simple(bytes);
        debug!("Roundtrip DC input: {:?}, alphabet: {:?}, distances: {:?}", bytes, alphabet, distances);
        let decoded = decode_simple(bytes.len(), alphabet.as_slice(), distances.as_slice());
        assert_eq!(decoded.as_slice(), bytes);
    }

    fn roundtrip_mtf(bytes: &[u8]) {
        info!("Roundtrip MTF of size {}", bytes.len());
        let mut mtf = MTF::new();
        mtf.reset_alphabetical();
        let ranks = bytes.map(|&sym| mtf.encode(sym));
        debug!("Roundtrip MTF input: {:?}, ranks: {:?}", bytes, ranks);
        mtf.reset_alphabetical();
        let decoded = ranks.map(|&r| mtf.decode(r));
        assert_eq!(decoded.as_slice(), bytes);
    }

    #[test]
    fn some_roundtrips_dc() {
        roundtrip_dc(bytes!("teeesst_dc"));
        roundtrip_dc(bytes!(""));
        roundtrip_dc(include_bin!("data/test.txt"));
    }

    #[test]
    fn some_roundtrips_mtf() {
        roundtrip_mtf(bytes!("teeesst_mtf"));
        roundtrip_mtf(bytes!(""));
        roundtrip_mtf(include_bin!("data/test.txt"));
    }
}
<commit_msg>util => mem update<commit_after>/*!

DC (Distance Coding) forward and backward transformation.
Designed to be used on BWT block output for compression.

MTF (Move To Front) encoder/decoder:
Used internally for DC processing.
Can also be used separately on the BWT output as an alternative to DC.

# Links

http://www.data-compression.info/Algorithms/DC/
http://en.wikipedia.org/wiki/Move-to-front_transform

# Example

```rust
use compress::dc;

let bytes = bytes!("abracadabra");
let (alphabet,distances) = dc::encode_simple(bytes);
let decoded = dc::decode_simple(bytes.len(),
                                alphabet.as_slice(),
                                distances.as_slice());
```

# Credit

This is an original implementation.
Thanks to Edgar Binder for inventing DC!

*/

use std::{io, iter, mem, vec};

pub type Symbol = u8;
pub type Rank = u8;
pub type Distance = uint;
pub static TotalSymbols: uint = 0x100;

/// MoveToFront encoder/decoder
pub struct MTF {
    /// rank-ordered list of unique Symbols
    symbols: [Symbol, ..TotalSymbols],
}

impl MTF {
    /// create a new zeroed MTF
    pub fn new() -> MTF {
        MTF { symbols: [0, ..TotalSymbols] }
    }

    /// set the order of symbols to be alphabetical
    pub fn reset_alphabetical(&mut self) {
        for (i,sym) in self.symbols.mut_iter().enumerate() {
            *sym = i as Symbol;
        }
    }

    /// encode a symbol into its rank
    pub fn encode(&mut self, sym: Symbol) -> Rank {
        let mut next = self.symbols[0];
        if next == sym {
            return 0
        }
        let mut rank: Rank = 1u8;
        loop {
            mem::swap(&mut self.symbols[rank], &mut next);
            if next == sym {
                break;
            }
            rank += 1;
            assert!((rank as uint) < self.symbols.len());
        }
        self.symbols[0] = sym;
        rank
    }

    /// decode a rank into its symbol
    pub fn decode(&mut self, rank: Rank) -> Symbol {
        let sym = self.symbols[rank];
        debug!("\tDecoding rank {} with symbol {}", rank, sym);
        for i in iter::range_inclusive(1,rank).rev() {
            self.symbols[i] = self.symbols[i-1];
        }
        self.symbols[0] = sym;
        sym
    }
}

/// encode a block of bytes 'input'
/// write output distance stream into 'distances'
/// return: unique bytes encountered in the order they appear
/// with the corresponding initial distances
pub fn encode(input: &[Symbol], distances: &mut [Distance], mtf: &mut MTF) -> ~[(Symbol,Distance)] {
    let N = input.len();
    assert_eq!(distances.len(), N);
    let mut last = [N, ..TotalSymbols];
    let mut unique: ~[(Symbol,Distance)] = ~[];
    for (i,&sym) in input.iter().enumerate() {
        distances[i] = N;
        let base = last[sym];
        last[sym] = i;
        debug!("\tProcessing symbol {} at position {}, last known at {}", sym, i, base);
        if base == N {
            let rank = unique.len();
            mtf.symbols[rank] = sym;
            mtf.encode(sym);    //==rank
            // initial distances are not ordered to support re-shuffle
            debug!("\t\tUnique => assigning rank {}, encoding {}", rank, i);
            unique.push((sym,i))
        }else {
            let rank = mtf.encode(sym) as Distance;
            if rank > 0 {
                debug!("\t\tRegular at rank {}, encoding {}", rank, i-base-rank-1);
                assert!(i >= base+rank+1);
                distances[base] = i-base-rank-1;
            }
        }
    }
    for (rank,&sym) in mtf.symbols.slice_to(unique.len()).iter().enumerate() {
        let base = last[sym];
        debug!("\tSweep symbol {} of rank {}, last known at {}, encoding {}", sym, rank, base, N-base-rank-1);
        assert!(N >= base+rank+1);
        distances[base] = N-base-rank-1;
    }
    assert_eq!(input.iter().zip(input.iter().skip(1)).zip(distances.iter()).
        position(|((&a,&b),&d)| d==N && a!=b), None);
    unique
}

/// encode with "batteries included" for quick testing
pub fn encode_simple(input: &[Symbol]) -> (~[Symbol],~[Distance]) {
    let N = input.len();
    if N==0 {
        (~[],~[])
    }else   {
        let mut raw_dist = vec::from_elem(N, 0 as Distance);
        let pairs = encode(input, raw_dist.as_mut_slice(), &mut MTF::new());
        let symbols = pairs.map(|&(sym,_)| sym);
        let init_iter = pairs.iter().map(|&(_,d)| d);
        // chain initial distances with intermediate ones
        let raw_iter = raw_dist.iter().filter_map(|&d| if d!=N {Some(d)} else {None});
        let mut combined = init_iter.chain(raw_iter);
        (symbols,combined.collect())
    }
}

/// Decode a block of distances with a list of initial symbols
pub fn decode(alphabet: Option<&[Symbol]>, output: &mut [Symbol], mtf: &mut MTF,
        fn_dist: |Symbol|->io::IoResult<Distance>) -> io::IoResult<()> {
    let N = output.len();
    let mut next = [N, ..TotalSymbols];
    let E = match alphabet  {
        Some([]) => {
            // alphabet is empty
            assert_eq!(N,0);
            return Ok(())
        },
        Some([sym]) => {
            // there is only one known symbol
            for out in output.mut_iter()    {
                *out = sym;
            }
            return Ok(())
        }
        Some(list) => {
            // given fixed alphabet
            for (rank,&sym) in list.iter().enumerate()   {
                // initial distances are not ordered
                next[sym] = match fn_dist(sym) {
                    Ok(d) => d, // + (rank as Distance)
                    Err(e) => return Err(e)
                };
                mtf.symbols[rank] = sym;
                debug!("\tRegistering symbol {} of rank {} at position {}", sym, rank, next[sym]);
            }
            for rank in range(list.len(),TotalSymbols) {
                mtf.symbols[rank] = 0; //erazing unused symbols
            }
            list.len()
        },
        None => {
            // alphabet is large, total range of symbols is assumed
            for i in range(0,TotalSymbols) {
                next[i] = match fn_dist(i as Symbol) {
                    Ok(d) => d,
                    Err(e) => return Err(e)
                };
                mtf.symbols[i] = i as Symbol;
                debug!("\tRegistering symbol {} at position {}", i, next[i]);
            }
            TotalSymbols
        },
    };
    let mut i = 0u;
    while i<N {
        let sym = mtf.symbols[0];
        let stop = next[mtf.symbols[1]];
        debug!("\tFilling region [{}-{}) with symbol {}", i, stop, sym);
        while i<stop    {
            output[i] = sym;
            i += 1;
        }
        let future = match fn_dist(sym) {
            Ok(d) => stop + d,
            Err(e) => return Err(e)
        };
        debug!("\t\tLooking for future position {}", future);
        let mut rank = 1u;
        while rank < E && future+rank > next[mtf.symbols[rank]] {
            mtf.symbols[rank-1] = mtf.symbols[rank];
            rank += 1;
        }
        if rank<E {
            debug!("\t\tFound sym {} of rank {} at position {}", mtf.symbols[rank],
                rank, next[mtf.symbols[rank]]);
        }else {
            debug!("\t\tNot found");
        }
        mtf.symbols[rank-1] = sym;
        debug!("\t\tAssigning future pos {} for symbol {}", future+rank-1, sym);
        next[sym] = future+rank-1;
    }
    assert_eq!(next.iter().position(|&d| d<N || d>=N+E), None);
    assert_eq!(i, N);
    Ok(())
}

/// decode with "batteries included" for quick testing
pub fn decode_simple(N: uint, alphabet: &[Symbol], distances: &[Distance]) -> ~[Symbol] {
    let mut output = vec::from_elem(N, 0 as Symbol);
    let mut di = 0u;
    decode(Some(alphabet), output.as_mut_slice(), &mut MTF::new(), |_sym| {
        di += 1;
        if di > distances.len() {
            Err(io::standard_error(io::EndOfFile))
        }else {
            Ok(distances[di-1])
        }
    }).unwrap();
    output
}

#[cfg(test)]
mod test {
    //use extra::test;
    use super::{MTF, encode_simple, decode_simple};

    fn roundtrip_dc(bytes: &[u8]) {
        info!("Roundtrip DC of size {}", bytes.len());
        let (alphabet,distances) = encode_simple(bytes);
        debug!("Roundtrip DC input: {:?}, alphabet: {:?}, distances: {:?}", bytes, alphabet, distances);
        let decoded = decode_simple(bytes.len(), alphabet.as_slice(), distances.as_slice());
        assert_eq!(decoded.as_slice(), bytes);
    }

    fn roundtrip_mtf(bytes: &[u8]) {
        info!("Roundtrip MTF of size {}", bytes.len());
        let mut mtf = MTF::new();
        mtf.reset_alphabetical();
        let ranks = bytes.map(|&sym| mtf.encode(sym));
        debug!("Roundtrip MTF input: {:?}, ranks: {:?}", bytes, ranks);
        mtf.reset_alphabetical();
        let decoded = ranks.map(|&r| mtf.decode(r));
        assert_eq!(decoded.as_slice(), bytes);
    }

    #[test]
    fn some_roundtrips_dc() {
        roundtrip_dc(bytes!("teeesst_dc"));
        roundtrip_dc(bytes!(""));
        roundtrip_dc(include_bin!("data/test.txt"));
    }

    #[test]
    fn some_roundtrips_mtf() {
        roundtrip_mtf(bytes!("teeesst_mtf"));
        roundtrip_mtf(bytes!(""));
        roundtrip_mtf(include_bin!("data/test.txt"));
    }
}
<|endoftext|>


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

use libc::{c_int, c_void, size_t, c_char};

// errors.h

pub type Error = c_int;
pub static OK: c_int = 0;
pub static REPROCESS: c_int = 1;
pub static ENCODINGCHANGE: c_int = 2;
pub static PAUSED: c_int = 3;
pub static NOMEM: c_int = 5;
pub static BADPARM: c_int = 6;
pub static INVALID: c_int = 7;
pub static FILENOTFOUND: c_int = 8;
pub static NEEDDATA: c_int = 9;
pub static BADENCODING: c_int = 10;
pub static UNKNOWN: c_int = 11;

#[cfg(target_os = "macos")]
#[link(name = "hubbub")]
#[link(name = "parserutils")]
#[link(name = "iconv")]
extern { }

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[link(name = "hubbub")]
#[link(name = "parserutils")]
extern { }

extern {
    pub fn hubbub_error_to_string(error: Error) -> *u8;
}

// parser.h

pub type Parser = c_void;

pub type ParserOptType = c_int;
pub static PARSER_TOKEN_HANDLER: c_int = 0;
pub static PARSER_ERROR_HANDLER: c_int = 1;
pub static PARSER_CONTENT_MODEL: c_int = 2;
pub static PARSER_TREE_HANDLER: c_int = 3;
pub static PARSER_DOCUMENT_NODE: c_int = 4;
pub static PARSER_ENABLE_SCRIPTING: c_int = 5;
pub static PARSER_PAUSE: c_int = 6;
pub static PARSER_ENABLE_STYLING: c_int = 7;

pub struct ParserOptParamsTokenHandler {
    pub handler: *u8,
    pub pw: *c_void
}

pub struct ParserOptParamsErrorHandler {
    pub handler: *u8,
    pub pw: *c_void
}

pub struct ParserOptParamsContentModel {
    pub content_model: ContentModel
}

pub mod parser {
    use libc::{c_void, size_t, c_char};
    use super::{Parser, Error, ParserOptType, CharsetSource};

    #[nolink]
    extern {
        pub fn hubbub_parser_create(enc: *u8,
                                    fix_enc: bool,
                                    alloc: extern "C" fn(*mut c_void, size_t, *c_void) -> *mut c_void,
                                    pw: *c_void,
                                    parser: **Parser)
            -> Error;
        pub fn hubbub_parser_destroy(parser: *Parser) -> Error;
        pub fn hubbub_parser_setopt(parser: *Parser, opt_type: ParserOptType, params: *c_void)
            -> Error;
        pub fn hubbub_parser_parse_chunk(parser: *Parser, data: *u8, len: size_t) -> Error;
        pub fn hubbub_parser_insert_chunk(parser: *Parser, data: *u8, len: size_t) -> Error;
        pub fn hubbub_parser_completed(parser: *Parser) -> Error;
        pub fn hubbub_parser_read_charset(parser: *Parser, source: *CharsetSource) -> *c_char;
    }
}

// tree.h

pub struct TreeHandler {
    pub create_comment: extern "C" fn(*c_void, *String, *mut *c_void) -> Error,
    pub create_doctype: extern "C" fn(*c_void, *Doctype, *mut *c_void) -> Error,
    pub create_element: extern "C" fn(*c_void, *Tag, *mut *c_void) -> Error,
    pub create_text: extern "C" fn(*c_void, *String, *mut *c_void) -> Error,
    pub ref_node: extern "C" fn(*c_void, *c_void) -> Error,
    pub unref_node: extern "C" fn(*c_void, *c_void) -> Error,
    pub append_child: extern "C" fn(*c_void, *c_void, *c_void, *mut *c_void) -> Error,
    pub insert_before: extern "C" fn(*c_void, *c_void, *c_void, *mut *c_void) -> Error,
    pub remove_child: extern "C" fn(*c_void, *c_void, *c_void, *mut *c_void) -> Error,
    pub clone_node: extern "C" fn(*c_void, *c_void, bool, *mut *c_void) -> Error,
    pub reparent_children: extern "C" fn(*c_void, *c_void, *c_void) -> Error,
    pub get_parent: extern "C" fn(*c_void, *c_void, bool, *mut *c_void) -> Error,
    pub has_children: extern "C" fn(*c_void, *c_void, *mut bool) -> Error,
    pub form_associate: extern "C" fn(*c_void, *c_void, *c_void) -> Error,
    pub add_attributes: extern "C" fn(*c_void, *c_void, *Attribute, u32) -> Error,
    pub set_quirks_mode: extern "C" fn(*c_void, QuirksMode) -> Error,
    pub encoding_change: extern "C" fn(*c_void, *c_char) -> Error,
    pub complete_script: extern "C" fn(*c_void, *c_void) -> Error,
    pub complete_style: extern "C" fn(*c_void, *c_void) -> Error,
    pub ctx: *c_void,
}

// types.h

// Source of charset information, in order of importance.
// A client-dictated charset will override all others.
// A document-specified charset will override autodetection or the default.
pub type CharsetSource = c_int;
pub static CHARSET_UNKNOWN: c_int = 0;
pub static CHARSET_TENTATIVE: c_int = 1;
pub static CHARSET_CONFIDENT: c_int = 2;

// Content model flag
pub type ContentModel = c_int;
pub static CONTENT_MODEL_PCDATA: c_int = 0;
pub static CONTENT_MODEL_RCDATA: c_int = 1;
pub static CONTENT_MODEL_CDATA: c_int = 2;
pub static CONTENT_MODEL_PLAINTEXT: c_int = 3;

// Quirks mode flag
pub type QuirksMode = c_int;
pub static QUIRKS_MODE_NONE: c_int = 0;
pub static QUIRKS_MODE_LIMITED: c_int = 1;
pub static QUIRKS_MODE_FULL: c_int = 2;

pub type TokenType = c_int;
pub static TOKEN_DOCTYPE: c_int = 0;
pub static TOKEN_START_TAG: c_int = 1;
pub static TOKEN_END_TAG: c_int = 2;
pub static TOKEN_COMMENT: c_int = 3;
pub static TOKEN_CHARACTER: c_int = 4;
pub static TOKEN_EOF: c_int = 5;

pub type NS = c_int;
pub static NS_NULL: c_int = 0;
pub static NS_HTML: c_int = 1;
pub static NS_MATHML: c_int = 2;
pub static NS_SVG: c_int = 3;
pub static NS_XLINK: c_int = 4;
pub static NS_XML: c_int = 5;
pub static NS_XMLNS: c_int = 6;

pub struct String {
    pub ptr: *u8,
    pub len: size_t
}

pub struct Attribute {
    pub ns: NS,
    pub name: String,
    pub value: String,
}

pub struct Doctype {
    pub name: String,
    pub public_missing: bool,
    pub public_id: String,
    pub system_missing: bool,
    pub system_id: String,
    pub force_quirks: bool,
}

pub struct Tag {
    pub ns: NS,
    pub name: String,
    pub n_attributes: u32,
    pub attributes: *Attribute,
    pub self_closing: bool,
}

// Token data
pub struct Token {
    pub token_type: TokenType,
    pub data: u8,   // union: one of Doctype, Tag, Comment (string), or Character (string)
}

<commit_msg>Remove bogus nolink attr<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use libc::{c_int, c_void, size_t, c_char};

// errors.h

pub type Error = c_int;
pub static OK: c_int = 0;
pub static REPROCESS: c_int = 1;
pub static ENCODINGCHANGE: c_int = 2;
pub static PAUSED: c_int = 3;
pub static NOMEM: c_int = 5;
pub static BADPARM: c_int = 6;
pub static INVALID: c_int = 7;
pub static FILENOTFOUND: c_int = 8;
pub static NEEDDATA: c_int = 9;
pub static BADENCODING: c_int = 10;
pub static UNKNOWN: c_int = 11;

#[cfg(target_os = "macos")]
#[link(name = "hubbub")]
#[link(name = "parserutils")]
#[link(name = "iconv")]
extern { }

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[link(name = "hubbub")]
#[link(name = "parserutils")]
extern { }

extern {
    pub fn hubbub_error_to_string(error: Error) -> *u8;
}

// parser.h

pub type Parser = c_void;

pub type ParserOptType = c_int;
pub static PARSER_TOKEN_HANDLER: c_int = 0;
pub static PARSER_ERROR_HANDLER: c_int = 1;
pub static PARSER_CONTENT_MODEL: c_int = 2;
pub static PARSER_TREE_HANDLER: c_int = 3;
pub static PARSER_DOCUMENT_NODE: c_int = 4;
pub static PARSER_ENABLE_SCRIPTING: c_int = 5;
pub static PARSER_PAUSE: c_int = 6;
pub static PARSER_ENABLE_STYLING: c_int = 7;

pub struct ParserOptParamsTokenHandler {
    pub handler: *u8,
    pub pw: *c_void
}

pub struct ParserOptParamsErrorHandler {
    pub handler: *u8,
    pub pw: *c_void
}

pub struct ParserOptParamsContentModel {
    pub content_model: ContentModel
}

pub mod parser {
    use libc::{c_void, size_t, c_char};
    use super::{Parser, Error, ParserOptType, CharsetSource};

    extern {
        pub fn hubbub_parser_create(enc: *u8,
                                    fix_enc: bool,
                                    alloc: extern "C" fn(*mut c_void, size_t, *c_void) -> *mut c_void,
                                    pw: *c_void,
                                    parser: **Parser)
            -> Error;
        pub fn hubbub_parser_destroy(parser: *Parser) -> Error;
        pub fn hubbub_parser_setopt(parser: *Parser, opt_type: ParserOptType, params: *c_void)
            -> Error;
        pub fn hubbub_parser_parse_chunk(parser: *Parser, data: *u8, len: size_t) -> Error;
        pub fn hubbub_parser_insert_chunk(parser: *Parser, data: *u8, len: size_t) -> Error;
        pub fn hubbub_parser_completed(parser: *Parser) -> Error;
        pub fn hubbub_parser_read_charset(parser: *Parser, source: *CharsetSource) -> *c_char;
    }
}

// tree.h

pub struct TreeHandler {
    pub create_comment: extern "C" fn(*c_void, *String, *mut *c_void) -> Error,
    pub create_doctype: extern "C" fn(*c_void, *Doctype, *mut *c_void) -> Error,
    pub create_element: extern "C" fn(*c_void, *Tag, *mut *c_void) -> Error,
    pub create_text: extern "C" fn(*c_void, *String, *mut *c_void) -> Error,
    pub ref_node: extern "C" fn(*c_void, *c_void) -> Error,
    pub unref_node: extern "C" fn(*c_void, *c_void) -> Error,
    pub append_child: extern "C" fn(*c_void, *c_void, *c_void, *mut *c_void) -> Error,
    pub insert_before: extern "C" fn(*c_void, *c_void, *c_void, *mut *c_void) -> Error,
    pub remove_child: extern "C" fn(*c_void, *c_void, *c_void, *mut *c_void) -> Error,
    pub clone_node: extern "C" fn(*c_void, *c_void, bool, *mut *c_void) -> Error,
    pub reparent_children: extern "C" fn(*c_void, *c_void, *c_void) -> Error,
    pub get_parent: extern "C" fn(*c_void, *c_void, bool, *mut *c_void) -> Error,
    pub has_children: extern "C" fn(*c_void, *c_void, *mut bool) -> Error,
    pub form_associate: extern "C" fn(*c_void, *c_void, *c_void) -> Error,
    pub add_attributes: extern "C" fn(*c_void, *c_void, *Attribute, u32) -> Error,
    pub set_quirks_mode: extern "C" fn(*c_void, QuirksMode) -> Error,
    pub encoding_change: extern "C" fn(*c_void, *c_char) -> Error,
    pub complete_script: extern "C" fn(*c_void, *c_void) -> Error,
    pub complete_style: extern "C" fn(*c_void, *c_void) -> Error,
    pub ctx: *c_void,
}

// types.h

// Source of charset information, in order of importance.
// A client-dictated charset will override all others.
// A document-specified charset will override autodetection or the default.
pub type CharsetSource = c_int;
pub static CHARSET_UNKNOWN: c_int = 0;
pub static CHARSET_TENTATIVE: c_int = 1;
pub static CHARSET_CONFIDENT: c_int = 2;

// Content model flag
pub type ContentModel = c_int;
pub static CONTENT_MODEL_PCDATA: c_int = 0;
pub static CONTENT_MODEL_RCDATA: c_int = 1;
pub static CONTENT_MODEL_CDATA: c_int = 2;
pub static CONTENT_MODEL_PLAINTEXT: c_int = 3;

// Quirks mode flag
pub type QuirksMode = c_int;
pub static QUIRKS_MODE_NONE: c_int = 0;
pub static QUIRKS_MODE_LIMITED: c_int = 1;
pub static QUIRKS_MODE_FULL: c_int = 2;

pub type TokenType = c_int;
pub static TOKEN_DOCTYPE: c_int = 0;
pub static TOKEN_START_TAG: c_int = 1;
pub static TOKEN_END_TAG: c_int = 2;
pub static TOKEN_COMMENT: c_int = 3;
pub static TOKEN_CHARACTER: c_int = 4;
pub static TOKEN_EOF: c_int = 5;

pub type NS = c_int;
pub static NS_NULL: c_int = 0;
pub static NS_HTML: c_int = 1;
pub static NS_MATHML: c_int = 2;
pub static NS_SVG: c_int = 3;
pub static NS_XLINK: c_int = 4;
pub static NS_XML: c_int = 5;
pub static NS_XMLNS: c_int = 6;

pub struct String {
    pub ptr: *u8,
    pub len: size_t
}

pub struct Attribute {
    pub ns: NS,
    pub name: String,
    pub value: String,
}

pub struct Doctype {
    pub name: String,
    pub public_missing: bool,
    pub public_id: String,
    pub system_missing: bool,
    pub system_id: String,
    pub force_quirks: bool,
}

pub struct Tag {
    pub ns: NS,
    pub name: String,
    pub n_attributes: u32,
    pub attributes: *Attribute,
    pub self_closing: bool,
}

// Token data
pub struct Token {
    pub token_type: TokenType,
    pub data: u8,   // union: one of Doctype, Tag, Comment (string), or Character (string)
}

<|endoftext|>


<commit_before>// Test or-patterns with slice-patterns

// run-pass

#![feature(or_patterns)]

#[derive(Debug, PartialEq)]
enum MatchArm {
    Arm(usize),
    Wild,
}

#[derive(Debug)]
enum Test {
    Foo,
    Bar,
    Baz,
    Qux,
}

fn test(foo: &[Option<Test>]) -> MatchArm {
    match foo {
        [.., Some(Test::Qux | Test::Foo)] => MatchArm::Arm(0),
        [Some(Test::Foo), .., Some(Test::Baz | Test::Bar)] => MatchArm::Arm(1),
        [.., Some(Test::Bar | Test::Baz), _] => MatchArm::Arm(2),
        _ => MatchArm::Wild,
    }
}

fn main() {
    let foo = vec![
        Some(Test::Foo),
        Some(Test::Bar),
        Some(Test::Baz),
        Some(Test::Qux),
    ];

    // path 1a
    assert_eq!(test(&foo), MatchArm::Arm(0));
    // path 1b
    assert_eq!(test(&[Some(Test::Bar), Some(Test::Foo)]), MatchArm::Arm(0));
    // path 2a
    assert_eq!(test(&foo[..3]), MatchArm::Arm(1));
    // path 2b
    assert_eq!(test(&[Some(Test::Foo), Some(Test::Foo), Some(Test::Bar)]), MatchArm::Arm(1));
    // path 3a
    assert_eq!(test(&foo[1..3]), MatchArm::Arm(2));
    // path 3b
    assert_eq!(test(&[Some(Test::Bar), Some(Test::Baz), Some(Test::Baz), Some(Test::Bar)]), MatchArm::Arm(2));
    // path 4
    assert_eq!(test(&foo[4..]), MatchArm::Wild);
}
<commit_msg>fix tidy error<commit_after>// Test or-patterns with slice-patterns

// run-pass

#![feature(or_patterns)]

#[derive(Debug, PartialEq)]
enum MatchArm {
    Arm(usize),
    Wild,
}

#[derive(Debug)]
enum Test {
    Foo,
    Bar,
    Baz,
    Qux,
}

fn test(foo: &[Option<Test>]) -> MatchArm {
    match foo {
        [.., Some(Test::Qux | Test::Foo)] => MatchArm::Arm(0),
        [Some(Test::Foo), .., Some(Test::Baz | Test::Bar)] => MatchArm::Arm(1),
        [.., Some(Test::Bar | Test::Baz), _] => MatchArm::Arm(2),
        _ => MatchArm::Wild,
    }
}

fn main() {
    let foo = vec![
        Some(Test::Foo),
        Some(Test::Bar),
        Some(Test::Baz),
        Some(Test::Qux),
    ];

    // path 1a
    assert_eq!(test(&foo), MatchArm::Arm(0));
    // path 1b
    assert_eq!(test(&[Some(Test::Bar), Some(Test::Foo)]), MatchArm::Arm(0));
    // path 2a
    assert_eq!(test(&foo[..3]), MatchArm::Arm(1));
    // path 2b
    assert_eq!(test(&[Some(Test::Foo), Some(Test::Foo), Some(Test::Bar)]), MatchArm::Arm(1));
    // path 3a
    assert_eq!(test(&foo[1..3]), MatchArm::Arm(2));
    // path 3b
    assert_eq!(test(&[Some(Test::Bar), Some(Test::Baz), Some(Test::Baz), Some(Test::Bar)]),
        MatchArm::Arm(2));
    // path 4
    assert_eq!(test(&foo[4..]), MatchArm::Wild);
}
<|endoftext|>


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

use appkit::NSRect;

use libc::{c_double, c_long};
use libc;

pub type Class = libc::intptr_t;
pub type IMP = extern "C" fn(id, SEL) -> id;
pub type Ivar = libc::intptr_t;
pub type SEL = libc::intptr_t;
pub type id = libc::intptr_t;

pub static nil: id = 0 as id;

extern {
    pub fn class_addMethod(cls: Class, name: SEL, imp: IMP, types: *libc::c_char) -> bool;
    pub fn class_addIvar(cls: Class,
                         name: *libc::c_char,
                         size: libc::size_t,
                         alignment: u8,
		                 types: *libc::c_char)
                         -> bool;
    pub fn object_setInstanceVariable(obj: id, name: *libc::c_char, value: *libc::c_void);
    pub fn object_getInstanceVariable(obj: id, name: *libc::c_char, outValue: **libc::c_void);
    pub fn objc_allocateClassPair(superclass: Class, name: *libc::c_char, extraBytes: libc::size_t)
                                  -> Class;
    pub fn objc_getClass(name: *libc::c_char) -> id;
    pub fn objc_msgSend(theReceiver: id, theSelector: SEL) -> id;
    pub fn objc_registerClassPair(cls: Class);
    pub fn sel_registerName(name: *libc::c_char) -> SEL;
}

/// A convenience method to convert the name of a class to the class object itself.
#[inline]
pub fn class(name: &str) -> id {
    unsafe {
        name.to_c_str().with_ref(|c_string| objc_getClass(c_string))
    }
}

/// A convenience method to convert the name of a selector to the selector object.
#[inline]
pub fn selector(name: &str) -> SEL {
    unsafe {
        name.to_c_str().with_ref(|c_string| sel_registerName(c_string))
    }
}

/// A trait that allows syntax like:
///
///     let string = "NSString".send("alloc").send("initWithCString:", "Hello world!");
pub trait ObjCMethodCall {
    unsafe fn send<S:ObjCSelector,A:ObjCMethodArgs>(self, selector: S, args: A) -> id;
    unsafe fn send_double<S:ObjCSelector,A:ObjCMethodDoubleArgs>(self, selector: S, args: A)
                          -> c_double;
    unsafe fn send_long<S:ObjCSelector,A:ObjCMethodLongArgs>(self, selector: S, args: A) -> c_long;
    unsafe fn send_void<S:ObjCSelector,A:ObjCMethodVoidArgs>(self, selector: S, args: A);
}

impl ObjCMethodCall for id {
    unsafe fn send<S:ObjCSelector,A:ObjCMethodArgs>(self, selector: S, args: A) -> id {
        args.send_args(self, selector.as_selector())
    }
    unsafe fn send_double<S:ObjCSelector,A:ObjCMethodDoubleArgs>(self, selector: S, args: A)
                          -> c_double {
        args.send_double_args(self, selector.as_selector())
    }
    unsafe fn send_long<S:ObjCSelector,A:ObjCMethodLongArgs>(self, selector: S, args: A)
                        -> c_long {
        args.send_long_args(self, selector.as_selector())
    }
    unsafe fn send_void<S:ObjCSelector,A:ObjCMethodVoidArgs>(self, selector: S, args: A) {
        args.send_void_args(self, selector.as_selector())
    }
}

/// A convenience implementation that allows methods on class names to be called directly, as in:
///
///     "NSString".send("alloc")
impl<'a> ObjCMethodCall for &'a str {
    unsafe fn send<S:ObjCSelector,A:ObjCMethodArgs>(self, selector: S, args: A) -> id {
        args.send_args(class(self), selector.as_selector())
    }
    unsafe fn send_double<S:ObjCSelector,A:ObjCMethodDoubleArgs>(self, selector: S, args: A)
                          -> c_double {
        args.send_double_args(class(self), selector.as_selector())
    }
    unsafe fn send_long<S:ObjCSelector,A:ObjCMethodLongArgs>(self, selector: S, args: A)
                        -> c_long {
        args.send_long_args(class(self), selector.as_selector())
    }
    unsafe fn send_void<S:ObjCSelector,A:ObjCMethodVoidArgs>(self, selector: S, args: A) {
        args.send_void_args(class(self), selector.as_selector())
    }
}

/// A trait that allows C strings to be used as selectors without having to convert them first.
pub trait ObjCSelector {
    fn as_selector(self) -> SEL;
}

impl<'a> ObjCSelector for &'a str {
    #[inline]
    fn as_selector(self) -> SEL {
        // TODO(pcwalton): Cache somehow.
        unsafe {
            self.to_c_str().with_ref(|c_string| sel_registerName(c_string))
        }
    }
}

impl ObjCSelector for SEL {
    #[inline]
    fn as_selector(self) -> SEL {
        self
    }
}

/// Traits that simulate variadic parameters for convenience when sending messages.
trait ObjCMethodArgs {
    unsafe fn send_args(self, receiver: id, selector: SEL) -> id;
}
trait ObjCMethodDoubleArgs {
    unsafe fn send_double_args(self, receiver: id, selector: SEL) -> c_double;
}
trait ObjCMethodLongArgs {
    unsafe fn send_long_args(self, receiver: id, selector: SEL) -> c_long;
}
trait ObjCMethodVoidArgs {
    unsafe fn send_void_args(self, receiver: id, selector: SEL);
}

impl ObjCMethodArgs for () {
    #[inline]
    unsafe fn send_args(self, receiver: id, selector: SEL) -> id {
        invoke_msg_id(receiver, selector)
    }
}

impl ObjCMethodArgs for (id, id, id, id, id) {
    #[inline]
    unsafe fn send_args(self, receiver: id, selector: SEL) -> id {
        let (first, second, third, fourth, fifth) = self;
        invoke_msg_id_id_id_id_id_id(receiver, selector, first, second, third, fourth, fifth)
    }
}

impl ObjCMethodArgs for NSRect {
    #[inline]
    unsafe fn send_args(self, receiver: id, selector: SEL) -> id {
        invoke_msg_id_NSRect(receiver, selector, &self)
    }
}

impl ObjCMethodDoubleArgs for () {
    #[inline]
    unsafe fn send_double_args(self, receiver: id, selector: SEL) -> f64 {
        invoke_msg_double(receiver, selector)
    }
}

impl ObjCMethodLongArgs for () {
    #[inline]
    unsafe fn send_long_args(self, receiver: id, selector: SEL) -> c_long {
        invoke_msg_long(receiver, selector)
    }
}

impl ObjCMethodVoidArgs for () {
    #[inline]
    unsafe fn send_void_args(self, receiver: id, selector: SEL) {
        invoke_msg_void(receiver, selector)
    }
}

impl ObjCMethodVoidArgs for bool {
    #[inline]
    unsafe fn send_void_args(self, receiver: id, selector: SEL) {
        invoke_msg_void_bool(receiver, selector, self)
    }
}

impl ObjCMethodVoidArgs for id {
    #[inline]
    unsafe fn send_void_args(self, receiver: id, selector: SEL) {
        invoke_msg_void_id(receiver, selector, self)
    }
}

/// A trait that simulates variadic parameters for method calls.

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

    #[test]
    pub fn test_nsapp() {
        unsafe {
            let _nsApp = "NSApplication".send("sharedApplication", ());
        }
    }

    #[test]
    pub fn test_custom_obj() {
        extern fn MyObject_doSomething(this: id, _: SEL) -> id {
            println!("doSomething");
            return this;
        }

        let NSObject = class("NSObject");
        let MyObject = "MyObject".to_c_str().with_ref(|s| {
            unsafe {
                objc_allocateClassPair(NSObject, s, 0 as libc::size_t)
            }
        });
        unsafe {
            let doSomething = selector("doSomething");
            let _ = "@@:".to_c_str().with_ref(|types| {
                class_addMethod(MyObject, doSomething, MyObject_doSomething, types)
            });

            objc_registerClassPair(MyObject);

            let mut obj: id = MyObject.send("alloc", ());
            obj = obj.send("init", ());
            obj.send_void("doSomething", ());
        }
    }
}

#[link(name = "msgsend")]
extern {
    fn invoke_msg_double(theReceiver: id, theSelector: SEL) -> f64;
    fn invoke_msg_id(theReceiver: id, theSelector: SEL) -> id;
    fn invoke_msg_id_id_id_id_id_id(theReceiver: id,
                                    theSelector: SEL,
                                    a: id,
                                    b: id,
                                    c: id,
                                    d: id,
                                    e: id)
                                    -> id;
    fn invoke_msg_id_NSRect(theReceiver: id, theSelector: SEL, a: &NSRect) -> id;
    fn invoke_msg_long(theReceiver: id, theSelector: SEL) -> c_long;
    fn invoke_msg_void(theReceiver: id, theSelector: SEL);
    fn invoke_msg_void_bool(theReceiver: id, theSelector: SEL, a: bool);
    fn invoke_msg_void_id(theReceiver: id, theSelector: SEL, a: id);
}

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

use appkit::NSRect;

use libc::{c_double, c_long};
use libc;

pub type Class = libc::intptr_t;
pub type IMP = extern "C" fn(id, SEL) -> id;
pub type Ivar = libc::intptr_t;
pub type SEL = libc::intptr_t;
#[allow(non_camel_case_types)]
pub type id = libc::intptr_t;

pub static nil: id = 0 as id;

extern {
    pub fn class_addMethod(cls: Class, name: SEL, imp: IMP, types: *libc::c_char) -> bool;
    pub fn class_addIvar(cls: Class,
                         name: *libc::c_char,
                         size: libc::size_t,
                         alignment: u8,
		                 types: *libc::c_char)
                         -> bool;
    pub fn object_setInstanceVariable(obj: id, name: *libc::c_char, value: *libc::c_void);
    pub fn object_getInstanceVariable(obj: id, name: *libc::c_char, outValue: **libc::c_void);
    pub fn objc_allocateClassPair(superclass: Class, name: *libc::c_char, extraBytes: libc::size_t)
                                  -> Class;
    pub fn objc_getClass(name: *libc::c_char) -> id;
    pub fn objc_msgSend(theReceiver: id, theSelector: SEL) -> id;
    pub fn objc_registerClassPair(cls: Class);
    pub fn sel_registerName(name: *libc::c_char) -> SEL;
}

/// A convenience method to convert the name of a class to the class object itself.
#[inline]
pub fn class(name: &str) -> id {
    unsafe {
        name.to_c_str().with_ref(|c_string| objc_getClass(c_string))
    }
}

/// A convenience method to convert the name of a selector to the selector object.
#[inline]
pub fn selector(name: &str) -> SEL {
    unsafe {
        name.to_c_str().with_ref(|c_string| sel_registerName(c_string))
    }
}

/// A trait that allows syntax like:
///
///     let string = "NSString".send("alloc").send("initWithCString:", "Hello world!");
pub trait ObjCMethodCall {
    unsafe fn send<S:ObjCSelector,A:ObjCMethodArgs>(self, selector: S, args: A) -> id;
    unsafe fn send_double<S:ObjCSelector,A:ObjCMethodDoubleArgs>(self, selector: S, args: A)
                          -> c_double;
    unsafe fn send_long<S:ObjCSelector,A:ObjCMethodLongArgs>(self, selector: S, args: A) -> c_long;
    unsafe fn send_void<S:ObjCSelector,A:ObjCMethodVoidArgs>(self, selector: S, args: A);
}

impl ObjCMethodCall for id {
    unsafe fn send<S:ObjCSelector,A:ObjCMethodArgs>(self, selector: S, args: A) -> id {
        args.send_args(self, selector.as_selector())
    }
    unsafe fn send_double<S:ObjCSelector,A:ObjCMethodDoubleArgs>(self, selector: S, args: A)
                          -> c_double {
        args.send_double_args(self, selector.as_selector())
    }
    unsafe fn send_long<S:ObjCSelector,A:ObjCMethodLongArgs>(self, selector: S, args: A)
                        -> c_long {
        args.send_long_args(self, selector.as_selector())
    }
    unsafe fn send_void<S:ObjCSelector,A:ObjCMethodVoidArgs>(self, selector: S, args: A) {
        args.send_void_args(self, selector.as_selector())
    }
}

/// A convenience implementation that allows methods on class names to be called directly, as in:
///
///     "NSString".send("alloc")
impl<'a> ObjCMethodCall for &'a str {
    unsafe fn send<S:ObjCSelector,A:ObjCMethodArgs>(self, selector: S, args: A) -> id {
        args.send_args(class(self), selector.as_selector())
    }
    unsafe fn send_double<S:ObjCSelector,A:ObjCMethodDoubleArgs>(self, selector: S, args: A)
                          -> c_double {
        args.send_double_args(class(self), selector.as_selector())
    }
    unsafe fn send_long<S:ObjCSelector,A:ObjCMethodLongArgs>(self, selector: S, args: A)
                        -> c_long {
        args.send_long_args(class(self), selector.as_selector())
    }
    unsafe fn send_void<S:ObjCSelector,A:ObjCMethodVoidArgs>(self, selector: S, args: A) {
        args.send_void_args(class(self), selector.as_selector())
    }
}

/// A trait that allows C strings to be used as selectors without having to convert them first.
pub trait ObjCSelector {
    fn as_selector(self) -> SEL;
}

impl<'a> ObjCSelector for &'a str {
    #[inline]
    fn as_selector(self) -> SEL {
        // TODO(pcwalton): Cache somehow.
        unsafe {
            self.to_c_str().with_ref(|c_string| sel_registerName(c_string))
        }
    }
}

impl ObjCSelector for SEL {
    #[inline]
    fn as_selector(self) -> SEL {
        self
    }
}

/// Traits that simulate variadic parameters for convenience when sending messages.
trait ObjCMethodArgs {
    unsafe fn send_args(self, receiver: id, selector: SEL) -> id;
}
trait ObjCMethodDoubleArgs {
    unsafe fn send_double_args(self, receiver: id, selector: SEL) -> c_double;
}
trait ObjCMethodLongArgs {
    unsafe fn send_long_args(self, receiver: id, selector: SEL) -> c_long;
}
trait ObjCMethodVoidArgs {
    unsafe fn send_void_args(self, receiver: id, selector: SEL);
}

impl ObjCMethodArgs for () {
    #[inline]
    unsafe fn send_args(self, receiver: id, selector: SEL) -> id {
        invoke_msg_id(receiver, selector)
    }
}

impl ObjCMethodArgs for (id, id, id, id, id) {
    #[inline]
    unsafe fn send_args(self, receiver: id, selector: SEL) -> id {
        let (first, second, third, fourth, fifth) = self;
        invoke_msg_id_id_id_id_id_id(receiver, selector, first, second, third, fourth, fifth)
    }
}

impl ObjCMethodArgs for NSRect {
    #[inline]
    unsafe fn send_args(self, receiver: id, selector: SEL) -> id {
        invoke_msg_id_NSRect(receiver, selector, &self)
    }
}

impl ObjCMethodDoubleArgs for () {
    #[inline]
    unsafe fn send_double_args(self, receiver: id, selector: SEL) -> f64 {
        invoke_msg_double(receiver, selector)
    }
}

impl ObjCMethodLongArgs for () {
    #[inline]
    unsafe fn send_long_args(self, receiver: id, selector: SEL) -> c_long {
        invoke_msg_long(receiver, selector)
    }
}

impl ObjCMethodVoidArgs for () {
    #[inline]
    unsafe fn send_void_args(self, receiver: id, selector: SEL) {
        invoke_msg_void(receiver, selector)
    }
}

impl ObjCMethodVoidArgs for bool {
    #[inline]
    unsafe fn send_void_args(self, receiver: id, selector: SEL) {
        invoke_msg_void_bool(receiver, selector, self)
    }
}

impl ObjCMethodVoidArgs for id {
    #[inline]
    unsafe fn send_void_args(self, receiver: id, selector: SEL) {
        invoke_msg_void_id(receiver, selector, self)
    }
}

/// A trait that simulates variadic parameters for method calls.

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

    #[test]
    pub fn test_nsapp() {
        unsafe {
            let _nsApp = "NSApplication".send("sharedApplication", ());
        }
    }

    #[test]
    pub fn test_custom_obj() {
        extern fn MyObject_doSomething(this: id, _: SEL) -> id {
            println!("doSomething");
            return this;
        }

        let ns_object = class("NSObject");
        let my_object = "MyObject".to_c_str().with_ref(|s| {
            unsafe {
                objc_allocateClassPair(ns_object, s, 0 as libc::size_t)
            }
        });
        unsafe {
            let doSomething = selector("doSomething");
            let _ = "@@:".to_c_str().with_ref(|types| {
                class_addMethod(my_object, doSomething, MyObject_doSomething, types)
            });

            objc_registerClassPair(my_object);

            let mut obj: id = my_object.send("alloc", ());
            obj = obj.send("init", ());
            obj.send_void("doSomething", ());
        }
    }
}

#[link(name = "msgsend")]
extern {
    fn invoke_msg_double(theReceiver: id, theSelector: SEL) -> f64;
    fn invoke_msg_id(theReceiver: id, theSelector: SEL) -> id;
    fn invoke_msg_id_id_id_id_id_id(theReceiver: id,
                                    theSelector: SEL,
                                    a: id,
                                    b: id,
                                    c: id,
                                    d: id,
                                    e: id)
                                    -> id;
    fn invoke_msg_id_NSRect(theReceiver: id, theSelector: SEL, a: &NSRect) -> id;
    fn invoke_msg_long(theReceiver: id, theSelector: SEL) -> c_long;
    fn invoke_msg_void(theReceiver: id, theSelector: SEL);
    fn invoke_msg_void_bool(theReceiver: id, theSelector: SEL, a: bool);
    fn invoke_msg_void_id(theReceiver: id, theSelector: SEL, a: id);
}

<|endoftext|>