<commit_before>extern crate clap;
extern crate error_chain;

use error_chain::*;
use clap::{Arg, ArgMatches, App, SubCommand};
use std::io::prelude::*;
use std::process::exit;
use std::fs::File;
use std::fmt::Display;

error_chain! {
    errors {
    }
}

fn main() {
    let matches = create_arg_parser().get_matches();
    match run(matches) {
        Ok(_) => exit(0),
        Err(e) => {
            report_error(e);
            exit(1)
        }
    }
}

fn run<'a>(args: ArgMatches<'a>) -> Result<()> {
    Ok(())
}

fn report_error<T: Display>(error: T) {
    println!("Error occured, details: {}", error)
}

fn create_arg_parser<'a, 'b>() -> App<'a, 'b> {
    App::new("A rust based clone of the all time classic xxd tool")
        .version("0.1.0")
        .author("Nicola Coretti <nicola.coretti@gmail.com>")
        .about("make a hexdump or the reverse")
        .arg(Arg::with_name("infile")
                 .required(false)
                 .global(true)
                 .index(1)
                 .help("Input file which shall be used (default: stdin)"))
        .arg(Arg::with_name("outfile")
                 .required(false)
                 .global(true)
                 .index(2)
                 .help("File to which the output will be written (default: stdout)"))
        .arg(Arg::with_name("length")
                 .short("l")
                 .long("length")
                 .required(false)
                 .takes_value(true)
                 .global(true)
                 .help("Amount of bytes which shall be read"))
        .arg(Arg::with_name("seek")
                 .short("s")
                 .long("seek")
                 .required(false)
                 .takes_value(true)
                 .global(true)
                 .help("Offset in the file where to start reading"))
        .subcommand(SubCommand::with_name("dump")
                        .about("Dumps an input file in the appropriate output format")
                        .arg(Arg::with_name("format")
                                 .short("f")
                                 .long("format")
                                 .required(false)
                                 .takes_value(true)
                                 .possible_value("hex")
                                 .possible_value("bin")
                                 .possible_value("oct")
                                 .help("Specifies the output format for the value (default: hex)"))
                        .arg(Arg::with_name("columns")
                                 .short("c")
                                 .long("columns")
                                 .required(false)
                                 .takes_value(true)
                                 .help("Specifies the amount of output columns")))
        .subcommand(SubCommand::with_name("convert")
                        .about("Converts input data to a file (e.g. hexstream -> binary file")
                        .arg(Arg::with_name("format")
                                 .short("f")
                                 .long("format")
                                 .required(false)
                                 .takes_value(true)
                                 .possible_value("binary")
                                 .possible_value("c-array")
                                 .possible_value("oct")
                                 .help("Specifies the output format (default: hex)")))
        .subcommand(SubCommand::with_name("generate")
                        .about("Generates a source file containing the specified file as array")
                        .arg(Arg::with_name("template")
                                 .short("t")
                                 .long("template")
                                 .required(false)
                                 .takes_value(true)
                                 .possible_value("c")
                                 .possible_value("cpp")
                                 .possible_value("rs")
                                 .help("Specifies a template file which shall be used for \
                                        generation"))
                        .arg(Arg::with_name("format")
                                 .short("f")
                                 .long("format")
                                 .required(false)
                                 .takes_value(true)
                                 .possible_value("hex")
                                 .possible_value("oct")
                                 .possible_value("dec")
                                 .possible_value("bin")
                                 .help("Specifies the output format (default: hex)"))
                        .arg(Arg::with_name("Separator")
                                 .long("separator")
                                 .required(false)
                                 .takes_value(true)
                                 .help("Specifies the the separator between single values \
                                        (default: ',')")))
}
<commit_msg>Setup error_chain according to the quickstart<commit_after>extern crate clap;
extern crate error_chain;

use clap::{Arg, ArgMatches, App, SubCommand};
use std::io::prelude::*;
use std::process::exit;
use std::fs::File;
use std::fmt::Display;

mod errors {
    use error_chain::*;
    error_chain! {}
}

use errors::*;

fn main() {
    let matches = create_arg_parser().get_matches();
    match run(matches) {
        Ok(_) => exit(0),
        Err(e) => {
            report_error(e);
            exit(1)
        }
    }
}

fn run<'a>(args: ArgMatches<'a>) -> Result<()> {
    Ok(())
}

fn report_error<T: Display>(error: T) {
    println!("Error occured, details: {}", error)
}

fn create_arg_parser<'a, 'b>() -> App<'a, 'b> {
    App::new("A rust based clone of the all time classic xxd tool")
        .version("0.1.0")
        .author("Nicola Coretti <nicola.coretti@gmail.com>")
        .about("make a hexdump or the reverse")
        .arg(Arg::with_name("infile")
                 .required(false)
                 .global(true)
                 .index(1)
                 .help("Input file which shall be used (default: stdin)"))
        .arg(Arg::with_name("outfile")
                 .required(false)
                 .global(true)
                 .index(2)
                 .help("File to which the output will be written (default: stdout)"))
        .arg(Arg::with_name("length")
                 .short("l")
                 .long("length")
                 .required(false)
                 .takes_value(true)
                 .global(true)
                 .help("Amount of bytes which shall be read"))
        .arg(Arg::with_name("seek")
                 .short("s")
                 .long("seek")
                 .required(false)
                 .takes_value(true)
                 .global(true)
                 .help("Offset in the file where to start reading"))
        .subcommand(SubCommand::with_name("dump")
                        .about("Dumps an input file in the appropriate output format")
                        .arg(Arg::with_name("format")
                                 .short("f")
                                 .long("format")
                                 .required(false)
                                 .takes_value(true)
                                 .possible_value("hex")
                                 .possible_value("bin")
                                 .possible_value("oct")
                                 .help("Specifies the output format for the value (default: hex)"))
                        .arg(Arg::with_name("columns")
                                 .short("c")
                                 .long("columns")
                                 .required(false)
                                 .takes_value(true)
                                 .help("Specifies the amount of output columns")))
        .subcommand(SubCommand::with_name("convert")
                        .about("Converts input data to a file (e.g. hexstream -> binary file")
                        .arg(Arg::with_name("format")
                                 .short("f")
                                 .long("format")
                                 .required(false)
                                 .takes_value(true)
                                 .possible_value("binary")
                                 .possible_value("c-array")
                                 .possible_value("oct")
                                 .help("Specifies the output format (default: hex)")))
        .subcommand(SubCommand::with_name("generate")
                        .about("Generates a source file containing the specified file as array")
                        .arg(Arg::with_name("template")
                                 .short("t")
                                 .long("template")
                                 .required(false)
                                 .takes_value(true)
                                 .possible_value("c")
                                 .possible_value("cpp")
                                 .possible_value("rs")
                                 .help("Specifies a template file which shall be used for \
                                        generation"))
                        .arg(Arg::with_name("format")
                                 .short("f")
                                 .long("format")
                                 .required(false)
                                 .takes_value(true)
                                 .possible_value("hex")
                                 .possible_value("oct")
                                 .possible_value("dec")
                                 .possible_value("bin")
                                 .help("Specifies the output format (default: hex)"))
                        .arg(Arg::with_name("Separator")
                                 .long("separator")
                                 .required(false)
                                 .takes_value(true)
                                 .help("Specifies the the separator between single values \
                                        (default: ',')")))
}
<|endoftext|>


<commit_before>use std::io::{TcpListener, TcpStream, BufferedReader};
use std::io::{Acceptor, Listener};

fn main() {
    println!("hello?");

    let socket = TcpListener::bind("127.0.0.1", 8080);

    let mut acceptor = socket.listen();

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => {}
            Ok(stream) => spawn(proc() {
                println!("New client!");
                let mut socket = BufferedReader::new(stream);
                let content = socket.read_to_str();
                println!("{}", content.unwrap());
                println!("Gone!")
            })
        }
    }

    drop(acceptor)
}
<commit_msg>Echo server.<commit_after>use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};

fn connection_handler(stream: TcpStream) {
    let mut sock = stream;
    println!("New client {}", sock.peer_name().unwrap());

    // Read request
    let mut buf = [0,..512];

    match sock.read(buf) {
        Err(e) => { println!("Error detected! {}", e) }
        Ok(count) => {
            println!("Received {} bytes:", count);
            println!("{}", std::str::from_utf8(buf));
        }
    }

    // Answer request
    match sock.write(buf) {
        _ => {}
    }

    println!("Gone!");
    drop(sock);
}

fn main() {
    // Create socket
    let socket = TcpListener::bind("127.0.0.1", 8080);

    // Listen for new connections
    let mut acceptor = socket.listen();

    // Spawn a new process for handling each incoming connection
    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("{}", e) }
            Ok(stream) => spawn(proc() { connection_handler(stream) })
        }
    }

    drop(acceptor);
}
<|endoftext|>


<commit_before>struct Fibonacci {
    current: u32,
    next: u32,
}

impl Iterator for Fibonacci {
    type Item = u32;
    fn next(&mut self) -> Option<u32> {
        let temp = self.current + self.next;
        self.current = self.next;
        self.next = temp;

        // Some is always returned
        Some(self.current)
    }
}

// sequence generator
fn fibonacci() -> Fibonacci {
    Fibonacci {
        current: 1,
        next: 1,
    }
}

fn main() {
    let mut sum:u32 = 0;
    for i in fibonacci().filter(|&x| x % 2 == 0).take_while(|&x| x < 4_000_000) {
        sum += i;
    }

    //let test  = fibonacci()
    //    .filter(|f| f % 2 == 0) // even elements
    //    .take_while(|&v| v <= 4_000_000u32);
    println!("The sum of all even Fibonacci elements with value below 4.000.000 equals to: {}", sum);
}
<commit_msg>removed old code<commit_after>struct Fibonacci {
    current: u32,
    next: u32,
}

impl Iterator for Fibonacci {
    type Item = u32;
    fn next(&mut self) -> Option<u32> {
        let temp = self.current + self.next;
        self.current = self.next;
        self.next = temp;

        // Some is always returned
        Some(self.current)
    }
}

// sequence generator
fn fibonacci() -> Fibonacci {
    Fibonacci {
        current: 1,
        next: 1,
    }
}

fn main() {
    let mut sum:u32 = 0;
    for i in fibonacci().filter(|&x| x % 2 == 0).take_while(|&x| x < 4_000_000) {
        sum += i;
    }

    println!("The sum of all even Fibonacci elements with value below 4.000.000 equals to: {}", sum);
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;

fn write(out: &str) {
    print!("{}", out);
    io::stdout().flush().unwrap_or(());
}

pub fn repl() {
    loop {
        let mut input = String::new();
        write("> ");

        let read_bytes = io::stdin().read_line(&mut input)
            .ok()
            .expect("Failed to read line!");

        if read_bytes == 0 {
            println!("\nExiting...");
            break;
        }

        write(&input);
    }
}<commit_msg>better error handling<commit_after>use std::io;
use std::io::Write;

fn write(out: &str) {
    print!("{}", out);
    match io::stdout().flush() {
        Ok(u)  => u,
        Err(e) => println!("Failed to flush stdout: {}", e),
    };
}

pub fn repl() {
    let mut input = String::new();

    loop {
        write("> ");

        input.clear();
        let bytes_read = match io::stdin().read_line(&mut input) {
            Ok(b)  => b,
            Err(e) => { println!("Failed to read stdin: {}", e); 0 },
        };

        if bytes_read == 0 {
            println!("\nExiting...");
            break;
        }

        write(&input);
    }
}<|endoftext|>


<commit_before>pub mod prometheus;

use std::io::prelude::*;
use chrono::*;
use analyzer;

pub trait Renderer {
    fn render(&mut self, result: Option<analyzer::RequestLogAnalyzerResult>) -> ();
}

pub struct TerminalRenderer {}

impl TerminalRenderer {
    pub fn new() -> TerminalRenderer {
        TerminalRenderer {}
    }
}

impl Renderer for TerminalRenderer {
    fn render(&mut self, result: Option<analyzer::RequestLogAnalyzerResult>) -> () {
        match result {
            Some(result) => {
                println!("count:\t{}", result.count);
                println!("time.avg:\t{}", result.avg);
                println!("time.min:\t{}", result.min);
                println!("time.median:\t{}", result.median);
                println!("time.90percent:\t{}", result.percentile90);
                println!("time.max:\t{}", result.max);
            }
            None => warn!("No matching log lines in file."),
        }
    }
}

pub struct GraphiteRenderer<'a> {
    time: DateTime<UTC>,
    prefix: Option<String>,
    stream: &'a mut Write,
}

impl<'a> GraphiteRenderer<'a> {
    pub fn new(time: DateTime<UTC>,
               prefix: Option<String>,
               stream: &'a mut Write)
               -> GraphiteRenderer<'a> {
        GraphiteRenderer {
            time: time,
            prefix: prefix,
            stream: stream,
        }
    }
}

impl<'a> Renderer for GraphiteRenderer<'a> {
    fn render(&mut self, result: Option<analyzer::RequestLogAnalyzerResult>) -> () {
        match result {
            Some(result) => {
                let prefix_text: String;
                let prefix_separator: &str;

                match self.prefix {
                    Some(ref p) => {
                        prefix_text = p.clone();
                        prefix_separator = ".";
                    }
                    None => {
                        prefix_text = String::from("");
                        prefix_separator = "";
                    }
                };

                let mut write = |text: String| {
                    let _ = self.stream.write(format!("{}{}{} {}\n",
                                                      prefix_text,
                                                      prefix_separator,
                                                      text,
                                                      self.time.timestamp())
                        .as_bytes());
                };

                write(format!("requests.count {}", result.count));
                write(format!("requests.time.max {}", result.max));
                write(format!("requests.time.min {}", result.min));
                write(format!("requests.time.avg {}", result.avg));
                write(format!("requests.time.median {}", result.median));
                write(format!("requests.time.90percent {}", result.percentile90));
            }
            None => warn!("No matching log lines in file."),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::prelude::*;
    use std::str;
    use chrono::*;
    use analyzer;
    use super::*;

    struct MockTcpStream {
        write_calls: Vec<String>,
    }

    impl Write for MockTcpStream {
        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
            self.write_calls.push(str::from_utf8(buf).unwrap().to_string());
            Ok(1)
        }

        fn flush(&mut self) -> io::Result<()> {
            Ok(())
        }
    }

    fn get_result_fixture() -> Option<analyzer::RequestLogAnalyzerResult> {
        Some(analyzer::RequestLogAnalyzerResult {
            count: 3,
            max: 100,
            min: 1,
            avg: 37,
            median: 10,
            percentile90: 100,
        })
    }

    fn get_time_fixture() -> DateTime<UTC> {
        let time: DateTime<UTC> = DateTime::parse_from_str("22/Sep/2016:22:41:59 +0200",
                                                           "%d/%b/%Y:%H:%M:%S %z")
            .unwrap()
            .with_timezone(&UTC);

        time
    }

    #[test]
    fn test_terminal_renderer() {
        let mut renderer = TerminalRenderer::new();

        let result = get_result_fixture();

        renderer.render(result);
    }

    #[test]
    fn test_render_graphite() {
        let mut mock_tcp_stream = MockTcpStream { write_calls: vec![] };

        {
            let mut renderer =
                GraphiteRenderer::new(get_time_fixture(), None, &mut mock_tcp_stream);
            renderer.render(get_result_fixture());
        }

        assert_eq!(&mock_tcp_stream.write_calls[0],
                   "requests.count 3 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[1],
                   "requests.time.max 100 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[2],
                   "requests.time.min 1 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[3],
                   "requests.time.avg 37 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[4],
                   "requests.time.median 10 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[5],
                   "requests.time.90percent 100 1474576919\n");
    }

    #[test]
    fn test_render_graphite_with_prefix() {
        let mut mock_tcp_stream = MockTcpStream { write_calls: vec![] };

        {
            let mut renderer = GraphiteRenderer::new(get_time_fixture(),
                                                     Some(String::from("my_prefix")),
                                                     &mut mock_tcp_stream);
            renderer.render(get_result_fixture());
        }

        assert_eq!(&mock_tcp_stream.write_calls[0],
                   "my_prefix.requests.count 3 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[1],
                   "my_prefix.requests.time.max 100 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[2],
                   "my_prefix.requests.time.min 1 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[3],
                   "my_prefix.requests.time.avg 37 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[4],
                   "my_prefix.requests.time.median 10 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[5],
                   "my_prefix.requests.time.90percent 100 1474576919\n");
    }
}
<commit_msg>Empty result rendering needs to be tested<commit_after>pub mod prometheus;

use std::io::prelude::*;
use chrono::*;
use analyzer;

pub trait Renderer {
    fn render(&mut self, result: Option<analyzer::RequestLogAnalyzerResult>) -> ();
}

pub struct TerminalRenderer {}

impl TerminalRenderer {
    pub fn new() -> TerminalRenderer {
        TerminalRenderer {}
    }
}

impl Renderer for TerminalRenderer {
    fn render(&mut self, result: Option<analyzer::RequestLogAnalyzerResult>) -> () {
        match result {
            Some(result) => {
                println!("count:\t{}", result.count);
                println!("time.avg:\t{}", result.avg);
                println!("time.min:\t{}", result.min);
                println!("time.median:\t{}", result.median);
                println!("time.90percent:\t{}", result.percentile90);
                println!("time.max:\t{}", result.max);
            }
            None => warn!("No matching log lines in file."),
        }
    }
}

pub struct GraphiteRenderer<'a> {
    time: DateTime<UTC>,
    prefix: Option<String>,
    stream: &'a mut Write,
}

impl<'a> GraphiteRenderer<'a> {
    pub fn new(time: DateTime<UTC>,
               prefix: Option<String>,
               stream: &'a mut Write)
               -> GraphiteRenderer<'a> {
        GraphiteRenderer {
            time: time,
            prefix: prefix,
            stream: stream,
        }
    }
}

impl<'a> Renderer for GraphiteRenderer<'a> {
    fn render(&mut self, result: Option<analyzer::RequestLogAnalyzerResult>) -> () {
        match result {
            Some(result) => {
                let prefix_text: String;
                let prefix_separator: &str;

                match self.prefix {
                    Some(ref p) => {
                        prefix_text = p.clone();
                        prefix_separator = ".";
                    }
                    None => {
                        prefix_text = String::from("");
                        prefix_separator = "";
                    }
                };

                let mut write = |text: String| {
                    let _ = self.stream.write(format!("{}{}{} {}\n",
                                                      prefix_text,
                                                      prefix_separator,
                                                      text,
                                                      self.time.timestamp())
                        .as_bytes());
                };

                write(format!("requests.count {}", result.count));
                write(format!("requests.time.max {}", result.max));
                write(format!("requests.time.min {}", result.min));
                write(format!("requests.time.avg {}", result.avg));
                write(format!("requests.time.median {}", result.median));
                write(format!("requests.time.90percent {}", result.percentile90));
            }
            None => warn!("No matching log lines in file."),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::prelude::*;
    use std::str;
    use chrono::*;
    use analyzer;
    use super::*;

    struct MockTcpStream {
        write_calls: Vec<String>,
    }

    impl Write for MockTcpStream {
        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
            self.write_calls.push(str::from_utf8(buf).unwrap().to_string());
            Ok(1)
        }

        fn flush(&mut self) -> io::Result<()> {
            Ok(())
        }
    }

    fn get_result_fixture() -> Option<analyzer::RequestLogAnalyzerResult> {
        Some(analyzer::RequestLogAnalyzerResult {
            count: 3,
            max: 100,
            min: 1,
            avg: 37,
            median: 10,
            percentile90: 100,
        })
    }

    fn get_time_fixture() -> DateTime<UTC> {
        let time: DateTime<UTC> = DateTime::parse_from_str("22/Sep/2016:22:41:59 +0200",
                                                           "%d/%b/%Y:%H:%M:%S %z")
            .unwrap()
            .with_timezone(&UTC);

        time
    }

    #[test]
    fn test_terminal_renderer() {
        let mut renderer = TerminalRenderer::new();

        let result = get_result_fixture();

        renderer.render(result);
    }

    #[test]
    fn test_terminal_renderer_empty() {
        let mut renderer = TerminalRenderer::new();

        renderer.render(None);
    }

    #[test]
    fn test_render_graphite() {
        let mut mock_tcp_stream = MockTcpStream { write_calls: vec![] };

        {
            let mut renderer =
                GraphiteRenderer::new(get_time_fixture(), None, &mut mock_tcp_stream);
            renderer.render(get_result_fixture());
        }

        assert_eq!(&mock_tcp_stream.write_calls[0],
                   "requests.count 3 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[1],
                   "requests.time.max 100 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[2],
                   "requests.time.min 1 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[3],
                   "requests.time.avg 37 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[4],
                   "requests.time.median 10 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[5],
                   "requests.time.90percent 100 1474576919\n");
    }

    #[test]
    fn test_render_graphite_with_prefix() {
        let mut mock_tcp_stream = MockTcpStream { write_calls: vec![] };

        {
            let mut renderer = GraphiteRenderer::new(get_time_fixture(),
                                                     Some(String::from("my_prefix")),
                                                     &mut mock_tcp_stream);
            renderer.render(get_result_fixture());
        }

        assert_eq!(&mock_tcp_stream.write_calls[0],
                   "my_prefix.requests.count 3 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[1],
                   "my_prefix.requests.time.max 100 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[2],
                   "my_prefix.requests.time.min 1 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[3],
                   "my_prefix.requests.time.avg 37 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[4],
                   "my_prefix.requests.time.median 10 1474576919\n");
        assert_eq!(&mock_tcp_stream.write_calls[5],
                   "my_prefix.requests.time.90percent 100 1474576919\n");
    }

    #[test]
    fn test_render_graphite_empty() {
        let mut mock_tcp_stream = MockTcpStream { write_calls: vec![] };

        {
            let mut renderer =
                GraphiteRenderer::new(get_time_fixture(), None, &mut mock_tcp_stream);
            renderer.render(None);
        }

        assert_eq!(mock_tcp_stream.write_calls.len(), 0);
    }
}
<|endoftext|>


<commit_before>use actix_web::{web::Json, web::Query, HttpRequest, Result};
use std::collections::HashMap;

pub mod messages;
use messages::*;

type JsonMessage<U> = Result<Json<OutgoingMsg<U>>>;

// Sends a default response message when requested an undefined resource.
pub fn not_understood(req: HttpRequest) -> JsonMessage<NotUnderstood> {
    let message = NotUnderstood {
        path: destruct_path(req.path()),
    };

    Ok(Json(message.as_outgoing()))
}

// Sends Callback message with information from HttpRequest.
pub fn callback(req: HttpRequest, query: Query<HashMap<String, String>>) -> JsonMessage<Callback> {
    let path = req.path();
    let method = req.method().as_str();

    let callback = Callback {
        path: destruct_path(path),
        request: String::from(method),
        content: query.into_inner(),
    };

    Ok(Json(callback.as_outgoing()))
}

// Takes an HttpRequest path and splits it into an array.
fn destruct_path(path: &str) -> Vec<String> {
    path.split_terminator("/")
        // first element is always blank due to link starting with "/api"
        .skip(1)
        .map(String::from)
        .collect::<Vec<String>>()
}
<commit_msg>Add unit tests for routes<commit_after>use actix_web::{web::Json, web::Query, HttpRequest, Result};
use std::collections::HashMap;

pub mod messages;
use messages::*;

type JsonMessage<U> = Result<Json<OutgoingMsg<U>>>;

// Sends a default response message when requested an undefined resource.
pub fn not_understood(req: HttpRequest) -> JsonMessage<NotUnderstood> {
    let message = NotUnderstood {
        path: destruct_path(req.path()),
    };

    Ok(Json(message.as_outgoing()))
}

// Sends Callback message with information from HttpRequest.
pub fn callback(req: HttpRequest, query: Query<HashMap<String, String>>) -> JsonMessage<Callback> {
    let path = req.path();
    let method = req.method().as_str();

    let callback = Callback {
        path: destruct_path(path),
        request: String::from(method),
        content: query.into_inner(),
    };

    Ok(Json(callback.as_outgoing()))
}

// Takes an HttpRequest path and splits it into an array.
fn destruct_path(path: &str) -> Vec<String> {
    path.split_terminator("/")
        // first element is always blank due to link starting with "/api"
        .skip(1)
        .map(String::from)
        .collect::<Vec<String>>()
}

#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::{http::Method, test::TestRequest};

    #[test]
    fn test_not_understood() {
        // Arrange
        let uri = "/api/phpmyadmin/index.rs";
        let req = gen_request(uri, None);

        // Act
        let result = not_understood(req);

        // Assert
        assert_eq!(result.is_ok(), true);

        let val = result.unwrap().into_inner();
        assert_eq!(val.result_type, "NOT_UNDERSTOOD");
        assert_eq!(val.content.path, vec!["api", "phpmyadmin", "index.rs"]);
    }

    #[test]
    fn test_not_understood_blank() {
        // Arrange
        let uri = "/";
        let req = gen_request(uri, None);

        // Act
        let result = not_understood(req);

        // Assert
        assert_eq!(result.is_ok(), true);

        let val = result.unwrap().into_inner();
        assert_eq!(val.result_type, "NOT_UNDERSTOOD");
        assert_eq!(val.content.path.is_empty(), true);
    }

    #[test]
    fn test_callback_get() {
        // Arrange
        let uri = "/api/phpmyadmin/index.rs";
        let req = gen_request(uri, None);

        let mut ref_map = HashMap::new();
        ref_map.insert("hello".to_string(), "world".to_string());
        ref_map.insert("id".to_string(), "10011".to_string());
        let query = gen_query(&ref_map);

        // Act
        let result = callback(req, query);

        // Assert
        assert_eq!(result.is_ok(), true);

        let val = result.unwrap().into_inner();
        assert_eq!(val.result_type, "CALLBACK");
        assert_eq!(val.content.path, vec!["api", "phpmyadmin", "index.rs"]);
        assert_eq!(val.content.request, "GET");
        assert_eq!(val.content.content, ref_map);
    }

    #[test]
    fn test_callback_post() {
        // Arrange
        let uri = "/api/phpmyadmin/index.rs";
        let req = gen_request(uri, Some(Method::POST));

        let mut ref_map = HashMap::new();
        ref_map.insert("hello".to_string(), "world".to_string());
        ref_map.insert("id".to_string(), "10012".to_string());
        let query = gen_query(&ref_map);

        // Act
        let result = callback(req, query);

        // Assert
        assert_eq!(result.is_ok(), true);

        let val = result.unwrap().into_inner();
        assert_eq!(val.result_type, "CALLBACK");
        assert_eq!(val.content.path, vec!["api", "phpmyadmin", "index.rs"]);
        assert_eq!(val.content.request, "POST");
        assert_eq!(val.content.content, ref_map);
    }

    #[test]
    fn test_callback_blank() {
        // Arrange
        let uri = "/";
        let req = gen_request(uri, None);
        let query = Query::from_query("").unwrap();

        // Act
        let result = callback(req, query);

        // Assert
        assert_eq!(result.is_ok(), true);

        let val = result.unwrap().into_inner();
        assert_eq!(val.result_type, "CALLBACK");
        assert_eq!(val.content.path.is_empty(), true);
        assert_eq!(val.content.request, "GET");
        assert_eq!(val.content.content.is_empty(), true);
    }

    #[test]
    fn test_destruct_path() {
        // Arrange
        let path = "/api/storm/breaking";

        // Act
        let result = destruct_path(path);

        // Assert
        assert_eq!(result, vec!["api", "storm", "breaking"]);
    }

    #[test]
    fn test_destruct_path_blank() {
        // Arrange
        let path = "/";

        // Act
        let result = destruct_path(path);

        // Assert
        assert_eq!(result.is_empty(), true);
    }

    #[test]
    fn test_destruct_path_empty() {
        // Arrange
        let path = "";

        // Act
        let result = destruct_path(path);

        // Assert
        assert_eq!(result.is_empty(), true);
    }

    fn gen_request(path: &str, method: Option<Method>) -> HttpRequest {
        TestRequest::with_uri(path)
            .method(method.unwrap_or(Method::GET))
            .to_http_request()
    }

    fn gen_query(map: &HashMap<String, String>) -> Query<HashMap<String, String>> {
        let mut query_str = String::new();
        for (key, val) in map.iter() {
            query_str.push_str(&format!("&{}={}", key, val));
        }

        Query::from_query(&query_str).unwrap()
    }
}
<|endoftext|>


<commit_before>//! Implementation of datasources for `Source`.

use std::io;

/// Abstraction over `io::Read`, `Iterator` and others.
pub trait DataSource {
    /// The type of items this data source produces.
    type Item: Copy + PartialEq;

    /// Populates the supplied buffer with data, returns the number of items written.
    ///
    /// # Notes
    ///
    /// * The number returned must not be larger than the length of the supplied slice.
    ///
    /// * If no data could be written (or is available), or if the slice is of zero-length, `Ok(0)`
    ///   should be returned (includes EOF).
    ///
    /// * The slice must not be read from, may contain uninitialized memory.
    #[inline]
    fn read(&mut self, &mut [Self::Item]) -> io::Result<usize>;
}

/// Implementation of `DataSource` for `io::Read` instances.
// TODO: Tests
#[derive(Debug)]
pub struct ReadDataSource<R: io::Read>(R);

impl<R: io::Read> ReadDataSource<R> {
    /// Creates a new `ReadDataSource` from a `Read` instance.
    #[inline]
    pub fn new(inner: R) -> Self {
        ReadDataSource(inner)
    }

    /// Consumes self to reveal the underlying `Read` instance.
    #[inline]
    pub fn into_inner(self) -> R {
        self.0
    }
}

impl<R: io::Read> DataSource for ReadDataSource<R> {
    type Item = u8;

    #[inline]
    fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
        self.0.read(buffer)
    }
}

/// Implementation of `DataSource` for `Iterator`.
// TODO: Tests
#[derive(Debug)]
pub struct IteratorDataSource<I: Iterator>(I);

impl<I: Iterator> IteratorDataSource<I> {
    /// Creates a new `IteratorDataSource` from an `Iterator` instance.
    #[inline]
    pub fn new(inner: I) -> Self {
        IteratorDataSource(inner)
    }

    /// Consumes self to reveal the underlying `Iterator` instance.
    #[inline]
    pub fn into_inner(self) -> I {
        self.0
    }
}

impl<I: Iterator> DataSource for IteratorDataSource<I>
  where I::Item: Copy + PartialEq {
    type Item = I::Item;

    #[inline]
    fn read(&mut self, buffer: &mut [I::Item]) -> io::Result<usize> {
        let mut n = 0;

        while buffer.len() > n {
            if let Some(i) = self.0.next() {
                buffer[n] = i;
            } else {
                break;
            }

            n += 1;
        }

        Ok(n)
    }
}
<commit_msg>buffer/data_source: add RWDataSource struct and impls<commit_after>//! Implementation of datasources for `Source`.

use std::io;

/// Abstraction over `io::Read`, `Iterator` and others.
pub trait DataSource {
    /// The type of items this data source produces.
    type Item: Copy + PartialEq;

    /// Populates the supplied buffer with data, returns the number of items written.
    ///
    /// # Notes
    ///
    /// * The number returned must not be larger than the length of the supplied slice.
    ///
    /// * If no data could be written (or is available), or if the slice is of zero-length, `Ok(0)`
    ///   should be returned (includes EOF).
    ///
    /// * The slice must not be read from, may contain uninitialized memory.
    #[inline]
    fn read(&mut self, &mut [Self::Item]) -> io::Result<usize>;
}

/// Implementation of `DataSource` for `io::Read` instances.
// TODO: Tests
#[derive(Debug)]
pub struct ReadDataSource<R: io::Read>(R);

impl<R: io::Read> ReadDataSource<R> {
    /// Creates a new `ReadDataSource` from a `Read` instance.
    #[inline]
    pub fn new(inner: R) -> Self {
        ReadDataSource(inner)
    }

    /// Consumes self to reveal the underlying `Read` instance.
    #[inline]
    pub fn into_inner(self) -> R {
        self.0
    }
}

impl<R: io::Read> DataSource for ReadDataSource<R> {
    type Item = u8;

    #[inline]
    fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
        self.0.read(buffer)
    }
}

/// Implementation of `DataSource` for streams (e.g. network connections) that you can `Read` and
/// `Write`. It's really helpful to have the ability to write through the `DataSource` and `Source`
/// objects, because once created, often they take full ownership of your input stream, and when
/// working with bidirectional connections you still need a way to write to them.
#[derive(Debug)]
pub struct RWDataSource<RW: io::Read + io::Write>(RW);

impl<RW: io::Read + io::Write> RWDataSource<RW> {
    /// Creates a new `RWDataSource` from a stream (e.g. network connection).
    pub fn new(inner: RW) -> Self {
        RWDataSource(inner)
    }

    /// Consumes self to reveal the underlying stream.
    #[inline]
    pub fn into_inner(self) -> RW {
        self.0
    }
}

impl<RW: io::Read + io::Write> DataSource for RWDataSource<RW> {
    type Item = u8;

    #[inline]
    fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
        self.0.read(buffer)
    }
}

impl<RW: io::Read + io::Write> io::Write for RWDataSource<RW> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

/// Implementation of `DataSource` for `Iterator`.
// TODO: Tests
#[derive(Debug)]
pub struct IteratorDataSource<I: Iterator>(I);

impl<I: Iterator> IteratorDataSource<I> {
    /// Creates a new `IteratorDataSource` from an `Iterator` instance.
    #[inline]
    pub fn new(inner: I) -> Self {
        IteratorDataSource(inner)
    }

    /// Consumes self to reveal the underlying `Iterator` instance.
    #[inline]
    pub fn into_inner(self) -> I {
        self.0
    }
}

impl<I: Iterator> DataSource for IteratorDataSource<I>
  where I::Item: Copy + PartialEq {
    type Item = I::Item;

    #[inline]
    fn read(&mut self, buffer: &mut [I::Item]) -> io::Result<usize> {
        let mut n = 0;

        while buffer.len() > n {
            if let Some(i) = self.0.next() {
                buffer[n] = i;
            } else {
                break;
            }

            n += 1;
        }

        Ok(n)
    }
}
<|endoftext|>


<commit_before>use curl;
use git2;

use failure::Error;

use crate::util::errors::{CargoResult, HttpNot200};
use crate::util::Config;

pub struct Retry<'a> {
    config: &'a Config,
    remaining: u32,
}

impl<'a> Retry<'a> {
    pub fn new(config: &'a Config) -> CargoResult<Retry<'a>> {
        Ok(Retry {
            config,
            remaining: config.get::<Option<u32>>("net.retry")?.unwrap_or(2),
        })
    }

    pub fn r#try<T>(&mut self, f: impl FnOnce() -> CargoResult<T>) -> CargoResult<Option<T>> {
        match f() {
            Err(ref e) if maybe_spurious(e) && self.remaining > 0 => {
                let msg = format!(
                    "spurious network error ({} tries \
                     remaining): {}",
                    self.remaining, e
                );
                self.config.shell().warn(msg)?;
                self.remaining -= 1;
                Ok(None)
            }
            other => other.map(Some),
        }
    }
}

fn maybe_spurious(err: &Error) -> bool {
    for e in err.iter_chain() {
        if let Some(git_err) = e.downcast_ref::<git2::Error>() {
            match git_err.class() {
                git2::ErrorClass::Net | git2::ErrorClass::Os => return true,
                _ => (),
            }
        }
        if let Some(curl_err) = e.downcast_ref::<curl::Error>() {
            if curl_err.is_couldnt_connect()
                || curl_err.is_couldnt_resolve_proxy()
                || curl_err.is_couldnt_resolve_host()
                || curl_err.is_operation_timedout()
                || curl_err.is_recv_error()
                || curl_err.is_http2_stream_error()
            {
                return true;
            }
        }
        if let Some(not_200) = e.downcast_ref::<HttpNot200>() {
            if 500 <= not_200.code && not_200.code < 600 {
                return true;
            }
        }
    }
    false
}

/// Wrapper method for network call retry logic.
///
/// Retry counts provided by Config object `net.retry`. Config shell outputs
/// a warning on per retry.
///
/// Closure must return a `CargoResult`.
///
/// # Examples
///
/// ```
/// # use crate::cargo::util::{CargoResult, Config};
/// # let download_something = || return Ok(());
/// # let config = Config::default().unwrap();
/// use cargo::util::network;
/// let cargo_result = network::with_retry(&config, || download_something());
/// ```
pub fn with_retry<T, F>(config: &Config, mut callback: F) -> CargoResult<T>
where
    F: FnMut() -> CargoResult<T>,
{
    let mut retry = Retry::new(config)?;
    loop {
        if let Some(ret) = retry.r#try(&mut callback)? {
            return Ok(ret);
        }
    }
}
#[test]
fn with_retry_repeats_the_call_then_works() {
    //Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry
    let error1 = HttpNot200 {
        code: 501,
        url: "Uri".to_string(),
    }
    .into();
    let error2 = HttpNot200 {
        code: 502,
        url: "Uri".to_string(),
    }
    .into();
    let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
    let config = Config::default().unwrap();
    let result = with_retry(&config, || results.pop().unwrap());
    assert_eq!(result.unwrap(), ())
}

#[test]
fn with_retry_finds_nested_spurious_errors() {
    //Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry
    //String error messages are not considered spurious
    let error1 = failure::Error::from(HttpNot200 {
        code: 501,
        url: "Uri".to_string(),
    });
    let error1 = failure::Error::from(error1.context("A non-spurious wrapping err"));
    let error2 = failure::Error::from(HttpNot200 {
        code: 502,
        url: "Uri".to_string(),
    });
    let error2 = failure::Error::from(error2.context("A second chained error"));
    let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
    let config = Config::default().unwrap();
    let result = with_retry(&config, || results.pop().unwrap());
    assert_eq!(result.unwrap(), ())
}

#[test]
fn curle_http2_stream_is_spurious() {
    let code = curl_sys::CURLE_HTTP2_STREAM;
    let err = curl::Error::new(code);
    assert!(maybe_spurious(&err.into()));
}
<commit_msg>Auto merge of #7318 - reitermarkus:ssl-connect-error, r=alexcrichton<commit_after>use curl;
use git2;

use failure::Error;

use crate::util::errors::{CargoResult, HttpNot200};
use crate::util::Config;

pub struct Retry<'a> {
    config: &'a Config,
    remaining: u32,
}

impl<'a> Retry<'a> {
    pub fn new(config: &'a Config) -> CargoResult<Retry<'a>> {
        Ok(Retry {
            config,
            remaining: config.get::<Option<u32>>("net.retry")?.unwrap_or(2),
        })
    }

    pub fn r#try<T>(&mut self, f: impl FnOnce() -> CargoResult<T>) -> CargoResult<Option<T>> {
        match f() {
            Err(ref e) if maybe_spurious(e) && self.remaining > 0 => {
                let msg = format!(
                    "spurious network error ({} tries \
                     remaining): {}",
                    self.remaining, e
                );
                self.config.shell().warn(msg)?;
                self.remaining -= 1;
                Ok(None)
            }
            other => other.map(Some),
        }
    }
}

fn maybe_spurious(err: &Error) -> bool {
    for e in err.iter_chain() {
        if let Some(git_err) = e.downcast_ref::<git2::Error>() {
            match git_err.class() {
                git2::ErrorClass::Net | git2::ErrorClass::Os => return true,
                _ => (),
            }
        }
        if let Some(curl_err) = e.downcast_ref::<curl::Error>() {
            if curl_err.is_couldnt_connect()
                || curl_err.is_couldnt_resolve_proxy()
                || curl_err.is_couldnt_resolve_host()
                || curl_err.is_operation_timedout()
                || curl_err.is_recv_error()
                || curl_err.is_http2_stream_error()
                || curl_err.is_ssl_connect_error()
            {
                return true;
            }
        }
        if let Some(not_200) = e.downcast_ref::<HttpNot200>() {
            if 500 <= not_200.code && not_200.code < 600 {
                return true;
            }
        }
    }
    false
}

/// Wrapper method for network call retry logic.
///
/// Retry counts provided by Config object `net.retry`. Config shell outputs
/// a warning on per retry.
///
/// Closure must return a `CargoResult`.
///
/// # Examples
///
/// ```
/// # use crate::cargo::util::{CargoResult, Config};
/// # let download_something = || return Ok(());
/// # let config = Config::default().unwrap();
/// use cargo::util::network;
/// let cargo_result = network::with_retry(&config, || download_something());
/// ```
pub fn with_retry<T, F>(config: &Config, mut callback: F) -> CargoResult<T>
where
    F: FnMut() -> CargoResult<T>,
{
    let mut retry = Retry::new(config)?;
    loop {
        if let Some(ret) = retry.r#try(&mut callback)? {
            return Ok(ret);
        }
    }
}
#[test]
fn with_retry_repeats_the_call_then_works() {
    //Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry
    let error1 = HttpNot200 {
        code: 501,
        url: "Uri".to_string(),
    }
    .into();
    let error2 = HttpNot200 {
        code: 502,
        url: "Uri".to_string(),
    }
    .into();
    let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
    let config = Config::default().unwrap();
    let result = with_retry(&config, || results.pop().unwrap());
    assert_eq!(result.unwrap(), ())
}

#[test]
fn with_retry_finds_nested_spurious_errors() {
    //Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry
    //String error messages are not considered spurious
    let error1 = failure::Error::from(HttpNot200 {
        code: 501,
        url: "Uri".to_string(),
    });
    let error1 = failure::Error::from(error1.context("A non-spurious wrapping err"));
    let error2 = failure::Error::from(HttpNot200 {
        code: 502,
        url: "Uri".to_string(),
    });
    let error2 = failure::Error::from(error2.context("A second chained error"));
    let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
    let config = Config::default().unwrap();
    let result = with_retry(&config, || results.pop().unwrap());
    assert_eq!(result.unwrap(), ())
}

#[test]
fn curle_http2_stream_is_spurious() {
    let code = curl_sys::CURLE_HTTP2_STREAM;
    let err = curl::Error::new(code);
    assert!(maybe_spurious(&err.into()));
}
<|endoftext|>


<commit_before>use super::*;
use db_key::Key;
use leveldb::database::kv::KV;
use leveldb::database::Database;
use leveldb::error::Error as LevelDBError;
use leveldb::options::{Options, ReadOptions, WriteOptions};
use parking_lot::RwLock;
use std::path::Path;

pub struct LevelDB<K: Key> {
    db: RwLock<Database<K>>,
}

impl<K: Key> LevelDB<K> {
    pub fn open(path: &Path) -> Result<Self, Error> {
        let mut options = Options::new();

        options.create_if_missing = true;

        let db = Database::open(path, options)?;

        Ok(Self {
            db: RwLock::new(db),
        })
    }

    fn read_options(&self) -> ReadOptions<K> {
        ReadOptions::new()
    }

    fn write_options(&self) -> WriteOptions {
        WriteOptions::new()
    }

    fn get_key_for_col(col: &str, key: &[u8]) -> BytesKey {
        let mut col = col.as_bytes().to_vec();
        col.append(&mut key.to_vec());
        BytesKey { key: col }
    }
}

pub struct BytesKey {
    key: Vec<u8>,
}

impl Key for BytesKey {
    fn from_u8(key: &[u8]) -> Self {
        Self { key: key.to_vec() }
    }

    fn as_slice<T, F: Fn(&[u8]) -> T>(&self, f: F) -> T {
        f(self.key.as_slice())
    }
}

impl Store for LevelDB<BytesKey> {
    fn get_bytes(&self, col: &str, key: &[u8]) -> Result<Option<DBValue>, Error> {
        let column_key = Self::get_key_for_col(col, key);

        self.db
            .read()
            .get(self.read_options(), column_key)
            .map_err(Into::into)
    }

    fn put_bytes(&self, col: &str, key: &[u8], val: &[u8]) -> Result<(), Error> {
        let column_key = Self::get_key_for_col(col, key);

        self.db
            .write()
            .put(self.write_options(), column_key, val)
            .map_err(Into::into)
    }

    fn key_exists(&self, col: &str, key: &[u8]) -> Result<bool, Error> {
        let column_key = Self::get_key_for_col(col, key);

        self.db
            .read()
            .get(self.read_options(), column_key)
            .map_err(Into::into)
            .and_then(|val| Ok(val.is_some()))
    }

    fn key_delete(&self, col: &str, key: &[u8]) -> Result<(), Error> {
        let column_key = Self::get_key_for_col(col, key);
        self.db
            .write()
            .delete(self.write_options(), column_key)
            .map_err(Into::into)
    }
}

impl From<LevelDBError> for Error {
    fn from(e: LevelDBError) -> Error {
        Error::DBError {
            message: format!("{:?}", e),
        }
    }
}
<commit_msg>Remove unnecessary RwLock from LevelDB<commit_after>use super::*;
use db_key::Key;
use leveldb::database::kv::KV;
use leveldb::database::Database;
use leveldb::error::Error as LevelDBError;
use leveldb::options::{Options, ReadOptions, WriteOptions};
use std::path::Path;

pub struct LevelDB<K: Key> {
    db: Database<K>,
}

impl<K: Key> LevelDB<K> {
    pub fn open(path: &Path) -> Result<Self, Error> {
        let mut options = Options::new();

        options.create_if_missing = true;

        let db = Database::open(path, options)?;

        Ok(Self { db })
    }

    fn read_options(&self) -> ReadOptions<K> {
        ReadOptions::new()
    }

    fn write_options(&self) -> WriteOptions {
        WriteOptions::new()
    }

    fn get_key_for_col(col: &str, key: &[u8]) -> BytesKey {
        let mut col = col.as_bytes().to_vec();
        col.append(&mut key.to_vec());
        BytesKey { key: col }
    }
}

pub struct BytesKey {
    key: Vec<u8>,
}

impl Key for BytesKey {
    fn from_u8(key: &[u8]) -> Self {
        Self { key: key.to_vec() }
    }

    fn as_slice<T, F: Fn(&[u8]) -> T>(&self, f: F) -> T {
        f(self.key.as_slice())
    }
}

impl Store for LevelDB<BytesKey> {
    fn get_bytes(&self, col: &str, key: &[u8]) -> Result<Option<DBValue>, Error> {
        let column_key = Self::get_key_for_col(col, key);

        self.db
            .get(self.read_options(), column_key)
            .map_err(Into::into)
    }

    fn put_bytes(&self, col: &str, key: &[u8], val: &[u8]) -> Result<(), Error> {
        let column_key = Self::get_key_for_col(col, key);

        self.db
            .put(self.write_options(), column_key, val)
            .map_err(Into::into)
    }

    fn key_exists(&self, col: &str, key: &[u8]) -> Result<bool, Error> {
        let column_key = Self::get_key_for_col(col, key);

        self.db
            .get(self.read_options(), column_key)
            .map_err(Into::into)
            .and_then(|val| Ok(val.is_some()))
    }

    fn key_delete(&self, col: &str, key: &[u8]) -> Result<(), Error> {
        let column_key = Self::get_key_for_col(col, key);
        self.db
            .delete(self.write_options(), column_key)
            .map_err(Into::into)
    }
}

impl From<LevelDBError> for Error {
    fn from(e: LevelDBError) -> Error {
        Error::DBError {
            message: format!("{:?}", e),
        }
    }
}
<|endoftext|>


<commit_before>use crate::widget_base::{Context, MessageReader, Registry};
use std::any::Any;

pub trait AsAny: Any {
    fn as_any(&self) -> &dyn Any;

    fn as_any_mut(&mut self) -> &mut dyn Any;
}

/// A state trait of a widget (the `state`) comes in handy to provide
/// interactivity.  You are not requested to define a `state` for your
/// widget. If you don't you can't change the properties. The `view`
/// of widget will stay static.
///
/// Each defined `state` of a widget inherits the values of its
/// associated properties (`current values`).  To gain the access each
/// state has to derive or implement the
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)
/// and the [`AsAny`] traits.  The defined methods of the `state` will
/// operate on the properties of the widget (the DECS components),
/// which are organized in the tree (parent, children or level
/// entities).
///
/// # Example
///
/// The following code will define a widget called `MyWidget` (the
/// `view`) with an associcated state called `MyState`. The `MyState`
/// structure defines a propery `count` (a level entity), that will
/// store values of type usize.  Inside the `state` trait, the method
/// `init` will manipulate the value of the count property (42). The
/// `update` method will increment the `count` property each time the
/// `view` got dirty and initiates a new render cycle.
///
/// ```rust
/// use orbtk::prelude::*;
///
/// #[derive(Default, AsAny)]
/// struct MyState {
///     count: usize
/// }
///
/// impl State for MyState {
///     fn init(&mut self, _registry: &mut Registry, _ctx: &mut Context) {
///         self.count = 42;
///         println!("MyState initialized.");
///     }
///
///     fn update(&mut self, _registry: &mut Registry, _ctx: &mut Context) {
///         self.count += 1;
///         println("MyState updated.");
///     }
///
///     fn update_post_layout(&mut self, _registry: &mut Registry, _ctx: &mut Context) {
///         println("MyState updated after layout is calculated.");
///     }
/// }
///
/// widget!(MyWidget<MyState>)
/// ```
///
/// [`widget`]: ./trait.Widget.html
/// [`Default`]: (https://doc.rust-lang.org/std/default/trait.Default.html)
/// [`AsAny`]: ./trait.AsAny.html

pub trait State: AsAny {
    /// Init is used to set up the initial state of a widget. The
    /// `state` fields values (level entities) are preset and
    ///  service(s) are registered. This method is called after the
    ///  widget is created.
    ///
    /// # Arguments
    /// * `_registry`: Provides access to the global Service Registry.
    /// * `_ctx`: Represents the context of the current widget.
    /// This structure allows the manipulation of the widget tree.
    fn init(&mut self, _registry: &mut Registry, _ctx: &mut Context) {}

    /// Used to cleanup the state and is called after window close is requested.
    /// # Arguments
    /// * `_registry`: Provides access to the global Service Registry.
    /// * `_ctx`: Represents the context of the current widget.
    /// This structure allows the manipulation of the widget tree.
    fn cleanup(&mut self, _registry: &mut Registry, _ctx: &mut Context) {}

    /// Updates the state of a widget **before layout is calculated**.
    /// When the widget gets `dirty`, that means a property of a
    /// widget is changed or an [`event`] is fired up, the update
    /// cycle is initiated.
    ///
    /// # Arguments * `_registry`: Provides access to the global
    /// Service Registry.
    /// * `_ctx`: Represents the context of the current widget.
    /// This struct allows the manipulation of the widget tree.
    ///
    /// [`event`]: ../trait.Event.html
    fn update(&mut self, _registry: &mut Registry, _ctx: &mut Context) {}

    /// This method is called, when a widget sends a message via the `MessageHandler`.
    /// `messages` will read from the message queue. This will
    /// be called after `update` and before `update_post_layout`.
    ///
    /// # Arguments
    /// * `_messages`: Provides access to messages of the widget.
    /// * `_registry`: Provides access to the global Service Registry.
    /// * `_ctx`: Represents the context of the current widget.Allows manipulation of the widget tree.
    fn messages(&mut self, _messages: MessageReader, _registry: &mut Registry, _ctx: &mut Context) {
    }

    /// Updates the state **after layout is calculated and before rendering**
    /// for the given context when the widget becomes "dirty",
    /// (e.g.: a property of a widget is changed, or an [`event`] is fired)
    ///
    /// # Arguments
    /// * `_registry`: Provides access to the global Service Registry.
    /// * `_ctx`: Represents the context of the current widget.Allows manipulation of the widget tree.
    ///
    /// [`event`]: ../trait.Event.html
    fn update_post_layout(&mut self, _registry: &mut Registry, _ctx: &mut Context) {}
}
<commit_msg>orbtk_core: update state documentation<commit_after>use crate::widget_base::{Context, MessageReader, Registry};
use std::any::Any;

pub trait AsAny: Any {
    fn as_any(&self) -> &dyn Any;

    fn as_any_mut(&mut self) -> &mut dyn Any;
}

/// A state trait of a widget (the `state`) comes in handy to provide
/// interactivity.  You are not requested to define a `state` for your
/// widget. If you don't you can't change the properties. The `view`
/// of widget will stay static.
///
/// Each defined `state` of a widget inherits the values of its
/// associated properties (`current values`).  To gain the access each
/// state has to derive or implement the
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)
/// and the [`AsAny`] traits.  The defined methods of the `state` will
/// operate on the properties of the widget (the DECS components),
/// which are organized in the tree (parent, children or level
/// entities).
///
/// # Example
///
/// The following code will define a widget called `MyWidget` (the
/// `view`) with an associcated state called `MyState`. The `MyState`
/// structure defines a propery `count` (a level entity), that will
/// store values of type usize.  Inside the `state` trait, the method
/// `init` will manipulate the value of the count property (42). The
/// `update` method will increment the `count` property each time the
/// `view` got dirty and initiates a new render cycle.
///
/// ```rust
/// use orbtk::prelude::*;
///
/// #[derive(Default, AsAny)]
/// struct MyState {
///     count: usize
/// }
///
/// impl State for MyState {
///     fn init(&mut self, _registry: &mut Registry, _ctx: &mut Context) {
///         self.count = 42;
///         println!("MyState initialized.");
///     }
///
///     fn update(&mut self, _registry: &mut Registry, _ctx: &mut Context) {
///         self.count += 1;
///         println("MyState updated.");
///     }
///
///     fn update_post_layout(&mut self, _registry: &mut Registry, _ctx: &mut Context) {
///         println("MyState updated after layout is calculated.");
///     }
/// }
///
/// widget!(MyWidget<MyState>)
/// ```
///
/// [`widget`]: ./trait.Widget.html
/// [`Default`]: (https://doc.rust-lang.org/std/default/trait.Default.html)
/// [`AsAny`]: ./trait.AsAny.html

pub trait State: AsAny {
    /// Init is used for setting up the initial state of a widget.
    ///
    /// Within the init process, you preset properties with intended
    /// initial values. You may register service(s).
    /// It is called **after creation** of a widget.
    ///
    /// # Arguments
    /// * `_registry`: Provides access to the global Service Registry.
    /// * `_ctx`: Represents the context of the current widget. Allows manipulation of the widget tree.
    fn init(&mut self, _registry: &mut Registry, _ctx: &mut Context) {}

    /// Cleanup is used to sanitize the sthe state of a widget.
    ///
    /// It is called **after window close** is requested.
    ///
    /// # Arguments
    /// * `_registry`: Provides access to the global Service Registry.
    /// * `_ctx`: Represents the context of the current widget. Allows manipulation of the widget tree.
    fn cleanup(&mut self, _registry: &mut Registry, _ctx: &mut Context) {}

    /// Update is used to update the state of a widget.
    ///
    /// Within the update process, you react on triggered
    /// `events`. You need to adapt, if entities of the given context
    /// are marked **dirty**. Property changes and handler messages
    /// will fire an [`event`].
    /// It is called **before layout calculation** is triggered.
    ///
    /// # Arguments
    /// * `_registry`: Provides access to the global Service Registry.
    /// * `_ctx`: Represents the context of the current widget. Allows manipulation of the widget tree.
    ///
    /// [`event`]: ./trait.Event.html
    fn update(&mut self, _registry: &mut Registry, _ctx: &mut Context) {}

    /// This method is called, when a widget sends a message via the `MessageHandler`.
    /// `messages` will read from the message queue. This will
    /// be called after `update` and before `update_post_layout`.
    ///
    /// # Arguments
    /// * `_messages`: Provides access to messages of the widget.
    /// * `_registry`: Provides access to the global Service Registry.
    /// * `_ctx`: Represents the context of the current widget.Allows manipulation of the widget tree.
    fn messages(&mut self, _messages: MessageReader, _registry: &mut Registry, _ctx: &mut Context) {
    }

    /// Updates the state **after layout is calculated and before rendering**
    /// for the given context when the widget becomes "dirty",
    /// (e.g.: a property of a widget is changed, or an [`event`] is fired)
    ///
    /// # Arguments
    /// * `_registry`: Provides access to the global Service Registry.
    /// * `_ctx`: Represents the context of the current widget.Allows manipulation of the widget tree.
    ///
    /// [`event`]: ./trait.Event.html
    fn update_post_layout(&mut self, _registry: &mut Registry, _ctx: &mut Context) {}
}
<|endoftext|>


<commit_before>/*
This is used to indicate why a scan has failed.
*/
#[deriving(Clone, Eq, PartialEq, Show)]
pub enum ScanError {
	NothingMatched,
	OtherScanError(String, uint),
	ScanIoError(::std::io::IoError),
}

impl ScanError {
	/*
	Takes two `ScanError` values and returns the "most interesting" one.  The general rules are:

	* An IO error takes precedence over anything else.
	* Scan errors which happened further along the input take precedence.  This should hopefully be the error from the most relevant arm.
	*/
	pub fn or(self, other: ScanError) -> ScanError {
		match (self, other) {
			(ScanIoError(ioerr), _) | (_, ScanIoError(ioerr)) => ScanIoError(ioerr),
			(NothingMatched, other) | (other, NothingMatched) => other,
			(OtherScanError(msga, offa), OtherScanError(msgb, offb)) => {
				if offa > offb {
					OtherScanError(msga, offa)
				} else {
					OtherScanError(msgb, offb)
				}
			}
		}
	}
}
<commit_msg>Added String formatter for ScanErrors.<commit_after>use std::fmt;
use std::fmt::{Formatter, FormatError};

/*
This is used to indicate why a scan has failed.
*/
#[deriving(Clone, Eq, PartialEq, Show)]
pub enum ScanError {
	NothingMatched,
	OtherScanError(String, uint),
	ScanIoError(::std::io::IoError),
}

impl ScanError {
	/*
	Takes two `ScanError` values and returns the "most interesting" one.  The general rules are:

	* An IO error takes precedence over anything else.
	* Scan errors which happened further along the input take precedence.  This should hopefully be the error from the most relevant arm.
	*/
	pub fn or(self, other: ScanError) -> ScanError {
		match (self, other) {
			(ScanIoError(ioerr), _) | (_, ScanIoError(ioerr)) => ScanIoError(ioerr),
			(NothingMatched, other) | (other, NothingMatched) => other,
			(OtherScanError(msga, offa), OtherScanError(msgb, offb)) => {
				if offa > offb {
					OtherScanError(msga, offa)
				} else {
					OtherScanError(msgb, offb)
				}
			}
		}
	}
}

impl fmt::String for ScanError {
	fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
		match self {
			&NothingMatched => write!(f, "nothing matched"),
			&OtherScanError(ref msg, at) => write!(f, "at offset {}: {}", at, msg),
			&ScanIoError(ref err) => write!(f, "io error: {}", err),
		}
	}
}
<|endoftext|>


<commit_before>//! # Schemes
//! A scheme is a primitive for handling filesystem syscalls in Redox.
//! Schemes accept paths from the kernel for `open`, and file descriptors that they generate
//! are then passed for operations like `close`, `read`, `write`, etc.
//!
//! The kernel validates paths and file descriptors before they are passed to schemes,
//! also stripping the scheme identifier of paths if necessary.

use alloc::arc::Arc;
use alloc::boxed::Box;
use collections::BTreeMap;
use core::sync::atomic::AtomicUsize;
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};

use syscall::error::*;
use syscall::scheme::Scheme;

use self::debug::DebugScheme;
use self::event::EventScheme;
use self::env::EnvScheme;
use self::initfs::InitFsScheme;
use self::irq::IrqScheme;
use self::memory::MemoryScheme;
use self::null::NullScheme;
use self::pipe::PipeScheme;
use self::root::RootScheme;
use self::sys::SysScheme;
use self::time::TimeScheme;
use self::zero::ZeroScheme;

/// `debug:` - provides access to serial console
pub mod debug;

/// `event:` - allows reading of `Event`s which are registered using `fevent`
pub mod event;

/// `env:` - access and modify environmental variables
pub mod env;

/// `initfs:` - a readonly filesystem used for initializing the system
pub mod initfs;

/// `irq:` - allows userspace handling of IRQs
pub mod irq;

/// When compiled with "live" feature - `disk:` - embedded filesystem for live disk
#[cfg(feature="live")]
pub mod live;

/// `memory:` - a scheme for accessing physical memory
pub mod memory;

/// `null:` - a scheme that will discard all writes, and read no bytes
pub mod null;

/// `pipe:` - used internally by the kernel to implement `pipe`
pub mod pipe;

/// `:` - allows the creation of userspace schemes, tightly dependent on `user`
pub mod root;

/// `sys:` - system information, such as the context list and scheme list
pub mod sys;

/// `time:` - allows reading time, setting timeouts and getting events when they are met
pub mod time;

/// A wrapper around userspace schemes, tightly dependent on `root`
pub mod user;

/// `zero:` - a scheme that will discard all writes, and always fill read buffers with zero
pub mod zero;

/// Limit on number of schemes
pub const SCHEME_MAX_SCHEMES: usize = 65536;

/// Unique identifier for a scheme namespace.
int_like!(SchemeNamespace, AtomicSchemeNamespace, usize, AtomicUsize);

/// Unique identifier for a scheme.
int_like!(SchemeId, AtomicSchemeId, usize, AtomicUsize);

pub const ATOMIC_SCHEMEID_INIT: AtomicSchemeId = AtomicSchemeId::default();

/// Unique identifier for a file descriptor.
int_like!(FileHandle, AtomicFileHandle, usize, AtomicUsize);

/// Scheme list type
pub struct SchemeList {
    map: BTreeMap<SchemeId, Arc<Box<Scheme + Send + Sync>>>,
    names: BTreeMap<SchemeNamespace, BTreeMap<Box<[u8]>, SchemeId>>,
    next_ns: usize,
    next_id: usize
}

impl SchemeList {
    /// Create a new scheme list.
    pub fn new() -> Self {
        let mut list = SchemeList {
            map: BTreeMap::new(),
            names: BTreeMap::new(),
            next_ns: 0,
            next_id: 1
        };
        list.new_root();
        list
    }

    /// Initialize a new namespace
    fn new_ns(&mut self) -> SchemeNamespace {
        let ns = SchemeNamespace(self.next_ns);
        self.next_ns += 1;
        self.names.insert(ns, BTreeMap::new());

        self.insert(ns, Box::new(*b""), |scheme_id| Arc::new(Box::new(RootScheme::new(ns, scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"event"), |_| Arc::new(Box::new(EventScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"env"), |_| Arc::new(Box::new(EnvScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"memory"), |_| Arc::new(Box::new(MemoryScheme))).unwrap();
        self.insert(ns, Box::new(*b"null"), |_| Arc::new(Box::new(NullScheme))).unwrap();
        self.insert(ns, Box::new(*b"sys"), |_| Arc::new(Box::new(SysScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"time"), |scheme_id| Arc::new(Box::new(TimeScheme::new(scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"zero"), |_| Arc::new(Box::new(ZeroScheme))).unwrap();

        ns
    }

    /// Initialize the root namespace
    #[cfg(not(feature="live"))]
    fn new_root(&mut self) {
        // Do common namespace initialization
        let ns = self.new_ns();

        // Debug, Initfs and IRQ are only available in the root namespace. Pipe is special
        self.insert(ns, Box::new(*b"debug"), |scheme_id| Arc::new(Box::new(DebugScheme::new(scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"initfs"), |_| Arc::new(Box::new(InitFsScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"irq"), |scheme_id| Arc::new(Box::new(IrqScheme::new(scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(Box::new(PipeScheme::new(scheme_id)))).unwrap();
    }

    /// Initialize the root namespace - with live disk
    #[cfg(feature="live")]
    fn new_root(&mut self) {
        // Do common namespace initialization
        let ns = self.new_ns();

        // Debug, Disk, Initfs and IRQ are only available in the root namespace. Pipe is special
        self.insert(ns, Box::new(*b"debug"), |scheme_id| Arc::new(Box::new(DebugScheme::new(scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"disk"), |_| Arc::new(Box::new(self::live::DiskScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"initfs"), |_| Arc::new(Box::new(InitFsScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"irq"), |scheme_id| Arc::new(Box::new(IrqScheme::new(scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(Box::new(PipeScheme::new(scheme_id)))).unwrap();
    }

    pub fn make_ns(&mut self, from: SchemeNamespace, names: &[&[u8]]) -> Result<SchemeNamespace> {
        // Create an empty namespace
        let to = self.new_ns();

        // Copy requested scheme IDs
        for name in names.iter() {
            let id = if let Some((id, _scheme)) = self.get_name(from, name) {
                id
            } else {
                return Err(Error::new(ENODEV));
            };

            if let Some(ref mut names) = self.names.get_mut(&to) {
                assert!(names.insert(name.to_vec().into_boxed_slice(), id).is_none());
            } else {
                panic!("scheme namespace not found");
            }
        }

        Ok(to)
    }

    pub fn iter(&self) -> ::collections::btree_map::Iter<SchemeId, Arc<Box<Scheme + Send + Sync>>> {
        self.map.iter()
    }

    pub fn iter_name(&self, ns: SchemeNamespace) -> ::collections::btree_map::Iter<Box<[u8]>, SchemeId> {
        self.names[&ns].iter()
    }

    /// Get the nth scheme.
    pub fn get(&self, id: SchemeId) -> Option<&Arc<Box<Scheme + Send + Sync>>> {
        self.map.get(&id)
    }

    pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc<Box<Scheme + Send + Sync>>)> {
        if let Some(&id) = self.names[&ns].get(name) {
            self.get(id).map(|scheme| (id, scheme))
        } else {
            None
        }
    }

    /// Create a new scheme.
    pub fn insert<F>(&mut self, ns: SchemeNamespace, name: Box<[u8]>, scheme_fn: F) -> Result<SchemeId>
        where F: Fn(SchemeId) -> Arc<Box<Scheme + Send + Sync>>
    {
        if self.names[&ns].contains_key(&name) {
            return Err(Error::new(EEXIST));
        }

        if self.next_id >= SCHEME_MAX_SCHEMES {
            self.next_id = 1;
        }

        while self.map.contains_key(&SchemeId(self.next_id)) {
            self.next_id += 1;
        }

        /* Allow scheme list to grow if required
        if self.next_id >= SCHEME_MAX_SCHEMES {
            return Err(Error::new(EAGAIN));
        }
        */

        let id = SchemeId(self.next_id);
        self.next_id += 1;

        let scheme = scheme_fn(id);

        assert!(self.map.insert(id, scheme).is_none());
        if let Some(ref mut names) = self.names.get_mut(&ns) {
            assert!(names.insert(name, id).is_none());
        } else {
            panic!("scheme namespace not found");
        }
        Ok(id)
    }
}

/// Schemes list
static SCHEMES: Once<RwLock<SchemeList>> = Once::new();

/// Initialize schemes, called if needed
fn init_schemes() -> RwLock<SchemeList> {
    RwLock::new(SchemeList::new())
}

/// Get the global schemes list, const
pub fn schemes() -> RwLockReadGuard<'static, SchemeList> {
    SCHEMES.call_once(init_schemes).read()
}

/// Get the global schemes list, mutable
pub fn schemes_mut() -> RwLockWriteGuard<'static, SchemeList> {
    SCHEMES.call_once(init_schemes).write()
}
<commit_msg>Move location of live disk<commit_after>//! # Schemes
//! A scheme is a primitive for handling filesystem syscalls in Redox.
//! Schemes accept paths from the kernel for `open`, and file descriptors that they generate
//! are then passed for operations like `close`, `read`, `write`, etc.
//!
//! The kernel validates paths and file descriptors before they are passed to schemes,
//! also stripping the scheme identifier of paths if necessary.

use alloc::arc::Arc;
use alloc::boxed::Box;
use collections::BTreeMap;
use core::sync::atomic::AtomicUsize;
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};

use syscall::error::*;
use syscall::scheme::Scheme;

use self::debug::DebugScheme;
use self::event::EventScheme;
use self::env::EnvScheme;
use self::initfs::InitFsScheme;
use self::irq::IrqScheme;
use self::memory::MemoryScheme;
use self::null::NullScheme;
use self::pipe::PipeScheme;
use self::root::RootScheme;
use self::sys::SysScheme;
use self::time::TimeScheme;
use self::zero::ZeroScheme;

/// `debug:` - provides access to serial console
pub mod debug;

/// `event:` - allows reading of `Event`s which are registered using `fevent`
pub mod event;

/// `env:` - access and modify environmental variables
pub mod env;

/// `initfs:` - a readonly filesystem used for initializing the system
pub mod initfs;

/// `irq:` - allows userspace handling of IRQs
pub mod irq;

/// When compiled with "live" feature - `disk:` - embedded filesystem for live disk
#[cfg(feature="live")]
pub mod live;

/// `memory:` - a scheme for accessing physical memory
pub mod memory;

/// `null:` - a scheme that will discard all writes, and read no bytes
pub mod null;

/// `pipe:` - used internally by the kernel to implement `pipe`
pub mod pipe;

/// `:` - allows the creation of userspace schemes, tightly dependent on `user`
pub mod root;

/// `sys:` - system information, such as the context list and scheme list
pub mod sys;

/// `time:` - allows reading time, setting timeouts and getting events when they are met
pub mod time;

/// A wrapper around userspace schemes, tightly dependent on `root`
pub mod user;

/// `zero:` - a scheme that will discard all writes, and always fill read buffers with zero
pub mod zero;

/// Limit on number of schemes
pub const SCHEME_MAX_SCHEMES: usize = 65536;

/// Unique identifier for a scheme namespace.
int_like!(SchemeNamespace, AtomicSchemeNamespace, usize, AtomicUsize);

/// Unique identifier for a scheme.
int_like!(SchemeId, AtomicSchemeId, usize, AtomicUsize);

pub const ATOMIC_SCHEMEID_INIT: AtomicSchemeId = AtomicSchemeId::default();

/// Unique identifier for a file descriptor.
int_like!(FileHandle, AtomicFileHandle, usize, AtomicUsize);

/// Scheme list type
pub struct SchemeList {
    map: BTreeMap<SchemeId, Arc<Box<Scheme + Send + Sync>>>,
    names: BTreeMap<SchemeNamespace, BTreeMap<Box<[u8]>, SchemeId>>,
    next_ns: usize,
    next_id: usize
}

impl SchemeList {
    /// Create a new scheme list.
    pub fn new() -> Self {
        let mut list = SchemeList {
            map: BTreeMap::new(),
            names: BTreeMap::new(),
            next_ns: 0,
            next_id: 1
        };
        list.new_root();
        list
    }

    /// Initialize a new namespace
    fn new_ns(&mut self) -> SchemeNamespace {
        let ns = SchemeNamespace(self.next_ns);
        self.next_ns += 1;
        self.names.insert(ns, BTreeMap::new());

        self.insert(ns, Box::new(*b""), |scheme_id| Arc::new(Box::new(RootScheme::new(ns, scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"event"), |_| Arc::new(Box::new(EventScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"env"), |_| Arc::new(Box::new(EnvScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"memory"), |_| Arc::new(Box::new(MemoryScheme))).unwrap();
        self.insert(ns, Box::new(*b"null"), |_| Arc::new(Box::new(NullScheme))).unwrap();
        self.insert(ns, Box::new(*b"sys"), |_| Arc::new(Box::new(SysScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"time"), |scheme_id| Arc::new(Box::new(TimeScheme::new(scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"zero"), |_| Arc::new(Box::new(ZeroScheme))).unwrap();

        ns
    }

    /// Initialize the root namespace
    #[cfg(not(feature="live"))]
    fn new_root(&mut self) {
        // Do common namespace initialization
        let ns = self.new_ns();

        // Debug, Initfs and IRQ are only available in the root namespace. Pipe is special
        self.insert(ns, Box::new(*b"debug"), |scheme_id| Arc::new(Box::new(DebugScheme::new(scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"initfs"), |_| Arc::new(Box::new(InitFsScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"irq"), |scheme_id| Arc::new(Box::new(IrqScheme::new(scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(Box::new(PipeScheme::new(scheme_id)))).unwrap();
    }

    /// Initialize the root namespace - with live disk
    #[cfg(feature="live")]
    fn new_root(&mut self) {
        // Do common namespace initialization
        let ns = self.new_ns();

        // Debug, Disk, Initfs and IRQ are only available in the root namespace. Pipe is special
        self.insert(ns, Box::new(*b"debug"), |scheme_id| Arc::new(Box::new(DebugScheme::new(scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"disk/live"), |_| Arc::new(Box::new(self::live::DiskScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"initfs"), |_| Arc::new(Box::new(InitFsScheme::new()))).unwrap();
        self.insert(ns, Box::new(*b"irq"), |scheme_id| Arc::new(Box::new(IrqScheme::new(scheme_id)))).unwrap();
        self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(Box::new(PipeScheme::new(scheme_id)))).unwrap();
    }

    pub fn make_ns(&mut self, from: SchemeNamespace, names: &[&[u8]]) -> Result<SchemeNamespace> {
        // Create an empty namespace
        let to = self.new_ns();

        // Copy requested scheme IDs
        for name in names.iter() {
            let id = if let Some((id, _scheme)) = self.get_name(from, name) {
                id
            } else {
                return Err(Error::new(ENODEV));
            };

            if let Some(ref mut names) = self.names.get_mut(&to) {
                assert!(names.insert(name.to_vec().into_boxed_slice(), id).is_none());
            } else {
                panic!("scheme namespace not found");
            }
        }

        Ok(to)
    }

    pub fn iter(&self) -> ::collections::btree_map::Iter<SchemeId, Arc<Box<Scheme + Send + Sync>>> {
        self.map.iter()
    }

    pub fn iter_name(&self, ns: SchemeNamespace) -> ::collections::btree_map::Iter<Box<[u8]>, SchemeId> {
        self.names[&ns].iter()
    }

    /// Get the nth scheme.
    pub fn get(&self, id: SchemeId) -> Option<&Arc<Box<Scheme + Send + Sync>>> {
        self.map.get(&id)
    }

    pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc<Box<Scheme + Send + Sync>>)> {
        if let Some(&id) = self.names[&ns].get(name) {
            self.get(id).map(|scheme| (id, scheme))
        } else {
            None
        }
    }

    /// Create a new scheme.
    pub fn insert<F>(&mut self, ns: SchemeNamespace, name: Box<[u8]>, scheme_fn: F) -> Result<SchemeId>
        where F: Fn(SchemeId) -> Arc<Box<Scheme + Send + Sync>>
    {
        if self.names[&ns].contains_key(&name) {
            return Err(Error::new(EEXIST));
        }

        if self.next_id >= SCHEME_MAX_SCHEMES {
            self.next_id = 1;
        }

        while self.map.contains_key(&SchemeId(self.next_id)) {
            self.next_id += 1;
        }

        /* Allow scheme list to grow if required
        if self.next_id >= SCHEME_MAX_SCHEMES {
            return Err(Error::new(EAGAIN));
        }
        */

        let id = SchemeId(self.next_id);
        self.next_id += 1;

        let scheme = scheme_fn(id);

        assert!(self.map.insert(id, scheme).is_none());
        if let Some(ref mut names) = self.names.get_mut(&ns) {
            assert!(names.insert(name, id).is_none());
        } else {
            panic!("scheme namespace not found");
        }
        Ok(id)
    }
}

/// Schemes list
static SCHEMES: Once<RwLock<SchemeList>> = Once::new();

/// Initialize schemes, called if needed
fn init_schemes() -> RwLock<SchemeList> {
    RwLock::new(SchemeList::new())
}

/// Get the global schemes list, const
pub fn schemes() -> RwLockReadGuard<'static, SchemeList> {
    SCHEMES.call_once(init_schemes).read()
}

/// Get the global schemes list, mutable
pub fn schemes_mut() -> RwLockWriteGuard<'static, SchemeList> {
    SCHEMES.call_once(init_schemes).write()
}
<|endoftext|>


<commit_before>use libc::{uint32_t, c_void};
use std::mem;
use sys::timer as ll;

pub fn get_ticks() -> u32 {
    unsafe { ll::SDL_GetTicks() }
}

pub fn get_performance_counter() -> u64 {
    unsafe { ll::SDL_GetPerformanceCounter() }
}

pub fn get_performance_frequency() -> u64 {
    unsafe { ll::SDL_GetPerformanceFrequency() }
}

pub fn delay(ms: u32) {
    unsafe { ll::SDL_Delay(ms) }
}

#[unstable = "Unstable because of move to unboxed closures and `box` syntax"]
pub struct Timer<F> {
    callback: Option<Box<F>>,
    _delay: usize,
    raw: ll::SDL_TimerID,
}

impl<F> Timer<F> {
    /// Constructs a new timer using the boxed closure `callback`.
    /// The timer is started immediately, it will be cancelled either:
    ///   * when the timer is dropped
    ///   * or when the callback returns a non-positive continuation interval
    pub fn new(delay: usize, callback: Box<F>) -> Timer<F>
    where F: Fn() -> u32, F: Send {

        let timer = unsafe {
            let timer_id = ll::SDL_AddTimer(delay as u32,
                                            Some(c_timer_callback::<F>),
                                            mem::transmute_copy(&callback));

            Timer {
                callback: Some(callback),
                _delay: delay,
                raw: timer_id,
            }
        };

        return timer;
    }

    pub fn into_inner(mut self) -> Box<F> { self.callback.take().unwrap() }
}

#[unsafe_destructor]
impl<F> Drop for Timer<F> {
    fn drop(&mut self) {
        let ret = unsafe { ll::SDL_RemoveTimer(self.raw) };
        if ret != 1 {
            println!("error dropping timer {}, maybe already removed.", self.raw);
        }
    }
}

extern "C" fn c_timer_callback<F>(_interval: u32, param: *const c_void) -> uint32_t
where F: Fn() -> u32, F: Send {
    unsafe {
        let f: *const F = mem::transmute(param);
        (*f)() as uint32_t
    }
}

#[test]
fn test_timer_runs_multiple_times() {
    use std::sync::{Arc, Mutex};

    let local_num = Arc::new(Mutex::new(0));
    let timer_num = local_num.clone();

    let timer = Timer::new(100, Box::new(move|| {
        // increment up to 10 times (0 -> 9)
        // tick again in 100ms after each increment
        //
        let mut num = timer_num.lock().unwrap();
        if *num < 9 {
            *num += 1;
            100
        } else { 0 }
    }));

    delay(1200);                         // tick the timer at least 10 times w/ 200ms of "buffer"
    let num = local_num.lock().unwrap(); // read the number back
    assert_eq!(*num, 9);                 // it should have incremented at least 10 times...
}

#[test]
fn test_timer_runs_at_least_once() {
    use std::sync::{Arc, Mutex};

    let local_flag = Arc::new(Mutex::new(false));
    let timer_flag = local_flag.clone();

    let timer = Timer::new(500, Box::new(move|| {
        let mut flag = timer_flag.lock().unwrap();
        *flag = true; 0
    }));

    delay(700);
    let flag = local_flag.lock().unwrap();
    assert_eq!(*flag, true);
}

#[test]
fn test_timer_can_be_recreated() {
    use std::sync::{Arc, Mutex};

    let local_num = Arc::new(Mutex::new(0));
    let timer_num = local_num.clone();

    // run the timer once and reclaim its closure
    let mut timer_1 = Timer::new(100, Box::new(move|| {
        let mut num = timer_num.lock().unwrap();
        *num += 1; // increment the number
        0          // do not run timer again
    }));

    // reclaim closure after timer runs
    delay(200);
    let closure = timer_1.into_inner();

    // create a second timer and increment again
    let timer_2 = Timer::new(100, closure);
    delay(200);

    // check that timer was incremented twice
    let num = local_num.lock().unwrap();
    assert_eq!(*num, 2);
}
<commit_msg>(style fixes)<commit_after>use libc::{uint32_t, c_void};
use std::mem;
use sys::timer as ll;

pub fn get_ticks() -> u32 {
    unsafe { ll::SDL_GetTicks() }
}

pub fn get_performance_counter() -> u64 {
    unsafe { ll::SDL_GetPerformanceCounter() }
}

pub fn get_performance_frequency() -> u64 {
    unsafe { ll::SDL_GetPerformanceFrequency() }
}

pub fn delay(ms: u32) {
    unsafe { ll::SDL_Delay(ms) }
}

#[unstable = "Unstable because of move to unboxed closures and `box` syntax"]
pub struct Timer<F> {
    callback: Option<Box<F>>,
    _delay: u32,
    raw: ll::SDL_TimerID,
}

impl<F> Timer<F> {
    /// Constructs a new timer using the boxed closure `callback`.
    /// The timer is started immediately, it will be cancelled either:
    ///   * when the timer is dropped
    ///   * or when the callback returns a non-positive continuation interval
    pub fn new(delay: u32, callback: Box<F>) -> Timer<F>
    where F: Fn() -> u32, F: Send {
        unsafe {
            let timer_id = ll::SDL_AddTimer(delay,
                                            Some(c_timer_callback::<F>),
                                            mem::transmute_copy(&callback));

            Timer {
                callback: Some(callback),
                _delay: delay,
                raw: timer_id,
            }
        }
    }

    pub fn into_inner(mut self) -> Box<F> { self.callback.take().unwrap() }
}

#[unsafe_destructor]
impl<F> Drop for Timer<F> {
    fn drop(&mut self) {
        let ret = unsafe { ll::SDL_RemoveTimer(self.raw) };
        if ret != 1 {
            println!("error dropping timer {}, maybe already removed.", self.raw);
        }
    }
}

extern "C" fn c_timer_callback<F>(_interval: u32, param: *const c_void) -> uint32_t
where F: Fn() -> u32, F: Send {
    unsafe {
        let f: *const F = mem::transmute(param);
        (*f)() as uint32_t
    }
}

#[test]
fn test_timer_runs_multiple_times() {
    use std::sync::{Arc, Mutex};

    let local_num = Arc::new(Mutex::new(0));
    let timer_num = local_num.clone();

    let timer = Timer::new(100, Box::new(move|| {
        // increment up to 10 times (0 -> 9)
        // tick again in 100ms after each increment
        //
        let mut num = timer_num.lock().unwrap();
        if *num < 9 {
            *num += 1;
            100
        } else { 0 }
    }));

    delay(1200);                         // tick the timer at least 10 times w/ 200ms of "buffer"
    let num = local_num.lock().unwrap(); // read the number back
    assert_eq!(*num, 9);                 // it should have incremented at least 10 times...
}

#[test]
fn test_timer_runs_at_least_once() {
    use std::sync::{Arc, Mutex};

    let local_flag = Arc::new(Mutex::new(false));
    let timer_flag = local_flag.clone();

    let timer = Timer::new(500, Box::new(move|| {
        let mut flag = timer_flag.lock().unwrap();
        *flag = true; 0
    }));

    delay(700);
    let flag = local_flag.lock().unwrap();
    assert_eq!(*flag, true);
}

#[test]
fn test_timer_can_be_recreated() {
    use std::sync::{Arc, Mutex};

    let local_num = Arc::new(Mutex::new(0));
    let timer_num = local_num.clone();

    // run the timer once and reclaim its closure
    let mut timer_1 = Timer::new(100, Box::new(move|| {
        let mut num = timer_num.lock().unwrap();
        *num += 1; // increment the number
        0          // do not run timer again
    }));

    // reclaim closure after timer runs
    delay(200);
    let closure = timer_1.into_inner();

    // create a second timer and increment again
    let timer_2 = Timer::new(100, closure);
    delay(200);

    // check that timer was incremented twice
    let num = local_num.lock().unwrap();
    assert_eq!(*num, 2);
}
<|endoftext|>