<commit_before>// Copyright (c) 2013-2014 Michael Dvorkin
// Ante is an esoteric programming language where all you've got is a deck of cards.
//
// This is Ante implementation in Rust.

extern crate regex;
extern crate num;

use std::io::File;
use std::collections::HashMap;
use std::num::Zero;
use std::num::from_int;
use std::str::{is_utf8, from_utf8};
use std::char::{from_u32};
use std::os;
use regex::Regex;
use num::bigint::BigInt;

const A: uint = 'A' as uint;
const J: uint = 'J' as uint;
const Q: uint = 'Q' as uint;
const K: uint = 'K' as uint;
const D: uint = '♦' as uint;
const H: uint = '♥' as uint;
const S: uint = '♠' as uint;
const C: uint = '♣' as uint;

struct Card {
    rank: uint,
    suit: uint
}

struct Ante {
    pc:     uint,                   // Program counter (index within ante.code)
    line:   uint,                   // Current line number.
    code:   Vec<Card>,              // Array of cards.
    vars:   HashMap<uint, BigInt>,  // Four registers hashed by suit.
    labels: HashMap<uint, uint>,    // Labels for ante.pc to jump to.
    buffer: Vec<u8>                 // Buffer to collect UTF-8 character bytes.
}

impl Ante {
    fn new(filename: &str) -> Ante {
        let code = Ante::parse(filename);
        let labels = Ante::resolve(&code);
        let mut vars: HashMap<uint, BigInt> = HashMap::new();
        vars.insert(D, Ante::big(0));
        vars.insert(H, Ante::big(0));
        vars.insert(S, Ante::big(0));
        vars.insert(C, Ante::big(0));

        Ante {
            pc:     0,
            line:   0,
            code:   code,
            vars:   vars,
            labels: labels,
            buffer: vec![]
        }
    }

    fn run(&mut self) -> &Ante {
        while self.pc < self.code.len() {
            let card = self.code[self.pc];
            self.pc += 1;
            match card.rank {
                0u  => self.newline(card),
                K   => self.jump(card),
                Q   => continue,
                J   => self.dump(card, true),
                10u => self.dump(card, false),
                _   => self.assign(card)
            };
        }
        self
    }

    // Turn source file into array of cards.
    fn parse(filename: &str) -> Vec<Card> {
        let mut file = match File::open(&Path::new(filename)) {
            // The `desc` field of `IoError` is a string that describes the error.
            Err(reason) => fail!("couldn't open {} ({})", filename, reason.desc),
            Ok(file) => file,
        };
        let program = file.read_to_string().unwrap();

        // Split program blob into lines getting rid of comments and whitespaces.
        let comments = Regex::new(r"#.*$").unwrap();
        let lines: Vec<String> = program.as_slice().lines().map( |line|
            comments.replace_all(line, "").as_slice().trim().to_string()
        ).collect();

        // Turn source file into array of cards. Each card a struct of rank and suit.
        let mut code: Vec<Card> = vec![];
        let card = Regex::new(r"(10|[2-9JQKA])([♦♥♠♣])").unwrap();
        for (i, line) in lines.iter().enumerate() {
            // Line number cards have zero rank.
            code.push(Card { rank: 0, suit: i + 1 });

            // Parse lines to turn them into array of cards.
            for caps in card.captures_iter(line.as_slice()) {
                let rank = caps.at(1).char_at(0);
                let suit = caps.at(2).char_at(0);
                let card = match rank {
                   '1'       => Card { rank: 10, suit: suit as uint },
                   '2'...'9' => Card { rank: rank as uint - 48, suit: suit as uint },
                   _         => Card { rank: rank as uint, suit: suit as uint }
                };
                code.push(card);
            }
        }
        code
    }

    // Extra pass to set up jump labels.
    fn resolve(code: &Vec<Card>) -> HashMap<uint, uint> {
        let mut pc = 0u;
        let mut labels: HashMap<uint, uint> = HashMap::new();

        while pc < code.len() - 1 {
            let card = code[pc];
            pc += 1;
            if card.rank == Q {
                let mut queen = card.suit as uint;
                while pc < code.len() && code[pc].rank == Q && code[pc].suit == card.suit {
                    queen += card.suit as uint;
                    pc += 1;
                }
                labels.insert(queen, pc);
            }
        }
        labels
    }

    fn newline(&mut self, card: Card) -> &Ante {
        self.line = card.suit as uint;
        self
    }

    fn jump(&mut self, card: Card) -> &Ante {
        let mut suit = card.suit as uint;
        while self.pc < self.code.len() && self.code[self.pc].rank == K && self.code[self.pc].suit == card.suit {
            suit += card.suit as uint;
            self.pc += 1;
        }

        if !self.vars[card.suit].is_zero() {
            let label = suit as uint;
            if self.labels.contains_key(&label) {
                self.pc = self.labels[label];
            } else {
                let label = format!("Q{:c}", from_u32(card.suit as u32).unwrap());
                self.exception(format!("can't find {} to go to", label.repeat(suit / card.suit)).as_slice());
            }
        }
        self
    }

    fn assign(&mut self, card: Card) -> &Ante {
        let operands = self.remaining(card);
        self.expression(operands)
    }

    fn dump(&mut self, card: Card, as_character: bool) -> &Ante {
        let value = self.vars[card.suit].clone();
        if as_character {
            if value < Ante::big(0) || value > Ante::big(255) {
                self.exception(format!("character code {} is not in 0..255 range", value).as_slice());
            } else {
                // Collect the bytes till we have full UTF-8 character.
                // Once the character is built dump it and reset the buffer.
                self.buffer.push(value.to_u8().unwrap());
                if is_utf8(self.buffer.as_slice()) {
                    print!("{}", from_utf8(self.buffer.as_slice()).unwrap());
                    self.buffer = vec![];
                }
            }
        } else {
            print!("{}", value);
        }
        self
    }

    fn remaining(&mut self, card: Card) -> Vec<Card> {
        let mut operands: Vec<Card> = vec![card];

        while self.pc < self.code.len() {
            let card = self.code[self.pc];
            if card.rank == 0 || card.rank == K || card.rank == Q || card.rank == J {
                break;
            }
            operands.push(card);
            self.pc += 1;
        }
        operands
    }

    fn expression(&mut self, operands: Vec<Card>) -> &Ante {
        let mut initial: BigInt = Ante::big(operands[0].rank as int);
        let target = operands[0].suit;

        if initial.to_uint().unwrap() == A {
            initial = self.vars[target].clone();
        }

        for i in range(1, operands.len()) {
            let mut rank = Ante::big(operands[i].rank as int);
            let suit = operands[i].suit;

            if rank.to_uint().unwrap() == A {
                rank = self.vars[suit].clone();
            }

            match suit {
                D => { initial = initial.add(&rank) },
                H => { initial = initial.mul(&rank) },
                S => { initial = initial.sub(&rank) },
                C => if !rank.is_zero() {
                        initial = initial.div(&rank);
                     } else {
                        self.exception("division by zero");
                     },
                _ => continue
            }
        }

        *self.vars.get_mut(&target) = initial;
        self
    }

    fn big(n: int) -> BigInt {
        from_int::<BigInt>(n).unwrap()
    }

    // NOTE: fail! got renamed to panic!
    fn exception(&self, message: &str) {
        fail!("Ante exception: {} on line {} (pc:{})\n", message, self.line, self.pc)
    }
}

fn main() {
    if os::args().len() == 2 {
        Ante::new(os::args()[1].as_slice()).run();
    } else {
        println!("usage: ante filename.ante");
    }
}
<commit_msg>Better names<commit_after>// Copyright (c) 2014-2015 Michael Dvorkin
// Ante is an esoteric programming language where all you've got is a deck of cards.
//
// This is Ante implementation in Rust.

extern crate regex;
extern crate num;

use std::io::File;
use std::collections::HashMap;
use std::num::Zero;
use std::num::from_int;
use std::str::{is_utf8, from_utf8};
use std::char::{from_u32};
use std::os;
use regex::Regex;
use num::bigint::BigInt;

const ACE:      uint = 'A' as uint;
const JACK:     uint = 'J' as uint;
const QUEEN:    uint = 'Q' as uint;
const KING:     uint = 'K' as uint;
const DIAMONDS: uint = '♦' as uint;
const HEARTS:   uint = '♥' as uint;
const SPADES:   uint = '♠' as uint;
const CLUBS:    uint = '♣' as uint;

struct Card {
    rank: uint,
    suit: uint
}

struct Ante {
    pc:     uint,                   // Program counter (index within ante.code)
    line:   uint,                   // Current line number.
    code:   Vec<Card>,              // Array of cards.
    vars:   HashMap<uint, BigInt>,  // Four registers hashed by suit.
    labels: HashMap<uint, uint>,    // Labels for ante.pc to jump to.
    buffer: Vec<u8>                 // Buffer to collect UTF-8 character bytes.
}

impl Ante {
    fn new(filename: &str) -> Ante {
        let code = Ante::parse(filename);
        let labels = Ante::resolve(&code);
        let mut vars: HashMap<uint, BigInt> = HashMap::new();
        vars.insert(DIAMONDS, Ante::big(0));
        vars.insert(HEARTS, Ante::big(0));
        vars.insert(SPADES, Ante::big(0));
        vars.insert(CLUBS, Ante::big(0));

        Ante {
            pc:     0,
            line:   0,
            code:   code,
            vars:   vars,
            labels: labels,
            buffer: vec![]
        }
    }

    fn run(&mut self) -> &Ante {
        while self.pc < self.code.len() {
            let card = self.code[self.pc];
            self.pc += 1;
            match card.rank {
                0u    => self.newline(card),
                10u   => self.dump(card, false),
                JACK  => self.dump(card, true),
                QUEEN => continue,
                KING  => self.jump(card),
                _     => self.assign(card)
            };
        }
        self
    }

    // Turn source file into array of cards.
    fn parse(filename: &str) -> Vec<Card> {
        let mut file = match File::open(&Path::new(filename)) {
            // The `desc` field of `IoError` is a string that describes the error.
            Err(reason) => fail!("couldn't open {} ({})", filename, reason.desc),
            Ok(file) => file,
        };
        let program = file.read_to_string().unwrap();

        // Split program blob into lines getting rid of comments and whitespaces.
        let comments = Regex::new(r"#.*$").unwrap();
        let lines: Vec<String> = program.as_slice().lines().map( |line|
            comments.replace_all(line, "").as_slice().trim().to_string()
        ).collect();

        // Turn source file into array of cards. Each card a struct of rank and suit.
        let mut code: Vec<Card> = vec![];
        let card = Regex::new(r"(10|[2-9JQKA])([♦♥♠♣])").unwrap();
        for (i, line) in lines.iter().enumerate() {
            // Line number cards have zero rank.
            code.push(Card { rank: 0, suit: i + 1 });

            // Parse lines to turn them into array of cards.
            for caps in card.captures_iter(line.as_slice()) {
                let rank = caps.at(1).char_at(0);
                let suit = caps.at(2).char_at(0);
                let card = match rank {
                   '1'       => Card { rank: 10, suit: suit as uint },
                   '2'...'9' => Card { rank: rank as uint - 48, suit: suit as uint },
                   _         => Card { rank: rank as uint, suit: suit as uint }
                };
                code.push(card);
            }
        }
        code
    }

    // Extra pass to set up jump labels.
    fn resolve(code: &Vec<Card>) -> HashMap<uint, uint> {
        let mut pc = 0u;
        let mut labels: HashMap<uint, uint> = HashMap::new();

        while pc < code.len() - 1 {
            let card = code[pc];
            pc += 1;
            if card.rank == QUEEN {
                let mut queen = card.suit as uint;
                while pc < code.len() && code[pc].rank == QUEEN && code[pc].suit == card.suit {
                    queen += card.suit as uint;
                    pc += 1;
                }
                labels.insert(queen, pc);
            }
        }
        labels
    }

    fn newline(&mut self, card: Card) -> &Ante {
        self.line = card.suit as uint;
        self
    }

    fn jump(&mut self, card: Card) -> &Ante {
        let mut suit = card.suit as uint;
        while self.pc < self.code.len() && self.code[self.pc].rank == KING && self.code[self.pc].suit == card.suit {
            suit += card.suit as uint;
            self.pc += 1;
        }

        if !self.vars[card.suit].is_zero() {
            let label = suit as uint;
            if self.labels.contains_key(&label) {
                self.pc = self.labels[label];
            } else {
                let label = format!("Q{:c}", from_u32(card.suit as u32).unwrap());
                self.exception(format!("can't find {} to go to", label.repeat(suit / card.suit)).as_slice());
            }
        }
        self
    }

    fn assign(&mut self, card: Card) -> &Ante {
        let operands = self.remaining(card);
        self.expression(operands)
    }

    fn dump(&mut self, card: Card, as_character: bool) -> &Ante {
        let value = self.vars[card.suit].clone();
        if as_character {
            if value < Ante::big(0) || value > Ante::big(255) {
                self.exception(format!("character code {} is not in 0..255 range", value).as_slice());
            } else {
                // Collect the bytes till we have full UTF-8 character.
                // Once the character is built dump it and reset the buffer.
                self.buffer.push(value.to_u8().unwrap());
                if is_utf8(self.buffer.as_slice()) {
                    print!("{}", from_utf8(self.buffer.as_slice()).unwrap());
                    self.buffer = vec![];
                }
            }
        } else {
            print!("{}", value);
        }
        self
    }

    fn remaining(&mut self, card: Card) -> Vec<Card> {
        let mut operands: Vec<Card> = vec![card];

        while self.pc < self.code.len() {
            let card = self.code[self.pc];
            if card.rank == 0 || card.rank == KING || card.rank == QUEEN || card.rank == JACK {
                break;
            }
            operands.push(card);
            self.pc += 1;
        }
        operands
    }

    fn expression(&mut self, operands: Vec<Card>) -> &Ante {
        let mut initial: BigInt = Ante::big(operands[0].rank as int);
        let target = operands[0].suit;

        if initial.to_uint().unwrap() == ACE {
            initial = self.vars[target].clone();
        }

        for i in range(1, operands.len()) {
            let mut rank = Ante::big(operands[i].rank as int);
            let suit = operands[i].suit;

            if rank.to_uint().unwrap() == ACE {
                rank = self.vars[suit].clone();
            }

            match suit {
                DIAMONDS => { initial = initial.add(&rank) },
                HEARTS   => { initial = initial.mul(&rank) },
                SPADES   => { initial = initial.sub(&rank) },
                CLUBS    => if !rank.is_zero() {
                                initial = initial.div(&rank);
                            } else {
                                self.exception("division by zero");
                            },
                _        => continue
            }
        }

        *self.vars.get_mut(&target) = initial;
        self
    }

    fn big(n: int) -> BigInt {
        from_int::<BigInt>(n).unwrap()
    }

    // NOTE: fail! got renamed to panic!
    fn exception(&self, message: &str) {
        fail!("Ante exception: {} on line {} (pc:{})\n", message, self.line, self.pc)
    }
}

fn main() {
    if os::args().len() == 2 {
        Ante::new(os::args()[1].as_slice()).run();
    } else {
        println!("usage: ante filename.ante");
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate porteurbars;

use clap::{App, SubCommand};
use porteurbars::Template;
use std::path::Path;

fn main() {

    let args = App::new("pb")
        .version(env!("CARGO_PKG_VERSION"))
        .about("portable git hosted project templates")
        .subcommand(SubCommand::with_name("apply")
            .about("applys template to provided data")
            .args_from_usage("-t, --target=[target] 'Target output directory. Defaults to \
                              current working directory'
                                     \
                              -d, --defaults=[defaults] 'Env file to load default names and \
                              values from. Defaults to default.env'
                                     \
                              -s, --src=[project] 'Project template src base path.Defaults to \
                              /src'
                                     <repo> 'git repository \
                              uri storing template src in full git uri form or github shorthand \
                              (user/repo)'"))
        .get_matches();

    let project = Template {
        target: Path::new(args.value_of("target").unwrap_or(".")),
        defaults: args.value_of("defaults").unwrap_or("default.env"),
        project: Path::new(args.value_of("project").unwrap_or(".")),
        repo: args.value_of("repo").unwrap(),
    };

    project.apply().unwrap();

    println!("off you go")
}
<commit_msg>use apply subcommand<commit_after>extern crate clap;
extern crate porteurbars;

use clap::{App, SubCommand};
use porteurbars::Template;
use std::path::Path;

fn main() {

    let args = App::new("pb")
        .version(env!("CARGO_PKG_VERSION"))
        .about("portable git hosted project templates")
        .subcommand(SubCommand::with_name("apply")
            .about("applys template to provided data")
            .args_from_usage("-t, --target=[target] 'Target output directory. Defaults to \
                              current working directory'
                                     \
                              -d, --defaults=[defaults] 'Env file to load default names and \
                              values from. Defaults to default.env'
                                     \
                              -s, --src=[project] 'Project template src base path.Defaults to \
                              /src'
                                     <repo> 'git repository \
                              uri storing template src in full git uri form or github shorthand \
                              (user/repo)'"))
        .get_matches();

    if let Some(args) = args.subcommand_matches("apply") {
        let project = Template {
            target: Path::new(args.value_of("target").unwrap_or(".")),
            defaults: args.value_of("defaults").unwrap_or("default.env"),
            project: Path::new(args.value_of("project").unwrap_or(".")),
            repo: args.value_of("repo").unwrap(),
        };

        project.apply().unwrap();

        println!("off you go")
    }

}
<|endoftext|>


<commit_before>use messages::outgoing;
use mio;
use node::Node;
use node;
use routing_table::{InsertOutcome, RoutingTable};
use routing_table;
use std::collections::HashMap;
use std::io::Cursor;
use std::thread;
use transaction::{TransactionId, TransactionIdGenerator};

pub enum ScheduledTask {
    ContinueBootstrap,
    ContinueHealthCheck
}

pub enum OneshotTask {
    Incoming(Vec<u8>),
    StartBootstrap
}

enum TableAction {
    Bootstrap(mio::Timeout),
    HealthCheck(mio::Timeout)
}

enum Status {
    Bootstrapping,
    Idle
}

pub struct Handler {
    port: u16,
    routing_table: RoutingTable,
    self_node: Box<node::Node + 'static>,
    transaction_ids: TransactionIdGenerator,
    status: Status,
    pending_actions: HashMap<TransactionId, TableAction>
}

impl Handler {
    pub fn new<N: node::Node + 'static>(self_node: N, port: u16, routers: Vec<Box<Node>>) -> Handler {
        let self_address = self_node.get_address();
        let routing_table = routing_table::RoutingTable::new(8, self_address, routers);

        Handler {
            port: port,
            routing_table: routing_table,
            self_node: Box::new(self_node),
            transaction_ids: TransactionIdGenerator::new(),
            status: Status::Idle,
            pending_actions: HashMap::new()
        }
    }

    pub fn run(mut self) {
        let mut event_loop = mio::EventLoop::new().unwrap();
        let loop_channel = event_loop.channel();

        create_incoming_udp_channel(self.port, loop_channel.clone());
        loop_channel.send(OneshotTask::StartBootstrap).unwrap();
        event_loop.run(&mut self).unwrap();
    }

    fn handle_incoming(&mut self, data: Vec<u8>, event_loop: &mut mio::EventLoop<Handler>) {
        use messages::incoming;
        use messages::incoming::*;
        let mut data = Cursor::new(data);
        let message = incoming::parse_from_reader(&mut data).unwrap();

        match message {
            Message::Query(transaction_id, origin, query) => {
                let origin_address = origin.get_address();
                match query {
                    Query::FindNode(target) => {
                        let response: Vec<u8> = outgoing::create_find_node_response(
                                transaction_id,
                                &self.self_node,
                                self.routing_table.nearest_to(&target, false));
                        origin.send(response);

                        self.routing_table.insert(origin).unwrap();
                        {
                            if let Some(origin) = self.routing_table.find_node(&origin_address) {
                                origin.received_query(transaction_id);
                            }
                        }
                    },
                    Query::Ping => {
                        let response = outgoing::create_ping_response(
                            transaction_id,
                            &self.self_node);
                        origin.send(response);

                        self.routing_table.insert(origin).unwrap();
                        if let Some(origin) = self.routing_table.find_node(&origin_address) {
                            origin.received_query(transaction_id);
                        }
                    }
                }
            }
            Message::Response(transaction_id, origin, response) => {
                let origin_address = origin.get_address();
                match response {
                    Response::FindNode(mut nodes) => {
                        let mut encounted_new_node = false;
                        let mut tail = vec![origin];
                        for node in nodes.drain(..).chain(tail.drain(..)) {
                            match self.routing_table.insert(node) {
                                Ok(InsertOutcome::Inserted) => {
                                    encounted_new_node = true;
                                }
                                _ => { }
                            }
                        }

                        {
                            let mut origin = self.routing_table
                                .find_node(&origin_address)
                                .expect("Got find node response from unknown node");
                            origin.received_response(transaction_id);
                        }

                        match self.pending_actions.remove(&transaction_id) {
                            Some(TableAction::Bootstrap(timeout)) => {
                                event_loop.clear_timeout(timeout);
                            }
                            Some(TableAction::HealthCheck(timeout)) => {
                                event_loop.clear_timeout(timeout);
                            }
                            None => { }
                        }

                        match self.status {
                            Status::Bootstrapping => {
                                if encounted_new_node {
                                    // Continue botstrapping
                                    self.continue_bootstrap(event_loop);
                                } else {
                                    self.status = Status::Idle;
                                    self.continue_health_check(event_loop);
                                }
                            }
                            _ => { }
                        }
                    }
                    Response::Ping => {
                        let mut origin = self.routing_table.find_node(&origin_address).expect("Got ping response from unknown node");
                        origin.received_response(transaction_id);
                    }
                }
            }
        }
    }

    fn start_bootstrap(&mut self, event_loop: &mut mio::EventLoop<Self>) {
        self.status = Status::Bootstrapping;
        self.continue_bootstrap(event_loop);
    }

    fn continue_bootstrap(&mut self, event_loop: &mut mio::EventLoop<Self>) {
        let transaction_id = self.find_self();
        let timeout = event_loop.timeout_ms(ScheduledTask::ContinueBootstrap, 1000).unwrap();
        self.pending_actions.insert(transaction_id, TableAction::Bootstrap(timeout));
    }

    fn continue_health_check(&mut self, event_loop: &mut mio::EventLoop<Self>) {
        let transaction_id = self.health_check();
        let timeout = event_loop.timeout_ms(ScheduledTask::ContinueHealthCheck, 1000).unwrap();
        self.pending_actions.insert(transaction_id, TableAction::HealthCheck(timeout));
    }

    fn find_self(&mut self) -> TransactionId {
        let transaction_id = self.transaction_ids.generate();
        let query = outgoing::create_find_node_query(
            transaction_id,
            &self.self_node,
            self.self_node.get_address());
        if let Some(node) = self.routing_table.nearest().get_mut(0) {
            {
                node.send(query);
            }
            node.sent_query(transaction_id);
        }
        transaction_id
    }

    fn health_check(&mut self) -> TransactionId {
        let transaction_id = self.transaction_ids.generate();
        let query = outgoing::create_ping_query(
            transaction_id, &self.self_node);
        if let Some(node) = self.routing_table.questionable_nodes().get_mut(0) {
            node.send(query);
            node.sent_query(transaction_id);
        }
        transaction_id
    }
}

impl mio::Handler for Handler {
    type Timeout = ScheduledTask;
    type Message = OneshotTask;

    fn notify(&mut self, event_loop: &mut mio::EventLoop<Handler>, task: OneshotTask) {
        match task {
            OneshotTask::Incoming(data) => self.handle_incoming(data, event_loop),
            OneshotTask::StartBootstrap => self.start_bootstrap(event_loop)
        }
    }

    fn timeout(&mut self, event_loop: &mut mio::EventLoop<Handler>, timeout: ScheduledTask) {
        match timeout {
            ScheduledTask::ContinueBootstrap => self.continue_bootstrap(event_loop),
            ScheduledTask::ContinueHealthCheck => self.continue_health_check(event_loop)
        }
    }
}

fn create_incoming_udp_channel(port: u16, sender: mio::Sender<OneshotTask>) {
    use std::net::UdpSocket;
    thread::spawn(move || {
        let address = ("0.0.0.0", port);
        let socket = UdpSocket::bind(address).unwrap();
        loop {
            let mut buf = [0; 4096];
            match socket.recv_from(&mut buf) {
                Ok((size, _src)) => {
                    sender.send(OneshotTask::Incoming(buf[..size].iter().cloned().collect())).unwrap();
                }
                Err(e) => panic!("Error receiving from server: {}", e)
            }
        }
    });
}
<commit_msg>Avoid generating a query when it's not used<commit_after>use messages::outgoing;
use mio;
use node::Node;
use node;
use routing_table::{InsertOutcome, RoutingTable};
use routing_table;
use std::collections::HashMap;
use std::io::Cursor;
use std::thread;
use transaction::{TransactionId, TransactionIdGenerator};

pub enum ScheduledTask {
    ContinueBootstrap,
    ContinueHealthCheck
}

pub enum OneshotTask {
    Incoming(Vec<u8>),
    StartBootstrap
}

enum TableAction {
    Bootstrap(mio::Timeout),
    HealthCheck(mio::Timeout)
}

enum Status {
    Bootstrapping,
    Idle
}

pub struct Handler {
    port: u16,
    routing_table: RoutingTable,
    self_node: Box<node::Node + 'static>,
    transaction_ids: TransactionIdGenerator,
    status: Status,
    pending_actions: HashMap<TransactionId, TableAction>
}

impl Handler {
    pub fn new<N: node::Node + 'static>(self_node: N, port: u16, routers: Vec<Box<Node>>) -> Handler {
        let self_address = self_node.get_address();
        let routing_table = routing_table::RoutingTable::new(8, self_address, routers);

        Handler {
            port: port,
            routing_table: routing_table,
            self_node: Box::new(self_node),
            transaction_ids: TransactionIdGenerator::new(),
            status: Status::Idle,
            pending_actions: HashMap::new()
        }
    }

    pub fn run(mut self) {
        let mut event_loop = mio::EventLoop::new().unwrap();
        let loop_channel = event_loop.channel();

        create_incoming_udp_channel(self.port, loop_channel.clone());
        loop_channel.send(OneshotTask::StartBootstrap).unwrap();
        event_loop.run(&mut self).unwrap();
    }

    fn handle_incoming(&mut self, data: Vec<u8>, event_loop: &mut mio::EventLoop<Handler>) {
        use messages::incoming;
        use messages::incoming::*;
        let mut data = Cursor::new(data);
        let message = incoming::parse_from_reader(&mut data).unwrap();

        match message {
            Message::Query(transaction_id, origin, query) => {
                let origin_address = origin.get_address();
                match query {
                    Query::FindNode(target) => {
                        let response: Vec<u8> = outgoing::create_find_node_response(
                                transaction_id,
                                &self.self_node,
                                self.routing_table.nearest_to(&target, false));
                        origin.send(response);

                        self.routing_table.insert(origin).unwrap();
                        {
                            if let Some(origin) = self.routing_table.find_node(&origin_address) {
                                origin.received_query(transaction_id);
                            }
                        }
                    },
                    Query::Ping => {
                        let response = outgoing::create_ping_response(
                            transaction_id,
                            &self.self_node);
                        origin.send(response);

                        self.routing_table.insert(origin).unwrap();
                        if let Some(origin) = self.routing_table.find_node(&origin_address) {
                            origin.received_query(transaction_id);
                        }
                    }
                }
            }
            Message::Response(transaction_id, origin, response) => {
                let origin_address = origin.get_address();
                match response {
                    Response::FindNode(mut nodes) => {
                        let mut encounted_new_node = false;
                        let mut tail = vec![origin];
                        for node in nodes.drain(..).chain(tail.drain(..)) {
                            match self.routing_table.insert(node) {
                                Ok(InsertOutcome::Inserted) => {
                                    encounted_new_node = true;
                                }
                                _ => { }
                            }
                        }

                        {
                            let mut origin = self.routing_table
                                .find_node(&origin_address)
                                .expect("Got find node response from unknown node");
                            origin.received_response(transaction_id);
                        }

                        match self.pending_actions.remove(&transaction_id) {
                            Some(TableAction::Bootstrap(timeout)) => {
                                event_loop.clear_timeout(timeout);
                            }
                            Some(TableAction::HealthCheck(timeout)) => {
                                event_loop.clear_timeout(timeout);
                            }
                            None => { }
                        }

                        match self.status {
                            Status::Bootstrapping => {
                                if encounted_new_node {
                                    // Continue botstrapping
                                    self.continue_bootstrap(event_loop);
                                } else {
                                    self.status = Status::Idle;
                                    self.continue_health_check(event_loop);
                                }
                            }
                            _ => { }
                        }
                    }
                    Response::Ping => {
                        let mut origin = self.routing_table.find_node(&origin_address).expect("Got ping response from unknown node");
                        origin.received_response(transaction_id);
                    }
                }
            }
        }
    }

    fn start_bootstrap(&mut self, event_loop: &mut mio::EventLoop<Self>) {
        self.status = Status::Bootstrapping;
        self.continue_bootstrap(event_loop);
    }

    fn continue_bootstrap(&mut self, event_loop: &mut mio::EventLoop<Self>) {
        let transaction_id = self.find_self();
        let timeout = event_loop.timeout_ms(ScheduledTask::ContinueBootstrap, 1000).unwrap();
        self.pending_actions.insert(transaction_id, TableAction::Bootstrap(timeout));
    }

    fn continue_health_check(&mut self, event_loop: &mut mio::EventLoop<Self>) {
        let transaction_id = self.health_check();
        let timeout = event_loop.timeout_ms(ScheduledTask::ContinueHealthCheck, 1000).unwrap();
        self.pending_actions.insert(transaction_id, TableAction::HealthCheck(timeout));
    }

    fn find_self(&mut self) -> TransactionId {
        let transaction_id = self.transaction_ids.generate();
        let query = outgoing::create_find_node_query(
            transaction_id,
            &self.self_node,
            self.self_node.get_address());
        if let Some(node) = self.routing_table.nearest().get_mut(0) {
            {
                node.send(query);
            }
            node.sent_query(transaction_id);
        }
        transaction_id
    }

    fn health_check(&mut self) -> TransactionId {
        let transaction_id = self.transaction_ids.generate();
        if let Some(node) = self.routing_table.questionable_nodes().get_mut(0) {
            let query = outgoing::create_ping_query(
                transaction_id, &self.self_node);
            node.send(query);
            node.sent_query(transaction_id);
        }
        transaction_id
    }
}

impl mio::Handler for Handler {
    type Timeout = ScheduledTask;
    type Message = OneshotTask;

    fn notify(&mut self, event_loop: &mut mio::EventLoop<Handler>, task: OneshotTask) {
        match task {
            OneshotTask::Incoming(data) => self.handle_incoming(data, event_loop),
            OneshotTask::StartBootstrap => self.start_bootstrap(event_loop)
        }
    }

    fn timeout(&mut self, event_loop: &mut mio::EventLoop<Handler>, timeout: ScheduledTask) {
        match timeout {
            ScheduledTask::ContinueBootstrap => self.continue_bootstrap(event_loop),
            ScheduledTask::ContinueHealthCheck => self.continue_health_check(event_loop)
        }
    }
}

fn create_incoming_udp_channel(port: u16, sender: mio::Sender<OneshotTask>) {
    use std::net::UdpSocket;
    thread::spawn(move || {
        let address = ("0.0.0.0", port);
        let socket = UdpSocket::bind(address).unwrap();
        loop {
            let mut buf = [0; 4096];
            match socket.recv_from(&mut buf) {
                Ok((size, _src)) => {
                    sender.send(OneshotTask::Incoming(buf[..size].iter().cloned().collect())).unwrap();
                }
                Err(e) => panic!("Error receiving from server: {}", e)
            }
        }
    });
}
<|endoftext|>


<commit_before>use std::collections::HashSet;

use pattern::{Pattern, PatternElem};
use stepper::Stepper;

/// A set of PatternElems, representing the set of valid operations at a given point in a sequence.
#[derive(Clone, Debug)]
pub struct PatternElemChoice(HashSet<PatternElem>);

impl PatternElemChoice {
    // TODO: Add ability to identify modulus.
    fn from_i32_pair(x: i32, y: i32) -> Self {
        let mut set = HashSet::new();
        set.insert(PatternElem::Const(y));
        set.insert(PatternElem::Plus(y - x));

        if x != 0 && y % x == 0 {
            set.insert(PatternElem::Mult(y / x));
        }

        if y != 0 && x % y == 0 {
            set.insert(PatternElem::Div(x / y));
        }

        if x * x == y {
            set.insert(PatternElem::Square);
        }

        if y * y == x {
            set.insert(PatternElem::SquareRoot);
        }

        if x * x * x == y {
            set.insert(PatternElem::Cube);
        }

        if y * y * y == x {
            set.insert(PatternElem::CubeRoot);
        }

        PatternElemChoice(set)
    }
}

fn intersection(vec: &[PatternElemChoice]) -> HashSet<PatternElem> {
    let base = match vec.first() {
        Some(&PatternElemChoice(ref choices)) => choices.to_owned(),
        None => return HashSet::new()
    };

    vec.into_iter().fold(base, |set, choice| set.intersection(&choice.0).cloned().collect())
}

/// Identifies patterns that describe a given sequence.
pub type Analyzer = Vec<PatternElemChoice>;

pub trait Analyze {
    /// Creates a new Analyze from a slice of integers.
    fn from_slice(seq: &[i32]) -> Self;

    /// Attempts to find exactly one pattern of `n` operations that described the given sequence.
    fn find_any_pattern_of_length(&self, n: usize) -> Option<Pattern> {
        self.find_patterns_of_length(n).pop()
    }

    /// Attempts to find exactly one pattern of maximum size `max` (in terms of number of
    /// operations) that describes the given sequence. It returns the smallest such pattern it can
    /// find .
    fn find_any_pattern(&self, max: usize) -> Option<Pattern> {
        for i in 1..max {
            let mut vec = self.find_patterns_of_length(i);

            if !vec.is_empty() {
                return vec.pop();
            }
        }

        return None;
    }

    /// Finds all patterns with `n` operations that describe the given sequence.
    fn find_patterns_of_length(&self, n: usize) -> Vec<Pattern>;

    /// Finds patterns of maximum size `max` (in terms of number of operations) that describe the
    /// given sequence. It will return all such patterns that are of minimal size (i.e. if a
    /// sequence can be described by a pattern of two operations, it will return all such patterns,
    /// but none of size three or greater).
    fn find_patterns(&self, max: usize) -> Vec<Pattern> {
        for i in 1..max {
            let vec = self.find_patterns_of_length(i);

            if !vec.is_empty() {
                return vec;
            }
        }

        return Vec::new();
    }
}

impl Analyze for Analyzer {
    fn from_slice(seq: &[i32]) -> Self {
        (0..seq.len() - 1).map(|i| PatternElemChoice::from_i32_pair(seq[i], seq[i + 1])).collect()
    }

    fn find_patterns_of_length(&self, range: usize) -> Vec<Pattern> {
        let mut pats = vec![Pattern::empty()];

        for i in 0..range {
            let choices: Vec<_> = step!(i => self.len(); range).map(|i| self[i].to_owned()).collect();

            let mut new = Vec::new();

            for pat in pats.iter_mut() {
                new.extend(pat.extend_each(intersection(&choices[..]).into_iter()));
            }

            pats = new;

            // Makes results deterministic, which is helpful.
            pats.sort();
        }

        pats
    }
}
<commit_msg>fix variable name to reflect type<commit_after>use std::collections::HashSet;

use pattern::{Pattern, PatternElem};
use stepper::Stepper;

/// A set of PatternElems, representing the set of valid operations at a given point in a sequence.
#[derive(Clone, Debug)]
pub struct PatternElemChoice(HashSet<PatternElem>);

impl PatternElemChoice {
    // TODO: Add ability to identify modulus.
    fn from_i32_pair(x: i32, y: i32) -> Self {
        let mut set = HashSet::new();
        set.insert(PatternElem::Const(y));
        set.insert(PatternElem::Plus(y - x));

        if x != 0 && y % x == 0 {
            set.insert(PatternElem::Mult(y / x));
        }

        if y != 0 && x % y == 0 {
            set.insert(PatternElem::Div(x / y));
        }

        if x * x == y {
            set.insert(PatternElem::Square);
        }

        if y * y == x {
            set.insert(PatternElem::SquareRoot);
        }

        if x * x * x == y {
            set.insert(PatternElem::Cube);
        }

        if y * y * y == x {
            set.insert(PatternElem::CubeRoot);
        }

        PatternElemChoice(set)
    }
}

fn intersection(slice: &[PatternElemChoice]) -> HashSet<PatternElem> {
    let base = match slice.first() {
        Some(&PatternElemChoice(ref choices)) => choices.to_owned(),
        None => return HashSet::new()
    };

    slice.into_iter().fold(base, |set, choice| set.intersection(&choice.0).cloned().collect())
}

/// Identifies patterns that describe a given sequence.
pub type Analyzer = Vec<PatternElemChoice>;

pub trait Analyze {
    /// Creates a new Analyze from a slice of integers.
    fn from_slice(seq: &[i32]) -> Self;

    /// Attempts to find exactly one pattern of `n` operations that described the given sequence.
    fn find_any_pattern_of_length(&self, n: usize) -> Option<Pattern> {
        self.find_patterns_of_length(n).pop()
    }

    /// Attempts to find exactly one pattern of maximum size `max` (in terms of number of
    /// operations) that describes the given sequence. It returns the smallest such pattern it can
    /// find .
    fn find_any_pattern(&self, max: usize) -> Option<Pattern> {
        for i in 1..max {
            let mut vec = self.find_patterns_of_length(i);

            if !vec.is_empty() {
                return vec.pop();
            }
        }

        return None;
    }

    /// Finds all patterns with `n` operations that describe the given sequence.
    fn find_patterns_of_length(&self, n: usize) -> Vec<Pattern>;

    /// Finds patterns of maximum size `max` (in terms of number of operations) that describe the
    /// given sequence. It will return all such patterns that are of minimal size (i.e. if a
    /// sequence can be described by a pattern of two operations, it will return all such patterns,
    /// but none of size three or greater).
    fn find_patterns(&self, max: usize) -> Vec<Pattern> {
        for i in 1..max {
            let vec = self.find_patterns_of_length(i);

            if !vec.is_empty() {
                return vec;
            }
        }

        return Vec::new();
    }
}

impl Analyze for Analyzer {
    fn from_slice(seq: &[i32]) -> Self {
        (0..seq.len() - 1).map(|i| PatternElemChoice::from_i32_pair(seq[i], seq[i + 1])).collect()
    }

    fn find_patterns_of_length(&self, range: usize) -> Vec<Pattern> {
        let mut pats = vec![Pattern::empty()];

        for i in 0..range {
            let choices: Vec<_> = step!(i => self.len(); range).map(|i| self[i].to_owned()).collect();

            let mut new = Vec::new();

            for pat in pats.iter_mut() {
                new.extend(pat.extend_each(intersection(&choices[..]).into_iter()));
            }

            pats = new;

            // Makes results deterministic, which is helpful.
            pats.sort();
        }

        pats
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp;
use std::slice;

#[derive(Copy)]
pub enum BufferResult {
    BufferUnderflow,
    BufferOverflow
}

pub trait ReadBuffer {
    fn is_empty(&self) -> bool;
    fn is_full(&self) -> bool;
    fn remaining(&self) -> uint;
    fn capacity(&self) -> uint;
    fn position(&self) -> uint { self.capacity() - self.remaining() }

    fn rewind(&mut self, distance: uint);
    fn truncate(&mut self, amount: uint);
    fn reset(&mut self);

    fn peek_next(&self, count: uint) -> &[u8];
    fn peek_remaining(&self) -> &[u8] {
        self.peek_next(self.remaining())
    }

    fn take_next(&mut self, count: uint) -> &[u8];
    fn take_remaining(&mut self) -> &[u8] {
        let rem = self.remaining();
        self.take_next(rem)
    }

    fn push_to<W: WriteBuffer>(&mut self, output: &mut W) {
        let count = cmp::min(output.remaining(), self.remaining());
        slice::bytes::copy_memory(output.take_next(count), self.take_next(count));
    }
}

pub trait WriteBuffer {
    fn is_empty(&self) -> bool;
    fn is_full(&self) -> bool;
    fn remaining(&self) -> uint;
    fn capacity(&self) -> uint;
    fn position(&self) -> uint { self.capacity() - self.remaining() }

    fn rewind(&mut self, distance: uint);
    fn reset(&mut self);

    // FIXME - Shouldn't need mut self
    fn peek_read_buffer(&mut self) -> RefReadBuffer;

    fn take_next(&mut self, count: uint) -> &mut [u8];
    fn take_remaining(&mut self) -> &mut [u8] {
        let rem = self.remaining();
        self.take_next(rem)
    }
    fn take_read_buffer(&mut self) -> RefReadBuffer;
}

pub struct RefReadBuffer<'a> {
    buff: &'a [u8],
    pos: uint
}

impl <'a> RefReadBuffer<'a> {
    pub fn new(buff: &[u8]) -> RefReadBuffer {
        RefReadBuffer {
            buff: buff,
            pos: 0
        }
    }
}

impl <'a> ReadBuffer for RefReadBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == self.buff.len() }
    fn is_full(&self) -> bool { self.pos == 0 }
    fn remaining(&self) -> uint { self.buff.len() - self.pos }
    fn capacity(&self) -> uint { self.buff.len() }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn truncate(&mut self, amount: uint) {
        self.buff = &self.buff[..self.buff.len() - amount];
    }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_next(&self, count: uint) -> &[u8] { &self.buff[self.pos..count] }

    fn take_next(&mut self, count: uint) -> &[u8] {
        let r = &self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
}

pub struct OwnedReadBuffer {
    buff: Vec<u8>,
    len: uint,
    pos: uint
}

impl OwnedReadBuffer {
    pub fn new(buff: Vec<u8>) -> OwnedReadBuffer {
        let len = buff.len();
        OwnedReadBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn new_with_len<'a>(buff: Vec<u8>, len: uint) -> OwnedReadBuffer {
        OwnedReadBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn into_write_buffer(self) -> OwnedWriteBuffer {
        OwnedWriteBuffer::new(self.buff)
    }
    pub fn borrow_write_buffer(&mut self) -> BorrowedWriteBuffer {
        self.pos = 0;
        self.len = 0;
        BorrowedWriteBuffer::new(self)
    }
}

impl ReadBuffer for OwnedReadBuffer {
    fn is_empty(&self) -> bool { self.pos == self.len }
    fn is_full(&self) -> bool { self.pos == 0 }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn truncate(&mut self, amount: uint) { self.len -= amount; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_next(&self, count: uint) -> &[u8] { &self.buff[self.pos..count] }

    fn take_next(&mut self, count: uint) -> &[u8] {
        let r = &self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
}

pub struct RefWriteBuffer<'a> {
    buff: &'a mut [u8],
    len: uint,
    pos: uint
}

impl <'a> RefWriteBuffer<'a> {
    pub fn new(buff: &mut [u8]) -> RefWriteBuffer {
        let len = buff.len();
        RefWriteBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
}

impl <'a> WriteBuffer for RefWriteBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_read_buffer(&mut self) -> RefReadBuffer {
        RefReadBuffer::new(self.buff.slice_to_mut(self.pos))
    }

    fn take_next(&mut self, count: uint) -> &mut [u8] {
        let r = &mut self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
    fn take_read_buffer(&mut self) -> RefReadBuffer {
        let r = RefReadBuffer::new(self.buff.slice_to_mut(self.pos));
        self.pos = 0;
        r
    }
}

pub struct BorrowedWriteBuffer<'a> {
    parent: &'a mut OwnedReadBuffer,
    pos: uint,
    len: uint
}

impl <'a> BorrowedWriteBuffer<'a> {
    fn new(parent: &mut OwnedReadBuffer) -> BorrowedWriteBuffer {
        let buff_len = parent.buff.len();
        BorrowedWriteBuffer {
            parent: parent,
            pos: 0,
            len: buff_len
        }
    }
}

impl <'a> WriteBuffer for BorrowedWriteBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) {
        self.pos -= distance;
        self.parent.len -= distance;
    }
    fn reset(&mut self) {
        self.pos = 0;
        self.parent.len = 0;
    }

    fn peek_read_buffer(&mut self) -> RefReadBuffer {
        RefReadBuffer::new(&self.parent.buff[..self.pos])
    }

    fn take_next<>(&mut self, count: uint) -> &mut [u8] {
        let r = &mut self.parent.buff[self.pos..self.pos + count];
        self.pos += count;
        self.parent.len += count;
        r
    }
    fn take_read_buffer(&mut self) -> RefReadBuffer {
        let r = RefReadBuffer::new(&self.parent.buff[..self.pos]);
        self.pos = 0;
        self.parent.len = 0;
        r
    }
}

pub struct OwnedWriteBuffer {
    buff: Vec<u8>,
    len: uint,
    pos: uint
}

impl OwnedWriteBuffer {
    pub fn new(buff: Vec<u8>) -> OwnedWriteBuffer {
        let len = buff.len();
        OwnedWriteBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn into_read_buffer(self) -> OwnedReadBuffer {
        let pos = self.pos;
        OwnedReadBuffer::new_with_len(self.buff, pos)
    }
}

impl WriteBuffer for OwnedWriteBuffer {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        RefReadBuffer::new(&self.buff[..self.pos])
    }

    fn take_next<'a>(&'a mut self, count: uint) -> &'a mut [u8] {
        let r = &mut self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
    fn take_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        let r = RefReadBuffer::new(&self.buff[..self.pos]);
        self.pos = 0;
        r
    }
}
<commit_msg>Pick more appropriate int types for buffer<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp;
use std::slice;

#[derive(Copy)]
pub enum BufferResult {
    BufferUnderflow,
    BufferOverflow
}

pub trait ReadBuffer {
    fn is_empty(&self) -> bool;
    fn is_full(&self) -> bool;
    fn remaining(&self) -> usize;
    fn capacity(&self) -> usize;
    fn position(&self) -> usize { self.capacity() - self.remaining() }

    fn rewind(&mut self, distance: usize);
    fn truncate(&mut self, amount: usize);
    fn reset(&mut self);

    fn peek_next(&self, count: usize) -> &[u8];
    fn peek_remaining(&self) -> &[u8] {
        self.peek_next(self.remaining())
    }

    fn take_next(&mut self, count: usize) -> &[u8];
    fn take_remaining(&mut self) -> &[u8] {
        let rem = self.remaining();
        self.take_next(rem)
    }

    fn push_to<W: WriteBuffer>(&mut self, output: &mut W) {
        let count = cmp::min(output.remaining(), self.remaining());
        slice::bytes::copy_memory(output.take_next(count), self.take_next(count));
    }
}

pub trait WriteBuffer {
    fn is_empty(&self) -> bool;
    fn is_full(&self) -> bool;
    fn remaining(&self) -> usize;
    fn capacity(&self) -> usize;
    fn position(&self) -> usize { self.capacity() - self.remaining() }

    fn rewind(&mut self, distance: usize);
    fn reset(&mut self);

    // FIXME - Shouldn't need mut self
    fn peek_read_buffer(&mut self) -> RefReadBuffer;

    fn take_next(&mut self, count: usize) -> &mut [u8];
    fn take_remaining(&mut self) -> &mut [u8] {
        let rem = self.remaining();
        self.take_next(rem)
    }
    fn take_read_buffer(&mut self) -> RefReadBuffer;
}

pub struct RefReadBuffer<'a> {
    buff: &'a [u8],
    pos: usize
}

impl <'a> RefReadBuffer<'a> {
    pub fn new(buff: &[u8]) -> RefReadBuffer {
        RefReadBuffer {
            buff: buff,
            pos: 0
        }
    }
}

impl <'a> ReadBuffer for RefReadBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == self.buff.len() }
    fn is_full(&self) -> bool { self.pos == 0 }
    fn remaining(&self) -> usize { self.buff.len() - self.pos }
    fn capacity(&self) -> usize { self.buff.len() }

    fn rewind(&mut self, distance: usize) { self.pos -= distance; }
    fn truncate(&mut self, amount: usize) {
        self.buff = &self.buff[..self.buff.len() - amount];
    }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_next(&self, count: usize) -> &[u8] { &self.buff[self.pos..count] }

    fn take_next(&mut self, count: usize) -> &[u8] {
        let r = &self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
}

pub struct OwnedReadBuffer {
    buff: Vec<u8>,
    len: usize,
    pos: usize
}

impl OwnedReadBuffer {
    pub fn new(buff: Vec<u8>) -> OwnedReadBuffer {
        let len = buff.len();
        OwnedReadBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn new_with_len<'a>(buff: Vec<u8>, len: usize) -> OwnedReadBuffer {
        OwnedReadBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn into_write_buffer(self) -> OwnedWriteBuffer {
        OwnedWriteBuffer::new(self.buff)
    }
    pub fn borrow_write_buffer(&mut self) -> BorrowedWriteBuffer {
        self.pos = 0;
        self.len = 0;
        BorrowedWriteBuffer::new(self)
    }
}

impl ReadBuffer for OwnedReadBuffer {
    fn is_empty(&self) -> bool { self.pos == self.len }
    fn is_full(&self) -> bool { self.pos == 0 }
    fn remaining(&self) -> usize { self.len - self.pos }
    fn capacity(&self) -> usize { self.len }

    fn rewind(&mut self, distance: usize) { self.pos -= distance; }
    fn truncate(&mut self, amount: usize) { self.len -= amount; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_next(&self, count: usize) -> &[u8] { &self.buff[self.pos..count] }

    fn take_next(&mut self, count: usize) -> &[u8] {
        let r = &self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
}

pub struct RefWriteBuffer<'a> {
    buff: &'a mut [u8],
    len: usize,
    pos: usize
}

impl <'a> RefWriteBuffer<'a> {
    pub fn new(buff: &mut [u8]) -> RefWriteBuffer {
        let len = buff.len();
        RefWriteBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
}

impl <'a> WriteBuffer for RefWriteBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> usize { self.len - self.pos }
    fn capacity(&self) -> usize { self.len }

    fn rewind(&mut self, distance: usize) { self.pos -= distance; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_read_buffer(&mut self) -> RefReadBuffer {
        RefReadBuffer::new(self.buff.slice_to_mut(self.pos))
    }

    fn take_next(&mut self, count: usize) -> &mut [u8] {
        let r = &mut self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
    fn take_read_buffer(&mut self) -> RefReadBuffer {
        let r = RefReadBuffer::new(self.buff.slice_to_mut(self.pos));
        self.pos = 0;
        r
    }
}

pub struct BorrowedWriteBuffer<'a> {
    parent: &'a mut OwnedReadBuffer,
    pos: usize,
    len: usize
}

impl <'a> BorrowedWriteBuffer<'a> {
    fn new(parent: &mut OwnedReadBuffer) -> BorrowedWriteBuffer {
        let buff_len = parent.buff.len();
        BorrowedWriteBuffer {
            parent: parent,
            pos: 0,
            len: buff_len
        }
    }
}

impl <'a> WriteBuffer for BorrowedWriteBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> usize { self.len - self.pos }
    fn capacity(&self) -> usize { self.len }

    fn rewind(&mut self, distance: usize) {
        self.pos -= distance;
        self.parent.len -= distance;
    }
    fn reset(&mut self) {
        self.pos = 0;
        self.parent.len = 0;
    }

    fn peek_read_buffer(&mut self) -> RefReadBuffer {
        RefReadBuffer::new(&self.parent.buff[..self.pos])
    }

    fn take_next<>(&mut self, count: usize) -> &mut [u8] {
        let r = &mut self.parent.buff[self.pos..self.pos + count];
        self.pos += count;
        self.parent.len += count;
        r
    }
    fn take_read_buffer(&mut self) -> RefReadBuffer {
        let r = RefReadBuffer::new(&self.parent.buff[..self.pos]);
        self.pos = 0;
        self.parent.len = 0;
        r
    }
}

pub struct OwnedWriteBuffer {
    buff: Vec<u8>,
    len: usize,
    pos: usize
}

impl OwnedWriteBuffer {
    pub fn new(buff: Vec<u8>) -> OwnedWriteBuffer {
        let len = buff.len();
        OwnedWriteBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn into_read_buffer(self) -> OwnedReadBuffer {
        let pos = self.pos;
        OwnedReadBuffer::new_with_len(self.buff, pos)
    }
}

impl WriteBuffer for OwnedWriteBuffer {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> usize { self.len - self.pos }
    fn capacity(&self) -> usize { self.len }

    fn rewind(&mut self, distance: usize) { self.pos -= distance; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        RefReadBuffer::new(&self.buff[..self.pos])
    }

    fn take_next<'a>(&'a mut self, count: usize) -> &'a mut [u8] {
        let r = &mut self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
    fn take_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        let r = RefReadBuffer::new(&self.buff[..self.pos]);
        self.pos = 0;
        r
    }
}
<|endoftext|>


<commit_before>use cocoa::base::id;
use cocoa::foundation::NSString;
use metal_sys::{MTLArgument, MTLArgumentAccess, MTLArgumentType, MTLDataType};
use objc::runtime::YES;
use std::borrow::Cow;
use std::ffi::CStr;
use {FromRaw, StructType};

pub struct Argument(id);

impl Argument {
    pub fn name(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.name().UTF8String()).to_string_lossy() }
    }

    pub fn access(&self) -> ArgumentAccess {
        unsafe { self.0.access().into() }
    }

    pub fn is_active(&self) -> bool {
        unsafe { self.0.active() == YES }
    }

    pub fn index(&self) -> usize {
        unsafe { self.0.index() as usize }
    }

    pub fn get_type(&self) -> ArgumentType {
        unsafe { self.0.getType().into() }
    }

    pub fn buffer_alignment(&self) -> Option<usize> {
        if self.get_type() == ArgumentType::Buffer {
            unsafe { Some(self.0.bufferAlignment() as usize) }
        } else {
            None
        }
    }

    pub fn buffer_data_size(&self) -> Option<usize> {
        if self.get_type() == ArgumentType::Buffer {
            unsafe { Some(self.0.bufferDataSize() as usize) }
        } else {
            None
        }
    }

    pub fn buffer_data_type(&self) -> Option<DataType> {
        if self.get_type() == ArgumentType::Buffer {
            unsafe { Some(self.0.bufferDataType().into()) }
        } else {
            None
        }
    }

    pub fn buffer_struct_type(&self) -> Option<StructType> {
        if self.get_type() == ArgumentType::Buffer {
            let struct_type = unsafe { self.0.bufferStructType() };
            StructType::from_raw(struct_type).ok()
        } else {
            None
        }
    }

    pub fn texture_data_type(&self) -> Option<DataType> {
        if self.get_type() == ArgumentType::Texture {
            unsafe { Some(self.0.textureDataType().into()) }
        } else {
            None
        }
    }

    pub fn texture_type(&self) -> ! {
        unimplemented!()
    }

    pub fn threadgroup_memory_alignment(&self) -> Option<usize> {
        if self.get_type() == ArgumentType::ThreadgroupMemory {
            unsafe { Some(self.0.threadgroupMemoryAlignment() as usize) }
        } else {
            None
        }
    }

    pub fn threadgroup_memory_data_size(&self) -> Option<usize> {
        if self.get_type() == ArgumentType::ThreadgroupMemory {
            unsafe { Some(self.0.threadgroupMemoryDataSize() as usize) }
        } else {
            None
        }
    }
}

impl_from_into_raw!(Argument, of class "MTLArgument");

convertible_enum!{
    #[derive(Clone, Copy, Eq, Hash, PartialEq)]
    enum ArgumentAccess : MTLArgumentAccess {
        ReadOnly => MTLArgumentAccessReadOnly,
        ReadWrite => MTLArgumentAccessReadWrite,
        WriteOnly => MTLArgumentAccessWriteOnly
    }
}

convertible_enum! {
    #[derive(Clone, Copy, Eq, Hash, PartialEq)]
    enum ArgumentType : MTLArgumentType {
        Buffer => MTLArgumentTypeBuffer,
        ThreadgroupMemory => MTLArgumentTypeThreadgroupMemory,
        Texture => MTLArgumentTypeTexture,
        Sampler => MTLArgumentTypeSampler
    }
}

convertible_enum! {
    #[derive(Clone, Copy, Eq, Hash, PartialEq)]
    enum DataType : MTLDataType {
        None => MTLDataTypeNone,
        Struct => MTLDataTypeStruct,
        Array => MTLDataTypeArray,

        Float => MTLDataTypeFloat,
        Float2 => MTLDataTypeFloat2,
        Float3 => MTLDataTypeFloat3,
        Float4 => MTLDataTypeFloat4,

        Float2x2 => MTLDataTypeFloat2x2,
        Float2x3 => MTLDataTypeFloat2x3,
        Float2x4 => MTLDataTypeFloat2x4,

        Float3x2 => MTLDataTypeFloat3x2,
        Float3x3 => MTLDataTypeFloat3x3,
        Float3x4 => MTLDataTypeFloat3x4,
        Float4x2 => MTLDataTypeFloat4x2,
        Float4x3 => MTLDataTypeFloat4x3,
        Float4x4 => MTLDataTypeFloat4x4,

        Half => MTLDataTypeHalf,
        Half2 => MTLDataTypeHalf2,
        Half3 => MTLDataTypeHalf3,
        Half4 => MTLDataTypeHalf4,

        Half2x2 => MTLDataTypeHalf2x2,
        Half2x3 => MTLDataTypeHalf2x3,
        Half2x4 => MTLDataTypeHalf2x4,

        Half3x2 => MTLDataTypeHalf3x2,
        Half3x3 => MTLDataTypeHalf3x3,
        Half3x4 => MTLDataTypeHalf3x4,

        Half4x2 => MTLDataTypeHalf4x2,
        Half4x3 => MTLDataTypeHalf4x3,
        Half4x4 => MTLDataTypeHalf4x4,

        Int => MTLDataTypeInt,
        Int2 => MTLDataTypeInt2,
        Int3 => MTLDataTypeInt3,
        Int4 => MTLDataTypeInt4,
        UInt => MTLDataTypeUInt,
        UInt2 => MTLDataTypeUInt2,
        UInt3 => MTLDataTypeUInt3,
        UInt4 => MTLDataTypeUInt4,

        Short => MTLDataTypeShort,
        Short2 => MTLDataTypeShort2,
        Short3 => MTLDataTypeShort3,
        Short4 => MTLDataTypeShort4,

        UShort => MTLDataTypeUShort,
        UShort2 => MTLDataTypeUShort2,
        UShort3 => MTLDataTypeUShort3,
        UShort4 => MTLDataTypeUShort4,

        Char => MTLDataTypeChar,
        Char2 => MTLDataTypeChar2,
        Char3 => MTLDataTypeChar3,
        Char4 => MTLDataTypeChar4,

        UChar => MTLDataTypeUChar,
        UChar2 => MTLDataTypeUChar2,
        UChar3 => MTLDataTypeUChar3,
        UChar4 => MTLDataTypeUChar4,

        Bool => MTLDataTypeBool,
        Bool2 => MTLDataTypeBool2,
        Bool3 => MTLDataTypeBool3,
        Bool4 => MTLDataTypeBool4
    }
}
<commit_msg>Implement Argument::texture_type<commit_after>use cocoa::base::id;
use cocoa::foundation::NSString;
use metal_sys::{MTLArgument, MTLArgumentAccess, MTLArgumentType, MTLDataType};
use objc::runtime::YES;
use std::borrow::Cow;
use std::ffi::CStr;
use {FromRaw, StructType, TextureType};

pub struct Argument(id);

impl Argument {
    pub fn name(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.name().UTF8String()).to_string_lossy() }
    }

    pub fn access(&self) -> ArgumentAccess {
        unsafe { self.0.access().into() }
    }

    pub fn is_active(&self) -> bool {
        unsafe { self.0.active() == YES }
    }

    pub fn index(&self) -> usize {
        unsafe { self.0.index() as usize }
    }

    pub fn get_type(&self) -> ArgumentType {
        unsafe { self.0.getType().into() }
    }

    pub fn buffer_alignment(&self) -> Option<usize> {
        if self.get_type() == ArgumentType::Buffer {
            unsafe { Some(self.0.bufferAlignment() as usize) }
        } else {
            None
        }
    }

    pub fn buffer_data_size(&self) -> Option<usize> {
        if self.get_type() == ArgumentType::Buffer {
            unsafe { Some(self.0.bufferDataSize() as usize) }
        } else {
            None
        }
    }

    pub fn buffer_data_type(&self) -> Option<DataType> {
        if self.get_type() == ArgumentType::Buffer {
            unsafe { Some(self.0.bufferDataType().into()) }
        } else {
            None
        }
    }

    pub fn buffer_struct_type(&self) -> Option<StructType> {
        if self.get_type() == ArgumentType::Buffer {
            let struct_type = unsafe { self.0.bufferStructType() };
            StructType::from_raw(struct_type).ok()
        } else {
            None
        }
    }

    pub fn texture_data_type(&self) -> Option<DataType> {
        if self.get_type() == ArgumentType::Texture {
            unsafe { Some(self.0.textureDataType().into()) }
        } else {
            None
        }
    }

    pub fn texture_type(&self) -> Option<TextureType> {
        if self.get_type() == ArgumentType::Texture {
            unsafe { Some(self.0.textureType().into()) }
        } else {
            None
        }
    }

    pub fn threadgroup_memory_alignment(&self) -> Option<usize> {
        if self.get_type() == ArgumentType::ThreadgroupMemory {
            unsafe { Some(self.0.threadgroupMemoryAlignment() as usize) }
        } else {
            None
        }
    }

    pub fn threadgroup_memory_data_size(&self) -> Option<usize> {
        if self.get_type() == ArgumentType::ThreadgroupMemory {
            unsafe { Some(self.0.threadgroupMemoryDataSize() as usize) }
        } else {
            None
        }
    }
}

impl_from_into_raw!(Argument, of class "MTLArgument");

convertible_enum!{
    #[derive(Clone, Copy, Eq, Hash, PartialEq)]
    enum ArgumentAccess : MTLArgumentAccess {
        ReadOnly => MTLArgumentAccessReadOnly,
        ReadWrite => MTLArgumentAccessReadWrite,
        WriteOnly => MTLArgumentAccessWriteOnly
    }
}

convertible_enum! {
    #[derive(Clone, Copy, Eq, Hash, PartialEq)]
    enum ArgumentType : MTLArgumentType {
        Buffer => MTLArgumentTypeBuffer,
        ThreadgroupMemory => MTLArgumentTypeThreadgroupMemory,
        Texture => MTLArgumentTypeTexture,
        Sampler => MTLArgumentTypeSampler
    }
}

convertible_enum! {
    #[derive(Clone, Copy, Eq, Hash, PartialEq)]
    enum DataType : MTLDataType {
        None => MTLDataTypeNone,
        Struct => MTLDataTypeStruct,
        Array => MTLDataTypeArray,

        Float => MTLDataTypeFloat,
        Float2 => MTLDataTypeFloat2,
        Float3 => MTLDataTypeFloat3,
        Float4 => MTLDataTypeFloat4,

        Float2x2 => MTLDataTypeFloat2x2,
        Float2x3 => MTLDataTypeFloat2x3,
        Float2x4 => MTLDataTypeFloat2x4,

        Float3x2 => MTLDataTypeFloat3x2,
        Float3x3 => MTLDataTypeFloat3x3,
        Float3x4 => MTLDataTypeFloat3x4,
        Float4x2 => MTLDataTypeFloat4x2,
        Float4x3 => MTLDataTypeFloat4x3,
        Float4x4 => MTLDataTypeFloat4x4,

        Half => MTLDataTypeHalf,
        Half2 => MTLDataTypeHalf2,
        Half3 => MTLDataTypeHalf3,
        Half4 => MTLDataTypeHalf4,

        Half2x2 => MTLDataTypeHalf2x2,
        Half2x3 => MTLDataTypeHalf2x3,
        Half2x4 => MTLDataTypeHalf2x4,

        Half3x2 => MTLDataTypeHalf3x2,
        Half3x3 => MTLDataTypeHalf3x3,
        Half3x4 => MTLDataTypeHalf3x4,

        Half4x2 => MTLDataTypeHalf4x2,
        Half4x3 => MTLDataTypeHalf4x3,
        Half4x4 => MTLDataTypeHalf4x4,

        Int => MTLDataTypeInt,
        Int2 => MTLDataTypeInt2,
        Int3 => MTLDataTypeInt3,
        Int4 => MTLDataTypeInt4,
        UInt => MTLDataTypeUInt,
        UInt2 => MTLDataTypeUInt2,
        UInt3 => MTLDataTypeUInt3,
        UInt4 => MTLDataTypeUInt4,

        Short => MTLDataTypeShort,
        Short2 => MTLDataTypeShort2,
        Short3 => MTLDataTypeShort3,
        Short4 => MTLDataTypeShort4,

        UShort => MTLDataTypeUShort,
        UShort2 => MTLDataTypeUShort2,
        UShort3 => MTLDataTypeUShort3,
        UShort4 => MTLDataTypeUShort4,

        Char => MTLDataTypeChar,
        Char2 => MTLDataTypeChar2,
        Char3 => MTLDataTypeChar3,
        Char4 => MTLDataTypeChar4,

        UChar => MTLDataTypeUChar,
        UChar2 => MTLDataTypeUChar2,
        UChar3 => MTLDataTypeUChar3,
        UChar4 => MTLDataTypeUChar4,

        Bool => MTLDataTypeBool,
        Bool2 => MTLDataTypeBool2,
        Bool3 => MTLDataTypeBool3,
        Bool4 => MTLDataTypeBool4
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::io::Read;
use std::path;

use toml;

use utils::ServerError;

macro_rules! pop_value {
    ($t:expr, $k:expr, $ty:path, $ty_repr:expr) => (
         try!(match $t.remove($k) {
             Some($ty(x)) => Ok(x),
             Some(_) => Err(Error::ValueError(format!("The {} parameter must be {:?}", $k, $ty_repr))),
             None => Err(Error::ValueError(format!("The {} parameter is missing", $k)))
         })
    )
}

#[derive(Clone)]
pub struct Config {
    pub listen: String,
    pub data_path: path::PathBuf,
    pub use_proxy_headers: bool
}

impl Config {
    pub fn read_file(path: &path::Path) -> Result<Self, ServerError> {
        let path = &env::current_dir().unwrap().join(path);
        let mut s = String::new();
        let mut f = try!(fs::File::open(path));
        try!(f.read_to_string(&mut s));

        let mut parser = toml::Parser::new(&s);
        let mut sections = match parser.parse() {
            Some(x) => x,
            None => return Err(Error::ParserError(parser.errors).into())
        };

        let mut main_section = pop_value!(sections, "main", toml::Value::Table, "a section");
        let listen = pop_value!(main_section, "listen", toml::Value::String, "a string");
        let data_path = path.parent().unwrap().join(pop_value!(main_section, "data_path", toml::Value::String, "a string"));
        let use_proxy_headers = pop_value!(main_section, "use_proxy_headers", toml::Value::Boolean, "a boolean");

        Ok(Config {
            listen: listen,
            data_path: data_path,
            use_proxy_headers: use_proxy_headers
        })
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        ParserError(errors: Vec<toml::ParserError>) {
            display("Multiple errors while parsing configuration: {:?}", errors)
            from()
        }
        ValueError(msg: String) {
            display("{}", msg)
        }
    }
}
<commit_msg>fix formatting<commit_after>use std::env;
use std::fs;
use std::io::Read;
use std::path;

use toml;

use utils::ServerError;

macro_rules! pop_value {
    ($t:expr, $k:expr, $ty:path, $ty_repr:expr) => (
         try!(match $t.remove($k) {
             Some($ty(x)) => Ok(x),
             Some(_) => Err(Error::ValueError(format!("The {} parameter must be {}", $k, $ty_repr))),
             None => Err(Error::ValueError(format!("The {} parameter is missing", $k)))
         })
    )
}

#[derive(Clone)]
pub struct Config {
    pub listen: String,
    pub data_path: path::PathBuf,
    pub use_proxy_headers: bool
}

impl Config {
    pub fn read_file(path: &path::Path) -> Result<Self, ServerError> {
        let path = &env::current_dir().unwrap().join(path);
        let mut s = String::new();
        let mut f = try!(fs::File::open(path));
        try!(f.read_to_string(&mut s));

        let mut parser = toml::Parser::new(&s);
        let mut sections = match parser.parse() {
            Some(x) => x,
            None => return Err(Error::ParserError(parser.errors).into())
        };

        let mut main_section = pop_value!(sections, "main", toml::Value::Table, "a section");
        let listen = pop_value!(main_section, "listen", toml::Value::String, "a string");
        let data_path = path.parent().unwrap().join(pop_value!(main_section, "data_path", toml::Value::String, "a string"));
        let use_proxy_headers = pop_value!(main_section, "use_proxy_headers", toml::Value::Boolean, "a boolean");

        Ok(Config {
            listen: listen,
            data_path: data_path,
            use_proxy_headers: use_proxy_headers
        })
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        ParserError(errors: Vec<toml::ParserError>) {
            display("Multiple errors while parsing configuration: {:?}", errors)
            from()
        }
        ValueError(msg: String) {
            display("{}", msg)
        }
    }
}
<|endoftext|>