<commit_before>use prolog::and_stack::*;
use prolog::ast::*;

use std::collections::HashMap;
use std::ops::IndexMut;

type Trail = Vec<(Ref, HeapCellValue)>;

pub(crate) struct RedirectInfo {
    trail: Trail
}

pub(crate) trait CopierTarget
{
    fn source(&self) -> usize;
    fn threshold(&self) -> usize;
    fn push(&mut self, HeapCellValue);
    fn store(&self, Addr) -> Addr;
    fn deref(&self, Addr) -> Addr;
    fn stack(&mut self) -> &mut AndStack;

    fn unwind_trail(&mut self, redirect: RedirectInfo)
      where Self: IndexMut<usize, Output=HeapCellValue>
    {
        for (r, hcv) in redirect.trail {
            match r {
                Ref::HeapCell(hc) => self[hc] = hcv.clone(),
                Ref::StackCell(fr, sc) => self.stack()[fr][sc] = hcv.as_addr(0)
            }
        }
    }

    // duplicate_term_impl(L1, L2) uses Cheney's algorithm to copy the term
    // at L1 to L2. trail is kept to restore the innards of L1 after
    // it's been copied to L2.
    fn duplicate_term_impl(&mut self, addr: Addr) -> RedirectInfo
      where Self: IndexMut<usize, Output=HeapCellValue>
    {
        let mut trail = Trail::new();
        let mut scan = self.source();
        let old_h = self.threshold();

        // Lists have a compressed representation as structures,
        // removing the need for NamedStr, so we use a redirection
        // table for copying lists.
        let mut list_redirect = HashMap::new();

        self.push(HeapCellValue::Addr(addr));

        while scan < self.threshold() {
            match self[scan].clone() {
                HeapCellValue::NamedStr(..) =>
                    scan += 1,
                HeapCellValue::Addr(a) =>
                    match a.clone() {
                        Addr::Lis(a) => {
                            if let Some(idx) = list_redirect.get(&a) {
                                self[scan] = HeapCellValue::Addr(Addr::Lis(*idx));
                                scan += 1;
                                continue;
                            }

                            list_redirect.insert(a, self.threshold());

                            self[scan] = HeapCellValue::Addr(Addr::Lis(self.threshold()));

                            let hcv = self[a].clone();
                            self.push(hcv);

                            let hcv = self[a+1].clone();
                            self.push(hcv);

                            scan += 1;
                        },
                        Addr::HeapCell(_) | Addr::StackCell(_, _) => {
                            let ra = a;
                            let rd = self.store(self.deref(ra.clone()));

                            match rd.clone() {
                                Addr::HeapCell(hc) if hc >= old_h => {
                                    self[scan] = HeapCellValue::Addr(rd);
                                    scan += 1;
                                },
                                _ if ra == rd => {
                                    self[scan] = HeapCellValue::Addr(Addr::HeapCell(scan));

                                    if let Addr::HeapCell(hc) = ra.clone() {
                                        self[hc] = HeapCellValue::Addr(Addr::HeapCell(scan));
                                        trail.push((Ref::HeapCell(hc),
                                                    HeapCellValue::Addr(Addr::HeapCell(hc))));
                                    } else if let Addr::StackCell(fr, sc) = ra {
                                        self.stack()[fr][sc] = Addr::HeapCell(scan);
                                        trail.push((Ref::StackCell(fr, sc),
                                                    HeapCellValue::Addr(Addr::StackCell(fr, sc))));
                                    }

                                    scan += 1;
                                },
                                _ => self[scan] = HeapCellValue::Addr(rd)
                            };
                        },
                        Addr::Str(s) => {
                            match self[s].clone() {
                                HeapCellValue::NamedStr(arity, name, fixity) => {
                                    let threshold = self.threshold();

                                    self[scan] = HeapCellValue::Addr(Addr::Str(threshold));
                                    self[s] = HeapCellValue::Addr(Addr::Str(threshold));

                                    trail.push((Ref::HeapCell(s),
                                                HeapCellValue::NamedStr(arity, name.clone(), fixity)));

                                    self.push(HeapCellValue::NamedStr(arity, name, fixity));

                                    for i in 0 .. arity {
                                        let hcv = self[s + 1 + i].clone();
                                        self.push(hcv);
                                    }
                                },
                                HeapCellValue::Addr(Addr::Str(o)) =>
                                    self[scan] = HeapCellValue::Addr(Addr::Str(o)),
                                _ => {}
                            };

                            scan += 1;
                        },
                        Addr::Con(_) => scan += 1
                    }
            }
        }

        RedirectInfo { trail }
    }

    fn duplicate_term(&mut self, addr: Addr)
      where Self: IndexMut<usize, Output=HeapCellValue>
    {
        let redirect = self.duplicate_term_impl(addr);
        self.unwind_trail(redirect);
    }
}
<commit_msg>realize full cheney in copier.rs<commit_after>use prolog::and_stack::*;
use prolog::ast::*;

use std::ops::IndexMut;

type Trail = Vec<(Ref, HeapCellValue)>;

pub(crate) struct RedirectInfo {
    trail: Trail
}

pub(crate) trait CopierTarget
{
    fn source(&self) -> usize;
    fn threshold(&self) -> usize;
    fn push(&mut self, HeapCellValue);
    fn store(&self, Addr) -> Addr;
    fn deref(&self, Addr) -> Addr;
    fn stack(&mut self) -> &mut AndStack;

    fn unwind_trail(&mut self, redirect: RedirectInfo)
      where Self: IndexMut<usize, Output=HeapCellValue>
    {
        for (r, hcv) in redirect.trail {
            match r {
                Ref::HeapCell(hc) => self[hc] = hcv.clone(),
                Ref::StackCell(fr, sc) => self.stack()[fr][sc] = hcv.as_addr(0)
            }
        }
    }

    // duplicate_term_impl(L1, L2) uses Cheney's algorithm to copy the term
    // at L1 to L2. trail is kept to restore the innards of L1 after
    // it's been copied to L2.
    fn duplicate_term_impl(&mut self, addr: Addr) -> RedirectInfo
      where Self: IndexMut<usize, Output=HeapCellValue>
    {
        let mut trail = Trail::new();
        let mut scan = self.source();
        let old_h = self.threshold();

        self.push(HeapCellValue::Addr(addr));

        while scan < self.threshold() {
            match self[scan].clone() {
                HeapCellValue::NamedStr(..) =>
                    scan += 1,
                HeapCellValue::Addr(a) =>
                    match a.clone() {
                        Addr::Lis(a) => {
                            if let HeapCellValue::Addr(Addr::Lis(b)) = self[a].clone() {
                                if b >= old_h {
                                    self[scan] = HeapCellValue::Addr(Addr::Lis(b));
                                    scan += 1;
                                    continue;
                                }
                            }

                            let threshold = self.threshold();
                            self[scan] = HeapCellValue::Addr(Addr::Lis(threshold));

                            let hcv = self[a].clone();
                            self.push(hcv);

                            let hcv = self[a+1].clone();
                            self.push(hcv);

                            trail.push((Ref::HeapCell(a), self[a].clone()));
                            self[a] = HeapCellValue::Addr(Addr::Lis(threshold));

                            scan += 1;
                        },
                        Addr::HeapCell(_) | Addr::StackCell(_, _) => {
                            let ra = a;
                            let rd = self.store(self.deref(ra.clone()));

                            match rd.clone() {
                                Addr::HeapCell(hc) if hc >= old_h => {
                                    self[scan] = HeapCellValue::Addr(rd);
                                    scan += 1;
                                },
                                _ if ra == rd => {
                                    self[scan] = HeapCellValue::Addr(Addr::HeapCell(scan));

                                    if let Addr::HeapCell(hc) = ra.clone() {
                                        self[hc] = HeapCellValue::Addr(Addr::HeapCell(scan));
                                        trail.push((Ref::HeapCell(hc),
                                                    HeapCellValue::Addr(Addr::HeapCell(hc))));
                                    } else if let Addr::StackCell(fr, sc) = ra {
                                        self.stack()[fr][sc] = Addr::HeapCell(scan);
                                        trail.push((Ref::StackCell(fr, sc),
                                                    HeapCellValue::Addr(Addr::StackCell(fr, sc))));
                                    }

                                    scan += 1;
                                },
                                _ => self[scan] = HeapCellValue::Addr(rd)
                            };
                        },
                        Addr::Str(s) => {
                            match self[s].clone() {
                                HeapCellValue::NamedStr(arity, name, fixity) => {
                                    let threshold = self.threshold();

                                    self[scan] = HeapCellValue::Addr(Addr::Str(threshold));
                                    self[s] = HeapCellValue::Addr(Addr::Str(threshold));

                                    trail.push((Ref::HeapCell(s),
                                                HeapCellValue::NamedStr(arity, name.clone(), fixity)));

                                    self.push(HeapCellValue::NamedStr(arity, name, fixity));

                                    for i in 0 .. arity {
                                        let hcv = self[s + 1 + i].clone();
                                        self.push(hcv);
                                    }
                                },
                                HeapCellValue::Addr(Addr::Str(o)) =>
                                    self[scan] = HeapCellValue::Addr(Addr::Str(o)),
                                _ => {}
                            };

                            scan += 1;
                        },
                        Addr::Con(_) => scan += 1
                    }
            }
        }

        RedirectInfo { trail }
    }

    fn duplicate_term(&mut self, addr: Addr)
      where Self: IndexMut<usize, Output=HeapCellValue>
    {
        let redirect = self.duplicate_term_impl(addr);
        self.unwind_trail(redirect);
    }
}
<|endoftext|>


<commit_before>use term::Term;
use document::Document;
use query::{Query, TermMatcher};

#[derive(Debug, PartialEq)]
pub enum BooleanQuery {
    MatchAll,
    MatchNone,
    MatchTerm {
        field: String,
        term: Term,
        matcher: TermMatcher,
    },
    And {
        queries: Vec<BooleanQuery>,
    },
    Or {
        queries: Vec<BooleanQuery>,
    },
    Not {
        query: Box<BooleanQuery>,
    }
}

impl BooleanQuery {
    pub fn matches(&self, doc: &Document) -> bool {
        match *self {
            BooleanQuery::MatchAll => true,
            BooleanQuery::MatchNone => false,
            BooleanQuery::MatchTerm{ref field, ref term, ref matcher} => {
                if let Some(field_value) = doc.fields.get(field) {
                    for field_token in field_value.iter() {
                        if matcher.matches(&field_token.term, term) {
                            return true;
                        }
                    }
                }

                false
            }
            BooleanQuery::And{ref queries} => {
                for query in queries {
                    if !query.matches(doc) {
                        return false;
                    }
                }

                return true;
            }
            BooleanQuery::Or{ref queries} => {
                for query in queries {
                    if query.matches(doc) {
                        return true;
                    }
                }

                return false;
            }
            BooleanQuery::Not{ref query} => {
                !query.matches(doc)
            }
        }
    }
}

impl Query {
    pub fn to_boolean_query(self) -> BooleanQuery {
        match self {
            Query::MatchAll => BooleanQuery::MatchAll,
            Query::MatchNone => BooleanQuery::MatchNone,
            Query::MatchTerm{field, term, matcher} => {
                BooleanQuery::MatchTerm{
                    field: field,
                    term: term,
                    matcher: matcher,
                }
            }
            Query::And{queries} => {
                let mut boolean_queries = Vec::with_capacity(queries.len());

                for query in queries {
                    boolean_queries.push(query.to_boolean_query());
                }

                BooleanQuery::And {
                    queries: boolean_queries,
                }
            }
            Query::Or{queries} => {
                let mut boolean_queries = Vec::with_capacity(queries.len());

                for query in queries {
                    boolean_queries.push(query.to_boolean_query());
                }

                BooleanQuery::Or {
                    queries: boolean_queries,
                }
            }
            Query::MultiOr{queries, minimum_should_match} => {
                let mut boolean_queries = Vec::with_capacity(queries.len());

                for query in queries {
                    boolean_queries.push(query.to_boolean_query());
                }

                BooleanQuery::Or {
                    queries: boolean_queries,
                }
            }
            Query::DisjunctionMax{queries} => {
                let mut boolean_queries = Vec::with_capacity(queries.len());

                for query in queries {
                    boolean_queries.push(query.to_boolean_query());
                }

                BooleanQuery::Or {
                    queries: boolean_queries,
                }
            }
            Query::Filter{query, filter} => {
                BooleanQuery::And {
                    queries: vec![
                        query.to_boolean_query(),
                        *filter,
                    ]
                }
            }
            Query::Exclude{query, exclude} => {
                BooleanQuery::And {
                    queries: vec![
                        query.to_boolean_query(),
                        BooleanQuery::Not {
                            query: exclude,
                        }
                    ]
                }
            }
            Query::Score{query, mul, add} => {
                query.to_boolean_query()
            }
        }
    }
}
<commit_msg>Replaced Not boolean query with .negate() method<commit_after>use term::Term;
use document::Document;
use query::{Query, TermMatcher};

#[derive(Debug, PartialEq)]
pub enum BooleanQuery {
    MatchAll,
    MatchNone,
    MatchTerm {
        field: String,
        term: Term,
        matcher: TermMatcher,
    },
    NotMatchTerm {
        field: String,
        term: Term,
        matcher: TermMatcher,
    },
    And {
        queries: Vec<BooleanQuery>,
    },
    Or {
        queries: Vec<BooleanQuery>,
    },
}

impl BooleanQuery {
    pub fn matches(&self, doc: &Document) -> bool {
        match *self {
            BooleanQuery::MatchAll => true,
            BooleanQuery::MatchNone => false,
            BooleanQuery::MatchTerm{ref field, ref term, ref matcher} => {
                if let Some(field_value) = doc.fields.get(field) {
                    for field_token in field_value.iter() {
                        if matcher.matches(&field_token.term, term) {
                            return true;
                        }
                    }
                }

                false
            }
            BooleanQuery::NotMatchTerm{ref field, ref term, ref matcher} => {
                if let Some(field_value) = doc.fields.get(field) {
                    for field_token in field_value.iter() {
                        if matcher.matches(&field_token.term, term) {
                            return false;
                        }
                    }
                }

                true
            }
            BooleanQuery::And{ref queries} => {
                for query in queries {
                    if !query.matches(doc) {
                        return false;
                    }
                }

                return true;
            }
            BooleanQuery::Or{ref queries} => {
                for query in queries {
                    if query.matches(doc) {
                        return true;
                    }
                }

                return false;
            }
        }
    }

    pub fn negate(self) -> BooleanQuery {
        match self {
            BooleanQuery::MatchAll => BooleanQuery::MatchNone,
            BooleanQuery::MatchNone => BooleanQuery::MatchAll,
            BooleanQuery::MatchTerm{field, term, matcher} => {
                BooleanQuery::NotMatchTerm {
                    field: field,
                    term: term,
                    matcher: matcher,
                }
            }
            BooleanQuery::NotMatchTerm{field, term, matcher} => {
                BooleanQuery::MatchTerm {
                    field: field,
                    term: term,
                    matcher: matcher,
                }
            }
            BooleanQuery::And{queries} => {
                let mut negated_queries = Vec::new();
                for query in queries {
                    negated_queries.push(query);
                }

                BooleanQuery::Or{
                    queries: negated_queries,
                }
            }
            BooleanQuery::Or{queries} => {
                let mut negated_queries = Vec::new();
                for query in queries {
                    negated_queries.push(query);
                }

                BooleanQuery::And{
                    queries: negated_queries,
                }
            }
        }
    }
}

impl Query {
    pub fn to_boolean_query(self) -> BooleanQuery {
        match self {
            Query::MatchAll => BooleanQuery::MatchAll,
            Query::MatchNone => BooleanQuery::MatchNone,
            Query::MatchTerm{field, term, matcher} => {
                BooleanQuery::MatchTerm{
                    field: field,
                    term: term,
                    matcher: matcher,
                }
            }
            Query::And{queries} => {
                let mut boolean_queries = Vec::with_capacity(queries.len());

                for query in queries {
                    boolean_queries.push(query.to_boolean_query());
                }

                BooleanQuery::And {
                    queries: boolean_queries,
                }
            }
            Query::Or{queries} => {
                let mut boolean_queries = Vec::with_capacity(queries.len());

                for query in queries {
                    boolean_queries.push(query.to_boolean_query());
                }

                BooleanQuery::Or {
                    queries: boolean_queries,
                }
            }
            Query::MultiOr{queries, minimum_should_match} => {
                let mut boolean_queries = Vec::with_capacity(queries.len());

                for query in queries {
                    boolean_queries.push(query.to_boolean_query());
                }

                BooleanQuery::Or {
                    queries: boolean_queries,
                }
            }
            Query::DisjunctionMax{queries} => {
                let mut boolean_queries = Vec::with_capacity(queries.len());

                for query in queries {
                    boolean_queries.push(query.to_boolean_query());
                }

                BooleanQuery::Or {
                    queries: boolean_queries,
                }
            }
            Query::Filter{query, filter} => {
                BooleanQuery::And {
                    queries: vec![
                        query.to_boolean_query(),
                        *filter,
                    ]
                }
            }
            Query::Exclude{query, exclude} => {
                BooleanQuery::And {
                    queries: vec![
                        query.to_boolean_query(),
                        exclude.negate(),
                    ]
                }
            }
            Query::Score{query, mul, add} => {
                query.to_boolean_query()
            }
        }
    }
}
<|endoftext|>


<commit_before>// A port of the simplistic benchmark from
//
//    http://github.com/PaulKeeble/ScalaVErlangAgents
//
// I *think* it's the same, more or less.

#![crate_id = "msgsend"]

extern crate native;
extern crate time;
extern crate zmq;

use std::task::TaskBuilder;
use native::NativeTaskBuilder;
use std::comm;
use std::os;

fn server(mut pull_socket: zmq::Socket, mut push_socket: zmq::Socket, mut workers: uint) {
    let mut count = 0u;
    let mut msg = zmq::Message::new();

    while workers != 0 {
        match pull_socket.recv(&mut msg, 0) {
            Err(e) => fail!(e.to_str()),
            Ok(()) => {
                msg.with_str(|s| {
                    if s == "" {
                        workers -= 1;
                    } else {
                        count += from_str::<uint>(s).unwrap();
                    }
                })
            }
        }
    }

    match push_socket.send_str(count.to_str().as_slice(), 0) {
        Ok(()) => { }
        Err(e) => fail!(e.to_str()),
    }
}

fn spawn_server(ctx: &mut zmq::Context, workers: uint) -> comm::Sender<()> {
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    pull_socket.bind("inproc://server-pull").unwrap();
    push_socket.bind("inproc://server-push").unwrap();

    // Spawn the server.
    let (ready_tx, ready_rx) = comm::channel();
    let (start_tx, start_rx) = comm::channel();

    // Mutable sockets cannot be implicitly captured.
    let pull_socket = pull_socket;
    let push_socket = push_socket;

    TaskBuilder::new().native().spawn(proc() {
        // Let the main thread know we're ready.
        ready_tx.send(());

        // Wait until we need to start.
        start_rx.recv();

        server(pull_socket, push_socket, workers);
    });

    // Wait for the server to start.
    ready_rx.recv();

    start_tx
}

fn worker(mut push_socket: zmq::Socket, count: uint) {
    for _ in range(0, count) {
        push_socket.send_str(100u.to_str().as_slice(), 0).unwrap();
    }

    // Let the server know we're done.
    push_socket.send_str("", 0).unwrap();
}

fn spawn_worker(ctx: &mut zmq::Context, count: uint) -> comm::Receiver<()> {
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();

    // Mutable sockets cannot be implicitly captured.
    let push_socket = push_socket;

    // Spawn the worker.
    let (tx, rx) = comm::channel();
    TaskBuilder::new().native().spawn(proc() {
        // Let the main thread we're ready.
        tx.send(());

        worker(push_socket, count);

        tx.send(());
    });

    // Wait for the worker to start.
    rx.recv();

    rx
}

fn run(ctx: &mut zmq::Context, size: uint, workers: uint) {
    let start_ch = spawn_server(ctx, workers);

    // Create some command/control sockets.
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    pull_socket.connect("inproc://server-push").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();
    //pull_socket.connect("tcp://127.0.0.1:3457").unwrap();

    // Spawn all the workers.
    let mut worker_results = Vec::new();
    for _ in range(0, workers) {
        worker_results.push(spawn_worker(ctx, size / workers));
    }

    let start = time::precise_time_s();

    start_ch.send(());

    // Block until all the workers finish.
    for po in worker_results.iter() {
        po.recv();
    }

    // Receive the final count.
    let result = match pull_socket.recv_msg(0) {
        Ok(msg) => msg.with_str(|s| from_str::<uint>(s).unwrap()),
        Err(e) => fail!(e.to_str()),
    };

    let end = time::precise_time_s();
    let elapsed = end - start;

    println!("Count is {}", result);
    println!("Test took {} seconds", elapsed);
    let thruput = ((size / workers * workers) as f64) / elapsed;
    println!("Throughput={:f} per sec", thruput);
}

fn main() {
    let args = os::args();

    let args = if os::getenv("RUST_BENCH").is_some() {
        vec!("".to_string(), "1000000".to_string(), "10000".to_string())
    } else if args.len() <= 1u {
        vec!("".to_string(), "10000".to_string(), "4".to_string())
    } else {
        args
    };

    let size = from_str::<uint>(args.get(1).as_slice()).unwrap();
    let workers = from_str::<uint>(args.get(2).as_slice()).unwrap();

    let mut ctx = zmq::Context::new();

    run(&mut ctx, size, workers);
}
<commit_msg>Update examples w/ change of `to_str()`<commit_after>// A port of the simplistic benchmark from
//
//    http://github.com/PaulKeeble/ScalaVErlangAgents
//
// I *think* it's the same, more or less.

#![crate_id = "msgsend"]

extern crate native;
extern crate time;
extern crate zmq;

use std::task::TaskBuilder;
use native::NativeTaskBuilder;
use std::comm;
use std::os;

fn server(mut pull_socket: zmq::Socket, mut push_socket: zmq::Socket, mut workers: uint) {
    let mut count = 0u;
    let mut msg = zmq::Message::new();

    while workers != 0 {
        match pull_socket.recv(&mut msg, 0) {
            Err(e) => fail!(e.to_string()),
            Ok(()) => {
                msg.with_str(|s| {
                    if s == "" {
                        workers -= 1;
                    } else {
                        count += from_str::<uint>(s).unwrap();
                    }
                })
            }
        }
    }

    match push_socket.send_str(count.to_string().as_slice(), 0) {
        Ok(()) => { }
        Err(e) => fail!(e.to_string()),
    }
}

fn spawn_server(ctx: &mut zmq::Context, workers: uint) -> comm::Sender<()> {
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    pull_socket.bind("inproc://server-pull").unwrap();
    push_socket.bind("inproc://server-push").unwrap();

    // Spawn the server.
    let (ready_tx, ready_rx) = comm::channel();
    let (start_tx, start_rx) = comm::channel();

    // Mutable sockets cannot be implicitly captured.
    let pull_socket = pull_socket;
    let push_socket = push_socket;

    TaskBuilder::new().native().spawn(proc() {
        // Let the main thread know we're ready.
        ready_tx.send(());

        // Wait until we need to start.
        start_rx.recv();

        server(pull_socket, push_socket, workers);
    });

    // Wait for the server to start.
    ready_rx.recv();

    start_tx
}

fn worker(mut push_socket: zmq::Socket, count: uint) {
    for _ in range(0, count) {
        push_socket.send_str(100u.to_string().as_slice(), 0).unwrap();
    }

    // Let the server know we're done.
    push_socket.send_str("", 0).unwrap();
}

fn spawn_worker(ctx: &mut zmq::Context, count: uint) -> comm::Receiver<()> {
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();

    // Mutable sockets cannot be implicitly captured.
    let push_socket = push_socket;

    // Spawn the worker.
    let (tx, rx) = comm::channel();
    TaskBuilder::new().native().spawn(proc() {
        // Let the main thread we're ready.
        tx.send(());

        worker(push_socket, count);

        tx.send(());
    });

    // Wait for the worker to start.
    rx.recv();

    rx
}

fn run(ctx: &mut zmq::Context, size: uint, workers: uint) {
    let start_ch = spawn_server(ctx, workers);

    // Create some command/control sockets.
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    pull_socket.connect("inproc://server-push").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();
    //pull_socket.connect("tcp://127.0.0.1:3457").unwrap();

    // Spawn all the workers.
    let mut worker_results = Vec::new();
    for _ in range(0, workers) {
        worker_results.push(spawn_worker(ctx, size / workers));
    }

    let start = time::precise_time_s();

    start_ch.send(());

    // Block until all the workers finish.
    for po in worker_results.iter() {
        po.recv();
    }

    // Receive the final count.
    let result = match pull_socket.recv_msg(0) {
        Ok(msg) => msg.with_str(|s| from_str::<uint>(s).unwrap()),
        Err(e) => fail!(e.to_string()),
    };

    let end = time::precise_time_s();
    let elapsed = end - start;

    println!("Count is {}", result);
    println!("Test took {} seconds", elapsed);
    let thruput = ((size / workers * workers) as f64) / elapsed;
    println!("Throughput={:f} per sec", thruput);
}

fn main() {
    let args = os::args();

    let args = if os::getenv("RUST_BENCH").is_some() {
        vec!("".to_string(), "1000000".to_string(), "10000".to_string())
    } else if args.len() <= 1u {
        vec!("".to_string(), "10000".to_string(), "4".to_string())
    } else {
        args
    };

    let size = from_str::<uint>(args.get(1).as_slice()).unwrap();
    let workers = from_str::<uint>(args.get(2).as_slice()).unwrap();

    let mut ctx = zmq::Context::new();

    run(&mut ctx, size, workers);
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
use std::io::Result as IoResult;
use std::result::Result;
use std::iter::{Iterator, IntoIterator};
use std::collections::HashMap;
use std::collections::hash_map;
use std::vec::Vec;
use std::cmp::{Eq, PartialEq};
use std::hash::{Hash, Hasher};
use std::convert::From;

pub type Pixels = usize;
pub type FileName = String;
pub type FilePath = String;

#[derive(Clone, Eq, PartialEq, Hash)]
pub enum ResolutionUnits {
    PixelsPerInch,
    PixelsPerCentimeter,
}

#[derive(Clone, Eq, PartialEq, Hash)]
pub enum Direction {
    Horizontal,
    Vertical,
}

#[derive(Clone, Eq, PartialEq, Hash)]
pub enum ImageFileFormat {
    TIFF,
    PNG,
    JPEG,
    UNKNOWN,
}

#[derive(Clone, Eq, PartialEq, Hash)]
struct ImageDimensions {
    x_pixels: Pixels,
    y_pixels: Pixels,
}

impl ImageDimensions {
    fn new(x: Pixels, y: Pixels) -> ImageDimensions {
        ImageDimensions {
            x_pixels: x,
            y_pixels: y,
        }
    }
}

#[derive(Clone, Eq, PartialEq, Hash)]
pub struct ImageResolution {
    amount: Pixels,
    units: ResolutionUnits,
}

impl ImageResolution {
    fn new(amount: usize, units: ResolutionUnits) -> ImageResolution {
        ImageResolution {
            amount: amount,
            units: units,
        }
    }
}

#[derive(Clone)]
pub enum PageOps {
    NoOperation,
    Identify(FileName, FilePath),
    Rescale(Pixels, Direction),
    ExpandLeftEdge(Pixels),
    ExpandRightEdge(Pixels),
    ExpandTopEdge(Pixels),
    ExpandBottomEdge(Pixels),
    TrimLeftEdge(Pixels),
    TrimRightEdge(Pixels),
    TrimTopEdge(Pixels),
    TrimBottomEdge(Pixels),
    SetResolution(ImageResolution),
}

pub trait ElementaryPageOperations {
    fn identify(file_name: FileName, path: FilePath) -> Self;
    fn rescale(amount: Pixels, dir: Direction)       -> Self;
    fn expand_left_edge(amount: Pixels)              -> Self;
    fn expand_right_edge(amount: Pixels)             -> Self;
    fn expand_top_edge(amount: Pixels)               -> Self;
    fn expand_bottom_edge(amount: Pixels)            -> Self;
    fn trim_left_edge(amount: Pixels)                -> Self;
    fn trim_right_edge(amount: Pixels)               -> Self;
    fn trim_top_edge(amount: Pixels)                 -> Self;
    fn trim_bottom_edge(amount: Pixels)              -> Self;
    fn set_resolution(res: ImageResolution)          -> Self;
    fn no_operation()                                -> Self;
}

pub trait RunOperation {
    fn run_operation(op: Self) -> OperationResults;
}

trait CompileOperation<OpType, Op> where Op: ElementaryPageOperations {
    fn compile_operation(op: OpType) -> Op;
}

impl<Op> CompileOperation<PageOps, Op> for Op where Op: ElementaryPageOperations {
    fn compile_operation(op: PageOps) -> Op {
        match op {
            PageOps::Identify(file, path)     => Op::identify(file, path),
            PageOps::Rescale(amount, dir)     => Op::rescale(amount, dir),
            PageOps::ExpandLeftEdge(amount)   => Op::expand_left_edge(amount),
            PageOps::ExpandRightEdge(amount)  => Op::expand_right_edge(amount),
            PageOps::ExpandTopEdge(amount)    => Op::expand_top_edge(amount),
            PageOps::ExpandBottomEdge(amount) => Op::expand_bottom_edge(amount),
            PageOps::TrimLeftEdge(amount)     => Op::trim_left_edge(amount),
            PageOps::TrimRightEdge(amount)    => Op::trim_right_edge(amount),
            PageOps::TrimTopEdge(amount)      => Op::trim_top_edge(amount),
            PageOps::TrimBottomEdge(amount)   => Op::trim_bottom_edge(amount),
            PageOps::SetResolution(res)       => Op::set_resolution(res),
            PageOps::NoOperation              => Op::no_operation(),
        }
    }
}

#[derive(Clone)]
struct CompoundPageOperation {
    page_name: FileName,
    page_path: FilePath,
    ops: Option<Vec<PageOps>>,
}

impl CompoundPageOperation {
    fn new(page_name: FileName, page_path: FilePath, ops: &[PageOps]) -> CompoundPageOperation {

        if ops.is_empty() {
            return CompoundPageOperation {
                page_name: page_name,
                page_path: page_path,
                ops: None,
            };
        }

        let mut vec = Vec::new();
        for op in ops.iter() {
            vec.push(op.clone());
        }

        CompoundPageOperation {
            page_name: page_name,
            page_path: page_path,
            ops: Some(vec),
        }
    }

    fn make_noop() -> CompoundPageOperation {
        CompoundPageOperation {
            page_name: String::from(""),
            page_path: String::from(""),
            ops: None,
        }
    }

    fn is_noop(&self) -> bool {
        match self.ops {
            Some(ref vec) => vec.is_empty(),
            None          => true,
        }
    }

    fn run_operation<Op>(&self) -> OperationResults
        where Op: ElementaryPageOperations + RunOperation + CompileOperation<PageOps, Op> {

        match self.ops {
            None      => {
                OperationResults::from(Ok(String::from("No Operation")))
            }
            Some(ref vec) => {
                if self.is_noop() {
                    // Should not happen.
                    unreachable!();
                    //return Ok(String::from("No Operation"));
                }

                let mut result = Ok(String::from(""));
                for op in vec.iter() {
                    let op_results = Op::run_operation(Op::compile_operation(op.clone()));
                    for res in op_results.results {
                        match res {
                            Ok(s) => {
                                continue;
                            }
                            Err(e) => {
                                // Fail fast if there is an error.
                                result = Err(e);
                                break;
                            }
                        }
                    }
                }

                OperationResults::from(result)
            }
        }
    }

}

impl<Op> CompileOperation<CompoundPageOperation, Op> for Op
    where Op: ElementaryPageOperations + CompileOperation<CompoundPageOperation, Op> {

    fn compile_operation(comp_op: CompoundPageOperation) -> Op {
        unimplemented!();
    }

}

#[derive(Clone, Eq)]
struct Page {
    file_name: FileName,
    file_extension: ImageFileFormat,
    file_path: FilePath,
    dimensions: ImageDimensions,
    resolution: ImageResolution,
}

impl Page {
    fn new  (
            file_name: FileName,
            file_extension: ImageFileFormat,
            file_path: FilePath,
            dimensions: ImageDimensions,
            resolution: ImageResolution
            ) -> Page
    {
        Page {
            file_name: file_name,
            file_extension: file_extension,
            file_path: file_path,
            dimensions: dimensions,
            resolution: resolution,
        }
    }
}

impl PartialEq for Page {
    fn eq(&self, other: &Page) -> bool {
            self.file_name      == other.file_name
        &&  self.file_extension == other.file_extension
        &&  self.file_path      == other.file_path
        &&  self.dimensions     == other.dimensions
        &&  self.resolution     == other.resolution
    }
}

impl Hash for Page {
    fn hash<H>(&self, state: &mut H) where H: Hasher {

        self.file_name.hash(state);
        self.file_extension.hash(state);
        self.file_path.hash(state);
        self.dimensions.hash(state);
        self.resolution.hash(state);
    }
}

pub type OperationResult = IoResult<String>;

pub struct OperationResults {
    results: Vec<OperationResult>,
}

impl OperationResults {
    pub fn new() -> OperationResults {
        OperationResults {
            results: Vec::new(),
        }
    }

    pub fn push(&mut self, result: OperationResult) {
        self.results.push(result);
    }

    pub fn append(&mut self, other: &mut OperationResults) {
        self.results.append(&mut other.results);
    }

}

impl From<Vec<OperationResult>> for OperationResults {
    fn from(vec: Vec<OperationResult>) -> OperationResults {
        unimplemented!();
    }
}

/// Destructive conversion from a mutable vector of OperationResult
/// to simplify the process of returning results from running operations.
impl<'a> From<&'a mut Vec<OperationResult>> for OperationResults {
    fn from(vec: &mut Vec<OperationResult>) -> OperationResults {
        let mut results = Vec::new();
        results.append(vec);

        OperationResults {
            results: results,
        }
    }
}

/// Generates an OperationResults struct from a single OperationResult.
/// For compatibility between operations that may return multiple results
/// and ones that may return only one result.
impl From<OperationResult> for OperationResults {
    fn from(op_res: OperationResult) -> OperationResults {
        let mut results = Vec::new();
        results.push(op_res);

        OperationResults {
            results: results
        }
    }
}

struct OperationPlan {
    schedule: HashMap<Page, CompoundPageOperation>,
}

#[derive(Clone, Eq, PartialEq)]
enum OperationScheduleError {
    LengthMismatch,
}

impl OperationPlan {
    fn new() -> OperationPlan {
        OperationPlan {
            schedule: HashMap::new(),
        }
    }

    fn add_operation(&mut self, page: Page, op: CompoundPageOperation) {
        self.schedule.insert(page, op);
    }

    fn build_schedule(pages: &[Page], ops: &[CompoundPageOperation]) -> Result<Self, OperationScheduleError> {
        if pages.len() == ops.len() {

            let mut schedule = OperationPlan::new();

            for page_number in 0..pages.len() {
                schedule.add_operation(pages[page_number].clone(), ops[page_number].clone());
            }

            Ok(schedule)

        } else {
            Err(OperationScheduleError::LengthMismatch)
        }

    }

    fn iter(&self) -> OpPlanIter {
        OpPlanIter {
            inner: self.schedule.iter()
        }
    }

    fn run_operation<Op>(&self) -> OperationResults
        where Op: ElementaryPageOperations + RunOperation + CompileOperation<PageOps, Op> {

        let mut results = OperationResults::new();

        for (page, op) in self {

            match op.ops {
                None => {
                    continue;
                }
                Some(ref operations) => {
                    for elem_op in operations {
                        let compiled_op = Op::compile_operation(elem_op.clone());
                        let mut result = Op::run_operation(compiled_op);
                        results.append(&mut result);
                    }
                }
            }

        }

        results
    }
}

/// Iterator implementation for OperationPlan.
struct OpPlanIter<'a> {
    inner:  hash_map::Iter<'a, Page, CompoundPageOperation>
}

impl<'a> Iterator for OpPlanIter<'a> {
    type Item = (&'a Page, &'a CompoundPageOperation);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }

}

/// IntoIterator implementation for OperationPlan.
impl<'a> IntoIterator for &'a OperationPlan {
    type Item = (&'a Page, &'a CompoundPageOperation);
    type IntoIter = OpPlanIter<'a>;

    fn into_iter(self) -> OpPlanIter<'a> {
        self.iter()
    }
}

struct OpPlanIntoIter {
    inner: hash_map::IntoIter<Page, CompoundPageOperation>,
}

impl IntoIterator for OperationPlan {
    type Item = (Page, CompoundPageOperation);
    type IntoIter = OpPlanIntoIter;

    fn into_iter(self) -> OpPlanIntoIter {
        OpPlanIntoIter {
            inner: self.schedule.into_iter()
        }
    }
}

impl Iterator for OpPlanIntoIter {
    type Item = (Page, CompoundPageOperation);

    fn next(&mut self) -> Option<(Page, CompoundPageOperation)> {
        self.inner.next()
    }
}

struct OperationPlanResult {
    results: HashMap<Page, OperationResults>,
}

impl OperationPlanResult {
    fn new() -> OperationPlanResult {
        OperationPlanResult {
            results: HashMap::new(),
        }
    }

    fn insert(&mut self, page: Page, res: OperationResults) {
        self.results.insert(page, res);
    }

    fn iter(&self) -> OpPlanResultIter {
        OpPlanResultIter {
            inner: self.results.iter()
        }
    }
}

struct OpPlanResultIter<'a> {
    inner: hash_map::Iter<'a, Page, OperationResults>,
}

impl<'a> Iterator for OpPlanResultIter<'a> {
    type Item = (&'a Page, &'a OperationResults);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }
}

/// IntoIterator implementation for OpPlanResultIter.
impl<'a> IntoIterator for &'a OperationPlanResult {
    type Item = (&'a Page, &'a OperationResults);
    type IntoIter = OpPlanResultIter<'a>;

    fn into_iter(self) -> OpPlanResultIter<'a> {
        self.iter()
    }
}

struct OpPlanResultIntoIter {
    inner: hash_map::IntoIter<Page, OperationResults>,
}

impl IntoIterator for OperationPlanResult {
    type Item = (Page, OperationResults);
    type IntoIter = OpPlanResultIntoIter;

    fn into_iter(self) -> OpPlanResultIntoIter {
        OpPlanResultIntoIter {
            inner: self.results.into_iter()
        }
    }
}

impl Iterator for OpPlanResultIntoIter {
    type Item = (Page, OperationResults);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }
}
<commit_msg>Add Aborted error to OperationPlanError.<commit_after>#![allow(dead_code)]
use std::io::Result as IoResult;
use std::result::Result;
use std::iter::{Iterator, IntoIterator};
use std::collections::HashMap;
use std::collections::hash_map;
use std::vec::Vec;
use std::cmp::{Eq, PartialEq};
use std::hash::{Hash, Hasher};
use std::convert::From;

pub type Pixels = usize;
pub type FileName = String;
pub type FilePath = String;

#[derive(Clone, Eq, PartialEq, Hash)]
pub enum ResolutionUnits {
    PixelsPerInch,
    PixelsPerCentimeter,
}

#[derive(Clone, Eq, PartialEq, Hash)]
pub enum Direction {
    Horizontal,
    Vertical,
}

#[derive(Clone, Eq, PartialEq, Hash)]
pub enum ImageFileFormat {
    TIFF,
    PNG,
    JPEG,
    UNKNOWN,
}

#[derive(Clone, Eq, PartialEq, Hash)]
struct ImageDimensions {
    x_pixels: Pixels,
    y_pixels: Pixels,
}

impl ImageDimensions {
    fn new(x: Pixels, y: Pixels) -> ImageDimensions {
        ImageDimensions {
            x_pixels: x,
            y_pixels: y,
        }
    }
}

#[derive(Clone, Eq, PartialEq, Hash)]
pub struct ImageResolution {
    amount: Pixels,
    units: ResolutionUnits,
}

impl ImageResolution {
    fn new(amount: usize, units: ResolutionUnits) -> ImageResolution {
        ImageResolution {
            amount: amount,
            units: units,
        }
    }
}

#[derive(Clone)]
pub enum PageOps {
    NoOperation,
    Identify(FileName, FilePath),
    Rescale(Pixels, Direction),
    ExpandLeftEdge(Pixels),
    ExpandRightEdge(Pixels),
    ExpandTopEdge(Pixels),
    ExpandBottomEdge(Pixels),
    TrimLeftEdge(Pixels),
    TrimRightEdge(Pixels),
    TrimTopEdge(Pixels),
    TrimBottomEdge(Pixels),
    SetResolution(ImageResolution),
}

pub trait ElementaryPageOperations {
    fn identify(file_name: FileName, path: FilePath) -> Self;
    fn rescale(amount: Pixels, dir: Direction)       -> Self;
    fn expand_left_edge(amount: Pixels)              -> Self;
    fn expand_right_edge(amount: Pixels)             -> Self;
    fn expand_top_edge(amount: Pixels)               -> Self;
    fn expand_bottom_edge(amount: Pixels)            -> Self;
    fn trim_left_edge(amount: Pixels)                -> Self;
    fn trim_right_edge(amount: Pixels)               -> Self;
    fn trim_top_edge(amount: Pixels)                 -> Self;
    fn trim_bottom_edge(amount: Pixels)              -> Self;
    fn set_resolution(res: ImageResolution)          -> Self;
    fn no_operation()                                -> Self;
}

pub trait RunOperation {
    fn run_operation(op: Self) -> OperationResults;
}

trait CompileOperation<OpType, Op> where Op: ElementaryPageOperations {
    fn compile_operation(op: OpType) -> Op;
    //fn apply_operation(&self, op: Op)   -> ();
}

impl<Op> CompileOperation<PageOps, Op> for Op where Op: ElementaryPageOperations {
    fn compile_operation(op: PageOps) -> Op {
        match op {
            PageOps::Identify(file, path)     => Op::identify(file, path),
            PageOps::Rescale(amount, dir)     => Op::rescale(amount, dir),
            PageOps::ExpandLeftEdge(amount)   => Op::expand_left_edge(amount),
            PageOps::ExpandRightEdge(amount)  => Op::expand_right_edge(amount),
            PageOps::ExpandTopEdge(amount)    => Op::expand_top_edge(amount),
            PageOps::ExpandBottomEdge(amount) => Op::expand_bottom_edge(amount),
            PageOps::TrimLeftEdge(amount)     => Op::trim_left_edge(amount),
            PageOps::TrimRightEdge(amount)    => Op::trim_right_edge(amount),
            PageOps::TrimTopEdge(amount)      => Op::trim_top_edge(amount),
            PageOps::TrimBottomEdge(amount)   => Op::trim_bottom_edge(amount),
            PageOps::SetResolution(res)       => Op::set_resolution(res),
            PageOps::NoOperation              => Op::no_operation(),
        }
    }
}

#[derive(Clone)]
struct CompoundPageOperation {
    page_name: FileName,
    page_path: FilePath,
    ops: Option<Vec<PageOps>>,
}

impl CompoundPageOperation {
    fn new(page_name: FileName, page_path: FilePath, ops: &[PageOps]) -> CompoundPageOperation {

        if ops.is_empty() {
            return CompoundPageOperation {
                page_name: page_name,
                page_path: page_path,
                ops: None,
            };
        }

        let mut vec = Vec::new();
        for op in ops.iter() {
            vec.push(op.clone());
        }

        CompoundPageOperation {
            page_name: page_name,
            page_path: page_path,
            ops: Some(vec),
        }
    }

    fn make_noop() -> CompoundPageOperation {
        CompoundPageOperation {
            page_name: String::from(""),
            page_path: String::from(""),
            ops: None,
        }
    }

    fn is_noop(&self) -> bool {
        match self.ops {
            Some(ref vec) => vec.is_empty(),
            None          => true,
        }
    }

    fn run_operation<Op>(&self) -> OperationResults
        where Op: ElementaryPageOperations + RunOperation + CompileOperation<PageOps, Op> {

        match self.ops {
            None      => {
                OperationResults::from(Ok(String::from("No Operation")))
            }
            Some(ref vec) => {
                if self.is_noop() {
                    // Should not happen.
                    unreachable!();
                    //return Ok(String::from("No Operation"));
                }

                let mut result = Ok(String::from(""));
                for op in vec.iter() {
                    let op_results = Op::run_operation(Op::compile_operation(op.clone()));
                    for res in op_results.results {
                        match res {
                            Ok(s) => {
                                continue;
                            }
                            Err(e) => {
                                // Fail fast if there is an error.
                                result = Err(e);
                                break;
                            }
                        }
                    }
                }

                OperationResults::from(result)
            }
        }
    }

}

#[derive(Clone, Eq)]
struct Page {
    file_name: FileName,
    file_extension: ImageFileFormat,
    file_path: FilePath,
    dimensions: ImageDimensions,
    resolution: ImageResolution,
}

impl Page {
    fn new  (
            file_name: FileName,
            file_extension: ImageFileFormat,
            file_path: FilePath,
            dimensions: ImageDimensions,
            resolution: ImageResolution
            ) -> Page
    {
        Page {
            file_name: file_name,
            file_extension: file_extension,
            file_path: file_path,
            dimensions: dimensions,
            resolution: resolution,
        }
    }
}

impl PartialEq for Page {
    fn eq(&self, other: &Page) -> bool {
            self.file_name      == other.file_name
        &&  self.file_extension == other.file_extension
        &&  self.file_path      == other.file_path
        &&  self.dimensions     == other.dimensions
        &&  self.resolution     == other.resolution
    }
}

impl Hash for Page {
    fn hash<H>(&self, state: &mut H) where H: Hasher {

        self.file_name.hash(state);
        self.file_extension.hash(state);
        self.file_path.hash(state);
        self.dimensions.hash(state);
        self.resolution.hash(state);
    }
}

pub type OperationResult = IoResult<String>;

pub struct OperationResults {
    results: Vec<OperationResult>,
}

impl OperationResults {
    pub fn new() -> OperationResults {
        OperationResults {
            results: Vec::new(),
        }
    }

    pub fn push(&mut self, result: OperationResult) {
        self.results.push(result);
    }

    pub fn append(&mut self, other: &mut OperationResults) {
        self.results.append(&mut other.results);
    }

}

impl From<Vec<OperationResult>> for OperationResults {
    fn from(vec: Vec<OperationResult>) -> OperationResults {
        unimplemented!();
    }
}

/// Destructive conversion from a mutable vector of OperationResult
/// to simplify the process of returning results from running operations.
impl<'a> From<&'a mut Vec<OperationResult>> for OperationResults {
    fn from(vec: &mut Vec<OperationResult>) -> OperationResults {
        let mut results = Vec::new();
        results.append(vec);

        OperationResults {
            results: results,
        }
    }
}

/// Generates an OperationResults struct from a single OperationResult.
/// For compatibility between operations that may return multiple results
/// and ones that may return only one result.
impl From<OperationResult> for OperationResults {
    fn from(op_res: OperationResult) -> OperationResults {
        let mut results = Vec::new();
        results.push(op_res);

        OperationResults {
            results: results
        }
    }
}

struct OperationPlan {
    schedule: HashMap<Page, CompoundPageOperation>,
}

#[derive(Clone, Eq, PartialEq)]
enum OperationPlanError {
    LengthMismatch,
    Aborted,
}

impl OperationPlan {
    fn new() -> OperationPlan {
        OperationPlan {
            schedule: HashMap::new(),
        }
    }

    fn add_operation(&mut self, page: Page, op: CompoundPageOperation) {
        self.schedule.insert(page, op);
    }

    fn build_schedule(pages: &[Page], ops: &[CompoundPageOperation]) -> Result<Self, OperationPlanError> {
        if pages.len() == ops.len() {

            let mut schedule = OperationPlan::new();

            for page_number in 0..pages.len() {
                schedule.add_operation(pages[page_number].clone(), ops[page_number].clone());
            }

            Ok(schedule)

        } else {
            Err(OperationPlanError::LengthMismatch)
        }

    }

    fn iter(&self) -> OpPlanIter {
        OpPlanIter {
            inner: self.schedule.iter()
        }
    }

    fn run_operation<Op>(&self) -> OperationResults
        where Op: ElementaryPageOperations + RunOperation + CompileOperation<PageOps, Op> {

        let mut results = OperationResults::new();

        for (page, op) in self {

            match op.ops {
                None => {
                    continue;
                }
                Some(ref operations) => {
                    for elem_op in operations {
                        let compiled_op = Op::compile_operation(elem_op.clone());
                        let mut result = Op::run_operation(compiled_op);
                        results.append(&mut result);
                    }
                }
            }

        }

        results
    }
}

/// Iterator implementation for OperationPlan.
struct OpPlanIter<'a> {
    inner:  hash_map::Iter<'a, Page, CompoundPageOperation>
}

impl<'a> Iterator for OpPlanIter<'a> {
    type Item = (&'a Page, &'a CompoundPageOperation);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }

}

/// IntoIterator implementation for OperationPlan.
impl<'a> IntoIterator for &'a OperationPlan {
    type Item = (&'a Page, &'a CompoundPageOperation);
    type IntoIter = OpPlanIter<'a>;

    fn into_iter(self) -> OpPlanIter<'a> {
        self.iter()
    }
}

struct OpPlanIntoIter {
    inner: hash_map::IntoIter<Page, CompoundPageOperation>,
}

impl IntoIterator for OperationPlan {
    type Item = (Page, CompoundPageOperation);
    type IntoIter = OpPlanIntoIter;

    fn into_iter(self) -> OpPlanIntoIter {
        OpPlanIntoIter {
            inner: self.schedule.into_iter()
        }
    }
}

impl Iterator for OpPlanIntoIter {
    type Item = (Page, CompoundPageOperation);

    fn next(&mut self) -> Option<(Page, CompoundPageOperation)> {
        self.inner.next()
    }
}

struct OperationPlanResult {
    results: HashMap<Page, OperationResults>,
}

impl OperationPlanResult {
    fn new() -> OperationPlanResult {
        OperationPlanResult {
            results: HashMap::new(),
        }
    }

    fn insert(&mut self, page: Page, res: OperationResults) {
        self.results.insert(page, res);
    }

    fn iter(&self) -> OpPlanResultIter {
        OpPlanResultIter {
            inner: self.results.iter()
        }
    }
}

struct OpPlanResultIter<'a> {
    inner: hash_map::Iter<'a, Page, OperationResults>,
}

impl<'a> Iterator for OpPlanResultIter<'a> {
    type Item = (&'a Page, &'a OperationResults);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }
}

/// IntoIterator implementation for OpPlanResultIter.
impl<'a> IntoIterator for &'a OperationPlanResult {
    type Item = (&'a Page, &'a OperationResults);
    type IntoIter = OpPlanResultIter<'a>;

    fn into_iter(self) -> OpPlanResultIter<'a> {
        self.iter()
    }
}

struct OpPlanResultIntoIter {
    inner: hash_map::IntoIter<Page, OperationResults>,
}

impl IntoIterator for OperationPlanResult {
    type Item = (Page, OperationResults);
    type IntoIter = OpPlanResultIntoIter;

    fn into_iter(self) -> OpPlanResultIntoIter {
        OpPlanResultIntoIter {
            inner: self.results.into_iter()
        }
    }
}

impl Iterator for OpPlanResultIntoIter {
    type Item = (Page, OperationResults);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }
}
<|endoftext|>


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

//! Runtime calls emitted by the compiler.

use cast::transmute;
use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int};
use managed::raw::BoxRepr;
use str;
use sys;
use unstable::exchange_alloc;
use cast::transmute;

#[allow(non_camel_case_types)]
pub type rust_task = c_void;

#[cfg(target_word_size = "32")]
pub static FROZEN_BIT: uint = 0x80000000;
#[cfg(target_word_size = "64")]
pub static FROZEN_BIT: uint = 0x8000000000000000;

pub mod rustrt {
    use libc::{c_char, uintptr_t};

    pub extern {
        #[rust_stack]
        unsafe fn rust_upcall_malloc(td: *c_char, size: uintptr_t) -> *c_char;

        #[rust_stack]
        unsafe fn rust_upcall_free(ptr: *c_char);
    }
}

#[lang="fail_"]
pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
    sys::begin_unwind_(expr, file, line);
}

#[lang="fail_bounds_check"]
pub unsafe fn fail_bounds_check(file: *c_char, line: size_t,
                                index: size_t, len: size_t) {
    let msg = fmt!("index out of bounds: the len is %d but the index is %d",
                    len as int, index as int);
    do str::as_buf(msg) |p, _len| {
        fail_(p as *c_char, file, line);
    }
}

pub unsafe fn fail_borrowed() {
    let msg = "borrowed";
    do str::as_buf(msg) |msg_p, _| {
        do str::as_buf("???") |file_p, _| {
            fail_(msg_p as *c_char, file_p as *c_char, 0);
        }
    }
}

// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
#[lang="exchange_malloc"]
pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
    transmute(exchange_alloc::malloc(transmute(td), transmute(size)))
}

// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[lang="exchange_free"]
pub unsafe fn exchange_free(ptr: *c_char) {
    exchange_alloc::free(transmute(ptr))
}

#[lang="malloc"]
pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
    return rustrt::rust_upcall_malloc(td, size);
}

// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[lang="free"]
pub unsafe fn local_free(ptr: *c_char) {
    rustrt::rust_upcall_free(ptr);
}

#[lang="borrow_as_imm"]
#[inline(always)]
pub unsafe fn borrow_as_imm(a: *u8) {
    let a: *mut BoxRepr = transmute(a);
    (*a).header.ref_count |= FROZEN_BIT;
}

#[lang="return_to_mut"]
#[inline(always)]
pub unsafe fn return_to_mut(a: *u8) {
    let a: *mut BoxRepr = transmute(a);
    (*a).header.ref_count &= !FROZEN_BIT;
}

#[lang="check_not_borrowed"]
#[inline(always)]
pub unsafe fn check_not_borrowed(a: *u8) {
    let a: *mut BoxRepr = transmute(a);
    if ((*a).header.ref_count & FROZEN_BIT) != 0 {
        fail_borrowed();
    }
}

#[lang="strdup_uniq"]
pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str {
    str::raw::from_buf_len(ptr, len)
}

#[lang="start"]
pub fn start(main: *u8, argc: int, argv: *c_char,
             crate_map: *u8) -> int {
    use libc::getenv;
    use rt::start;

    unsafe {
        let use_new_rt = do str::as_c_str("RUST_NEWRT") |s| {
            getenv(s).is_null()
        };
        if use_new_rt {
            return rust_start(main as *c_void, argc as c_int, argv,
                              crate_map as *c_void) as int;
        } else {
            return start(main, argc, argv, crate_map);
        }
    }

    extern {
        fn rust_start(main: *c_void, argc: c_int, argv: *c_char,
                      crate_map: *c_void) -> c_int;
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Check for null in return_to_mut.  Fixes #4904.<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Runtime calls emitted by the compiler.

use cast::transmute;
use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int};
use managed::raw::BoxRepr;
use str;
use sys;
use unstable::exchange_alloc;
use cast::transmute;

#[allow(non_camel_case_types)]
pub type rust_task = c_void;

#[cfg(target_word_size = "32")]
pub static FROZEN_BIT: uint = 0x80000000;
#[cfg(target_word_size = "64")]
pub static FROZEN_BIT: uint = 0x8000000000000000;

pub mod rustrt {
    use libc::{c_char, uintptr_t};

    pub extern {
        #[rust_stack]
        unsafe fn rust_upcall_malloc(td: *c_char, size: uintptr_t) -> *c_char;

        #[rust_stack]
        unsafe fn rust_upcall_free(ptr: *c_char);
    }
}

#[lang="fail_"]
pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
    sys::begin_unwind_(expr, file, line);
}

#[lang="fail_bounds_check"]
pub unsafe fn fail_bounds_check(file: *c_char, line: size_t,
                                index: size_t, len: size_t) {
    let msg = fmt!("index out of bounds: the len is %d but the index is %d",
                    len as int, index as int);
    do str::as_buf(msg) |p, _len| {
        fail_(p as *c_char, file, line);
    }
}

pub unsafe fn fail_borrowed() {
    let msg = "borrowed";
    do str::as_buf(msg) |msg_p, _| {
        do str::as_buf("???") |file_p, _| {
            fail_(msg_p as *c_char, file_p as *c_char, 0);
        }
    }
}

// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
#[lang="exchange_malloc"]
pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
    transmute(exchange_alloc::malloc(transmute(td), transmute(size)))
}

// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[lang="exchange_free"]
pub unsafe fn exchange_free(ptr: *c_char) {
    exchange_alloc::free(transmute(ptr))
}

#[lang="malloc"]
pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
    return rustrt::rust_upcall_malloc(td, size);
}

// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[lang="free"]
pub unsafe fn local_free(ptr: *c_char) {
    rustrt::rust_upcall_free(ptr);
}

#[lang="borrow_as_imm"]
#[inline(always)]
pub unsafe fn borrow_as_imm(a: *u8) {
    let a: *mut BoxRepr = transmute(a);
    (*a).header.ref_count |= FROZEN_BIT;
}

#[lang="return_to_mut"]
#[inline(always)]
pub unsafe fn return_to_mut(a: *u8) {
    // Sometimes the box is null, if it is conditionally frozen.
    // See e.g. #4904.
    if !a.is_null() {
        let a: *mut BoxRepr = transmute(a);
        (*a).header.ref_count &= !FROZEN_BIT;
    }
}

#[lang="check_not_borrowed"]
#[inline(always)]
pub unsafe fn check_not_borrowed(a: *u8) {
    let a: *mut BoxRepr = transmute(a);
    if ((*a).header.ref_count & FROZEN_BIT) != 0 {
        fail_borrowed();
    }
}

#[lang="strdup_uniq"]
pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str {
    str::raw::from_buf_len(ptr, len)
}

#[lang="start"]
pub fn start(main: *u8, argc: int, argv: *c_char,
             crate_map: *u8) -> int {
    use libc::getenv;
    use rt::start;

    unsafe {
        let use_new_rt = do str::as_c_str("RUST_NEWRT") |s| {
            getenv(s).is_null()
        };
        if use_new_rt {
            return rust_start(main as *c_void, argc as c_int, argv,
                              crate_map as *c_void) as int;
        } else {
            return start(main, argc, argv, crate_map);
        }
    }

    extern {
        fn rust_start(main: *c_void, argc: c_int, argv: *c_char,
                      crate_map: *c_void) -> c_int;
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


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

#[doc(primitive = "bool")]
//
/// The boolean type.
///
mod prim_bool { }

#[doc(primitive = "char")]
//
/// A Unicode scalar value.
///
/// A `char` represents a
/// *[Unicode scalar
/// value](http://www.unicode.org/glossary/#unicode_scalar_value)*, as it can
/// contain any Unicode code point except high-surrogate and low-surrogate code
/// points.
///
/// As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\]
/// (inclusive) are allowed. A `char` can always be safely cast to a `u32`;
/// however the converse is not always true due to the above range limits
/// and, as such, should be performed via the `from_u32` function.
///
/// *[See also the `std::char` module](char/index.html).*
///
mod prim_char { }

#[doc(primitive = "unit")]
//
/// The `()` type, sometimes called "unit" or "nil".
///
/// The `()` type has exactly one value `()`, and is used when there
/// is no other meaningful value that could be returned. `()` is most
/// commonly seen implicitly: functions without a `-> ...` implicitly
/// have return type `()`, that is, these are equivalent:
///
/// ```rust
/// fn long() -> () {}
///
/// fn short() {}
/// ```
///
/// The semicolon `;` can be used to discard the result of an
/// expression at the end of a block, making the expression (and thus
/// the block) evaluate to `()`. For example,
///
/// ```rust
/// fn returns_i64() -> i64 {
///     1i64
/// }
/// fn returns_unit() {
///     1i64;
/// }
///
/// let is_i64 = {
///     returns_i64()
/// };
/// let is_unit = {
///     returns_i64();
/// };
/// ```
///
mod prim_unit { }

#[doc(primitive = "pointer")]
//
/// Raw, unsafe pointers, `*const T`, and `*mut T`.
///
/// Working with raw pointers in Rust is uncommon,
/// typically limited to a few patterns.
///
/// Use the `null` function to create null pointers, and the `is_null` method
/// of the `*const T` type  to check for null. The `*const T` type also defines
/// the `offset` method, for pointer math.
///
/// # Common ways to create raw pointers
///
/// ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`).
///
/// ```
/// let my_num: i32 = 10;
/// let my_num_ptr: *const i32 = &my_num;
/// let mut my_speed: i32 = 88;
/// let my_speed_ptr: *mut i32 = &mut my_speed;
/// ```
///
/// To get a pointer to a boxed value, dereference the box:
///
/// ```
/// let my_num: Box<i32> = Box::new(10);
/// let my_num_ptr: *const i32 = &*my_num;
/// let mut my_speed: Box<i32> = Box::new(88);
/// let my_speed_ptr: *mut i32 = &mut *my_speed;
/// ```
///
/// This does not take ownership of the original allocation
/// and requires no resource management later,
/// but you must not use the pointer after its lifetime.
///
/// ## 2. Consume a box (`Box<T>`).
///
/// The `into_raw` function consumes a box and returns
/// the raw pointer. It doesn't destroy `T` or deallocate any memory.
///
/// ```
/// let my_speed: Box<i32> = Box::new(88);
/// let my_speed: *mut i32 = Box::into_raw(my_speed);
///
/// // By taking ownership of the original `Box<T>` though
/// // we are obligated to put it together later to be destroyed.
/// unsafe {
///     drop(Box::from_raw(my_speed));
/// }
/// ```
///
/// Note that here the call to `drop` is for clarity - it indicates
/// that we are done with the given value and it should be destroyed.
///
/// ## 3. Get it from C.
///
/// ```
/// # #![feature(libc)]
/// extern crate libc;
///
/// use std::mem;
///
/// fn main() {
///     unsafe {
///         let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>() as libc::size_t) as *mut i32;
///         if my_num.is_null() {
///             panic!("failed to allocate memory");
///         }
///         libc::free(my_num as *mut libc::c_void);
///     }
/// }
/// ```
///
/// Usually you wouldn't literally use `malloc` and `free` from Rust,
/// but C APIs hand out a lot of pointers generally, so are a common source
/// of raw pointers in Rust.
///
/// *[See also the `std::ptr` module](ptr/index.html).*
///
mod prim_pointer { }

#[doc(primitive = "array")]
//
/// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and
/// the non-negative compile time constant size, `N`.
///
/// Arrays values are created either with an explicit expression that lists
/// each element: `[x, y, z]` or a repeat expression: `[x; N]`. The repeat
/// expression requires that the element type is `Copy`.
///
/// The type `[T; N]` is `Copy` if `T: Copy`.
///
/// Arrays of sizes from 0 to 32 (inclusive) implement the following traits
/// if the element type allows it:
///
/// - `Clone`
/// - `Debug`
/// - `IntoIterator` (implemented for `&[T; N]` and `&mut [T; N]`)
/// - `PartialEq`, `PartialOrd`, `Ord`, `Eq`
/// - `Hash`
/// - `AsRef`, `AsMut`
///
/// Arrays dereference to [slices (`[T]`)][slice], so their methods can be called
/// on arrays.
///
/// [slice]: primitive.slice.html
///
/// Rust does not currently support generics over the size of an array type.
///
/// # Examples
///
/// ```
/// let mut array: [i32; 3] = [0; 3];
///
/// array[1] = 1;
/// array[2] = 2;
///
/// assert_eq!([1, 2], &array[1..]);
///
/// // This loop prints: 0 1 2
/// for x in &array {
///     print!("{} ", x);
/// }
///
/// ```
///
mod prim_array { }

#[doc(primitive = "slice")]
//
/// A dynamically-sized view into a contiguous sequence, `[T]`.
///
/// Slices are a view into a block of memory represented as a pointer and a
/// length.
///
/// ```
/// // slicing a Vec
/// let vec = vec![1, 2, 3];
/// let int_slice = &vec[..];
/// // coercing an array to a slice
/// let str_slice: &[&str] = &["one", "two", "three"];
/// ```
///
/// Slices are either mutable or shared. The shared slice type is `&[T]`,
/// while the mutable slice type is `&mut [T]`, where `T` represents the element
/// type. For example, you can mutate the block of memory that a mutable slice
/// points to:
///
/// ```
/// let x = &mut [1, 2, 3];
/// x[1] = 7;
/// assert_eq!(x, &[1, 7, 3]);
/// ```
///
/// *[See also the `std::slice` module](slice/index.html).*
///
mod prim_slice { }

#[doc(primitive = "str")]
//
/// Unicode string slices.
///
/// Rust's `str` type is one of the core primitive types of the language. `&str`
/// is the borrowed string type. This type of string can only be created from
/// other strings, unless it is a `&'static str` (see below). It is not possible
/// to move out of borrowed strings because they are owned elsewhere.
///
/// # Examples
///
/// Here's some code that uses a `&str`:
///
/// ```
/// let s = "Hello, world.";
/// ```
///
/// This `&str` is a `&'static str`, which is the type of string literals.
/// They're `'static` because literals are available for the entire lifetime of
/// the program.
///
/// You can get a non-`'static` `&str` by taking a slice of a `String`:
///
/// ```
/// let some_string = "Hello, world.".to_string();
/// let s = &some_string;
/// ```
///
/// # Representation
///
/// Rust's string type, `str`, is a sequence of Unicode scalar values encoded as
/// a stream of UTF-8 bytes. All [strings](../../reference.html#literals) are
/// guaranteed to be validly encoded UTF-8 sequences. Additionally, strings are
/// not null-terminated and can thus contain null bytes.
///
/// The actual representation of `str`s have direct mappings to slices: `&str`
/// is the same as `&[u8]`.
///
/// *[See also the `std::str` module](str/index.html).*
///
mod prim_str { }

#[doc(primitive = "tuple")]
//
/// A finite heterogeneous sequence, `(T, U, ..)`.
///
/// To access the _N_-th element of a tuple one can use `N` itself
/// as a field of the tuple.
///
/// Indexing starts from zero, so `0` returns first value, `1`
/// returns second value, and so on. In general, a tuple with _S_
/// elements provides aforementioned fields from `0` to `S-1`.
///
/// If every type inside a tuple implements one of the following
/// traits, then a tuple itself also implements it.
///
/// * `Clone`
/// * `PartialEq`
/// * `Eq`
/// * `PartialOrd`
/// * `Ord`
/// * `Debug`
/// * `Default`
/// * `Hash`
///
/// # Examples
///
/// Accessing elements of a tuple at specified indices:
///
/// ```
/// let x = ("colorless",  "green", "ideas", "sleep", "furiously");
/// assert_eq!(x.3, "sleep");
///
/// let v = (3, 3);
/// let u = (1, -5);
/// assert_eq!(v.0 * u.0 + v.1 * u.1, -12);
/// ```
///
/// Using traits implemented for tuples:
///
/// ```
/// let a = (1, 2);
/// let b = (3, 4);
/// assert!(a != b);
///
/// let c = b.clone();
/// assert!(b == c);
///
/// let d : (u32, f32) = Default::default();
/// assert_eq!(d, (0, 0.0f32));
/// ```
///
mod prim_tuple { }

#[doc(primitive = "f32")]
/// The 32-bit floating point type.
///
/// *[See also the `std::f32` module](f32/index.html).*
///
mod prim_f32 { }

#[doc(primitive = "f64")]
//
/// The 64-bit floating point type.
///
/// *[See also the `std::f64` module](f64/index.html).*
///
mod prim_f64 { }

#[doc(primitive = "i8")]
//
/// The 8-bit signed integer type.
///
/// *[See also the `std::i8` module](i8/index.html).*
///
mod prim_i8 { }

#[doc(primitive = "i16")]
//
/// The 16-bit signed integer type.
///
/// *[See also the `std::i16` module](i16/index.html).*
///
mod prim_i16 { }

#[doc(primitive = "i32")]
//
/// The 32-bit signed integer type.
///
/// *[See also the `std::i32` module](i32/index.html).*
///
mod prim_i32 { }

#[doc(primitive = "i64")]
//
/// The 64-bit signed integer type.
///
/// *[See also the `std::i64` module](i64/index.html).*
///
mod prim_i64 { }

#[doc(primitive = "u8")]
//
/// The 8-bit unsigned integer type.
///
/// *[See also the `std::u8` module](u8/index.html).*
///
mod prim_u8 { }

#[doc(primitive = "u16")]
//
/// The 16-bit unsigned integer type.
///
/// *[See also the `std::u16` module](u16/index.html).*
///
mod prim_u16 { }

#[doc(primitive = "u32")]
//
/// The 32-bit unsigned integer type.
///
/// *[See also the `std::u32` module](u32/index.html).*
///
mod prim_u32 { }

#[doc(primitive = "u64")]
//
/// The 64-bit unsigned integer type.
///
/// *[See also the `std::u64` module](u64/index.html).*
///
mod prim_u64 { }

#[doc(primitive = "isize")]
//
/// The pointer-sized signed integer type.
///
/// *[See also the `std::isize` module](isize/index.html).*
///
mod prim_isize { }

#[doc(primitive = "usize")]
//
/// The pointer-sized unsigned integer type.
///
/// *[See also the `std::usize` module](usize/index.html).*
///
mod prim_usize { }

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

#[doc(primitive = "bool")]
//
/// The boolean type.
///
mod prim_bool { }

#[doc(primitive = "char")]
//
/// A Unicode scalar value.
///
/// A `char` represents a
/// *[Unicode scalar
/// value](http://www.unicode.org/glossary/#unicode_scalar_value)*, as it can
/// contain any Unicode code point except high-surrogate and low-surrogate code
/// points.
///
/// As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\]
/// (inclusive) are allowed. A `char` can always be safely cast to a `u32`;
/// however the converse is not always true due to the above range limits
/// and, as such, should be performed via the `from_u32` function.
///
/// *[See also the `std::char` module](char/index.html).*
///
mod prim_char { }

#[doc(primitive = "unit")]
//
/// The `()` type, sometimes called "unit" or "nil".
///
/// The `()` type has exactly one value `()`, and is used when there
/// is no other meaningful value that could be returned. `()` is most
/// commonly seen implicitly: functions without a `-> ...` implicitly
/// have return type `()`, that is, these are equivalent:
///
/// ```rust
/// fn long() -> () {}
///
/// fn short() {}
/// ```
///
/// The semicolon `;` can be used to discard the result of an
/// expression at the end of a block, making the expression (and thus
/// the block) evaluate to `()`. For example,
///
/// ```rust
/// fn returns_i64() -> i64 {
///     1i64
/// }
/// fn returns_unit() {
///     1i64;
/// }
///
/// let is_i64 = {
///     returns_i64()
/// };
/// let is_unit = {
///     returns_i64();
/// };
/// ```
///
mod prim_unit { }

#[doc(primitive = "pointer")]
//
/// Raw, unsafe pointers, `*const T`, and `*mut T`.
///
/// Working with raw pointers in Rust is uncommon,
/// typically limited to a few patterns.
///
/// Use the `null` function to create null pointers, and the `is_null` method
/// of the `*const T` type  to check for null. The `*const T` type also defines
/// the `offset` method, for pointer math.
///
/// # Common ways to create raw pointers
///
/// ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`).
///
/// ```
/// let my_num: i32 = 10;
/// let my_num_ptr: *const i32 = &my_num;
/// let mut my_speed: i32 = 88;
/// let my_speed_ptr: *mut i32 = &mut my_speed;
/// ```
///
/// To get a pointer to a boxed value, dereference the box:
///
/// ```
/// let my_num: Box<i32> = Box::new(10);
/// let my_num_ptr: *const i32 = &*my_num;
/// let mut my_speed: Box<i32> = Box::new(88);
/// let my_speed_ptr: *mut i32 = &mut *my_speed;
/// ```
///
/// This does not take ownership of the original allocation
/// and requires no resource management later,
/// but you must not use the pointer after its lifetime.
///
/// ## 2. Consume a box (`Box<T>`).
///
/// The `into_raw` function consumes a box and returns
/// the raw pointer. It doesn't destroy `T` or deallocate any memory.
///
/// ```
/// let my_speed: Box<i32> = Box::new(88);
/// let my_speed: *mut i32 = Box::into_raw(my_speed);
///
/// // By taking ownership of the original `Box<T>` though
/// // we are obligated to put it together later to be destroyed.
/// unsafe {
///     drop(Box::from_raw(my_speed));
/// }
/// ```
///
/// Note that here the call to `drop` is for clarity - it indicates
/// that we are done with the given value and it should be destroyed.
///
/// ## 3. Get it from C.
///
/// ```
/// # #![feature(libc)]
/// extern crate libc;
///
/// use std::mem;
///
/// fn main() {
///     unsafe {
///         let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>() as libc::size_t) as *mut i32;
///         if my_num.is_null() {
///             panic!("failed to allocate memory");
///         }
///         libc::free(my_num as *mut libc::c_void);
///     }
/// }
/// ```
///
/// Usually you wouldn't literally use `malloc` and `free` from Rust,
/// but C APIs hand out a lot of pointers generally, so are a common source
/// of raw pointers in Rust.
///
/// *[See also the `std::ptr` module](ptr/index.html).*
///
mod prim_pointer { }

#[doc(primitive = "array")]
//
/// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and
/// the non-negative compile time constant size, `N`.
///
/// Arrays values are created either with an explicit expression that lists
/// each element: `[x, y, z]` or a repeat expression: `[x; N]`. The repeat
/// expression requires that the element type is `Copy`.
///
/// The type `[T; N]` is `Copy` if `T: Copy`.
///
/// Arrays of sizes from 0 to 32 (inclusive) implement the following traits
/// if the element type allows it:
///
/// - `Clone` (only if `T: Copy`)
/// - `Debug`
/// - `IntoIterator` (implemented for `&[T; N]` and `&mut [T; N]`)
/// - `PartialEq`, `PartialOrd`, `Ord`, `Eq`
/// - `Hash`
/// - `AsRef`, `AsMut`
/// - `Borrow`, `BorrowMut`
/// - `Default`
///
/// Arrays dereference to [slices (`[T]`)][slice], so their methods can be called
/// on arrays.
///
/// [slice]: primitive.slice.html
///
/// Rust does not currently support generics over the size of an array type.
///
/// # Examples
///
/// ```
/// let mut array: [i32; 3] = [0; 3];
///
/// array[1] = 1;
/// array[2] = 2;
///
/// assert_eq!([1, 2], &array[1..]);
///
/// // This loop prints: 0 1 2
/// for x in &array {
///     print!("{} ", x);
/// }
///
/// ```
///
mod prim_array { }

#[doc(primitive = "slice")]
//
/// A dynamically-sized view into a contiguous sequence, `[T]`.
///
/// Slices are a view into a block of memory represented as a pointer and a
/// length.
///
/// ```
/// // slicing a Vec
/// let vec = vec![1, 2, 3];
/// let int_slice = &vec[..];
/// // coercing an array to a slice
/// let str_slice: &[&str] = &["one", "two", "three"];
/// ```
///
/// Slices are either mutable or shared. The shared slice type is `&[T]`,
/// while the mutable slice type is `&mut [T]`, where `T` represents the element
/// type. For example, you can mutate the block of memory that a mutable slice
/// points to:
///
/// ```
/// let x = &mut [1, 2, 3];
/// x[1] = 7;
/// assert_eq!(x, &[1, 7, 3]);
/// ```
///
/// *[See also the `std::slice` module](slice/index.html).*
///
mod prim_slice { }

#[doc(primitive = "str")]
//
/// Unicode string slices.
///
/// Rust's `str` type is one of the core primitive types of the language. `&str`
/// is the borrowed string type. This type of string can only be created from
/// other strings, unless it is a `&'static str` (see below). It is not possible
/// to move out of borrowed strings because they are owned elsewhere.
///
/// # Examples
///
/// Here's some code that uses a `&str`:
///
/// ```
/// let s = "Hello, world.";
/// ```
///
/// This `&str` is a `&'static str`, which is the type of string literals.
/// They're `'static` because literals are available for the entire lifetime of
/// the program.
///
/// You can get a non-`'static` `&str` by taking a slice of a `String`:
///
/// ```
/// let some_string = "Hello, world.".to_string();
/// let s = &some_string;
/// ```
///
/// # Representation
///
/// Rust's string type, `str`, is a sequence of Unicode scalar values encoded as
/// a stream of UTF-8 bytes. All [strings](../../reference.html#literals) are
/// guaranteed to be validly encoded UTF-8 sequences. Additionally, strings are
/// not null-terminated and can thus contain null bytes.
///
/// The actual representation of `str`s have direct mappings to slices: `&str`
/// is the same as `&[u8]`.
///
/// *[See also the `std::str` module](str/index.html).*
///
mod prim_str { }

#[doc(primitive = "tuple")]
//
/// A finite heterogeneous sequence, `(T, U, ..)`.
///
/// To access the _N_-th element of a tuple one can use `N` itself
/// as a field of the tuple.
///
/// Indexing starts from zero, so `0` returns first value, `1`
/// returns second value, and so on. In general, a tuple with _S_
/// elements provides aforementioned fields from `0` to `S-1`.
///
/// If every type inside a tuple implements one of the following
/// traits, then a tuple itself also implements it.
///
/// * `Clone`
/// * `PartialEq`
/// * `Eq`
/// * `PartialOrd`
/// * `Ord`
/// * `Debug`
/// * `Default`
/// * `Hash`
///
/// # Examples
///
/// Accessing elements of a tuple at specified indices:
///
/// ```
/// let x = ("colorless",  "green", "ideas", "sleep", "furiously");
/// assert_eq!(x.3, "sleep");
///
/// let v = (3, 3);
/// let u = (1, -5);
/// assert_eq!(v.0 * u.0 + v.1 * u.1, -12);
/// ```
///
/// Using traits implemented for tuples:
///
/// ```
/// let a = (1, 2);
/// let b = (3, 4);
/// assert!(a != b);
///
/// let c = b.clone();
/// assert!(b == c);
///
/// let d : (u32, f32) = Default::default();
/// assert_eq!(d, (0, 0.0f32));
/// ```
///
mod prim_tuple { }

#[doc(primitive = "f32")]
/// The 32-bit floating point type.
///
/// *[See also the `std::f32` module](f32/index.html).*
///
mod prim_f32 { }

#[doc(primitive = "f64")]
//
/// The 64-bit floating point type.
///
/// *[See also the `std::f64` module](f64/index.html).*
///
mod prim_f64 { }

#[doc(primitive = "i8")]
//
/// The 8-bit signed integer type.
///
/// *[See also the `std::i8` module](i8/index.html).*
///
mod prim_i8 { }

#[doc(primitive = "i16")]
//
/// The 16-bit signed integer type.
///
/// *[See also the `std::i16` module](i16/index.html).*
///
mod prim_i16 { }

#[doc(primitive = "i32")]
//
/// The 32-bit signed integer type.
///
/// *[See also the `std::i32` module](i32/index.html).*
///
mod prim_i32 { }

#[doc(primitive = "i64")]
//
/// The 64-bit signed integer type.
///
/// *[See also the `std::i64` module](i64/index.html).*
///
mod prim_i64 { }

#[doc(primitive = "u8")]
//
/// The 8-bit unsigned integer type.
///
/// *[See also the `std::u8` module](u8/index.html).*
///
mod prim_u8 { }

#[doc(primitive = "u16")]
//
/// The 16-bit unsigned integer type.
///
/// *[See also the `std::u16` module](u16/index.html).*
///
mod prim_u16 { }

#[doc(primitive = "u32")]
//
/// The 32-bit unsigned integer type.
///
/// *[See also the `std::u32` module](u32/index.html).*
///
mod prim_u32 { }

#[doc(primitive = "u64")]
//
/// The 64-bit unsigned integer type.
///
/// *[See also the `std::u64` module](u64/index.html).*
///
mod prim_u64 { }

#[doc(primitive = "isize")]
//
/// The pointer-sized signed integer type.
///
/// *[See also the `std::isize` module](isize/index.html).*
///
mod prim_isize { }

#[doc(primitive = "usize")]
//
/// The pointer-sized unsigned integer type.
///
/// *[See also the `std::usize` module](usize/index.html).*
///
mod prim_usize { }

<|endoftext|>


<commit_before>#![feature(no_std,core_intrinsics)]
#![no_std]

#[macro_export]
macro_rules! impl_fmt
{
	(@as_item $($i:item)*) => {$($i)*};

	($( /*$(<($($params:tt)+)>)* */ $tr:ident($s:ident, $f:ident) for $t:ty { $($code:stmt)*} )+) => {
		$(impl_from!{ @as_item
			impl/*$(<$($params)+>)* */ ::std::fmt::$tr for $t {
				fn fmt(&$s, $f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
					$( $code )*
				}
			}
		})+
		};
}

#[macro_export]
macro_rules! impl_from {
	(@as_item $($i:item)*) => {$($i)*};

	($( $(<($($params:tt)+)>)* From<$src:ty>($v:ident) for $t:ty { $($code:stmt)*} )+) => {
		$(impl_from!{ @as_item
			impl$(<$($params)+>)* ::std::convert::From<$src> for $t {
				fn from($v: $src) -> $t {
					$($code)*
				}
			}
		})+
	};
}

pub fn type_name<T: ?::core::marker::Sized>() -> &'static str {
	// SAFE: Intrinsic with no sideeffect
	unsafe { ::core::intrinsics::type_name::<T>() }
}
#[macro_export]
macro_rules! type_name {
	($t:ty) => ( $crate::type_name::<$t>() );
}

#[macro_export]
macro_rules! todo
{
	( $s:expr ) => ( panic!( concat!("TODO: ",$s) ) );
	( $s:expr, $($v:tt)* ) => ( panic!( concat!("TODO: ",$s), $($v)* ) );
}

/// Override libcore's `try!` macro with one that backs onto `From`
#[macro_export]
macro_rules! try {
	($e:expr) => (
		match $e {
		Ok(v) => v,
		Err(e) => return Err(From::from(e)),
		}
		);
}
<commit_msg>Usermode/libmacros - Common convert trait macro<commit_after>#![feature(no_std,core_intrinsics)]
#![no_std]

#[macro_export]
macro_rules! impl_fmt
{
	(@as_item $($i:item)*) => {$($i)*};

	($( /*$(<($($params:tt)+)>)* */ $tr:ident($s:ident, $f:ident) for $t:ty { $($code:stmt)*} )+) => {
		$(impl_from!{ @as_item
			impl/*$(<$($params)+>)* */ ::std::fmt::$tr for $t {
				fn fmt(&$s, $f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
					$( $code )*
				}
			}
		})+
		};
}

#[macro_export]
macro_rules! impl_conv {
	(@as_item $($i:item)*) => {$($i)*};

	(@match_ $( $(<($($params:tt)+)>)* From<$src:ty>($v:ident) for $t:ty { $($code:stmt)*} )+) => {
		$(impl_from!{ @as_item
			impl$(<$($params)+>)* ::std::convert::From<$src> for $t {
				fn from($v: $src) -> $t {
					$($code)*
				}
			}
		})+
	};
	(@match_ $( $(<($($params:tt)+)>)* Into<$dst:ty>($self_:ident) for $t:ty { $($code:stmt)*} )+) => {
		$(impl_from!{ @as_item
			impl$(<$($params)+>)* ::std::convert::Into<$dst> for $t {
				fn into($self_) -> $dst {
					$($code)*
				}
			}
		})+
	};
	(@match_ $( $(<($($params:tt)+)>)* AsRef<$dst:ty>($self_:ident) for $t:ty { $($code:stmt)*} )+) => {
		$(impl_from!{ @as_item
			impl$(<$($params)+>)* ::std::convert::AsRef<$dst> for $t {
				fn as_ref($self_) -> &$dst {
					$($code)*
				}
			}
		})+
	};

	($( $(<($($params:tt)+)>)* $name:ident<$src:ty>($v:ident) for $t:ty { $($code:stmt)*} )+) => {
		$(impl_conv!{ @match_ $(<($($params:tt)+)>)* $name<$src>($v) for $t { $($code)* } })+
	};
}

#[macro_export]
macro_rules! impl_from {
	(@as_item $($i:item)*) => {$($i)*};

	($( $(<($($params:tt)+)>)* From<$src:ty>($v:ident) for $t:ty { $($code:stmt)*} )+) => {
		$(impl_from!{ @as_item
			impl$(<$($params)+>)* ::std::convert::From<$src> for $t {
				fn from($v: $src) -> $t {
					$($code)*
				}
			}
		})+
	};
}

pub fn type_name<T: ?::core::marker::Sized>() -> &'static str {
	// SAFE: Intrinsic with no sideeffect
	unsafe { ::core::intrinsics::type_name::<T>() }
}
#[macro_export]
macro_rules! type_name {
	($t:ty) => ( $crate::type_name::<$t>() );
}

#[macro_export]
macro_rules! todo
{
	( $s:expr ) => ( panic!( concat!("TODO: ",$s) ) );
	( $s:expr, $($v:tt)* ) => ( panic!( concat!("TODO: ",$s), $($v)* ) );
}

/// Override libcore's `try!` macro with one that backs onto `From`
#[macro_export]
macro_rules! try {
	($e:expr) => (
		match $e {
		Ok(v) => v,
		Err(e) => return Err(From::from(e)),
		}
		);
}
<|endoftext|>


<commit_before>use super::super::StreamId;
use super::frames::{
    Frame,
    Flag,
    parse_padded_payload,
    pack_header,
    RawFrame,
    FrameHeader
};

/// An enum representing the flags that a `ContinuationFrame` can have.
/// The integer representation associated to each variant is that flag's
/// bitmask.
///
/// HTTP/2 spec, section 6.10.
#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
#[derive(Copy)]
pub enum ContinuationFlag {
    EndHeaders = 0x4,
}

impl Flag for ContinuationFlag {
    #[inline]
    fn bitmask(&self) -> u8 {
        *self as u8
    }
}

/// A struct representing the CONTINUATION frame for HTTP/2, as defined in the
/// HTTP/2 spec, section 6.10.
pub struct ContinuationFrame {
    /// The header block fragment bytes stored within the frame.
    pub header_fragment: Vec<u8>,
    /// The ID of the stream with which this frame is associated
    pub stream_id: StreamId,
    /// The set of flags for the frame, packed into a single byte.
    flags: u8,
}

impl ContinuationFrame {
    /// Creates a new `ContinuationFrame` with the given header fragment and stream
    /// ID. No flags are set.
    pub fn new(fragment: Vec<u8>, stream_id: StreamId) -> ContinuationFrame {
        ContinuationFrame {
            header_fragment: fragment,
            stream_id: stream_id,
            flags: 0,
        }
    }

    /// Returns whether this frame ends the headers. If not, there MUST be a
    /// number of follow up CONTINUATION frames that send the rest of the
    /// header data.
    pub fn is_headers_end(&self) -> bool {
        self.is_set(ContinuationFlag::EndHeaders)
    }

    /// Returns the length of the payload of the current frame, including any
    /// possible padding in the number of bytes.
    fn payload_len(&self) -> u32 {
        self.header_fragment.len() as u32
    }
}

impl Frame for ContinuationFrame {
    /// The type that represents the flags that the particular `Frame` can take.
    /// This makes sure that only valid `Flag`s are used with each `Frame`.
    type FlagType = ContinuationFlag;

    /// Creates a new `ContinuationFrame` with the given `RawFrame` (i.e. header and
    /// payload), if possible.
    ///
    /// # Returns
    ///
    /// `None` if a valid `ContinuationFrame` cannot be constructed from the given
    /// `RawFrame`. The stream ID *must not* be 0.
    ///
    /// Otherwise, returns a newly constructed `ContinuationFrame`.
    fn from_raw(raw_frame: RawFrame) -> Option<ContinuationFrame> {
        // Unpack the header
        let (len, frame_type, flags, stream_id) = raw_frame.header;
        // Check that the frame type is correct for this frame implementation
        if frame_type != 0x9 {
            return None;
        }
        // Check that the length given in the header matches the payload
        // length; if not, something went wrong and we do not consider this a
        // valid frame.
        if (len as usize) != raw_frame.payload.len() {
            return None;
        }
        // Check that the CONTINUATION frame is not associated to stream 0
        if stream_id == 0 {
            return None;
        }

        let payload = &raw_frame.payload[..];

        Some(ContinuationFrame {
            header_fragment: &raw_frame.payload[..],
            stream_id: stream_id,
            flags: flags
        })
    }
}
<commit_msg>finished continuation frames, not integrated into other frames yet<commit_after>use super::super::StreamId;
use super::frames::{
    Frame,
    Flag,
    parse_padded_payload,
    pack_header,
    RawFrame,
    FrameHeader
};

/// An enum representing the flags that a `ContinuationFrame` can have.
/// The integer representation associated to each variant is that flag's
/// bitmask.
///
/// HTTP/2 spec, section 6.10.
#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
#[derive(Copy)]
pub enum ContinuationFlag {
    EndHeaders = 0x4,
}

impl Flag for ContinuationFlag {
    #[inline]
    fn bitmask(&self) -> u8 {
        *self as u8
    }
}

/// A struct representing the CONTINUATION frame for HTTP/2, as defined in the
/// HTTP/2 spec, section 6.10.
pub struct ContinuationFrame {
    /// The header block fragment bytes stored within the frame.
    pub header_fragment: Vec<u8>,
    /// The ID of the stream with which this frame is associated
    pub stream_id: StreamId,
    /// The set of flags for the frame, packed into a single byte.
    flags: u8,
}

impl ContinuationFrame {
    /// Creates a new `ContinuationFrame` with the given header fragment and stream
    /// ID. No flags are set.
    pub fn new(fragment: Vec<u8>, stream_id: StreamId) -> ContinuationFrame {
        ContinuationFrame {
            header_fragment: fragment,
            stream_id: stream_id,
            flags: 0,
        }
    }

    /// Returns whether this frame ends the headers. If not, there MUST be a
    /// number of follow up CONTINUATION frames that send the rest of the
    /// header data.
    pub fn is_headers_end(&self) -> bool {
        self.is_set(ContinuationFlag::EndHeaders)
    }

    /// Returns the length of the payload of the current frame, including any
    /// possible padding in the number of bytes.
    fn payload_len(&self) -> u32 {
        self.header_fragment.len() as u32
    }
}

impl Frame for ContinuationFrame {
    /// The type that represents the flags that the particular `Frame` can take.
    /// This makes sure that only valid `Flag`s are used with each `Frame`.
    type FlagType = ContinuationFlag;

    /// Creates a new `ContinuationFrame` with the given `RawFrame` (i.e. header and
    /// payload), if possible.
    ///
    /// # Returns
    ///
    /// `None` if a valid `ContinuationFrame` cannot be constructed from the given
    /// `RawFrame`. The stream ID *must not* be 0.
    ///
    /// Otherwise, returns a newly constructed `ContinuationFrame`.
    fn from_raw(raw_frame: RawFrame) -> Option<ContinuationFrame> {
        // Unpack the header
        let (len, frame_type, flags, stream_id) = raw_frame.header;
        // Check that the frame type is correct for this frame implementation
        if frame_type != 0x9 {
            return None;
        }
        // Check that the length given in the header matches the payload
        // length; if not, something went wrong and we do not consider this a
        // valid frame.
        if (len as usize) != raw_frame.payload.len() {
            return None;
        }
        // Check that the CONTINUATION frame is not associated to stream 0
        if stream_id == 0 {
            return None;
        }

        let payload = &raw_frame.payload[..];

        Some(ContinuationFrame {
            header_fragment: &raw_frame.payload[..],
            stream_id: stream_id,
            flags: flags
        })
    }

    /// Tests if the given flag is set for the frame.
    fn is_set(&self, flag: ContinuationFlag) -> bool {
        (self.flags & flag.bitmask()) != 0
    }

    // Returns the `StreamId` of the stream to which the frame is associated.
    ///
    /// A `SettingsFrame` always has to be associated to stream `0`.
    fn get_stream_id(&self) -> StreamId {
        self.stream_id
    }

    /// Returns a `FrameHeader` based on the current state of the `Frame`.
    fn get_header(&self) -> FrameHeader {
        (self.payload_len(), 0x9, self.flags, self.stream_id)
    }

    /// Sets the given flag for the frame.
    fn set_flag(&mut self, flag: ContinuationFlag) {
        self.flags |= flag.bitmask();
    }

    /// Returns a `Vec` with the serialized representation of the frame.
    fn serialize(&self) -> Vec<u8> {
        let mut buf = Vec::with_capacity(self.payload_len() as usize);
        // First the header...
        buf.extend(pack_header(&self.get_header()).to_vec().into_iter());
        // Now the actual headers fragment
        buf.extend(self.header_fragment.clone().into_iter());

        buf
    }
}
<|endoftext|>