<commit_before>mod common;

use common::util::TestScenario;

#[cfg(unix)]
use std::os::unix::fs::symlink as symlink_file;
#[cfg(windows)]
use std::os::windows::fs::symlink_file;

#[test]
#[cfg(feature = "ls")]
fn execution_phrase_double() {
    use std::process::Command;

    let scenario = TestScenario::new("ls");
    let output = Command::new(&scenario.bin_path)
        .arg("ls")
        .arg("--some-invalid-arg")
        .output()
        .unwrap();
    assert!(String::from_utf8(output.stderr)
        .unwrap()
        .contains(&format!("USAGE:\n    {} ls", scenario.bin_path.display(),)));
}

#[test]
#[cfg(feature = "ls")]
fn execution_phrase_single() {
    use std::process::Command;

    let scenario = TestScenario::new("ls");
    symlink_file(scenario.bin_path, scenario.fixtures.plus("uu-ls")).unwrap();
    let output = Command::new(scenario.fixtures.plus("uu-ls"))
        .arg("--some-invalid-arg")
        .output()
        .unwrap();
    assert!(String::from_utf8(output.stderr).unwrap().contains(&format!(
        "USAGE:\n    {}",
        scenario.fixtures.plus("uu-ls").display()
    )));
}

#[test]
#[cfg(feature = "sort")]
fn util_name_double() {
    use std::{
        io::Write,
        process::{Command, Stdio},
    };

    let scenario = TestScenario::new("sort");
    let mut child = Command::new(&scenario.bin_path)
        .arg("sort")
        .stdin(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn()
        .unwrap();
    // input invalid utf8 to cause an error
    child.stdin.take().unwrap().write_all(&[255]).unwrap();
    let output = child.wait_with_output().unwrap();
    assert!(String::from_utf8(output.stderr).unwrap().contains("sort: "));
}

#[test]
#[cfg(feature = "sort")]
fn util_name_single() {
    use std::{
        io::Write,
        process::{Command, Stdio},
    };

    let scenario = TestScenario::new("sort");
    symlink_file(scenario.bin_path, scenario.fixtures.plus("uu-sort")).unwrap();
    let mut child = Command::new(scenario.fixtures.plus("uu-sort"))
        .stdin(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn()
        .unwrap();
    // input invalid utf8 to cause an error
    child.stdin.take().unwrap().write_all(&[255]).unwrap();
    let output = child.wait_with_output().unwrap();
    assert!(String::from_utf8(output.stderr).unwrap().contains(&format!(
        "{}: ",
        scenario.fixtures.plus("uu-sort").display()
    )));
}
<commit_msg>tests: silence clippy warnings for unused_imports<commit_after>#![allow(unused_imports)]
mod common;

use common::util::TestScenario;

#[cfg(unix)]
use std::os::unix::fs::symlink as symlink_file;
#[cfg(windows)]
use std::os::windows::fs::symlink_file;

#[test]
#[cfg(feature = "ls")]
fn execution_phrase_double() {
    use std::process::Command;

    let scenario = TestScenario::new("ls");
    let output = Command::new(&scenario.bin_path)
        .arg("ls")
        .arg("--some-invalid-arg")
        .output()
        .unwrap();
    assert!(String::from_utf8(output.stderr)
        .unwrap()
        .contains(&format!("USAGE:\n    {} ls", scenario.bin_path.display(),)));
}

#[test]
#[cfg(feature = "ls")]
#[cfg(any(unix, windows))]
fn execution_phrase_single() {
    use std::process::Command;

    let scenario = TestScenario::new("ls");
    symlink_file(scenario.bin_path, scenario.fixtures.plus("uu-ls")).unwrap();
    let output = Command::new(scenario.fixtures.plus("uu-ls"))
        .arg("--some-invalid-arg")
        .output()
        .unwrap();
    assert!(String::from_utf8(output.stderr).unwrap().contains(&format!(
        "USAGE:\n    {}",
        scenario.fixtures.plus("uu-ls").display()
    )));
}

#[test]
#[cfg(feature = "sort")]
fn util_name_double() {
    use std::{
        io::Write,
        process::{Command, Stdio},
    };

    let scenario = TestScenario::new("sort");
    let mut child = Command::new(&scenario.bin_path)
        .arg("sort")
        .stdin(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn()
        .unwrap();
    // input invalid utf8 to cause an error
    child.stdin.take().unwrap().write_all(&[255]).unwrap();
    let output = child.wait_with_output().unwrap();
    assert!(String::from_utf8(output.stderr).unwrap().contains("sort: "));
}

#[test]
#[cfg(feature = "sort")]
#[cfg(any(unix, windows))]
fn util_name_single() {
    use std::{
        io::Write,
        process::{Command, Stdio},
    };

    let scenario = TestScenario::new("sort");
    symlink_file(scenario.bin_path, scenario.fixtures.plus("uu-sort")).unwrap();
    let mut child = Command::new(scenario.fixtures.plus("uu-sort"))
        .stdin(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn()
        .unwrap();
    // input invalid utf8 to cause an error
    child.stdin.take().unwrap().write_all(&[255]).unwrap();
    let output = child.wait_with_output().unwrap();
    assert!(String::from_utf8(output.stderr).unwrap().contains(&format!(
        "{}: ",
        scenario.fixtures.plus("uu-sort").display()
    )));
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

extern crate yaml;

use yaml::constructor::YamlStandardData;
use yaml::ffi::YamlEncoding;
use std::os;
use std::io::{File, BufferedReader};

fn match_utf8(filename: &str, expected: YamlStandardData) {
    match_file(YamlEncoding::YamlUtf8Encoding, filename, expected);
}

fn match_file(encoding: yaml::ffi::YamlEncoding, filename: &str, expected: YamlStandardData) {
    let this_path = os::args().as_slice()[0].clone();
    let file_path = Path::new(this_path).join("../../tests/source").join(filename);
    println!("{}", file_path.display());
    let mut reader = BufferedReader::new(File::open(&file_path));
    match yaml::parse_io(&mut reader, encoding) {
        Ok(docs) => if docs.len() == 1 {
            assert_eq!(docs.as_slice().head().unwrap(), &expected)
        } else {
            panic!("too many number of documents: {}", docs)
        },
        Err(e) => panic!("parse failure: {}", e)
    }
}

macro_rules! ystr(
    ($e: expr) => (
        YamlStandardData::YamlString($e.to_string())
    )
)

macro_rules! yint(
    ($e: expr) => (
        YamlStandardData::YamlInteger($e)
    )
)

macro_rules! yfloat(
    ($e: expr) => (
        YamlStandardData::YamlFloat($e)
    )
)

macro_rules! yseq(
    ($($e:expr),*) => (
        YamlStandardData::YamlSequence(vec![$(($e),)*])
    )
)

macro_rules! ymap(
    ($($k:expr : $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$((ystr!($k), $v),)*])
    )
)

macro_rules! y_cmp_map(
    ($($k:expr : $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$(($k, $v),)*])
    )
)

#[test]
fn sequence_of_scalars() {
    match_utf8("ball_players.yml", yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa"), ystr!("Ken Griffey")]);
}

#[test]
fn scalar_mappings() {
    match_utf8("player_stat.yml", ymap!{
                                    "hr": yint!(65),
                                    "avg": yfloat!(0.278),
                                    "rbi": yint!(147)
                                })
}

#[test]
fn maps_of_sequences() {
    match_utf8("ball_clubs.yml", ymap!{
                                    "american": yseq![ystr!("Boston Red Sox"), ystr!("Detroit Tigers"), ystr!("New York Yankees")],
                                    "national": yseq![ystr!("New York Mets"), ystr!("Chicago Cubs"), ystr!("Atlanta Braves")]
                                })
}

#[test]
fn sequence_of_maps() {
    match_utf8("multiple_player_stat.yml",
    yseq![
        ymap!{
            "name": ystr!("Mark McGwire"),
            "hr": yint!(65)
        },
        ymap!{
            "name": ystr!("Sammy Sosa"),
            "hr": yint!(63)
        }
    ])
}

#[test]
fn sequence_of_sequences() {
    match_utf8("csv.yml",
    yseq![
        yseq![ystr!("name"), ystr!("hr")],
        yseq![ystr!("Mark McGwire"), yint!(65)],
        yseq![ystr!("Sammy Sosa"), yint!(63)]
    ])
}

#[test]
fn mapping_of_mappings() {
    match_utf8("map_map.yml",
    ymap!{
        "Mark McGwire": ymap!{ "hr": yint!(65) },
        "Sammy Sosa": ymap!{ "hr": yint!(63) }
    })
}

#[test]
fn alias() {
    match_utf8("alias.yml",
    ymap!{
        "hr": yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa")],
        "rbi": yseq![ystr!("Sammy Sosa"), ystr!("Ken Griffey")]
    })
}

#[test]
fn complex_keys() {
    match_utf8("complex_key.yml",
    y_cmp_map!{
        yseq![ystr!("Detroit Tigers"), ystr!("Chicago Cubs")]: yseq![ystr!("2001-07-23")],
        yseq![ystr!("New York Yankees"), ystr!("Atlanta Braves")]: yseq![ystr!("2001-07-02"), ystr!("2001-08-12"), ystr!("2001-08-14")]
    })
}

#[test]
fn block_literal() {
    match_utf8("block_literal.yml", ystr!("\\//||\\/||\n// ||  ||__\n"))
}

#[test]
fn plain_scalar() {
    match_utf8("plain_scalar.yml", ystr!("Mark McGwire's year was crippled by a knee injury."))
}

#[test]
fn quoted_scalar() {
    match_utf8("quoted_scalar.yml",
    ymap!{
        "unicode": ystr!("Sosa did fine.\u{263A}"),
        "control": ystr!("\x081998\t1999\t2000\n"),
        "hexesc":  ystr!("\x13\x10 is \r\n"),
        "single": ystr!(r#""Howdy!" he cried."#),
        "quoted": ystr!(" # not a 'comment'."),
        "tie-fighter": ystr!(r"|\-*-/|")
    })
}

#[test]
fn multi_line_scalar() {
    match_utf8("multi_line_scalar.yml",
    ymap!{
        "plain": ystr!("This unquoted scalar spans many lines."),
        "quoted": ystr!("So does this quoted scalar.\n")
    })
}

#[test]
fn utf16le() {
    match_file(YamlEncoding::YamlUtf16LeEncoding, "utf16le.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}

#[test]
fn utf16be() {
    match_file(YamlEncoding::YamlUtf16BeEncoding, "utf16be.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}
<commit_msg>Macro syntax changes<commit_after>#![feature(macro_rules)]

extern crate yaml;

use yaml::constructor::YamlStandardData;
use yaml::ffi::YamlEncoding;
use std::os;
use std::io::{File, BufferedReader};

fn match_utf8(filename: &str, expected: YamlStandardData) {
    match_file(YamlEncoding::YamlUtf8Encoding, filename, expected);
}

fn match_file(encoding: yaml::ffi::YamlEncoding, filename: &str, expected: YamlStandardData) {
    let this_path = os::args().as_slice()[0].clone();
    let file_path = Path::new(this_path).join("../../tests/source").join(filename);
    println!("{}", file_path.display());
    let mut reader = BufferedReader::new(File::open(&file_path));
    match yaml::parse_io(&mut reader, encoding) {
        Ok(docs) => if docs.len() == 1 {
            assert_eq!(docs.as_slice().head().unwrap(), &expected)
        } else {
            panic!("too many number of documents: {}", docs)
        },
        Err(e) => panic!("parse failure: {}", e)
    }
}

macro_rules! ystr{
    ($e: expr) => (
        YamlStandardData::YamlString($e.to_string())
    )
}

macro_rules! yint{
    ($e: expr) => (
        YamlStandardData::YamlInteger($e)
    )
}

macro_rules! yfloat{
    ($e: expr) => (
        YamlStandardData::YamlFloat($e)
    )
}

macro_rules! yseq{
    ($($e:expr),*) => (
        YamlStandardData::YamlSequence(vec![$(($e),)*])
    )
}

macro_rules! ymap{
    ($($k:expr : $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$((ystr!($k), $v),)*])
    )
}

macro_rules! y_cmp_map{
    ($($k:expr : $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$(($k, $v),)*])
    )
}

#[test]
fn sequence_of_scalars() {
    match_utf8("ball_players.yml", yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa"), ystr!("Ken Griffey")]);
}

#[test]
fn scalar_mappings() {
    match_utf8("player_stat.yml", ymap!{
                                    "hr": yint!(65),
                                    "avg": yfloat!(0.278),
                                    "rbi": yint!(147)
                                })
}

#[test]
fn maps_of_sequences() {
    match_utf8("ball_clubs.yml", ymap!{
                                    "american": yseq![ystr!("Boston Red Sox"), ystr!("Detroit Tigers"), ystr!("New York Yankees")],
                                    "national": yseq![ystr!("New York Mets"), ystr!("Chicago Cubs"), ystr!("Atlanta Braves")]
                                })
}

#[test]
fn sequence_of_maps() {
    match_utf8("multiple_player_stat.yml",
    yseq![
        ymap!{
            "name": ystr!("Mark McGwire"),
            "hr": yint!(65)
        },
        ymap!{
            "name": ystr!("Sammy Sosa"),
            "hr": yint!(63)
        }
    ])
}

#[test]
fn sequence_of_sequences() {
    match_utf8("csv.yml",
    yseq![
        yseq![ystr!("name"), ystr!("hr")],
        yseq![ystr!("Mark McGwire"), yint!(65)],
        yseq![ystr!("Sammy Sosa"), yint!(63)]
    ])
}

#[test]
fn mapping_of_mappings() {
    match_utf8("map_map.yml",
    ymap!{
        "Mark McGwire": ymap!{ "hr": yint!(65) },
        "Sammy Sosa": ymap!{ "hr": yint!(63) }
    })
}

#[test]
fn alias() {
    match_utf8("alias.yml",
    ymap!{
        "hr": yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa")],
        "rbi": yseq![ystr!("Sammy Sosa"), ystr!("Ken Griffey")]
    })
}

#[test]
fn complex_keys() {
    match_utf8("complex_key.yml",
    y_cmp_map!{
        yseq![ystr!("Detroit Tigers"), ystr!("Chicago Cubs")]: yseq![ystr!("2001-07-23")],
        yseq![ystr!("New York Yankees"), ystr!("Atlanta Braves")]: yseq![ystr!("2001-07-02"), ystr!("2001-08-12"), ystr!("2001-08-14")]
    })
}

#[test]
fn block_literal() {
    match_utf8("block_literal.yml", ystr!("\\//||\\/||\n// ||  ||__\n"))
}

#[test]
fn plain_scalar() {
    match_utf8("plain_scalar.yml", ystr!("Mark McGwire's year was crippled by a knee injury."))
}

#[test]
fn quoted_scalar() {
    match_utf8("quoted_scalar.yml",
    ymap!{
        "unicode": ystr!("Sosa did fine.\u{263A}"),
        "control": ystr!("\x081998\t1999\t2000\n"),
        "hexesc":  ystr!("\x13\x10 is \r\n"),
        "single": ystr!(r#""Howdy!" he cried."#),
        "quoted": ystr!(" # not a 'comment'."),
        "tie-fighter": ystr!(r"|\-*-/|")
    })
}

#[test]
fn multi_line_scalar() {
    match_utf8("multi_line_scalar.yml",
    ymap!{
        "plain": ystr!("This unquoted scalar spans many lines."),
        "quoted": ystr!("So does this quoted scalar.\n")
    })
}

#[test]
fn utf16le() {
    match_file(YamlEncoding::YamlUtf16LeEncoding, "utf16le.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}

#[test]
fn utf16be() {
    match_file(YamlEncoding::YamlUtf16BeEncoding, "utf16be.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}
<|endoftext|>


<commit_before>use opengles;   // FIXME: Should only be for tests.
import glut::{check_loop, create_window, destroy_window, init, init_display_mode, swap_buffers};
import opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, COMPILE_STATUS};
import opengles::gl2::{FRAGMENT_SHADER, LINK_STATUS, NO_ERROR, STATIC_DRAW};
import opengles::gl2::{TRIANGLE_STRIP, VERTEX_SHADER, GLclampf, GLenum};
import opengles::gl2::{GLsizei, GLuint, attach_shader, bind_buffer};
import opengles::gl2::{buffer_data, create_program, clear, clear_color};
import opengles::gl2::{compile_shader, create_shader, draw_arrays};
import opengles::gl2::{enable_vertex_attrib_array, gen_buffers};
import opengles::gl2::{get_attrib_location, get_error, get_program_iv};
import opengles::gl2::{get_shader_info_log, get_shader_iv};
import opengles::gl2::{get_uniform_location, link_program, shader_source};
import opengles::gl2::{use_program, vertex_attrib_pointer_f32};

import comm::{chan, peek, port, recv, send};
import io::println;
import ptr::{addr_of, null};
import str::bytes;
import task::{builder, get_opts, run_listener, set_opts};
import vec::unsafe::to_ptr;

fn fragment_shader_source() -> ~str {
    ~"
    #ifdef GLES2
        precision mediump float;
    #endif

        void main(void) {
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
    "
}

fn vertex_shader_source() -> ~str {
    ~"
        attribute vec3 aVertexPosition;

        /*uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;*/

        void main(void) {
            gl_Position = /*uPMatrix * uMVMatrix **/
                vec4(aVertexPosition, 1.0);
        }
    "
}

fn load_shader(source_str: ~str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, ~[bytes(source_str)]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(#fmt("error: %d", get_error() as int));
        fail ~"failed to compile shader with error";
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(get_shader_info_log(shader_id));
        fail ~"failed to compile shader";
    }
    ret shader_id;
}

class shader_program {
    let program: GLuint;
    let aVertexPosition: c_int;
    /*let uPMatrix: c_int;
    let uMVMatrix: c_int;*/

    new(program: GLuint) {
        self.program = program;
        self.aVertexPosition = get_attrib_location(program, ~"aVertexPosition");
        /*self.uPMatrix = get_uniform_location(program, "uPMatrix");
        self.uMVMatrix = get_uniform_location(program, "uMVMatrix");*/

        enable_vertex_attrib_array(self.aVertexPosition as GLuint);
    }
}

fn init_shaders() -> shader_program {
    let vertex_shader = load_shader(vertex_shader_source(), VERTEX_SHADER);
    let fragment_shader = load_shader(fragment_shader_source(),
                                      FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail ~"failed to initialize program";
    }

    use_program(program);

    ret shader_program(program);
}

fn init_buffers() -> GLuint {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);
    let vertices = ~[
        0.0f32, 1.0f32, 0.0f32,
        1.0f32, 0.0f32, 0.0f32,
        0.0f32, 0.0f32, 0.0f32
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);
    ret triangle_vertex_buffer;
}

fn draw_scene(shader_program: shader_program, vertex_buffer: GLuint) {
    clear_color(0.0f32, 0.0f32, 1.0f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    bind_buffer(ARRAY_BUFFER, vertex_buffer);
    vertex_attrib_pointer_f32(shader_program.aVertexPosition as GLuint,
                              3 as GLint, false, 0 as GLsizei, 0 as GLuint);
    draw_arrays(TRIANGLE_STRIP, 0 as GLint, 3 as GLint);
}

fn display_callback() {
    let program = init_shaders();
    let vertex_buffer = init_buffers();
    draw_scene(program, vertex_buffer);

    swap_buffers();
}

#[test]
fn test_triangle_and_square() unsafe {
    let builder = builder();
    let opts = {
        sched: some({ mode: task::osmain, foreign_stack_size: none })
        with get_opts(builder)
    };
    set_opts(builder, opts);

    let po: port<()> = port();
    let ch = chan(po);
    let _result_ch: chan<()> = run_listener(builder, |_port| {
        init();
        init_display_mode(0 as c_uint);
        let window = create_window(~"Rust GLUT");
        display_func(display_callback);

        let wakeup = port();
        let wakeup_chan = chan(wakeup);
        timer_func(1000, || send(wakeup_chan, ()));

        loop {
            check_loop();

            if peek(wakeup) {
                recv(wakeup);
                send(ch, ());
                destroy_window(window);
                break;
            }
        }
    });

    recv(po);
}

<commit_msg>Change rust-glut test.rs to new task::task_builder interface<commit_after>use opengles;   // FIXME: Should only be for tests.
import glut::{check_loop, create_window, destroy_window, init, init_display_mode, swap_buffers};
import opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, COMPILE_STATUS};
import opengles::gl2::{FRAGMENT_SHADER, LINK_STATUS, NO_ERROR, STATIC_DRAW};
import opengles::gl2::{TRIANGLE_STRIP, VERTEX_SHADER, GLclampf, GLenum};
import opengles::gl2::{GLsizei, GLuint, attach_shader, bind_buffer};
import opengles::gl2::{buffer_data, create_program, clear, clear_color};
import opengles::gl2::{compile_shader, create_shader, draw_arrays};
import opengles::gl2::{enable_vertex_attrib_array, gen_buffers};
import opengles::gl2::{get_attrib_location, get_error, get_program_iv};
import opengles::gl2::{get_shader_info_log, get_shader_iv};
import opengles::gl2::{get_uniform_location, link_program, shader_source};
import opengles::gl2::{use_program, vertex_attrib_pointer_f32};

import comm::{chan, peek, port, recv, send};
import io::println;
import ptr::{addr_of, null};
import str::bytes;
import task::{task_builder, get_opts, run_listener, set_opts};
import vec::unsafe::to_ptr;

fn fragment_shader_source() -> ~str {
    ~"
    #ifdef GLES2
        precision mediump float;
    #endif

        void main(void) {
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
    "
}

fn vertex_shader_source() -> ~str {
    ~"
        attribute vec3 aVertexPosition;

        /*uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;*/

        void main(void) {
            gl_Position = /*uPMatrix * uMVMatrix **/
                vec4(aVertexPosition, 1.0);
        }
    "
}

fn load_shader(source_str: ~str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, ~[bytes(source_str)]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(#fmt("error: %d", get_error() as int));
        fail ~"failed to compile shader with error";
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(get_shader_info_log(shader_id));
        fail ~"failed to compile shader";
    }
    ret shader_id;
}

class shader_program {
    let program: GLuint;
    let aVertexPosition: c_int;
    /*let uPMatrix: c_int;
    let uMVMatrix: c_int;*/

    new(program: GLuint) {
        self.program = program;
        self.aVertexPosition = get_attrib_location(program, ~"aVertexPosition");
        /*self.uPMatrix = get_uniform_location(program, "uPMatrix");
        self.uMVMatrix = get_uniform_location(program, "uMVMatrix");*/

        enable_vertex_attrib_array(self.aVertexPosition as GLuint);
    }
}

fn init_shaders() -> shader_program {
    let vertex_shader = load_shader(vertex_shader_source(), VERTEX_SHADER);
    let fragment_shader = load_shader(fragment_shader_source(),
                                      FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail ~"failed to initialize program";
    }

    use_program(program);

    ret shader_program(program);
}

fn init_buffers() -> GLuint {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);
    let vertices = ~[
        0.0f32, 1.0f32, 0.0f32,
        1.0f32, 0.0f32, 0.0f32,
        0.0f32, 0.0f32, 0.0f32
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);
    ret triangle_vertex_buffer;
}

fn draw_scene(shader_program: shader_program, vertex_buffer: GLuint) {
    clear_color(0.0f32, 0.0f32, 1.0f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    bind_buffer(ARRAY_BUFFER, vertex_buffer);
    vertex_attrib_pointer_f32(shader_program.aVertexPosition as GLuint,
                              3 as GLint, false, 0 as GLsizei, 0 as GLuint);
    draw_arrays(TRIANGLE_STRIP, 0 as GLint, 3 as GLint);
}

fn display_callback() {
    let program = init_shaders();
    let vertex_buffer = init_buffers();
    draw_scene(program, vertex_buffer);

    swap_buffers();
}

#[test]
fn test_triangle_and_square() unsafe {
    let builder = task::task().sched_mode(task::osmain);

    let po: port<()> = port();
    let ch = chan(po);
    let _result_ch: chan<()> = builder.spawn_listener(|_port| {
        init();
        init_display_mode(0 as c_uint);
        let window = create_window(~"Rust GLUT");
        display_func(display_callback);

        let wakeup = port();
        let wakeup_chan = chan(wakeup);
        timer_func(1000, || send(wakeup_chan, ()));

        loop {
            check_loop();

            if peek(wakeup) {
                recv(wakeup);
                send(ch, ());
                destroy_window(window);
                break;
            }
        }
    });

    recv(po);
}

<|endoftext|>


<commit_before>use glut;
use azure;
use geom;

import geom::point::Point2D;
import geom::rect::Rect;
import geom::size::Size2D;
import layers::*;
import scene::*;
import rendergl::*;
import util::convert_rgb32_to_rgb24;

import glut::{DOUBLE, check_loop, create_window, destroy_window, display_func, init};
import glut::{init_display_mode, post_redisplay, swap_buffers, timer_func};

import azure::cairo::CAIRO_FORMAT_RGB24;
import CairoContext = azure::cairo_hl::Context;
import azure::azure_hl::{Color, ColorPattern, DrawTarget};
import azure::cairo_hl::ImageSurface;

import comm::{chan, peek, port, recv, send};
import libc::c_uint;
import os::{getenv, setenv};
import task::{task_builder, get_opts, run_listener, set_opts};

class Renderer {
    let image: @Image;
    let mut image_layer: @ImageLayer;
    let mut t: f32;
    let mut delta: f32;
    let mut render_context: option<RenderContext>;

    new() {
        let cairo_image = ImageSurface(CAIRO_FORMAT_RGB24, 500, 704);

        let draw_target = DrawTarget(cairo_image);
        draw_target.fill_rect(Rect(Point2D(50.0f32, 50.0f32), Size2D(300.0f32, 284.0f32)),
                              ColorPattern(Color(1.0f32, 1.0f32, 0.0f32, 1.0f32)));
        draw_target.flush();

        self.image = @Image(cairo_image.width() as uint, cairo_image.height() as uint, RGB24Format,
                            convert_rgb32_to_rgb24(cairo_image.data()));
        io::println(#fmt("image is %ux%u", self.image.width, self.image.height));

        self.image_layer = @ImageLayer(self.image);

        self.t = 1.0f32;
        self.delta = -0.001f32;

        self.render_context = none;
    }

    fn get_display_callback(this: @Renderer) -> fn@() {
        fn@() {
            (*this).display_callback();
        }
    }

    fn display_callback() {
        alt self.render_context {
            none {
                self.render_context = some(init_render_context());
            }
            some(_) {
                // Nothing to do.
            }
        }
        let context = alt self.render_context {
            none { fail }
            some(ctx) { ctx }
        };

        let t = self.t;
        self.image_layer.common.transform = Matrix4(400.0f32 * t, 0.0f32,       0.0f32, 0.0f32,
                                                    0.0f32,       300.0f32 * t, 0.0f32, 0.0f32,
                                                    0.0f32,       0.0f32,       1.0f32, 0.0f32,
                                                    0.0f32,       0.0f32,       0.0f32, 1.0f32);

        let mut scene = Scene(ImageLayerKind(self.image_layer), Size2D(400.0f32, 300.0f32));
        render_scene(context, scene);

        self.t += self.delta;
        if self.t < 0.0f32 || self.t > 1.0f32 {
            self.delta = -self.delta;
        }

        swap_buffers();

        post_redisplay();
    }
}

#[test]
fn test_triangle_and_square() unsafe {
    let builder = task::task().sched_mode(task::osmain);

    let po: port<()> = port();
    let ch = chan(po);
    let _result_ch: chan<()> = do builder.spawn_listener |_po| {
        let renderer = @Renderer();

        init();
        init_display_mode(DOUBLE as c_uint);
        let window = create_window(~"Rust Layers");
        display_func(renderer.get_display_callback(renderer));

        let wakeup = port();
        let wakeup_chan = chan(wakeup);
        do timer_func(2500) {
            send(wakeup_chan, ());
        }

        loop {
            check_loop();

            if peek(wakeup) {
                recv(wakeup);
                send(ch, ());
                destroy_window(window);
                break;
            }
        }

        send(ch, ());
    };

    recv(po);
}

<commit_msg>Fix task imports in rust-layers test.rs<commit_after>use glut;
use azure;
use geom;

import geom::point::Point2D;
import geom::rect::Rect;
import geom::size::Size2D;
import layers::*;
import scene::*;
import rendergl::*;
import util::convert_rgb32_to_rgb24;

import glut::{DOUBLE, check_loop, create_window, destroy_window, display_func, init};
import glut::{init_display_mode, post_redisplay, swap_buffers, timer_func};

import azure::cairo::CAIRO_FORMAT_RGB24;
import CairoContext = azure::cairo_hl::Context;
import azure::azure_hl::{Color, ColorPattern, DrawTarget};
import azure::cairo_hl::ImageSurface;

import comm::{chan, peek, port, recv, send};
import libc::c_uint;
import os::{getenv, setenv};
import task::task_builder;

class Renderer {
    let image: @Image;
    let mut image_layer: @ImageLayer;
    let mut t: f32;
    let mut delta: f32;
    let mut render_context: option<RenderContext>;

    new() {
        let cairo_image = ImageSurface(CAIRO_FORMAT_RGB24, 500, 704);

        let draw_target = DrawTarget(cairo_image);
        draw_target.fill_rect(Rect(Point2D(50.0f32, 50.0f32), Size2D(300.0f32, 284.0f32)),
                              ColorPattern(Color(1.0f32, 1.0f32, 0.0f32, 1.0f32)));
        draw_target.flush();

        self.image = @Image(cairo_image.width() as uint, cairo_image.height() as uint, RGB24Format,
                            convert_rgb32_to_rgb24(cairo_image.data()));
        io::println(#fmt("image is %ux%u", self.image.width, self.image.height));

        self.image_layer = @ImageLayer(self.image);

        self.t = 1.0f32;
        self.delta = -0.001f32;

        self.render_context = none;
    }

    fn get_display_callback(this: @Renderer) -> fn@() {
        fn@() {
            (*this).display_callback();
        }
    }

    fn display_callback() {
        alt self.render_context {
            none {
                self.render_context = some(init_render_context());
            }
            some(_) {
                // Nothing to do.
            }
        }
        let context = alt self.render_context {
            none { fail }
            some(ctx) { ctx }
        };

        let t = self.t;
        self.image_layer.common.transform = Matrix4(400.0f32 * t, 0.0f32,       0.0f32, 0.0f32,
                                                    0.0f32,       300.0f32 * t, 0.0f32, 0.0f32,
                                                    0.0f32,       0.0f32,       1.0f32, 0.0f32,
                                                    0.0f32,       0.0f32,       0.0f32, 1.0f32);

        let mut scene = Scene(ImageLayerKind(self.image_layer), Size2D(400.0f32, 300.0f32));
        render_scene(context, scene);

        self.t += self.delta;
        if self.t < 0.0f32 || self.t > 1.0f32 {
            self.delta = -self.delta;
        }

        swap_buffers();

        post_redisplay();
    }
}

#[test]
fn test_triangle_and_square() unsafe {
    let builder = task::task().sched_mode(task::osmain);

    let po: port<()> = port();
    let ch = chan(po);
    let _result_ch: chan<()> = do builder.spawn_listener |_po| {
        let renderer = @Renderer();

        init();
        init_display_mode(DOUBLE as c_uint);
        let window = create_window(~"Rust Layers");
        display_func(renderer.get_display_callback(renderer));

        let wakeup = port();
        let wakeup_chan = chan(wakeup);
        do timer_func(2500) {
            send(wakeup_chan, ());
        }

        loop {
            check_loop();

            if peek(wakeup) {
                recv(wakeup);
                send(ch, ());
                destroy_window(window);
                break;
            }
        }

        send(ch, ());
    };

    recv(po);
}

<|endoftext|>


<commit_before>extern crate system;

use std::env;
use std::io::{stdin, Read, Write, Result};
use std::str;
use std::sync::Arc;
use std::thread;

use std::cell::UnsafeCell;
use std::fs::File;

/// Redox domain socket
pub struct Socket {
    file: UnsafeCell<File>
}

unsafe impl Send for Socket {}
unsafe impl Sync for Socket {}

impl Socket {
    pub fn open(path: &str) -> Result<Socket> {
        let file = try!(File::open(path));
        Ok(Socket {
            file: UnsafeCell::new(file)
        })
    }

    pub fn receive(&self, buf: &mut [u8]) -> Result<usize> {
        unsafe { (*self.file.get()).read(buf) }
    }

    pub fn send(&self, buf: &[u8]) -> Result<usize> {
        unsafe { (*self.file.get()).write(buf) }
    }
}

fn main() {
    let mut args = env::args().skip(1);
    if let Some(path) = args.next() {
        let socket_write = Arc::new(Socket::open(&path).unwrap());
        let socket_read = socket_write.clone();

        println!("USING {}", path);

        thread::spawn(move || {
            loop {
                let mut buffer = [0; 65536];
                let count = socket_read.receive(&mut buffer).unwrap();
                print!("{}", unsafe { str::from_utf8_unchecked(&buffer[..count]) });
            }
        });

        loop {
            let mut buffer = [0; 65536];
            let count = stdin().read(&mut buffer).unwrap();
            socket_write.send(&buffer[..count]).unwrap();
        }
    }
}
<commit_msg>Remove nc<commit_after><|endoftext|>


<commit_before>use core::{usize, u8, u16, u32, u64};
use core::{isize, i8, i16, i32, i64};
use core::{f32, f64};
use core::num::Wrapping;

/// Numbers which have upper and lower bounds
pub trait Bounded {
    // FIXME (#5527): These should be associated constants
    /// returns the smallest finite number this type can represent
    fn min_value() -> Self;
    /// returns the largest finite number this type can represent
    fn max_value() -> Self;
}

macro_rules! bounded_impl {
    ($t:ty, $min:expr, $max:expr) => {
        impl Bounded for $t {
            #[inline]
            fn min_value() -> $t { $min }

            #[inline]
            fn max_value() -> $t { $max }
        }
    }
}

bounded_impl!(usize, usize::MIN, usize::MAX);
bounded_impl!(u8,    u8::MIN,    u8::MAX);
bounded_impl!(u16,   u16::MIN,   u16::MAX);
bounded_impl!(u32,   u32::MIN,   u32::MAX);
bounded_impl!(u64,   u64::MIN,   u64::MAX);

bounded_impl!(isize, isize::MIN, isize::MAX);
bounded_impl!(i8,    i8::MIN,    i8::MAX);
bounded_impl!(i16,   i16::MIN,   i16::MAX);
bounded_impl!(i32,   i32::MIN,   i32::MAX);
bounded_impl!(i64,   i64::MIN,   i64::MAX);

impl<T: Bounded> Bounded for Wrapping<T> {
    fn min_value() -> Self { Wrapping(T::min_value()) }
    fn max_value() -> Self { Wrapping(T::max_value()) }
}

bounded_impl!(f32, f32::MIN, f32::MAX);

macro_rules! for_each_tuple_ {
    ( $m:ident !! ) => (
        $m! { }
    );
    ( $m:ident !! $h:ident, $($t:ident,)* ) => (
        $m! { $h $($t)* }
        for_each_tuple_! { $m !! $($t,)* }
    );
}
macro_rules! for_each_tuple {
    ( $m:ident ) => (
        for_each_tuple_! { $m !! A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, }
    );
}

macro_rules! bounded_tuple {
    ( $($name:ident)* ) => (
        impl<$($name: Bounded,)*> Bounded for ($($name,)*) {
            #[inline]
            fn min_value() -> Self {
                ($($name::min_value(),)*)
            }
            #[inline]
            fn max_value() -> Self {
                ($($name::max_value(),)*)
            }
        }
    );
}

for_each_tuple!(bounded_tuple);
bounded_impl!(f64, f64::MIN, f64::MAX);

#[test]
fn wrapping_bounded() {
    macro_rules! test_wrapping_bounded {
        ($($t:ty)+) => {
            $(
                assert_eq!(Wrapping::<$t>::min_value().0, <$t>::min_value());
                assert_eq!(Wrapping::<$t>::max_value().0, <$t>::max_value());
            )+
        };
    }

    test_wrapping_bounded!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
}

#[test]
fn wrapping_is_bounded() {
    fn require_bounded<T: Bounded>(_: &T) {}
    require_bounded(&Wrapping(42_u32));
    require_bounded(&Wrapping(-42));
}
<commit_msg>Added impls of `Bounded` for `i128` and `u128`<commit_after>use core::{usize, u8, u16, u32, u64};
use core::{isize, i8, i16, i32, i64};
use core::{f32, f64};
use core::num::Wrapping;

/// Numbers which have upper and lower bounds
pub trait Bounded {
    // FIXME (#5527): These should be associated constants
    /// returns the smallest finite number this type can represent
    fn min_value() -> Self;
    /// returns the largest finite number this type can represent
    fn max_value() -> Self;
}

macro_rules! bounded_impl {
    ($t:ty, $min:expr, $max:expr) => {
        impl Bounded for $t {
            #[inline]
            fn min_value() -> $t { $min }

            #[inline]
            fn max_value() -> $t { $max }
        }
    }
}

bounded_impl!(usize, usize::MIN, usize::MAX);
bounded_impl!(u8,    u8::MIN,    u8::MAX);
bounded_impl!(u16,   u16::MIN,   u16::MAX);
bounded_impl!(u32,   u32::MIN,   u32::MAX);
bounded_impl!(u64,   u64::MIN,   u64::MAX);
#[cfg(feature = "i128")]
bounded_impl!(u128,  u128::MIN,  u128::MAX);

bounded_impl!(isize, isize::MIN, isize::MAX);
bounded_impl!(i8,    i8::MIN,    i8::MAX);
bounded_impl!(i16,   i16::MIN,   i16::MAX);
bounded_impl!(i32,   i32::MIN,   i32::MAX);
bounded_impl!(i64,   i64::MIN,   i64::MAX);
#[cfg(feature = "i128")]
bounded_impl!(i128,  i128::MIN,  i128::MAX);

impl<T: Bounded> Bounded for Wrapping<T> {
    fn min_value() -> Self { Wrapping(T::min_value()) }
    fn max_value() -> Self { Wrapping(T::max_value()) }
}

bounded_impl!(f32, f32::MIN, f32::MAX);

macro_rules! for_each_tuple_ {
    ( $m:ident !! ) => (
        $m! { }
    );
    ( $m:ident !! $h:ident, $($t:ident,)* ) => (
        $m! { $h $($t)* }
        for_each_tuple_! { $m !! $($t,)* }
    );
}
macro_rules! for_each_tuple {
    ( $m:ident ) => (
        for_each_tuple_! { $m !! A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, }
    );
}

macro_rules! bounded_tuple {
    ( $($name:ident)* ) => (
        impl<$($name: Bounded,)*> Bounded for ($($name,)*) {
            #[inline]
            fn min_value() -> Self {
                ($($name::min_value(),)*)
            }
            #[inline]
            fn max_value() -> Self {
                ($($name::max_value(),)*)
            }
        }
    );
}

for_each_tuple!(bounded_tuple);
bounded_impl!(f64, f64::MIN, f64::MAX);

#[test]
fn wrapping_bounded() {
    macro_rules! test_wrapping_bounded {
        ($($t:ty)+) => {
            $(
                assert_eq!(Wrapping::<$t>::min_value().0, <$t>::min_value());
                assert_eq!(Wrapping::<$t>::max_value().0, <$t>::max_value());
            )+
        };
    }

    test_wrapping_bounded!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);

    #[cfg(feature = "i128")]
    test_wrapping_bounded!(u128 i128);
}

#[test]
fn wrapping_is_bounded() {
    fn require_bounded<T: Bounded>(_: &T) {}
    require_bounded(&Wrapping(42_u32));
    require_bounded(&Wrapping(-42));
}
<|endoftext|>


<commit_before>use std::cmp::{Ordering};
use std::error::{Error, FromError};
use std::fmt;
use std::hash::{self, Hash, Hasher};
use std::slice::bytes::copy_memory;

use protobuf::MessageStatic;
use rustc_serialize::{self, Decodable, Decoder, Encodable, Encoder};
use rustc_serialize::base64::{self, ToBase64};
use sodiumoxide::crypto::hash::sha512;
use sodiumoxide::crypto::sign::ed25519::{self,
    PUBLICKEYBYTES, SECRETKEYBYTES, SIGNATUREBYTES,
    sign_detached, verify_detached};
use time::now_utc;

use error::{SimplesError, SimplesResult};

pub use sodiumoxide::crypto::hash::sha512::HASHBYTES;
pub use sodiumoxide::crypto::sign::ed25519::{SecretKey, Signature};

pub trait CryptoPrimitive {
    fn bytes(&self) -> &[u8];
}

// HashDigest:

pub struct HashDigest(pub [u8; HASHBYTES]);

pub fn hash(bytes: &[u8]) -> HashDigest {
    HashDigest(sha512::hash(bytes).0)
}

impl HashDigest {
    pub fn from_u64(mut value: u64) -> HashDigest {
        let mut proof_hash = HashDigest([0; HASHBYTES]);
        let mut index = 0us;
        while value > 0u64 {
            proof_hash.0[index] = (value & 0xffu64) as u8;
            value = value >> 8;
            index += 1;
        }
        proof_hash
    }

    pub fn from_bytes(bytes: &[u8]) -> SimplesResult<HashDigest> {
        match bytes.len() != HASHBYTES {
            true => Err(SimplesError::new(&format!(
                "Invalid length for a hash {} != {} (required).",
                bytes.len(), HASHBYTES))),
            false => {
                let mut digest = HashDigest([0; HASHBYTES]);
                copy_memory(&mut digest.0[], bytes);
                Ok(digest)
            }
        }
    }

    pub fn multiply_u8_in_place(&mut self, other: u8) {
        let mut quot = 0u16;
        for index in range(0, HASHBYTES) {
            quot = self.0[index] as u16 * other as u16 + quot;
            self.0[index] = (quot & 0x00ffu16) as u8;
            quot = quot >> 8;
        }
    }

    pub fn add_in_place(&mut self, other: &HashDigest) {
        let mut rem = 0u16;
        for index in range(0, HASHBYTES) {
            rem = self.0[index] as u16  + other.0[index] as u16 + rem;
            self.0[index] = (rem & 0x00ffu16) as u8;
            rem = rem >> 8;
        }
    }
}

impl CryptoPrimitive for HashDigest {
    fn bytes(&self) -> &[u8] { &self.0[] }
}

impl Clone for HashDigest {
    fn clone(&self) -> HashDigest { HashDigest::from_bytes(&self.0[]).unwrap() }
}

impl<C: CryptoPrimitive> PartialEq for C {
    fn eq(&self, other: &C) -> bool { self.bytes() == other.bytes() }
}

// impl<C: CryptoPrimitive> Eq for C {}

impl Eq for HashDigest {}

impl PartialOrd for HashDigest {
    fn partial_cmp(&self, other: &HashDigest) -> Option<Ordering> {
        for (byte1, byte2) in self.0.iter().rev().zip(
            other.0.iter().rev()) {
            if byte1 > byte2 {
                return Some(Ordering::Greater);
            } else if byte2 > byte1 {
                return Some(Ordering::Less);
            }
        }
        return Some(Ordering::Equal);
    }
}

impl Ord for HashDigest {
    fn cmp(&self, other: &HashDigest) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl fmt::Debug for HashDigest {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:?}", &self.0[])
    }
}

impl fmt::Display for HashDigest {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", &self.0[].to_base64(base64::STANDARD))
    }
}

impl Encodable for HashDigest {
    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
        self.0.to_vec().encode(encoder)
    }
}

impl Decodable for HashDigest {
    fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, D::Error> {
        let bytes = &try!(<Vec<u8> as Decodable>::decode(decoder))[];
        let n_bytes = bytes.len();
        match HashDigest::from_bytes(bytes) {
            Ok(digest) => Ok(digest),
            Err(err) => Err(decoder.error(err.description()))
        }
    }
}

// PublicKey:

pub struct PublicKey(pub [u8; PUBLICKEYBYTES]);

pub fn sign(secret_key: &SecretKey, message: &[u8]) -> Signature {
    sign_detached(message, secret_key)
}

pub fn verify_signature(
    public_key: &PublicKey, message: &[u8], signature: &Signature) -> bool {
    verify_detached(signature, message, &ed25519::PublicKey(public_key.0))
}

impl PublicKey {
    pub fn from_bytes(bytes: &[u8]) -> Option<PublicKey> {
        match bytes.len() != PUBLICKEYBYTES {
            true => None,
            false => {
                let mut digest = PublicKey([0; PUBLICKEYBYTES]);
                copy_memory(&mut digest.0[], bytes);
                Some(digest)
            }
        }
    }
}

impl PartialEq for PublicKey {
    fn eq(&self, other: &PublicKey) -> bool { &self.0[] == &other.0[] }
}

impl Eq for PublicKey {}

impl<H: Hasher + hash::Writer> Hash<H> for PublicKey {
    fn hash(&self, state: &mut H) { state.write(&self.0[]); }
}

// SecretKey:

pub fn gen_keypair() -> (PublicKey, SecretKey) {
    let (pk, sk) = ed25519::gen_keypair();
    (PublicKey(pk.0), sk)
}

// Utilities for crypto on protobufs:

pub fn hash_message<M: MessageStatic>(message: &M) -> HashDigest {
    hash(&message.write_to_bytes().unwrap()[])
}

pub fn sign_message<M: MessageStatic>(
    secret_key: &SecretKey, message: &M) -> Signature
{
    let msg_bytes = &message.write_to_bytes().unwrap()[];
    sign(secret_key, msg_bytes)
}

pub fn verify_signed_message<M: MessageStatic>(
    public_key: &PublicKey, message: &M, signature: &Signature) -> bool
{
    let msg_bytes: &[u8] = &message.write_to_bytes().unwrap()[];
    verify_signature(public_key, msg_bytes, signature)
}

pub fn slice_to_pk(bytes: &[u8]) -> Option<PublicKey> {
    if bytes.len() != PUBLICKEYBYTES { return None; }
    let mut key:[u8; PUBLICKEYBYTES] = [0; PUBLICKEYBYTES];
    for i in range(0, PUBLICKEYBYTES) {
        key[i] = bytes[i];
    }
    Some(PublicKey(key))
}

pub fn slice_to_sk(bytes: &[u8]) -> Option<SecretKey> {
    if bytes.len() != SECRETKEYBYTES { return None; }
    let mut key:[u8; SECRETKEYBYTES] = [0; SECRETKEYBYTES];
    for i in range(0, SECRETKEYBYTES) {
        key[i] = bytes[i];
    }
    Some(SecretKey(key))
}

pub fn slice_to_signature(bytes: &[u8]) -> Option<Signature> {
    if bytes.len() != SIGNATUREBYTES { return None; }
    let mut sign:[u8; SIGNATUREBYTES] = [0; SIGNATUREBYTES];
    for i in range(0, SIGNATUREBYTES) {
        sign[i] = bytes[i];
    }
    Some(Signature(sign))
}

// Tests:

#[test]
fn test_digest_from_u64() {
    let mut hash1 = HashDigest::from_u64(2100);
    let mut hash2 = HashDigest::from_u64(65535);

    assert!(hash1.0[0] == 52);
    assert!(hash1.0[1] == 8);
    assert!(hash2.0[0] == 255);
    assert!(hash2.0[1] == 255);
    for i in range(3, HASHBYTES) {
        assert!(hash1.0[i] == 0);
        assert!(hash2.0[i] == 0);
    }
}

#[test]
fn test_digest_multiply_u8() {
    let mut hash1 = HashDigest::from_u64(101);
    let mut hash2 = HashDigest::from_u64(256);
    hash1.multiply_u8_in_place(7);
    hash2.multiply_u8_in_place(2);
    assert!(HashDigest::from_u64(707) == hash1);
    assert!(HashDigest::from_u64(512) == hash2);
    hash1.multiply_u8_in_place(7);
    hash2.multiply_u8_in_place(4);
    assert!(HashDigest::from_u64(4949) == hash1);
    assert!(HashDigest::from_u64(2048) == hash2);
}

#[test]
fn test_digest_add() {
    let mut hash1 = HashDigest::from_u64(101);
    let mut hash2 = HashDigest::from_u64(256);
    hash1.add_in_place(&HashDigest::from_u64(100001));
    hash2.add_in_place(&HashDigest::from_u64(256));
    assert!(HashDigest::from_u64(100102) == hash1);
    assert!(HashDigest::from_u64(512) == hash2);
    hash1.add_in_place(&HashDigest::from_u64(256));
    hash2.add_in_place(&HashDigest::from_u64(1000));
    assert!(HashDigest::from_u64(100358) == hash1);
    assert!(HashDigest::from_u64(1512) == hash2);
}

// #[test]
// fn test_digest_multiply() {
//     let mut hash1 = HashDigest::from_u64(256);
//     let mut hash2 = HashDigest::from_u64(256);
//     hash1.multiply_in_place(&hash2);
//     assert!(hash1.0[0] == 0);
//     assert!(hash1.0[1] == 1);
//     for i in range(1, HASHBYTES) {
//         assert!(hash1.0[i] == 0);
//     }

//     let mut hash3 = HashDigest::from_u64(65536);
//     println!("* hash3: {:?}", hash3);
//     println!("* hash3 == hash3: {}", hash3 == hash3);
//     println!("* hash3 > hash3: {}", hash3 > hash3);
//     println!("* hash3 > hash2: {}", hash3 > hash2);
//     println!("* hash3 < hash2: {}", hash3 < hash2);
//     // hash3.multiply
// }

#[test]
fn test_digest_ord() {
    let hashes = [
        HashDigest::from_u64(0), HashDigest::from_u64(2100),
        HashDigest::from_u64(65535), HashDigest::from_u64(65536),
        HashDigest::from_u64(65536 * 100000)];

    for i in range(0, hashes.len() - 1) {
        for j in range(i + 1, hashes.len()) {
            assert!(hashes[i] < hashes[j]);
            assert!(hashes[j] > hashes[i]);
        }
    }
}

#[test]
fn test_digest_encoding() {
    let hash1 = hash(b"hello world2");
    let hash2 = HashDigest::from_u64(123456);

    let hash1_enc = json::encode(&hash1).unwrap();
    let hash2_enc = json::encode(&hash2).unwrap();

    let hash1_dec: HashDigest = json::decode(&hash1_enc[]).unwrap();
    let hash2_dec: HashDigest = json::decode(&hash2_enc[]).unwrap();

    println!("hash1 = {}", hash1_enc);
    println!("hash2 = {}", hash2_enc);
    println!("hash1_dec = {}", hash1_dec);
    println!("hash2_dec = {}", hash2_dec);

    assert!(hash1 == hash1_dec);
    assert!(hash2 == hash2_dec);
}

// #[test]
// fn test_digest() {
//     let HashDigest(target_hash_bytes) = hash(b"hello world2");
//     let target_hash = HashDigest(target_hash_bytes);
//     let now_secs = now_utc().to_timespec().sec;
//     println!("now_secs = {}", now_secs);
//     println!("target_hash = {:?}", target_hash);
//     for i in range(0, 100) {
//         let HashDigest(hash_bytes) = hash(
//             format!("{}", now_secs + i).as_bytes());
//         let hash = HashDigest(hash_bytes);
//         if hash > target_hash {
//             println!("hash({}) = {:?}", now_secs + i, hash);
//         }
//     }
// }
<commit_msg>Refactored crypto utility Option -> SimplesResult<commit_after>use std::cmp::{Ordering};
use std::error::{Error, FromError};
use std::fmt;
use std::hash::{self, Hash, Hasher};
use std::slice::bytes::copy_memory;

use protobuf::MessageStatic;
use rustc_serialize::{self, Decodable, Decoder, Encodable, Encoder, json};
use rustc_serialize::base64::{self, ToBase64};
use sodiumoxide::crypto::hash::sha512;
use sodiumoxide::crypto::sign::ed25519::{self,
    PUBLICKEYBYTES, SECRETKEYBYTES, SIGNATUREBYTES,
    sign_detached, verify_detached};
use time::now_utc;

use error::{SimplesError, SimplesResult};

pub use sodiumoxide::crypto::hash::sha512::HASHBYTES;
pub use sodiumoxide::crypto::sign::ed25519::{SecretKey, Signature};

pub trait CryptoPrimitive {
    fn bytes(&self) -> &[u8];
}

// HashDigest:

pub struct HashDigest(pub [u8; HASHBYTES]);

pub fn hash(bytes: &[u8]) -> HashDigest {
    HashDigest(sha512::hash(bytes).0)
}

impl HashDigest {
    pub fn from_u64(mut value: u64) -> HashDigest {
        let mut proof_hash = HashDigest([0; HASHBYTES]);
        let mut index = 0us;
        while value > 0u64 {
            proof_hash.0[index] = (value & 0xffu64) as u8;
            value = value >> 8;
            index += 1;
        }
        proof_hash
    }

    pub fn from_bytes(bytes: &[u8]) -> SimplesResult<HashDigest> {
        match bytes.len() != HASHBYTES {
            true => Err(SimplesError::new(&format!(
                "Invalid length for a hash {} != {} (required).",
                bytes.len(), HASHBYTES))),
            false => {
                let mut digest = HashDigest([0; HASHBYTES]);
                copy_memory(&mut digest.0[], bytes);
                Ok(digest)
            }
        }
    }

    pub fn multiply_u8_in_place(&mut self, other: u8) {
        let mut quot = 0u16;
        for index in range(0, HASHBYTES) {
            quot = self.0[index] as u16 * other as u16 + quot;
            self.0[index] = (quot & 0x00ffu16) as u8;
            quot = quot >> 8;
        }
    }

    pub fn add_in_place(&mut self, other: &HashDigest) {
        let mut rem = 0u16;
        for index in range(0, HASHBYTES) {
            rem = self.0[index] as u16  + other.0[index] as u16 + rem;
            self.0[index] = (rem & 0x00ffu16) as u8;
            rem = rem >> 8;
        }
    }
}

impl CryptoPrimitive for HashDigest {
    fn bytes(&self) -> &[u8] { &self.0[] }
}

impl Clone for HashDigest {
    fn clone(&self) -> HashDigest { HashDigest::from_bytes(&self.0[]).unwrap() }
}

impl<C: CryptoPrimitive> PartialEq for C {
    fn eq(&self, other: &C) -> bool { self.bytes() == other.bytes() }
}

// impl<C: CryptoPrimitive> Eq for C {}

impl Eq for HashDigest {}

impl PartialOrd for HashDigest {
    fn partial_cmp(&self, other: &HashDigest) -> Option<Ordering> {
        for (byte1, byte2) in self.0.iter().rev().zip(
            other.0.iter().rev()) {
            if byte1 > byte2 {
                return Some(Ordering::Greater);
            } else if byte2 > byte1 {
                return Some(Ordering::Less);
            }
        }
        return Some(Ordering::Equal);
    }
}

impl Ord for HashDigest {
    fn cmp(&self, other: &HashDigest) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl fmt::Debug for HashDigest {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:?}", &self.0[])
    }
}

impl fmt::Display for HashDigest {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", &self.0[].to_base64(base64::STANDARD))
    }
}

impl Encodable for HashDigest {
    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
        self.0.to_vec().encode(encoder)
    }
}

impl Decodable for HashDigest {
    fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, D::Error> {
        let bytes = &try!(<Vec<u8> as Decodable>::decode(decoder))[];
        let n_bytes = bytes.len();
        match HashDigest::from_bytes(bytes) {
            Ok(digest) => Ok(digest),
            Err(err) => Err(decoder.error(err.description()))
        }
    }
}

// PublicKey:

pub struct PublicKey(pub [u8; PUBLICKEYBYTES]);

pub fn sign(secret_key: &SecretKey, message: &[u8]) -> Signature {
    sign_detached(message, secret_key)
}

pub fn verify_signature(
    public_key: &PublicKey, message: &[u8], signature: &Signature) -> bool {
    verify_detached(signature, message, &ed25519::PublicKey(public_key.0))
}

impl PublicKey {
    pub fn from_bytes(bytes: &[u8]) -> Option<PublicKey> {
        match bytes.len() != PUBLICKEYBYTES {
            true => None,
            false => {
                let mut digest = PublicKey([0; PUBLICKEYBYTES]);
                copy_memory(&mut digest.0[], bytes);
                Some(digest)
            }
        }
    }
}

impl PartialEq for PublicKey {
    fn eq(&self, other: &PublicKey) -> bool { &self.0[] == &other.0[] }
}

impl Eq for PublicKey {}

impl<H: Hasher + hash::Writer> Hash<H> for PublicKey {
    fn hash(&self, state: &mut H) { state.write(&self.0[]); }
}

// SecretKey:

pub fn gen_keypair() -> (PublicKey, SecretKey) {
    let (pk, sk) = ed25519::gen_keypair();
    (PublicKey(pk.0), sk)
}

// Utilities for crypto on protobufs:

pub fn hash_message<M: MessageStatic>(message: &M) -> HashDigest {
    hash(&message.write_to_bytes().unwrap()[])
}

pub fn sign_message<M: MessageStatic>(
    secret_key: &SecretKey, message: &M) -> Signature
{
    let msg_bytes = &message.write_to_bytes().unwrap()[];
    sign(secret_key, msg_bytes)
}

pub fn verify_signed_message<M: MessageStatic>(
    public_key: &PublicKey, message: &M, signature: &Signature) -> bool
{
    let msg_bytes: &[u8] = &message.write_to_bytes().unwrap()[];
    verify_signature(public_key, msg_bytes, signature)
}

pub fn slice_to_pk(bytes: &[u8]) -> SimplesResult<PublicKey> {
    if bytes.len() != PUBLICKEYBYTES {
        return Err(SimplesError::new(
            &format!("Invalid public key length {} != {} (requires)",
                     bytes.len(), PUBLICKEYBYTES)[]));
    }
    let mut key:[u8; PUBLICKEYBYTES] = [0; PUBLICKEYBYTES];
    for i in range(0, PUBLICKEYBYTES) {
        key[i] = bytes[i];
    }
    Ok(PublicKey(key))
}

pub fn slice_to_sk(bytes: &[u8]) -> SimplesResult<SecretKey> {
    if bytes.len() != SECRETKEYBYTES {
        return Err(SimplesError::new(
            &format!("Invalid secret key length {} != {} (requires)",
                     bytes.len(), SECRETKEYBYTES)[]));
    }
    let mut key:[u8; SECRETKEYBYTES] = [0; SECRETKEYBYTES];
    for i in range(0, SECRETKEYBYTES) {
        key[i] = bytes[i];
    }
    Ok(SecretKey(key))
}

pub fn slice_to_signature(bytes: &[u8]) -> SimplesResult<Signature> {
    if bytes.len() != SIGNATUREBYTES {
        return Err(SimplesError::new(
            &format!("Invalid signature length {} != {} (requires)",
                     bytes.len(), SIGNATUREBYTES)[]));
    }
    let mut sign:[u8; SIGNATUREBYTES] = [0; SIGNATUREBYTES];
    for i in range(0, SIGNATUREBYTES) {
        sign[i] = bytes[i];
    }
    Ok(Signature(sign))
}

// Tests:

#[test]
fn test_digest_from_u64() {
    let mut hash1 = HashDigest::from_u64(2100);
    let mut hash2 = HashDigest::from_u64(65535);

    assert!(hash1.0[0] == 52);
    assert!(hash1.0[1] == 8);
    assert!(hash2.0[0] == 255);
    assert!(hash2.0[1] == 255);
    for i in range(3, HASHBYTES) {
        assert!(hash1.0[i] == 0);
        assert!(hash2.0[i] == 0);
    }
}

#[test]
fn test_digest_multiply_u8() {
    let mut hash1 = HashDigest::from_u64(101);
    let mut hash2 = HashDigest::from_u64(256);
    hash1.multiply_u8_in_place(7);
    hash2.multiply_u8_in_place(2);
    assert!(HashDigest::from_u64(707) == hash1);
    assert!(HashDigest::from_u64(512) == hash2);
    hash1.multiply_u8_in_place(7);
    hash2.multiply_u8_in_place(4);
    assert!(HashDigest::from_u64(4949) == hash1);
    assert!(HashDigest::from_u64(2048) == hash2);
}

#[test]
fn test_digest_add() {
    let mut hash1 = HashDigest::from_u64(101);
    let mut hash2 = HashDigest::from_u64(256);
    hash1.add_in_place(&HashDigest::from_u64(100001));
    hash2.add_in_place(&HashDigest::from_u64(256));
    assert!(HashDigest::from_u64(100102) == hash1);
    assert!(HashDigest::from_u64(512) == hash2);
    hash1.add_in_place(&HashDigest::from_u64(256));
    hash2.add_in_place(&HashDigest::from_u64(1000));
    assert!(HashDigest::from_u64(100358) == hash1);
    assert!(HashDigest::from_u64(1512) == hash2);
}

// #[test]
// fn test_digest_multiply() {
//     let mut hash1 = HashDigest::from_u64(256);
//     let mut hash2 = HashDigest::from_u64(256);
//     hash1.multiply_in_place(&hash2);
//     assert!(hash1.0[0] == 0);
//     assert!(hash1.0[1] == 1);
//     for i in range(1, HASHBYTES) {
//         assert!(hash1.0[i] == 0);
//     }

//     let mut hash3 = HashDigest::from_u64(65536);
//     println!("* hash3: {:?}", hash3);
//     println!("* hash3 == hash3: {}", hash3 == hash3);
//     println!("* hash3 > hash3: {}", hash3 > hash3);
//     println!("* hash3 > hash2: {}", hash3 > hash2);
//     println!("* hash3 < hash2: {}", hash3 < hash2);
//     // hash3.multiply
// }

#[test]
fn test_digest_ord() {
    let hashes = [
        HashDigest::from_u64(0), HashDigest::from_u64(2100),
        HashDigest::from_u64(65535), HashDigest::from_u64(65536),
        HashDigest::from_u64(65536 * 100000)];

    for i in range(0, hashes.len() - 1) {
        for j in range(i + 1, hashes.len()) {
            assert!(hashes[i] < hashes[j]);
            assert!(hashes[j] > hashes[i]);
        }
    }
}

#[test]
fn test_digest_encoding() {
    let hash1 = hash(b"hello world2");
    let hash2 = HashDigest::from_u64(123456);

    let hash1_enc = json::encode(&hash1).unwrap();
    let hash2_enc = json::encode(&hash2).unwrap();

    let hash1_dec: HashDigest = json::decode(&hash1_enc[]).unwrap();
    let hash2_dec: HashDigest = json::decode(&hash2_enc[]).unwrap();

    println!("hash1 = {}", hash1_enc);
    println!("hash2 = {}", hash2_enc);
    println!("hash1_dec = {}", hash1_dec);
    println!("hash2_dec = {}", hash2_dec);

    assert!(hash1 == hash1_dec);
    assert!(hash2 == hash2_dec);
}

// #[test]
// fn test_digest() {
//     let HashDigest(target_hash_bytes) = hash(b"hello world2");
//     let target_hash = HashDigest(target_hash_bytes);
//     let now_secs = now_utc().to_timespec().sec;
//     println!("now_secs = {}", now_secs);
//     println!("target_hash = {:?}", target_hash);
//     for i in range(0, 100) {
//         let HashDigest(hash_bytes) = hash(
//             format!("{}", now_secs + i).as_bytes());
//         let hash = HashDigest(hash_bytes);
//         if hash > target_hash {
//             println!("hash({}) = {:?}", now_secs + i, hash);
//         }
//     }
// }
<|endoftext|>


<commit_before>/// The Toml Delete extensions

use toml::Value;

use tokenizer::Token;
use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueDeleteExt {

    /// Extension function for deleting a value in the current toml::Value document
    /// using a custom seperator.
    ///
    /// # Semantics
    ///
    /// The function does _not_ delete non-empty data structures. So deleting `array` from
    ///
    /// ```toml
    /// array = [ 1 ]
    /// ```
    ///
    /// does _not_ work.
    ///
    /// # Return value
    ///
    /// If the delete operation worked correctly, `Ok(Option<Value>)` is returned.
    ///
    /// The `Option<Value>` part is `None` if no value was actually removed as there was no value
    /// there. For example, if you're deleting `table.a` and the Table `table` has no key `a`, then
    /// `Ok(None)` is returned. Also, if you're deleting from an Array, but there is nothing in the
    /// array, or the array is shorter than the index you're deleting.
    /// If the delete operation actually removed something from the toml document, this value is
    /// returned as `Ok(Some(Value))`.
    ///
    /// On failure, `Err(e)` is returned
    ///
    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>>;

    /// Extension function for inserting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueinsertExt::insert_with_seperator`
    fn delete(&mut self, query: &String) -> Result<Option<Value>> {
        self.delete_with_seperator(query, '.')
    }

}

impl TomlValueDeleteExt for Value {

    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;
        use std::ops::Index;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last_token = tokens.pop_last();

        /// Check whether a structure (Table/Array) is empty. If the Value has not these types,
        /// the default value is returned
        #[inline]
        fn is_empty(val: Option<&Value>, default: bool) -> bool {
            val.map(|v| match v {
                    &Value::Table(ref tab) => tab.is_empty(),
                    &Value::Array(ref arr) => arr.is_empty(),
                    _                      => default
                })
                .unwrap_or(default)
        }

        #[inline]
        fn is_table(val: Option<&Value>) -> bool {
            val.map(|v| is_match!(v, &Value::Table(_))).unwrap_or(false)
        }

        #[inline]
        fn is_array(val: Option<&Value>) -> bool {
            val.map(|v| is_match!(v, &Value::Array(_))).unwrap_or(false)
        }

        #[inline]
        fn name_of_val(val: Option<&Value>) -> &'static str {
            val.map(|v| match v {
                &Value::Array(_)    => "Array",
                &Value::Boolean(_)  => "Boolean",
                &Value::Datetime(_) => "Datetime",
                &Value::Float(_)    => "Float",
                &Value::Integer(_)  => "Integer",
                &Value::String(_)   => "String",
                &Value::Table(_)    => "Table",
            }).unwrap_or("None")
        }

        if last_token.is_none() {
            match self {
                &mut Value::Table(ref mut tab) => {
                    match tokens {
                        Token::Identifier { ident, .. } => {
                            if is_empty(tab.get(&ident), true) {
                                Ok(tab.remove(&ident))
                            } else {
                                if is_table(tab.get(&ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyTable(ident.clone());
                                    Err(Error::from(kind))
                                } else if is_array(tab.get(&ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyArray(ident.clone());
                                    Err(Error::from(kind))
                                } else {
                                    let act = name_of_val(tab.get(&ident));
                                    let tbl = "table";
                                    let k   = ErrorKind::CannotAccessBecauseTypeMismatch(tbl, act);
                                    Err(Error::from(k))
                                }
                            }
                        },
                        _ => Ok(None)
                    }
                },
                _ => unimplemented!()
            }
        } else {
            let mut val = try!(resolve(self, &tokens));
            let last_token = last_token.unwrap();
            match val {
                &mut Value::Table(ref mut tab) => {
                    match *last_token {
                        Token::Identifier { ref ident, .. } => {
                            if is_empty(tab.get(ident), true) {
                                Ok(tab.remove(ident))
                            } else {
                                if is_table(tab.get(ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyTable(ident.clone());
                                    Err(Error::from(kind))
                                } else if is_array(tab.get(ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyArray(ident.clone());
                                    Err(Error::from(kind))
                                } else {
                                    let act = name_of_val(tab.get(ident));
                                    let tbl = "table";
                                    let k   = ErrorKind::CannotAccessBecauseTypeMismatch(tbl, act);
                                    Err(Error::from(k))
                                }
                            }
                        },
                        Token::Index { idx, .. } => {
                            unimplemented!()
                        },
                    }
                },
                &mut Value::Array(ref mut arr) => {
                    match *last_token {
                        Token::Identifier { ref ident, .. } => {
                            unimplemented!()
                        },
                        Token::Index { idx, .. } => {
                            if is_empty(Some(&arr.index(idx)), true) {
                                Ok(Some(arr.remove(idx)))
                            } else {
                                unimplemented!()
                            }
                        },
                    }
                },
                _ => {
                    unimplemented!()
                }
            }
        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use error::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_delete_from_empty_document() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.delete_with_seperator(&String::from("a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_from_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_integer() {
        let mut toml : Value = toml_from_str(r#"
        value = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(1)));
    }

    #[test]
    fn test_delete_string() {
        let mut toml : Value = toml_from_str(r#"
        value = "foo"
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::String(_)));
        match res {
            Value::String(ref s) => assert_eq!("foo", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Table(_)));
        match res {
            Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Array(_)));
        match res {
            Value::Array(ref a) => assert!(a.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_nonempty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyTable(_)));
    }

    #[test]
    fn test_delete_nonempty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyArray(_)));
    }

    #[test]
    fn test_delete_int_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        int = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.int"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_array_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        array = []
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.array"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Array(_))));
    }

    #[test]
    fn test_delete_int_from_array_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.array.[0]"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_int_from_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array.[0]"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_int_from_table_from_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ { table = { int = 1 } } ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array.[0].table.int"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_from_array_value() {
        use read::TomlValueReadExt;

        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let mut ary = toml.read_mut(&String::from("array")).unwrap();
        let res     = ary.delete_with_seperator(&String::from("[0]"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_from_int_value() {
        use read::TomlValueReadExt;

        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let mut ary = toml.read_mut(&String::from("array.[0]")).unwrap();
        let res     = ary.delete_with_seperator(&String::from("nonexist"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::QueryingValueAsTable(_)));
    }

    #[test]
    fn test_delete_index_from_non_array() {
        use read::TomlValueReadExt;

        let mut toml : Value = toml_from_str(r#"
        array = 1
        "#).unwrap();

        let mut ary = toml.read_mut(&String::from("array")).unwrap();
        let res     = ary.delete_with_seperator(&String::from("[0]"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotAccessBecauseTypeMismatch(_, _)));
    }

}

<commit_msg>Impl Value::delete_with_seperator to fix test_delete_from_array_value<commit_after>/// The Toml Delete extensions

use toml::Value;

use tokenizer::Token;
use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueDeleteExt {

    /// Extension function for deleting a value in the current toml::Value document
    /// using a custom seperator.
    ///
    /// # Semantics
    ///
    /// The function does _not_ delete non-empty data structures. So deleting `array` from
    ///
    /// ```toml
    /// array = [ 1 ]
    /// ```
    ///
    /// does _not_ work.
    ///
    /// # Return value
    ///
    /// If the delete operation worked correctly, `Ok(Option<Value>)` is returned.
    ///
    /// The `Option<Value>` part is `None` if no value was actually removed as there was no value
    /// there. For example, if you're deleting `table.a` and the Table `table` has no key `a`, then
    /// `Ok(None)` is returned. Also, if you're deleting from an Array, but there is nothing in the
    /// array, or the array is shorter than the index you're deleting.
    /// If the delete operation actually removed something from the toml document, this value is
    /// returned as `Ok(Some(Value))`.
    ///
    /// On failure, `Err(e)` is returned
    ///
    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>>;

    /// Extension function for inserting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueinsertExt::insert_with_seperator`
    fn delete(&mut self, query: &String) -> Result<Option<Value>> {
        self.delete_with_seperator(query, '.')
    }

}

impl TomlValueDeleteExt for Value {

    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;
        use std::ops::Index;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last_token = tokens.pop_last();

        /// Check whether a structure (Table/Array) is empty. If the Value has not these types,
        /// the default value is returned
        #[inline]
        fn is_empty(val: Option<&Value>, default: bool) -> bool {
            val.map(|v| match v {
                    &Value::Table(ref tab) => tab.is_empty(),
                    &Value::Array(ref arr) => arr.is_empty(),
                    _                      => default
                })
                .unwrap_or(default)
        }

        #[inline]
        fn is_table(val: Option<&Value>) -> bool {
            val.map(|v| is_match!(v, &Value::Table(_))).unwrap_or(false)
        }

        #[inline]
        fn is_array(val: Option<&Value>) -> bool {
            val.map(|v| is_match!(v, &Value::Array(_))).unwrap_or(false)
        }

        #[inline]
        fn name_of_val(val: Option<&Value>) -> &'static str {
            val.map(|v| match v {
                &Value::Array(_)    => "Array",
                &Value::Boolean(_)  => "Boolean",
                &Value::Datetime(_) => "Datetime",
                &Value::Float(_)    => "Float",
                &Value::Integer(_)  => "Integer",
                &Value::String(_)   => "String",
                &Value::Table(_)    => "Table",
            }).unwrap_or("None")
        }

        if last_token.is_none() {
            match self {
                &mut Value::Table(ref mut tab) => {
                    match tokens {
                        Token::Identifier { ident, .. } => {
                            if is_empty(tab.get(&ident), true) {
                                Ok(tab.remove(&ident))
                            } else {
                                if is_table(tab.get(&ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyTable(ident.clone());
                                    Err(Error::from(kind))
                                } else if is_array(tab.get(&ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyArray(ident.clone());
                                    Err(Error::from(kind))
                                } else {
                                    let act = name_of_val(tab.get(&ident));
                                    let tbl = "table";
                                    let k   = ErrorKind::CannotAccessBecauseTypeMismatch(tbl, act);
                                    Err(Error::from(k))
                                }
                            }
                        },
                        _ => Ok(None)
                    }
                },
                &mut Value::Array(ref mut arr) => {
                    match tokens {
                        Token::Identifier { ident, .. } => {
                            let ek = ErrorKind::NoIdentifierInArray(ident);
                            Err(Error::from(ek))
                        },
                        Token::Index { idx , .. } => {
                            if is_empty(Some(arr.index(idx)), true) {
                                Ok(Some(arr.remove(idx)))
                            } else {
                                unimplemented!()
                            }
                        },
                    }
                },
                _ => unimplemented!()
            }
        } else {
            let mut val = try!(resolve(self, &tokens));
            let last_token = last_token.unwrap();
            match val {
                &mut Value::Table(ref mut tab) => {
                    match *last_token {
                        Token::Identifier { ref ident, .. } => {
                            if is_empty(tab.get(ident), true) {
                                Ok(tab.remove(ident))
                            } else {
                                if is_table(tab.get(ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyTable(ident.clone());
                                    Err(Error::from(kind))
                                } else if is_array(tab.get(ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyArray(ident.clone());
                                    Err(Error::from(kind))
                                } else {
                                    let act = name_of_val(tab.get(ident));
                                    let tbl = "table";
                                    let k   = ErrorKind::CannotAccessBecauseTypeMismatch(tbl, act);
                                    Err(Error::from(k))
                                }
                            }
                        },
                        Token::Index { idx, .. } => {
                            unimplemented!()
                        },
                    }
                },
                &mut Value::Array(ref mut arr) => {
                    match *last_token {
                        Token::Identifier { ref ident, .. } => {
                            unimplemented!()
                        },
                        Token::Index { idx, .. } => {
                            if is_empty(Some(&arr.index(idx)), true) {
                                Ok(Some(arr.remove(idx)))
                            } else {
                                unimplemented!()
                            }
                        },
                    }
                },
                _ => {
                    unimplemented!()
                }
            }
        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use error::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_delete_from_empty_document() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.delete_with_seperator(&String::from("a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_from_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_integer() {
        let mut toml : Value = toml_from_str(r#"
        value = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(1)));
    }

    #[test]
    fn test_delete_string() {
        let mut toml : Value = toml_from_str(r#"
        value = "foo"
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::String(_)));
        match res {
            Value::String(ref s) => assert_eq!("foo", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Table(_)));
        match res {
            Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Array(_)));
        match res {
            Value::Array(ref a) => assert!(a.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_nonempty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyTable(_)));
    }

    #[test]
    fn test_delete_nonempty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyArray(_)));
    }

    #[test]
    fn test_delete_int_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        int = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.int"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_array_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        array = []
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.array"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Array(_))));
    }

    #[test]
    fn test_delete_int_from_array_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.array.[0]"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_int_from_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array.[0]"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_int_from_table_from_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ { table = { int = 1 } } ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array.[0].table.int"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_from_array_value() {
        use read::TomlValueReadExt;

        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let mut ary = toml.read_mut(&String::from("array")).unwrap();
        let res     = ary.delete_with_seperator(&String::from("[0]"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_from_int_value() {
        use read::TomlValueReadExt;

        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let mut ary = toml.read_mut(&String::from("array.[0]")).unwrap();
        let res     = ary.delete_with_seperator(&String::from("nonexist"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::QueryingValueAsTable(_)));
    }

    #[test]
    fn test_delete_index_from_non_array() {
        use read::TomlValueReadExt;

        let mut toml : Value = toml_from_str(r#"
        array = 1
        "#).unwrap();

        let mut ary = toml.read_mut(&String::from("array")).unwrap();
        let res     = ary.delete_with_seperator(&String::from("[0]"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotAccessBecauseTypeMismatch(_, _)));
    }

}

<|endoftext|>


<commit_before>// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#![allow(dead_code)]

use std; // To refer to std::result::Result.

use std::collections::BTreeSet;

use rusqlite;

use edn;

use core_traits::{
    Attribute,
    ValueType,
};

use db_traits::errors::DbError;
use query_algebrizer_traits::errors::{
    AlgebrizerError,
};
use query_projector_traits::errors::{
    ProjectorError,
};
use query_pull_traits::errors::{
    PullError,
};
use sql_traits::errors::{
    SQLError,
};

#[cfg(feature = "syncable")]
use tolstoy_traits::errors::{
    TolstoyError,
};

pub type Result<T> = std::result::Result<T, MentatError>;

#[macro_export]
macro_rules! bail {
    ($e:expr) => (
        return Err($e.into());
    )
}

#[derive(Debug, Fail)]
pub enum MentatError {
    #[fail(display = "bad uuid {}", _0)]
    BadUuid(String),

    #[fail(display = "path {} already exists", _0)]
    PathAlreadyExists(String),

    #[fail(display = "variables {:?} unbound at query execution time", _0)]
    UnboundVariables(BTreeSet<String>),

    #[fail(display = "invalid argument name: '{}'", _0)]
    InvalidArgumentName(String),

    #[fail(display = "unknown attribute: '{}'", _0)]
    UnknownAttribute(String),

    #[fail(display = "invalid vocabulary version")]
    InvalidVocabularyVersion,

    #[fail(display = "vocabulary {}/{} already has attribute {}, and the requested definition differs", _0, _1, _2)]
    ConflictingAttributeDefinitions(String, ::vocabulary::Version, String, Attribute, Attribute),

    #[fail(display = "existing vocabulary {} too new: wanted {}, got {}", _0, _1, _2)]
    ExistingVocabularyTooNew(String, ::vocabulary::Version, ::vocabulary::Version),

    #[fail(display = "core schema: wanted {}, got {:?}", _0, _1)]
    UnexpectedCoreSchema(::vocabulary::Version, Option<::vocabulary::Version>),

    #[fail(display = "Lost the transact() race!")]
    UnexpectedLostTransactRace,

    #[fail(display = "missing core attribute {}", _0)]
    MissingCoreVocabulary(edn::query::Keyword),

    #[fail(display = "schema changed since query was prepared")]
    PreparedQuerySchemaMismatch,

    #[fail(display = "provided value of type {} doesn't match attribute value type {}", _0, _1)]
    ValueTypeMismatch(ValueType, ValueType),

    #[fail(display = "{}", _0)]
    IoError(#[cause] std::io::Error),

    // It would be better to capture the underlying `rusqlite::Error`, but that type doesn't
    // implement many useful traits, including `Clone`, `Eq`, and `PartialEq`.
    #[fail(display = "SQL error: {}", _0)]
    RusqliteError(String),

    #[fail(display = "{}", _0)]
    EdnParseError(#[cause] edn::ParseError),

    #[fail(display = "{}", _0)]
    DbError(#[cause] DbError),

    #[fail(display = "{}", _0)]
    AlgebrizerError(#[cause] AlgebrizerError),

    #[fail(display = "{}", _0)]
    ProjectorError(#[cause] ProjectorError),

    #[fail(display = "{}", _0)]
    PullError(#[cause] PullError),

    #[fail(display = "{}", _0)]
    SQLError(#[cause] SQLError),

    #[cfg(feature = "syncable")]
    #[fail(display = "{}", _0)]
    TolstoyError(#[cause] TolstoyError),
}

impl From<std::io::Error> for MentatError {
    fn from(error: std::io::Error) -> MentatError {
        MentatError::IoError(error)
    }
}

impl From<rusqlite::Error> for MentatError {
    fn from(error: rusqlite::Error) -> MentatError {
        MentatError::RusqliteError(error.to_string())
    }
}

impl From<edn::ParseError> for MentatError {
    fn from(error: edn::ParseError) -> MentatError {
        MentatError::EdnParseError(error)
    }
}

impl From<DbError> for MentatError {
    fn from(error: DbError) -> MentatError {
        MentatError::DbError(error)
    }
}

impl From<AlgebrizerError> for MentatError {
    fn from(error: AlgebrizerError) -> MentatError {
        MentatError::AlgebrizerError(error)
    }
}

impl From<ProjectorError> for MentatError {
    fn from(error: ProjectorError) -> MentatError {
        MentatError::ProjectorError(error)
    }
}

impl From<PullError> for MentatError {
    fn from(error: PullError) -> MentatError {
        MentatError::PullError(error)
    }
}

impl From<SQLError> for MentatError {
    fn from(error: SQLError) -> MentatError {
        MentatError::SQLError(error)
    }
}

#[cfg(feature = "syncable")]
impl From<TolstoyError> for MentatError {
    fn from(error: TolstoyError) -> MentatError {
        MentatError::TolstoyError(error)
    }
}
<commit_msg>Pre: Remove :: dependency from src/errors.rs<commit_after>// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#![allow(dead_code)]

use std; // To refer to std::result::Result.

use std::collections::BTreeSet;

use rusqlite;

use edn;

use core_traits::{
    Attribute,
    ValueType,
};

use db_traits::errors::DbError;
use query_algebrizer_traits::errors::{
    AlgebrizerError,
};
use query_projector_traits::errors::{
    ProjectorError,
};
use query_pull_traits::errors::{
    PullError,
};
use sql_traits::errors::{
    SQLError,
};

#[cfg(feature = "syncable")]
use tolstoy_traits::errors::{
    TolstoyError,
};

pub type Result<T> = std::result::Result<T, MentatError>;

#[macro_export]
macro_rules! bail {
    ($e:expr) => (
        return Err($e.into());
    )
}

#[derive(Debug, Fail)]
pub enum MentatError {
    #[fail(display = "bad uuid {}", _0)]
    BadUuid(String),

    #[fail(display = "path {} already exists", _0)]
    PathAlreadyExists(String),

    #[fail(display = "variables {:?} unbound at query execution time", _0)]
    UnboundVariables(BTreeSet<String>),

    #[fail(display = "invalid argument name: '{}'", _0)]
    InvalidArgumentName(String),

    #[fail(display = "unknown attribute: '{}'", _0)]
    UnknownAttribute(String),

    #[fail(display = "invalid vocabulary version")]
    InvalidVocabularyVersion,

    #[fail(display = "vocabulary {}/version {} already has attribute {}, and the requested definition differs", _0, _1, _2)]
    ConflictingAttributeDefinitions(String, u32, String, Attribute, Attribute),

    #[fail(display = "existing vocabulary {} too new: wanted version {}, got version {}", _0, _1, _2)]
    ExistingVocabularyTooNew(String, u32, u32),

    #[fail(display = "core schema: wanted version {}, got version {:?}", _0, _1)]
    UnexpectedCoreSchema(u32, Option<u32>),

    #[fail(display = "Lost the transact() race!")]
    UnexpectedLostTransactRace,

    #[fail(display = "missing core attribute {}", _0)]
    MissingCoreVocabulary(edn::query::Keyword),

    #[fail(display = "schema changed since query was prepared")]
    PreparedQuerySchemaMismatch,

    #[fail(display = "provided value of type {} doesn't match attribute value type {}", _0, _1)]
    ValueTypeMismatch(ValueType, ValueType),

    #[fail(display = "{}", _0)]
    IoError(#[cause] std::io::Error),

    // It would be better to capture the underlying `rusqlite::Error`, but that type doesn't
    // implement many useful traits, including `Clone`, `Eq`, and `PartialEq`.
    #[fail(display = "SQL error: {}", _0)]
    RusqliteError(String),

    #[fail(display = "{}", _0)]
    EdnParseError(#[cause] edn::ParseError),

    #[fail(display = "{}", _0)]
    DbError(#[cause] DbError),

    #[fail(display = "{}", _0)]
    AlgebrizerError(#[cause] AlgebrizerError),

    #[fail(display = "{}", _0)]
    ProjectorError(#[cause] ProjectorError),

    #[fail(display = "{}", _0)]
    PullError(#[cause] PullError),

    #[fail(display = "{}", _0)]
    SQLError(#[cause] SQLError),

    #[cfg(feature = "syncable")]
    #[fail(display = "{}", _0)]
    TolstoyError(#[cause] TolstoyError),
}

impl From<std::io::Error> for MentatError {
    fn from(error: std::io::Error) -> MentatError {
        MentatError::IoError(error)
    }
}

impl From<rusqlite::Error> for MentatError {
    fn from(error: rusqlite::Error) -> MentatError {
        MentatError::RusqliteError(error.to_string())
    }
}

impl From<edn::ParseError> for MentatError {
    fn from(error: edn::ParseError) -> MentatError {
        MentatError::EdnParseError(error)
    }
}

impl From<DbError> for MentatError {
    fn from(error: DbError) -> MentatError {
        MentatError::DbError(error)
    }
}

impl From<AlgebrizerError> for MentatError {
    fn from(error: AlgebrizerError) -> MentatError {
        MentatError::AlgebrizerError(error)
    }
}

impl From<ProjectorError> for MentatError {
    fn from(error: ProjectorError) -> MentatError {
        MentatError::ProjectorError(error)
    }
}

impl From<PullError> for MentatError {
    fn from(error: PullError) -> MentatError {
        MentatError::PullError(error)
    }
}

impl From<SQLError> for MentatError {
    fn from(error: SQLError) -> MentatError {
        MentatError::SQLError(error)
    }
}

#[cfg(feature = "syncable")]
impl From<TolstoyError> for MentatError {
    fn from(error: TolstoyError) -> MentatError {
        MentatError::TolstoyError(error)
    }
}
<|endoftext|>