<commit_before>use util::is_english;
use keypool::KeyPool;
use encryption::decrypt;
use std::sync::mpsc::{channel, Sender};
use std::thread;
use std::str::from_utf8;

fn dc(cipher_text: Vec<u8>,
      key: KeyPool,
      sender: &Sender<Vec<u8>>,
      tdone: &Sender<bool>)
      -> KeyPool {
    let key = key.clone();
    match decrypt(&cipher_text[..], &key.to_vec()) {
        Ok(decrypted_data) => {
            match from_utf8(&decrypted_data) {
                Ok(pt) => {
                    println!("Msg found \"{}\", key = {}", pt, key);
                    if is_english(pt.to_string()) {
                        match sender.send(key.to_vec()) {
                            Ok(_) => {
                                tdone.send(true).unwrap();
                                println!("Sent key");
                            }
                            Err(e) => panic!("Sorry master.. I fucked up... -- {}", e),
                        }
                    }

                }
                Err(_) => {
                    tdone.send(false).unwrap();
                }

            }
        }
        Err(_) => {
            tdone.send(false).unwrap();
        }
    }
    key.inc()
}

// returns potential keys
pub fn crack(kp: KeyPool, cipher_text: Vec<u8>, thread_count: i64) -> Vec<Vec<u8>> {
    let keys = kp.split_key(thread_count as u64);
    for k in keys.clone() {
        println!("{}", k);
    }
    // let mut tc = Arc::new(thread_count.clone());

    let mut threads = vec![]; // thread pool

    // com. channels
    let (tx, rx) = channel();
    let (tdone, rdone) = channel::<bool>();
    let (tcount, rcount) = channel();

    // let ref rcc = tc.as_ref();
    let klen = keys.len();

    for key in keys {
        let mut key = key.clone();
        let tx = tx.clone();
        let tcount = tcount.clone();
        let tdone = tdone.clone();
        let cipher_text = cipher_text.clone();

        threads.push(thread::spawn(move || {
            // let mut key = key.clone();
            loop {
                if !key.is_done() {
                    key = dc(cipher_text.clone(), key.clone(), &tx, &tdone);
                } else {
                    tcount.send(1).unwrap();
                    break;
                }
            }
        }));
    }

    let mut count = 0;
    let mut output = vec![]; // This will become the list of potential keys

    loop {
        match rdone.try_recv() {
            Ok(value) if value => {
                println!("Awesome");
                let v = rx.recv().unwrap();
                output.push(v);
                println!("Key sent!");
                break;
            }
            _ => {
                // if count == klen {
                //     println!("Here");
                //     break;
                // }
            }
        }

        match rcount.try_recv() {
            Ok(n) => {
                count = count + n;
            }
            _ => ()
        }
        if count == klen {
            println!("Here");
            break;
        }

    }

    for t in threads {
        t.join().unwrap();
    }

    println!("I got here!");

    output
}
<commit_msg>removing those bombs<commit_after>use util::is_english;
use keypool::KeyPool;
use encryption::decrypt;
use std::sync::mpsc::{channel, Sender};
use std::thread;
use std::str::from_utf8;

fn dc(cipher_text: Vec<u8>,
      key: KeyPool,
      sender: &Sender<Vec<u8>>,
      tdone: &Sender<bool>)
      -> KeyPool {
    let key = key.clone();
    match decrypt(&cipher_text[..], &key.to_vec()) {
        Ok(decrypted_data) => {
            match from_utf8(&decrypted_data) {
                Ok(pt) => {
                    println!("Msg found \"{}\", key = {}", pt, key);
                    if is_english(pt.to_string()) {
                        match sender.send(key.to_vec()) {
                            Ok(_) => {
                                tdone.send(true).unwrap();
                                println!("Sent key");
                            }
                            Err(e) => panic!("Sorry master.. I failed... -- {}", e),
                        }
                    }

                }
                Err(_) => {
                    tdone.send(false).unwrap();
                }

            }
        }
        Err(_) => {
            tdone.send(false).unwrap();
        }
    }
    key.inc()
}

// returns potential keys
pub fn crack(kp: KeyPool, cipher_text: Vec<u8>, thread_count: i64) -> Vec<Vec<u8>> {
    let keys = kp.split_key(thread_count as u64);
    for k in keys.clone() {
        println!("{}", k);
    }
    // let mut tc = Arc::new(thread_count.clone());

    let mut threads = vec![]; // thread pool

    // com. channels
    let (tx, rx) = channel();
    let (tdone, rdone) = channel::<bool>();
    let (tcount, rcount) = channel();

    // let ref rcc = tc.as_ref();
    let klen = keys.len();

    for key in keys {
        let mut key = key.clone();
        let tx = tx.clone();
        let tcount = tcount.clone();
        let tdone = tdone.clone();
        let cipher_text = cipher_text.clone();

        threads.push(thread::spawn(move || {
            // let mut key = key.clone();
            loop {
                if !key.is_done() {
                    key = dc(cipher_text.clone(), key.clone(), &tx, &tdone);
                } else {
                    tcount.send(1).unwrap();
                    break;
                }
            }
        }));
    }

    let mut count = 0;
    let mut output = vec![]; // This will become the list of potential keys

    loop {
        match rdone.try_recv() {
            Ok(value) if value => {
                println!("Awesome");
                let v = rx.recv().unwrap();
                output.push(v);
                println!("Key sent!");
                break;
            }
            _ => {
                // if count == klen {
                //     println!("Here");
                //     break;
                // }
            }
        }

        match rcount.try_recv() {
            Ok(n) => {
                count = count + n;
            }
            _ => ()
        }
        if count == klen {
            println!("Here");
            break;
        }

    }

    for t in threads {
        t.join().unwrap();
    }

    println!("I got here!");

    output
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![crate_name = "gfx-perf"]
#![feature(globs)]

extern crate cgmath;
extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;
extern crate glfw;
extern crate native;
extern crate time;
extern crate gl;

use time::precise_time_s;
use cgmath::FixedArray;
use cgmath::{Matrix, Point3, Vector3, Matrix3, ToMatrix4};
use cgmath::{Transform, AffineMatrix3, Vector4, Array1};
use gfx::{Device, DeviceHelper};
use glfw::Context;
use gl::types::*;
use std::mem;
use std::ptr;
use std::str;
use std::os;
use std::from_str::FromStr;

#[vertex_format]
struct Vertex {
    #[as_float]
    #[name = "a_Pos"]
    pos: [i8, ..3],
}

// The shader_param attribute makes sure the following struct can be used to
// pass parameters to a shader. Its argument is the name of the type that will
// be generated to represent your the program. Search for link_program below, to
// see how it's used.
#[shader_param(MyProgram)]
struct Params {
    #[name = "u_Transform"]
    transform: [[f32, ..4], ..4],
}

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    in vec3 a_Pos;
    uniform mat4 u_Transform;

    void main() {
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    out vec4 o_Color;

    void main() {
        o_Color = vec4(1., 0., 0., 1.);
    }
"
};

//----------------------------------------

// We need to run on the main thread, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn gfx_main(glfw: glfw::Glfw,
            window: glfw::Window,
            events: Receiver<(f64, glfw::WindowEvent)>,
            dimension: int) {
    let (w, h) = window.get_framebuffer_size();
    let frame = gfx::Frame::new(w as u16, h as u16);

    let mut device = gfx::GlDevice::new(|s| glfw.get_proc_address(s));
    let mut renderer = device.create_renderer();

    let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

    let vertex_data = vec![
        // front (0, 1, 0)
        Vertex { pos: [-1,  1, -1] },
        Vertex { pos: [ 1,  1, -1] },
        Vertex { pos: [ 1,  1,  1] },
    ];

    let mesh = device.create_mesh(vertex_data);
    let slice = mesh.get_slice(gfx::TriangleList);

    let texture_info = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let image_info = texture_info.to_image_info();
    let texture = device.create_texture(texture_info).unwrap();
    device.update_texture(&texture, &image_info,
                          &vec![0x20u8, 0xA0u8, 0xC0u8, 0x00u8].as_slice())
        .unwrap();

    let prog: MyProgram = device
        .link_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone())
        .unwrap();

    let view: AffineMatrix3<f32> = Transform::look_at(
        &Point3::new(0f32, -5.0, 0.0),
        &Point3::new(0f32, 0.0, 0.0),
        &Vector3::unit_z(),
    );
    let aspect = w as f32 / h as f32;
    let proj = cgmath::perspective(cgmath::deg(45.0f32), aspect, 1.0, 10.0);

    let clear_data = gfx::ClearData {
        color: Some([0.3, 0.3, 0.3, 1.0]),
        depth: Some(1.0),
        stencil: None,
    };

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _) =>
                    window.set_should_close(true),
                _ => {},
            }
        }

        let start = precise_time_s() * 1000.;
        renderer.reset();
        renderer.clear(clear_data, &frame);

        for x in range(-dimension, dimension) {
            for y in range(-dimension, dimension) {
                let mut model = Matrix3::identity().mul_s(0.01f32).to_matrix4();
                model.w = Vector4::new(x as f32 * 0.05,
                                       0f32,
                                       y as f32 * 0.05,
                                       1f32);

                let data = Params {
                    transform: proj.mul_m(&view.mat)
                                   .mul_m(&model).into_fixed(),
                };
                renderer.draw(&mesh, slice, &frame, (&prog, &data), &state).unwrap();
            }
        }

        let pre_submit = precise_time_s() * 1000.;
        device.submit(renderer.as_buffer());
        let post_submit = precise_time_s() * 1000.;
        window.swap_buffers();
        let swap = precise_time_s() * 1000.;

        println!("total time:\t\t{0:4.2f}ms", swap - start);
        println!("\tcreate list:\t{0:4.2f}ms", pre_submit - start);
        println!("\tsubmit:\t\t{0:4.2f}ms", post_submit - pre_submit);
        println!("\tgpu wait:\t{0:4.2f}ms", swap - post_submit)
    }
}

static VS_SRC: &'static str = "
    #version 150 core
    in vec3 a_Pos;
    uniform mat4 u_Transform;

    void main() {
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
    }
";

static FS_SRC: &'static str = "
    #version 150 core
    out vec4 o_Color;

    void main() {
        o_Color = vec4(1., 0., 0., 1.);
    }
";

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
    let shader = gl::CreateShader(ty);
    unsafe {
        // Attempt to compile the shader
        src.with_c_str(|ptr| gl::ShaderSource(shader, 1, &ptr, ptr::null()));
        gl::CompileShader(shader);

        // Get the compile status
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = Vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetShaderInfoLog(shader, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!("{}", str::from_utf8(buf.as_slice()).expect("ShaderInfoLog not valid utf8"));
        }
    }
    shader
}

fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
    let program = gl::CreateProgram();
    gl::AttachShader(program, vs);
    gl::AttachShader(program, fs);
    gl::LinkProgram(program);
    unsafe {
        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = Vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!("{}", str::from_utf8(buf.as_slice()).expect("ProgramInfoLog not valid utf8"));
        }
    }
    program
}

fn gl_main(glfw: glfw::Glfw,
           window: glfw::Window,
           _: Receiver<(f64, glfw::WindowEvent),>,
           dimension: int) {
    // Create GLSL shaders
    let vs = compile_shader(VS_SRC, gl::VERTEX_SHADER);
    let fs = compile_shader(FS_SRC, gl::FRAGMENT_SHADER);
    let program = link_program(vs, fs);

    let mut vao = 0;
    let mut vbo = 0;

    let trans_uniform = unsafe {
        // Create Vertex Array Object
        gl::GenVertexArrays(1, &mut vao);
        gl::BindVertexArray(vao);

        // Create a Vertex Buffer Object and copy the vertex data to it
        gl::GenBuffers(1, &mut vbo);
        gl::BindBuffer(gl::ARRAY_BUFFER, vbo);

        let vertex_data = vec![
            // front (0, 1, 0)
            Vertex { pos: [-1,  1, -1] },
            Vertex { pos: [ 1,  1, -1] },
            Vertex { pos: [ 1,  1,  1] },
        ];

        gl::BufferData(gl::ARRAY_BUFFER,
                       (vertex_data.len() * mem::size_of::<Vertex>()) as GLsizeiptr,
                       mem::transmute(&vertex_data[0]),
                       gl::STATIC_DRAW);

        // Use shader program
        gl::UseProgram(program);
        "o_Color".with_c_str(|ptr| gl::BindFragDataLocation(program, 0, ptr));

        // Specify the layout of the vertex data
        let pos_attr = "a_Pos".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
        gl::EnableVertexAttribArray(pos_attr as GLuint);
        gl::VertexAttribPointer(pos_attr as GLuint, 3, gl::BYTE,
                                gl::FALSE as GLboolean, 0, ptr::null());

        "u_Transform".with_c_str(|ptr|
            gl::GetUniformLocation(program, ptr)
        )
    };

    let (w, h) = window.get_framebuffer_size();
    let view: AffineMatrix3<f32> = Transform::look_at(
        &Point3::new(0f32, -5.0, 0.0),
        &Point3::new(0f32, 0.0, 0.0),
        &Vector3::unit_z(),
    );
    let aspect = w as f32 / h as f32;
    let proj = cgmath::perspective(cgmath::deg(45.0f32), aspect, 1.0, 10.0);

    while !window.should_close() {
        // Poll events
        glfw.poll_events();

        let start = precise_time_s() * 1000.;

        // Clear the screen to black
        gl::ClearColor(0.3, 0.3, 0.3, 1.0);
        gl::Clear(gl::COLOR_BUFFER_BIT);

        for x in range(-dimension, dimension) {
            for y in range(-dimension, dimension) {
                let mut model = Matrix3::identity().mul_s(0.01f32).to_matrix4();
                model.w = Vector4::new(x as f32 * 0.05,
                                       0f32,
                                       y as f32 * 0.05,
                                       1f32);

                let mat = proj.mul_m(&view.mat).mul_m(&model);

                unsafe {
                    gl::UniformMatrix4fv(trans_uniform,
                                         1,
                                         gl::FALSE,
                                         mat.x.ptr());
                }

                gl::DrawArrays(gl::TRIANGLES, 0, 3);
            }
        }

        let submit = precise_time_s() * 1000.;

        // Swap buffers
        window.swap_buffers();
        let swap = precise_time_s() * 1000.;

        println!("total time:\t\t{0:4.2f}ms", swap - start);
        println!("\tsubmit:\t\t{0:4.2f}ms", submit - start);
        println!("\tgpu wait:\t{0:4.2f}ms", swap - submit)

    }

    // Cleanup
    gl::DeleteProgram(program);
    gl::DeleteShader(fs);
    gl::DeleteShader(vs);
    unsafe {
        gl::DeleteBuffers(1, &vbo);
        gl::DeleteVertexArrays(1, &vao);
    }
}

fn main() {
    let args = os::args();
    if args.len() == 1 {
        println!("gfx-perf [gl|gfx] <size>");
        return;
    }

    let mode = &args[1];
    let count: int = if args.len() >= 2 {
        FromStr::from_str(args[2].as_slice())
    } else {
        None
    }.unwrap_or(100);

    let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::ContextVersion(3, 2));
    glfw.window_hint(glfw::OpenglForwardCompat(true));
    glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));

    let (window, events) = glfw
        .create_window(640, 480, "Cube example", glfw::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();
    gl::load_with(|s| glfw.get_proc_address(s));
    glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
    window.set_key_polling(true);

    match mode.as_slice() {
        "gfx" => gfx_main(glfw, window, events, count),
        "gl" => gl_main(glfw, window, events, count),
        x => {
            println!("{} is not a known mode", x)
        }
    }
}
<commit_msg>update perf to latest gfx<commit_after>#![feature(phase)]
#![crate_name = "gfx-perf"]
#![feature(globs)]

extern crate cgmath;
extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;
extern crate glfw;
extern crate native;
extern crate time;
extern crate gl;

use time::precise_time_s;
use cgmath::FixedArray;
use cgmath::{Matrix, Point3, Vector3, Matrix3, ToMatrix4};
use cgmath::{Transform, AffineMatrix3, Vector4, Array1};
use gfx::{Device, DeviceHelper};
use glfw::Context;
use gl::types::*;
use std::mem;
use std::ptr;
use std::str;
use std::os;
use std::from_str::FromStr;

#[vertex_format]
struct Vertex {
    #[as_float]
    #[name = "a_Pos"]
    pos: [i8, ..3],
}

// The shader_param attribute makes sure the following struct can be used to
// pass parameters to a shader. Its argument is the name of the type that will
// be generated to represent your the program. Search for link_program below, to
// see how it's used.
#[shader_param(TriangleBatch)]
struct Params {
    #[name = "u_Transform"]
    transform: [[f32, ..4], ..4],
}

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    in vec3 a_Pos;
    uniform mat4 u_Transform;

    void main() {
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    out vec4 o_Color;

    void main() {
        o_Color = vec4(1., 0., 0., 1.);
    }
"
};

//----------------------------------------

// We need to run on the main thread, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn gfx_main(glfw: glfw::Glfw,
            window: glfw::Window,
            events: Receiver<(f64, glfw::WindowEvent)>,
            dimension: int) {
    let (w, h) = window.get_framebuffer_size();
    let frame = gfx::Frame::new(w as u16, h as u16);

    let mut device = gfx::GlDevice::new(|s| glfw.get_proc_address(s));

    let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

    let vertex_data = vec![
        // front (0, 1, 0)
        Vertex { pos: [-1,  1, -1] },
        Vertex { pos: [ 1,  1, -1] },
        Vertex { pos: [ 1,  1,  1] },
    ];

    let mesh = device.create_mesh(vertex_data);
    let slice = mesh.get_slice(gfx::TriangleList);

    let texture_info = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let image_info = texture_info.to_image_info();
    let texture = device.create_texture(texture_info).unwrap();
    device.update_texture(&texture, &image_info,
                          &vec![0x20u8, 0xA0u8, 0xC0u8, 0x00u8].as_slice())
        .unwrap();

    let program = device.link_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone())
                        .unwrap();
    let view: AffineMatrix3<f32> = Transform::look_at(
        &Point3::new(0f32, -5.0, 0.0),
        &Point3::new(0f32, 0.0, 0.0),
        &Vector3::unit_z(),
    );
    let aspect = w as f32 / h as f32;
    let proj = cgmath::perspective(cgmath::deg(45.0f32), aspect, 1.0, 10.0);

    let clear_data = gfx::ClearData {
        color: Some([0.3, 0.3, 0.3, 1.0]),
        depth: Some(1.0),
        stencil: None,
    };

    let mut graphics = gfx::Graphics::new(device);
    let batch: TriangleBatch = graphics.make_batch(&mesh, slice, &program, &state).unwrap();

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _) =>
                    window.set_should_close(true),
                _ => {},
            }
        }

        let start = precise_time_s() * 1000.;
        graphics.clear(clear_data, &frame);

        for x in range(-dimension, dimension) {
            for y in range(-dimension, dimension) {
                let mut model = Matrix3::identity().mul_s(0.01f32).to_matrix4();
                model.w = Vector4::new(x as f32 * 0.05,
                                       0f32,
                                       y as f32 * 0.05,
                                       1f32);

                let data = Params {
                    transform: proj.mul_m(&view.mat)
                                   .mul_m(&model).into_fixed(),
                };
                graphics.draw(&batch, &data, &frame);
            }
        }

        let pre_submit = precise_time_s() * 1000.;
        graphics.end_frame();
        let post_submit = precise_time_s() * 1000.;
        window.swap_buffers();
        let swap = precise_time_s() * 1000.;

        println!("total time:\t\t{0:4.2f}ms", swap - start);
        println!("\tcreate list:\t{0:4.2f}ms", pre_submit - start);
        println!("\tsubmit:\t\t{0:4.2f}ms", post_submit - pre_submit);
        println!("\tgpu wait:\t{0:4.2f}ms", swap - post_submit)
    }
}

static VS_SRC: &'static str = "
    #version 150 core
    in vec3 a_Pos;
    uniform mat4 u_Transform;

    void main() {
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
    }
";

static FS_SRC: &'static str = "
    #version 150 core
    out vec4 o_Color;

    void main() {
        o_Color = vec4(1., 0., 0., 1.);
    }
";

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
    let shader = gl::CreateShader(ty);
    unsafe {
        // Attempt to compile the shader
        src.with_c_str(|ptr| gl::ShaderSource(shader, 1, &ptr, ptr::null()));
        gl::CompileShader(shader);

        // Get the compile status
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = Vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetShaderInfoLog(shader, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!("{}", str::from_utf8(buf.as_slice()).expect("ShaderInfoLog not valid utf8"));
        }
    }
    shader
}

fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
    let program = gl::CreateProgram();
    gl::AttachShader(program, vs);
    gl::AttachShader(program, fs);
    gl::LinkProgram(program);
    unsafe {
        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = Vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!("{}", str::from_utf8(buf.as_slice()).expect("ProgramInfoLog not valid utf8"));
        }
    }
    program
}

fn gl_main(glfw: glfw::Glfw,
           window: glfw::Window,
           _: Receiver<(f64, glfw::WindowEvent),>,
           dimension: int) {
    // Create GLSL shaders
    let vs = compile_shader(VS_SRC, gl::VERTEX_SHADER);
    let fs = compile_shader(FS_SRC, gl::FRAGMENT_SHADER);
    let program = link_program(vs, fs);

    let mut vao = 0;
    let mut vbo = 0;

    let trans_uniform = unsafe {
        // Create Vertex Array Object
        gl::GenVertexArrays(1, &mut vao);
        gl::BindVertexArray(vao);

        // Create a Vertex Buffer Object and copy the vertex data to it
        gl::GenBuffers(1, &mut vbo);
        gl::BindBuffer(gl::ARRAY_BUFFER, vbo);

        let vertex_data = vec![
            // front (0, 1, 0)
            Vertex { pos: [-1,  1, -1] },
            Vertex { pos: [ 1,  1, -1] },
            Vertex { pos: [ 1,  1,  1] },
        ];

        gl::BufferData(gl::ARRAY_BUFFER,
                       (vertex_data.len() * mem::size_of::<Vertex>()) as GLsizeiptr,
                       mem::transmute(&vertex_data[0]),
                       gl::STATIC_DRAW);

        // Use shader program
        gl::UseProgram(program);
        "o_Color".with_c_str(|ptr| gl::BindFragDataLocation(program, 0, ptr));

        // Specify the layout of the vertex data
        let pos_attr = "a_Pos".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
        gl::EnableVertexAttribArray(pos_attr as GLuint);
        gl::VertexAttribPointer(pos_attr as GLuint, 3, gl::BYTE,
                                gl::FALSE as GLboolean, 0, ptr::null());

        "u_Transform".with_c_str(|ptr|
            gl::GetUniformLocation(program, ptr)
        )
    };

    let (w, h) = window.get_framebuffer_size();
    let view: AffineMatrix3<f32> = Transform::look_at(
        &Point3::new(0f32, -5.0, 0.0),
        &Point3::new(0f32, 0.0, 0.0),
        &Vector3::unit_z(),
    );
    let aspect = w as f32 / h as f32;
    let proj = cgmath::perspective(cgmath::deg(45.0f32), aspect, 1.0, 10.0);

    while !window.should_close() {
        // Poll events
        glfw.poll_events();

        let start = precise_time_s() * 1000.;

        // Clear the screen to black
        gl::ClearColor(0.3, 0.3, 0.3, 1.0);
        gl::Clear(gl::COLOR_BUFFER_BIT);

        for x in range(-dimension, dimension) {
            for y in range(-dimension, dimension) {
                let mut model = Matrix3::identity().mul_s(0.01f32).to_matrix4();
                model.w = Vector4::new(x as f32 * 0.05,
                                       0f32,
                                       y as f32 * 0.05,
                                       1f32);

                let mat = proj.mul_m(&view.mat).mul_m(&model);

                unsafe {
                    gl::UniformMatrix4fv(trans_uniform,
                                         1,
                                         gl::FALSE,
                                         mat.x.ptr());
                }

                gl::DrawArrays(gl::TRIANGLES, 0, 3);
            }
        }

        let submit = precise_time_s() * 1000.;

        // Swap buffers
        window.swap_buffers();
        let swap = precise_time_s() * 1000.;

        println!("total time:\t\t{0:4.2f}ms", swap - start);
        println!("\tsubmit:\t\t{0:4.2f}ms", submit - start);
        println!("\tgpu wait:\t{0:4.2f}ms", swap - submit)

    }

    // Cleanup
    gl::DeleteProgram(program);
    gl::DeleteShader(fs);
    gl::DeleteShader(vs);
    unsafe {
        gl::DeleteBuffers(1, &vbo);
        gl::DeleteVertexArrays(1, &vao);
    }
}

fn main() {
    let args = os::args();
    if args.len() == 1 {
        println!("gfx-perf [gl|gfx] <size>");
        return;
    }

    let mode = &args[1];
    let count: int = if args.len() >= 2 {
        FromStr::from_str(args[2].as_slice())
    } else {
        None
    }.unwrap_or(10000);

    let count = ((count as f64).sqrt() / 2.) as int;

    let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::ContextVersion(3, 2));
    glfw.window_hint(glfw::OpenglForwardCompat(true));
    glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));

    let (window, events) = glfw
        .create_window(640, 480, "Cube example", glfw::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();
    gl::load_with(|s| glfw.get_proc_address(s));
    glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
    window.set_key_polling(true);

    println!("count is {}", count*count*4);
    match mode.as_slice() {
        "gfx" => gfx_main(glfw, window, events, count),
        "gl" => gl_main(glfw, window, events, count),
        x => {
            println!("{} is not a known mode", x)
        }
    }
}
<|endoftext|>


<commit_before>use std::error;
use std::error::FromError;
use std::io;
use std::fmt;
use byteorder;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Error {
    UnexpectedSize(usize, usize),
    Io(io::Error),
    Byteorder(byteorder::Error)
}

impl FromError<io::Error> for Error {
    fn from_error(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl FromError<byteorder::Error> for Error {
    fn from_error(err: byteorder::Error) -> Error {
        Error::Byteorder(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::UnexpectedSize(expected_size, size) =>
                write!(f, "Unexpected number of bytes in NTP datagram (expected:{}; actual:{})", expected_size, size),
            Error::Io(ref err) => err.fmt(f),
            Error::Byteorder(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::UnexpectedSize(_, _) => "Unexpected number of bytes in NTP datagram",
            Error::Io(ref err) => error::Error::description(err),
            Error::Byteorder(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::UnexpectedSize(_, _) => None,
            Error::Io(ref err) => err.cause(),
            Error::Byteorder(ref err) => err.cause(),
        }
    }
}
<commit_msg>Replaced FromError with From<commit_after>use std::error;
use std::io;
use std::fmt;
use byteorder;

#[derive(Debug)]
pub enum Error {
    UnexpectedSize(usize, usize),
    Io(io::Error),
    Byteorder(byteorder::Error)
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<byteorder::Error> for Error {
    fn from(err: byteorder::Error) -> Error {
        Error::Byteorder(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::UnexpectedSize(expected_size, size) =>
                write!(f, "Unexpected number of bytes in NTP datagram (expected:{}; actual:{})", expected_size, size),
            Error::Io(ref err) => err.fmt(f),
            Error::Byteorder(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::UnexpectedSize(_, _) => "Unexpected number of bytes in NTP datagram",
            Error::Io(ref err) => error::Error::description(err),
            Error::Byteorder(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::UnexpectedSize(_, _) => None,
            Error::Io(ref err) => err.cause(),
            Error::Byteorder(ref err) => err.cause(),
        }
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

use std::{io, str};

/// Error type used for some library functions
#[derive(Debug)]
pub enum WpaError {
    /// Represents all cases of `std::io::Error`.
    Io(io::Error),

    /// Represents all cases of `nix::Error`.
    Nix(nix::Error),

    /// Represents a failure to interpret a sequence of u8 as a string slice.
    Utf8ToStr(str::Utf8Error),

    /// Represents a failed `ATTACH` request to wpasupplicant.
    Attach,

    /// Represents a failed `DETACH` request to wpasupplicant.
    Detach,
}

impl std::error::Error for WpaError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match *self {
            WpaError::Attach => None,
            WpaError::Detach => None,
            WpaError::Io(_) => None,
            WpaError::Nix(_) => None,
            WpaError::Utf8ToStr(_) => None,
        }
    }
}

impl std::fmt::Display for WpaError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            WpaError::Attach => {
                write!(f, "Failed to attach to wpasupplicant")
            }
            WpaError::Detach => {
                write!(f, "Failed to detach from wpasupplicant")
            }
            WpaError::Io(ref err) => {
                write!(f, "Failed to execute the specified command: {}", err)
            }
            WpaError::Nix(ref err) => {
                write!(f, "Failed to execute the specified command: {}", err)
            }
            WpaError::Utf8ToStr(ref err) => err.fmt(f),
        }
    }
}

impl From<std::io::Error> for WpaError {
    fn from(err: std::io::Error) -> WpaError {
        WpaError::Io(err)
    }
}

impl From<nix::Error> for WpaError {
    fn from(err: nix::Error) -> WpaError {
        WpaError::Nix(err)
    }
}

impl From<str::Utf8Error> for WpaError {
    fn from(err: str::Utf8Error) -> WpaError {
        WpaError::Utf8ToStr(err)
    }
}
<commit_msg>provide source for underlying errors<commit_after>#![deny(missing_docs)]

use std::{io, str};

/// Error type used for some library functions
#[derive(Debug)]
pub enum WpaError {
    /// Represents all cases of `std::io::Error`.
    Io(io::Error),

    /// Represents all cases of `nix::Error`.
    Nix(nix::Error),

    /// Represents a failure to interpret a sequence of u8 as a string slice.
    Utf8ToStr(str::Utf8Error),

    /// Represents a failed `ATTACH` request to wpasupplicant.
    Attach,

    /// Represents a failed `DETACH` request to wpasupplicant.
    Detach,
}

impl std::error::Error for WpaError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match *self {
            WpaError::Attach => None,
            WpaError::Detach => None,
            WpaError::Io(ref source) => Some(source),
            WpaError::Nix(ref source) => Some(source),
            WpaError::Utf8ToStr(ref source) => Some(source),
        }
    }
}

impl std::fmt::Display for WpaError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            WpaError::Attach => {
                write!(f, "Failed to attach to wpasupplicant")
            }
            WpaError::Detach => {
                write!(f, "Failed to detach from wpasupplicant")
            }
            WpaError::Io(ref err) => {
                write!(f, "Failed to execute the specified command: {}", err)
            }
            WpaError::Nix(ref err) => {
                write!(f, "Failed to execute the specified command: {}", err)
            }
            WpaError::Utf8ToStr(ref err) => {
                write!(f, "Failed to parse UTF8 to string: {}", err)
            }
        }
    }
}

impl From<std::io::Error> for WpaError {
    fn from(err: std::io::Error) -> WpaError {
        WpaError::Io(err)
    }
}

impl From<nix::Error> for WpaError {
    fn from(err: nix::Error) -> WpaError {
        WpaError::Nix(err)
    }
}

impl From<str::Utf8Error> for WpaError {
    fn from(err: str::Utf8Error) -> WpaError {
        WpaError::Utf8ToStr(err)
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt;
use std::result;

use serde::de;
use serde::ser;

#[derive(Debug)]
pub enum Unexpected {
    Bool(bool),
    I64(i64),
    I128(i128),
    U64(u64),
    U128(u128),
    Float(f64),
    Str(String),
    Unit,
    Seq,
    Map,
}

impl fmt::Display for Unexpected {
    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        match *self {
            Unexpected::Bool(b) => write!(f, "boolean `{}`", b),
            Unexpected::I64(i) => write!(f, "integer 64 bit `{}`", i),
            Unexpected::I128(i) => write!(f, "integer 128 bit `{}`", i),
            Unexpected::U64(i) => write!(f, "unsigned integer 64 bit `{}`", i),
            Unexpected::U128(i) => write!(f, "unsigned integer 128 bit `{}`", i),
            Unexpected::Float(v) => write!(f, "floating point `{}`", v),
            Unexpected::Str(ref s) => write!(f, "string {:?}", s),
            Unexpected::Unit => write!(f, "unit value"),
            Unexpected::Seq => write!(f, "sequence"),
            Unexpected::Map => write!(f, "map"),
        }
    }
}

/// Represents all possible errors that can occur when working with
/// configuration.
pub enum ConfigError {
    /// Configuration is frozen and no further mutations can be made.
    Frozen,

    /// Configuration property was not found
    NotFound(String),

    /// Configuration path could not be parsed.
    PathParse(nom::error::ErrorKind),

    /// Configuration could not be parsed from file.
    FileParse {
        /// The URI used to access the file (if not loaded from a string).
        /// Example: `/path/to/config.json`
        uri: Option<String>,

        /// The captured error from attempting to parse the file in its desired format.
        /// This is the actual error object from the library used for the parsing.
        cause: Box<dyn Error + Send + Sync>,
    },

    /// Value could not be converted into the requested type.
    Type {
        /// The URI that references the source that the value came from.
        /// Example: `/path/to/config.json` or `Environment` or `etcd://localhost`
        // TODO: Why is this called Origin but FileParse has a uri field?
        origin: Option<String>,

        /// What we found when parsing the value
        unexpected: Unexpected,

        /// What was expected when parsing the value
        expected: &'static str,

        /// The key in the configuration hash of this value (if available where the
        /// error is generated).
        key: Option<String>,
    },

    /// Custom message
    Message(String),

    /// Unadorned error from a foreign origin.
    Foreign(Box<dyn Error + Send + Sync>),
}

impl ConfigError {
    // FIXME: pub(crate)
    #[doc(hidden)]
    pub fn invalid_type(
        origin: Option<String>,
        unexpected: Unexpected,
        expected: &'static str,
    ) -> Self {
        ConfigError::Type {
            origin,
            unexpected,
            expected,
            key: None,
        }
    }

    // Have a proper error fire if the root of a file is ever not a Table
    // TODO: for now only json5 checked, need to finish others
    #[doc(hidden)]
    pub fn invalid_root(origin: Option<&String>, unexpected: Unexpected) -> Box<Self> {
        Box::new(ConfigError::Type {
            origin: origin.map(|s| s.to_owned()),
            unexpected,
            expected: "a map",
            key: None,
        })
    }

    // FIXME: pub(crate)
    #[doc(hidden)]
    #[must_use]
    pub fn extend_with_key(self, key: &str) -> Self {
        match self {
            ConfigError::Type {
                origin,
                unexpected,
                expected,
                ..
            } => ConfigError::Type {
                origin,
                unexpected,
                expected,
                key: Some(key.into()),
            },

            _ => self,
        }
    }

    #[must_use]
    fn prepend(self, segment: &str, add_dot: bool) -> Self {
        let concat = |key: Option<String>| {
            let key = key.unwrap_or_else(String::new);
            let dot = if add_dot && key.as_bytes().get(0).unwrap_or(&b'[') != &b'[' {
                "."
            } else {
                ""
            };
            format!("{}{}{}", segment, dot, key)
        };
        match self {
            ConfigError::Type {
                origin,
                unexpected,
                expected,
                key,
            } => ConfigError::Type {
                origin,
                unexpected,
                expected,
                key: Some(concat(key)),
            },
            ConfigError::NotFound(key) => ConfigError::NotFound(concat(Some(key))),
            _ => self,
        }
    }

    #[must_use]
    pub(crate) fn prepend_key(self, key: &str) -> Self {
        self.prepend(key, true)
    }

    #[must_use]
    pub(crate) fn prepend_index(self, idx: usize) -> Self {
        self.prepend(&format!("[{}]", idx), false)
    }
}

/// Alias for a `Result` with the error type set to `ConfigError`.
pub type Result<T> = result::Result<T, ConfigError>;

// Forward Debug to Display for readable panic! messages
impl fmt::Debug for ConfigError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", *self)
    }
}

impl fmt::Display for ConfigError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ConfigError::Frozen => write!(f, "configuration is frozen"),

            ConfigError::PathParse(ref kind) => write!(f, "{}", kind.description()),

            ConfigError::Message(ref s) => write!(f, "{}", s),

            ConfigError::Foreign(ref cause) => write!(f, "{}", cause),

            ConfigError::NotFound(ref key) => {
                write!(f, "configuration property {:?} not found", key)
            }

            ConfigError::Type {
                ref origin,
                ref unexpected,
                expected,
                ref key,
            } => {
                write!(f, "invalid type: {}, expected {}", unexpected, expected)?;

                if let Some(ref key) = *key {
                    write!(f, " for key `{}`", key)?;
                }

                if let Some(ref origin) = *origin {
                    write!(f, " in {}", origin)?;
                }

                Ok(())
            }

            ConfigError::FileParse { ref cause, ref uri } => {
                write!(f, "{}", cause)?;

                if let Some(ref uri) = *uri {
                    write!(f, " in {}", uri)?;
                }

                Ok(())
            }
        }
    }
}

impl Error for ConfigError {}

impl de::Error for ConfigError {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        ConfigError::Message(msg.to_string())
    }
}

impl ser::Error for ConfigError {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        ConfigError::Message(msg.to_string())
    }
}
<commit_msg>Fix clippy: Replace unwrap_or_else() with unwrap_or_default()<commit_after>use std::error::Error;
use std::fmt;
use std::result;

use serde::de;
use serde::ser;

#[derive(Debug)]
pub enum Unexpected {
    Bool(bool),
    I64(i64),
    I128(i128),
    U64(u64),
    U128(u128),
    Float(f64),
    Str(String),
    Unit,
    Seq,
    Map,
}

impl fmt::Display for Unexpected {
    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        match *self {
            Unexpected::Bool(b) => write!(f, "boolean `{}`", b),
            Unexpected::I64(i) => write!(f, "integer 64 bit `{}`", i),
            Unexpected::I128(i) => write!(f, "integer 128 bit `{}`", i),
            Unexpected::U64(i) => write!(f, "unsigned integer 64 bit `{}`", i),
            Unexpected::U128(i) => write!(f, "unsigned integer 128 bit `{}`", i),
            Unexpected::Float(v) => write!(f, "floating point `{}`", v),
            Unexpected::Str(ref s) => write!(f, "string {:?}", s),
            Unexpected::Unit => write!(f, "unit value"),
            Unexpected::Seq => write!(f, "sequence"),
            Unexpected::Map => write!(f, "map"),
        }
    }
}

/// Represents all possible errors that can occur when working with
/// configuration.
pub enum ConfigError {
    /// Configuration is frozen and no further mutations can be made.
    Frozen,

    /// Configuration property was not found
    NotFound(String),

    /// Configuration path could not be parsed.
    PathParse(nom::error::ErrorKind),

    /// Configuration could not be parsed from file.
    FileParse {
        /// The URI used to access the file (if not loaded from a string).
        /// Example: `/path/to/config.json`
        uri: Option<String>,

        /// The captured error from attempting to parse the file in its desired format.
        /// This is the actual error object from the library used for the parsing.
        cause: Box<dyn Error + Send + Sync>,
    },

    /// Value could not be converted into the requested type.
    Type {
        /// The URI that references the source that the value came from.
        /// Example: `/path/to/config.json` or `Environment` or `etcd://localhost`
        // TODO: Why is this called Origin but FileParse has a uri field?
        origin: Option<String>,

        /// What we found when parsing the value
        unexpected: Unexpected,

        /// What was expected when parsing the value
        expected: &'static str,

        /// The key in the configuration hash of this value (if available where the
        /// error is generated).
        key: Option<String>,
    },

    /// Custom message
    Message(String),

    /// Unadorned error from a foreign origin.
    Foreign(Box<dyn Error + Send + Sync>),
}

impl ConfigError {
    // FIXME: pub(crate)
    #[doc(hidden)]
    pub fn invalid_type(
        origin: Option<String>,
        unexpected: Unexpected,
        expected: &'static str,
    ) -> Self {
        ConfigError::Type {
            origin,
            unexpected,
            expected,
            key: None,
        }
    }

    // Have a proper error fire if the root of a file is ever not a Table
    // TODO: for now only json5 checked, need to finish others
    #[doc(hidden)]
    pub fn invalid_root(origin: Option<&String>, unexpected: Unexpected) -> Box<Self> {
        Box::new(ConfigError::Type {
            origin: origin.map(|s| s.to_owned()),
            unexpected,
            expected: "a map",
            key: None,
        })
    }

    // FIXME: pub(crate)
    #[doc(hidden)]
    #[must_use]
    pub fn extend_with_key(self, key: &str) -> Self {
        match self {
            ConfigError::Type {
                origin,
                unexpected,
                expected,
                ..
            } => ConfigError::Type {
                origin,
                unexpected,
                expected,
                key: Some(key.into()),
            },

            _ => self,
        }
    }

    #[must_use]
    fn prepend(self, segment: &str, add_dot: bool) -> Self {
        let concat = |key: Option<String>| {
            let key = key.unwrap_or_default();
            let dot = if add_dot && key.as_bytes().get(0).unwrap_or(&b'[') != &b'[' {
                "."
            } else {
                ""
            };
            format!("{}{}{}", segment, dot, key)
        };
        match self {
            ConfigError::Type {
                origin,
                unexpected,
                expected,
                key,
            } => ConfigError::Type {
                origin,
                unexpected,
                expected,
                key: Some(concat(key)),
            },
            ConfigError::NotFound(key) => ConfigError::NotFound(concat(Some(key))),
            _ => self,
        }
    }

    #[must_use]
    pub(crate) fn prepend_key(self, key: &str) -> Self {
        self.prepend(key, true)
    }

    #[must_use]
    pub(crate) fn prepend_index(self, idx: usize) -> Self {
        self.prepend(&format!("[{}]", idx), false)
    }
}

/// Alias for a `Result` with the error type set to `ConfigError`.
pub type Result<T> = result::Result<T, ConfigError>;

// Forward Debug to Display for readable panic! messages
impl fmt::Debug for ConfigError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", *self)
    }
}

impl fmt::Display for ConfigError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ConfigError::Frozen => write!(f, "configuration is frozen"),

            ConfigError::PathParse(ref kind) => write!(f, "{}", kind.description()),

            ConfigError::Message(ref s) => write!(f, "{}", s),

            ConfigError::Foreign(ref cause) => write!(f, "{}", cause),

            ConfigError::NotFound(ref key) => {
                write!(f, "configuration property {:?} not found", key)
            }

            ConfigError::Type {
                ref origin,
                ref unexpected,
                expected,
                ref key,
            } => {
                write!(f, "invalid type: {}, expected {}", unexpected, expected)?;

                if let Some(ref key) = *key {
                    write!(f, " for key `{}`", key)?;
                }

                if let Some(ref origin) = *origin {
                    write!(f, " in {}", origin)?;
                }

                Ok(())
            }

            ConfigError::FileParse { ref cause, ref uri } => {
                write!(f, "{}", cause)?;

                if let Some(ref uri) = *uri {
                    write!(f, " in {}", uri)?;
                }

                Ok(())
            }
        }
    }
}

impl Error for ConfigError {}

impl de::Error for ConfigError {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        ConfigError::Message(msg.to_string())
    }
}

impl ser::Error for ConfigError {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        ConfigError::Message(msg.to_string())
    }
}
<|endoftext|>


<commit_before>use std;
use std::fmt::{self, Debug, Display};
use std::iter::FromIterator;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
use crate::thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: crate::rustdoc_workaround::parse_module
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
pub struct Error {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test
where
    Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: crate::parse::ParseBuffer::error
    ///
    /// # Example
    ///
    /// ```
    /// use syn::{Error, Ident, LitStr, Result, Token};
    /// use syn::parse::ParseStream;
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            start_span: ThreadBound::new(span),
            end_span: ThreadBound::new(span),
            message: message.to_string(),
        }
    }

    /// Creates an error with the specified message spanning the given syntax
    /// tree node.
    ///
    /// Unlike the `Error::new` constructor, this constructor takes an argument
    /// `tokens` which is a syntax tree node. This allows the resulting `Error`
    /// to attempt to span all tokens inside of `tokens`. While you would
    /// typically be able to use the `Spanned` trait with the above `Error::new`
    /// constructor, implementation limitations today mean that
    /// `Error::new_spanned` may provide a higher-quality error message on
    /// stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map_or_else(Span::call_site, |t| t.span());
        let end = iter.last().map_or(start, |t| t.span());
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: message.to_string(),
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        let end = match self.end_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        start.join(end).unwrap_or(start)
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    pub fn to_compile_error(&self) -> TokenStream {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

#[cfg(feature = "parsing")]
pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        let span = crate::buffer::open_span_of_group(cursor);
        Error::new(span, message)
    }
}

impl Debug for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_tuple("Error").field(&self.message).finish()
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.message)
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}
<commit_msg>Error is exposed regardless of parsing feature<commit_after>use std;
use std::fmt::{self, Debug, Display};
use std::iter::FromIterator;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
use crate::thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: crate::rustdoc_workaround::parse_module
pub struct Error {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test
where
    Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: crate::parse::ParseBuffer::error
    ///
    /// # Example
    ///
    /// ```
    /// use syn::{Error, Ident, LitStr, Result, Token};
    /// use syn::parse::ParseStream;
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            start_span: ThreadBound::new(span),
            end_span: ThreadBound::new(span),
            message: message.to_string(),
        }
    }

    /// Creates an error with the specified message spanning the given syntax
    /// tree node.
    ///
    /// Unlike the `Error::new` constructor, this constructor takes an argument
    /// `tokens` which is a syntax tree node. This allows the resulting `Error`
    /// to attempt to span all tokens inside of `tokens`. While you would
    /// typically be able to use the `Spanned` trait with the above `Error::new`
    /// constructor, implementation limitations today mean that
    /// `Error::new_spanned` may provide a higher-quality error message on
    /// stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map_or_else(Span::call_site, |t| t.span());
        let end = iter.last().map_or(start, |t| t.span());
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: message.to_string(),
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        let end = match self.end_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        start.join(end).unwrap_or(start)
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    pub fn to_compile_error(&self) -> TokenStream {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

#[cfg(feature = "parsing")]
pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        let span = crate::buffer::open_span_of_group(cursor);
        Error::new(span, message)
    }
}

impl Debug for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_tuple("Error").field(&self.message).finish()
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.message)
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}
<|endoftext|>


<commit_before>/// Error types

error_chain! {
    types {
        Error, ErrorKind, ResultExt, Result;
    }

    errors {

        // Errors for tokenizer

        QueryParsingError(query: String) {
            description("parsing the query failed")
            display("Parsing the query '{}' failed", query)
        }

        EmptyQueryError {
            description("the query is empty")
            display("The query on the TOML is empty")
        }

        EmptyIdentifier {
            description("Query an empty identifier: ''")
            display("The passed query has an empty identifier")
        }

        ArrayAccessWithoutIndex {
            description("trying to access array without index")
            display("The passed query tries to access an array but does not specify the index")
        }

        ArrayAccessWithInvalidIndex {
            description("trying to pass an invalid index")
            display("The passed query tries to access an array but does not specify a valid index")
        }

        // Errors for Resolver

        IdentifierNotFoundInDocument(ident: String) {
            description("Identifier missing in document")
            display("The identfier '{}' is not present in the document", ident)
        }

        NoIndexInTable(i: usize) {
            description("Cannot deref index from table")
            display("Got an index query '[{}]' but have table", i)
        }

        NoIdentifierInArray(s: String) {
            description("Cannot query identifier in array")
            display("Got an identifier query '{}' but have array", s)
        }

    }
}
<commit_msg>Add error types for query on value error<commit_after>/// Error types

error_chain! {
    types {
        Error, ErrorKind, ResultExt, Result;
    }

    errors {

        // Errors for tokenizer

        QueryParsingError(query: String) {
            description("parsing the query failed")
            display("Parsing the query '{}' failed", query)
        }

        EmptyQueryError {
            description("the query is empty")
            display("The query on the TOML is empty")
        }

        EmptyIdentifier {
            description("Query an empty identifier: ''")
            display("The passed query has an empty identifier")
        }

        ArrayAccessWithoutIndex {
            description("trying to access array without index")
            display("The passed query tries to access an array but does not specify the index")
        }

        ArrayAccessWithInvalidIndex {
            description("trying to pass an invalid index")
            display("The passed query tries to access an array but does not specify a valid index")
        }

        // Errors for Resolver

        IdentifierNotFoundInDocument(ident: String) {
            description("Identifier missing in document")
            display("The identfier '{}' is not present in the document", ident)
        }

        NoIndexInTable(i: usize) {
            description("Cannot deref index from table")
            display("Got an index query '[{}]' but have table", i)
        }

        NoIdentifierInArray(s: String) {
            description("Cannot query identifier in array")
            display("Got an identifier query '{}' but have array", s)
        }

        QueryingValueAsTable(s: String) {
            description("Querying a table where a value is")
            display("Got an identifier query '{}' but have value", s)
        }

        QueryingValueAsArray(i: usize) {
            description("Querying a table where a value is")
            display("Got an index query '{}' but have value", i)
        }

    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "serialize")]
use serde::ser::{Serialize, SerializeStruct, Serializer};
use std::error;
use std::error::Error;
use std::fmt;
use std::net::AddrParseError;
use std::num::ParseFloatError;
use std::num::ParseIntError;

#[derive(Debug, Clone)]
pub enum SdpParserInternalError {
    Generic(String),
    Unsupported(String),
    Integer(ParseIntError),
    Float(ParseFloatError),
    Address(AddrParseError),
}

impl fmt::Display for SdpParserInternalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SdpParserInternalError::Generic(ref message) => {
                write!(f, "Generic parsing error: {}", message)
            }
            SdpParserInternalError::Unsupported(ref message) => {
                write!(f, "Unsupported parsing error: {}", message)
            }
            SdpParserInternalError::Integer(ref error) => {
                write!(f, "Integer parsing error: {}", error.description())
            }
            SdpParserInternalError::Float(ref error) => {
                write!(f, "Float parsing error: {}", error.description())
            }
            SdpParserInternalError::Address(ref error) => {
                write!(f, "IP address parsing error: {}", error.description())
            }
        }
    }
}

impl error::Error for SdpParserInternalError {
    fn description(&self) -> &str {
        match *self {
            SdpParserInternalError::Generic(ref message)
            | SdpParserInternalError::Unsupported(ref message) => message,
            SdpParserInternalError::Integer(ref error) => error.description(),
            SdpParserInternalError::Float(ref error) => error.description(),
            SdpParserInternalError::Address(ref error) => error.description(),
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            SdpParserInternalError::Integer(ref error) => Some(error),
            SdpParserInternalError::Float(ref error) => Some(error),
            SdpParserInternalError::Address(ref error) => Some(error),
            // Can't tell much more about our internal errors
            _ => None,
        }
    }
}

#[test]
#[allow(deprecated)] // see issue #102
fn test_sdp_parser_internal_error_generic() {
    let generic = SdpParserInternalError::Generic("generic message".to_string());
    assert_eq!(
        format!("{}", generic),
        "Generic parsing error: generic message"
    );
    assert_eq!(generic.description(), "generic message");
    assert!(generic.cause().is_none());
}

#[test]
#[allow(deprecated)] // see issue #102
fn test_sdp_parser_internal_error_unsupported() {
    let unsupported =
        SdpParserInternalError::Unsupported("unsupported internal message".to_string());
    assert_eq!(
        format!("{}", unsupported),
        "Unsupported parsing error: unsupported internal message"
    );
    assert_eq!(unsupported.description(), "unsupported internal message");
    assert!(unsupported.cause().is_none());
}

#[test]
#[allow(deprecated)] // see issue #102
fn test_sdp_parser_internal_error_integer() {
    let v = "12a";
    let integer = v.parse::<u64>();
    assert!(integer.is_err());
    let int_err = SdpParserInternalError::Integer(integer.err().unwrap());
    assert_eq!(
        format!("{}", int_err),
        "Integer parsing error: invalid digit found in string"
    );
    assert_eq!(int_err.description(), "invalid digit found in string");
    assert!(!int_err.cause().is_none());
}

#[test]
#[allow(deprecated)] // see issue #102
fn test_sdp_parser_internal_error_float() {
    let v = "12.2a";
    let float = v.parse::<f32>();
    assert!(float.is_err());
    let int_err = SdpParserInternalError::Float(float.err().unwrap());
    assert_eq!(
        format!("{}", int_err),
        "Float parsing error: invalid float literal"
    );
    assert_eq!(int_err.description(), "invalid float literal");
    assert!(!int_err.cause().is_none());
}

#[test]
#[allow(deprecated)] // see issue #102
fn test_sdp_parser_internal_error_address() {
    let v = "127.0.0.a";
    use std::net::IpAddr;
    use std::str::FromStr;
    let addr = IpAddr::from_str(v);
    assert!(addr.is_err());
    let addr_err = SdpParserInternalError::Address(addr.err().unwrap());
    assert_eq!(
        format!("{}", addr_err),
        "IP address parsing error: invalid IP address syntax"
    );
    assert_eq!(addr_err.description(), "invalid IP address syntax");
    assert!(!addr_err.cause().is_none());
}

#[derive(Debug, Clone)]
pub enum SdpParserError {
    Line {
        error: SdpParserInternalError,
        line: String,
        line_number: usize,
    },
    Unsupported {
        error: SdpParserInternalError,
        line: String,
        line_number: usize,
    },
    Sequence {
        message: String,
        line_number: usize,
    },
}

#[cfg(feature = "serialize")]
impl Serialize for SdpParserError {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state = serializer.serialize_struct(
            "error",
            match *self {
                SdpParserError::Sequence { .. } => 3,
                _ => 4,
            },
        )?;
        match *self {
            SdpParserError::Line {
                ref error,
                ref line,
                ..
            } => {
                state.serialize_field("type", "Line")?;
                state.serialize_field("message", &format!("{}", error))?;
                state.serialize_field("line", &line)?
            }
            SdpParserError::Unsupported {
                ref error,
                ref line,
                ..
            } => {
                state.serialize_field("type", "Unsupported")?;
                state.serialize_field("message", &format!("{}", error))?;
                state.serialize_field("line", &line)?
            }
            SdpParserError::Sequence { ref message, .. } => {
                state.serialize_field("type", "Sequence")?;
                state.serialize_field("message", &message)?;
            }
        };
        state.serialize_field(
            "line_number",
            &match *self {
                SdpParserError::Line { line_number, .. } => line_number,
                SdpParserError::Unsupported { line_number, .. } => line_number,
                SdpParserError::Sequence { line_number, .. } => line_number,
            },
        )?;
        state.end()
    }
}

impl fmt::Display for SdpParserError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SdpParserError::Line {
                ref error,
                ref line,
                ref line_number,
            } => write!(
                f,
                "Line error: {} in line({}): {}",
                error.description(),
                line_number,
                line
            ),
            SdpParserError::Unsupported {
                ref error,
                ref line,
                ref line_number,
            } => write!(
                f,
                "Unsupported: {} in line({}): {}",
                error.description(),
                line_number,
                line
            ),
            SdpParserError::Sequence {
                ref message,
                ref line_number,
            } => write!(f, "Sequence error in line({}): {}", line_number, message),
        }
    }
}

impl error::Error for SdpParserError {
    fn description(&self) -> &str {
        match *self {
            SdpParserError::Line { ref error, .. }
            | SdpParserError::Unsupported { ref error, .. } => error.description(),
            SdpParserError::Sequence { ref message, .. } => message,
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            SdpParserError::Line { ref error, .. }
            | SdpParserError::Unsupported { ref error, .. } => Some(error),
            // Can't tell much more about our internal errors
            _ => None,
        }
    }
}

impl From<ParseIntError> for SdpParserInternalError {
    fn from(err: ParseIntError) -> SdpParserInternalError {
        SdpParserInternalError::Integer(err)
    }
}

impl From<AddrParseError> for SdpParserInternalError {
    fn from(err: AddrParseError) -> SdpParserInternalError {
        SdpParserInternalError::Address(err)
    }
}

impl From<ParseFloatError> for SdpParserInternalError {
    fn from(err: ParseFloatError) -> SdpParserInternalError {
        SdpParserInternalError::Float(err)
    }
}

#[test]
#[allow(deprecated)] // see issue #102
fn test_sdp_parser_error_line() {
    let line1 = SdpParserError::Line {
        error: SdpParserInternalError::Generic("test message".to_string()),
        line: "test line".to_string(),
        line_number: 13,
    };
    assert_eq!(
        format!("{}", line1),
        "Line error: test message in line(13): test line"
    );
    assert_eq!(line1.description(), "test message");
    assert!(line1.cause().is_some());
}

#[test]
#[allow(deprecated)] // see issue #102
fn test_sdp_parser_error_unsupported() {
    let unsupported1 = SdpParserError::Unsupported {
        error: SdpParserInternalError::Generic("unsupported value".to_string()),
        line: "unsupported line".to_string(),
        line_number: 21,
    };
    assert_eq!(
        format!("{}", unsupported1),
        "Unsupported: unsupported value in line(21): unsupported line"
    );
    assert_eq!(unsupported1.description(), "unsupported value");
    assert!(unsupported1.cause().is_some());
}

#[test]
#[allow(deprecated)] // see issue #102
fn test_sdp_parser_error_sequence() {
    let sequence1 = SdpParserError::Sequence {
        message: "sequence message".to_string(),
        line_number: 42,
    };
    assert_eq!(
        format!("{}", sequence1),
        "Sequence error in line(42): sequence message"
    );
    assert_eq!(sequence1.description(), "sequence message");
    assert!(sequence1.cause().is_none());
}
<commit_msg>replace cause() with source() - fixes #102 (#121)<commit_after>#[cfg(feature = "serialize")]
use serde::ser::{Serialize, SerializeStruct, Serializer};
use std::error;
use std::error::Error;
use std::fmt;
use std::net::AddrParseError;
use std::num::ParseFloatError;
use std::num::ParseIntError;

#[derive(Debug, Clone)]
pub enum SdpParserInternalError {
    Generic(String),
    Unsupported(String),
    Integer(ParseIntError),
    Float(ParseFloatError),
    Address(AddrParseError),
}

impl fmt::Display for SdpParserInternalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SdpParserInternalError::Generic(ref message) => {
                write!(f, "Generic parsing error: {}", message)
            }
            SdpParserInternalError::Unsupported(ref message) => {
                write!(f, "Unsupported parsing error: {}", message)
            }
            SdpParserInternalError::Integer(ref error) => {
                write!(f, "Integer parsing error: {}", error.description())
            }
            SdpParserInternalError::Float(ref error) => {
                write!(f, "Float parsing error: {}", error.description())
            }
            SdpParserInternalError::Address(ref error) => {
                write!(f, "IP address parsing error: {}", error.description())
            }
        }
    }
}

impl error::Error for SdpParserInternalError {
    fn description(&self) -> &str {
        match *self {
            SdpParserInternalError::Generic(ref message)
            | SdpParserInternalError::Unsupported(ref message) => message,
            SdpParserInternalError::Integer(ref error) => error.description(),
            SdpParserInternalError::Float(ref error) => error.description(),
            SdpParserInternalError::Address(ref error) => error.description(),
        }
    }

    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match *self {
            SdpParserInternalError::Integer(ref error) => Some(error),
            SdpParserInternalError::Float(ref error) => Some(error),
            SdpParserInternalError::Address(ref error) => Some(error),
            // Can't tell much more about our internal errors
            _ => None,
        }
    }
}

#[test]
fn test_sdp_parser_internal_error_generic() {
    let generic = SdpParserInternalError::Generic("generic message".to_string());
    assert_eq!(
        format!("{}", generic),
        "Generic parsing error: generic message"
    );
    assert_eq!(generic.description(), "generic message");
    assert!(generic.source().is_none());
}

#[test]
fn test_sdp_parser_internal_error_unsupported() {
    let unsupported =
        SdpParserInternalError::Unsupported("unsupported internal message".to_string());
    assert_eq!(
        format!("{}", unsupported),
        "Unsupported parsing error: unsupported internal message"
    );
    assert_eq!(unsupported.description(), "unsupported internal message");
    assert!(unsupported.source().is_none());
}

#[test]
fn test_sdp_parser_internal_error_integer() {
    let v = "12a";
    let integer = v.parse::<u64>();
    assert!(integer.is_err());
    let int_err = SdpParserInternalError::Integer(integer.err().unwrap());
    assert_eq!(
        format!("{}", int_err),
        "Integer parsing error: invalid digit found in string"
    );
    assert_eq!(int_err.description(), "invalid digit found in string");
    assert!(!int_err.source().is_none());
}

#[test]
fn test_sdp_parser_internal_error_float() {
    let v = "12.2a";
    let float = v.parse::<f32>();
    assert!(float.is_err());
    let int_err = SdpParserInternalError::Float(float.err().unwrap());
    assert_eq!(
        format!("{}", int_err),
        "Float parsing error: invalid float literal"
    );
    assert_eq!(int_err.description(), "invalid float literal");
    assert!(!int_err.source().is_none());
}

#[test]
fn test_sdp_parser_internal_error_address() {
    let v = "127.0.0.a";
    use std::net::IpAddr;
    use std::str::FromStr;
    let addr = IpAddr::from_str(v);
    assert!(addr.is_err());
    let addr_err = SdpParserInternalError::Address(addr.err().unwrap());
    assert_eq!(
        format!("{}", addr_err),
        "IP address parsing error: invalid IP address syntax"
    );
    assert_eq!(addr_err.description(), "invalid IP address syntax");
    assert!(!addr_err.source().is_none());
}

#[derive(Debug, Clone)]
pub enum SdpParserError {
    Line {
        error: SdpParserInternalError,
        line: String,
        line_number: usize,
    },
    Unsupported {
        error: SdpParserInternalError,
        line: String,
        line_number: usize,
    },
    Sequence {
        message: String,
        line_number: usize,
    },
}

#[cfg(feature = "serialize")]
impl Serialize for SdpParserError {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state = serializer.serialize_struct(
            "error",
            match *self {
                SdpParserError::Sequence { .. } => 3,
                _ => 4,
            },
        )?;
        match *self {
            SdpParserError::Line {
                ref error,
                ref line,
                ..
            } => {
                state.serialize_field("type", "Line")?;
                state.serialize_field("message", &format!("{}", error))?;
                state.serialize_field("line", &line)?
            }
            SdpParserError::Unsupported {
                ref error,
                ref line,
                ..
            } => {
                state.serialize_field("type", "Unsupported")?;
                state.serialize_field("message", &format!("{}", error))?;
                state.serialize_field("line", &line)?
            }
            SdpParserError::Sequence { ref message, .. } => {
                state.serialize_field("type", "Sequence")?;
                state.serialize_field("message", &message)?;
            }
        };
        state.serialize_field(
            "line_number",
            &match *self {
                SdpParserError::Line { line_number, .. } => line_number,
                SdpParserError::Unsupported { line_number, .. } => line_number,
                SdpParserError::Sequence { line_number, .. } => line_number,
            },
        )?;
        state.end()
    }
}

impl fmt::Display for SdpParserError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SdpParserError::Line {
                ref error,
                ref line,
                ref line_number,
            } => write!(
                f,
                "Line error: {} in line({}): {}",
                error.description(),
                line_number,
                line
            ),
            SdpParserError::Unsupported {
                ref error,
                ref line,
                ref line_number,
            } => write!(
                f,
                "Unsupported: {} in line({}): {}",
                error.description(),
                line_number,
                line
            ),
            SdpParserError::Sequence {
                ref message,
                ref line_number,
            } => write!(f, "Sequence error in line({}): {}", line_number, message),
        }
    }
}

impl error::Error for SdpParserError {
    fn description(&self) -> &str {
        match *self {
            SdpParserError::Line { ref error, .. }
            | SdpParserError::Unsupported { ref error, .. } => error.description(),
            SdpParserError::Sequence { ref message, .. } => message,
        }
    }

    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match *self {
            SdpParserError::Line { ref error, .. }
            | SdpParserError::Unsupported { ref error, .. } => Some(error),
            // Can't tell much more about our internal errors
            _ => None,
        }
    }
}

impl From<ParseIntError> for SdpParserInternalError {
    fn from(err: ParseIntError) -> SdpParserInternalError {
        SdpParserInternalError::Integer(err)
    }
}

impl From<AddrParseError> for SdpParserInternalError {
    fn from(err: AddrParseError) -> SdpParserInternalError {
        SdpParserInternalError::Address(err)
    }
}

impl From<ParseFloatError> for SdpParserInternalError {
    fn from(err: ParseFloatError) -> SdpParserInternalError {
        SdpParserInternalError::Float(err)
    }
}

#[test]
fn test_sdp_parser_error_line() {
    let line1 = SdpParserError::Line {
        error: SdpParserInternalError::Generic("test message".to_string()),
        line: "test line".to_string(),
        line_number: 13,
    };
    assert_eq!(
        format!("{}", line1),
        "Line error: test message in line(13): test line"
    );
    assert_eq!(line1.description(), "test message");
    assert!(line1.source().is_some());
}

#[test]
fn test_sdp_parser_error_unsupported() {
    let unsupported1 = SdpParserError::Unsupported {
        error: SdpParserInternalError::Generic("unsupported value".to_string()),
        line: "unsupported line".to_string(),
        line_number: 21,
    };
    assert_eq!(
        format!("{}", unsupported1),
        "Unsupported: unsupported value in line(21): unsupported line"
    );
    assert_eq!(unsupported1.description(), "unsupported value");
    assert!(unsupported1.source().is_some());
}

#[test]
fn test_sdp_parser_error_sequence() {
    let sequence1 = SdpParserError::Sequence {
        message: "sequence message".to_string(),
        line_number: 42,
    };
    assert_eq!(
        format!("{}", sequence1),
        "Sequence error in line(42): sequence message"
    );
    assert_eq!(sequence1.description(), "sequence message");
    assert!(sequence1.source().is_none());
}
<|endoftext|>