<commit_before>/*!

*/
use buffer::{mod, Buffer};
use gl;
use GlObject;
use {IndicesSource, IndicesSourceHelper};

/// A list of indices loaded in the graphics card's memory.
#[deriving(Show)]
pub struct IndexBuffer {
    buffer: Buffer,
    data_type: gl::types::GLenum,
    primitives: gl::types::GLenum,
}

impl IndexBuffer {
    /// Builds a new index buffer.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate glium;
    /// # extern crate glutin;
    /// # use glium::DisplayBuild;
    /// # fn main() {
    /// # let display: glium::Display = glutin::HeadlessRendererBuilder::new(1024, 768)
    /// #  .build_glium().unwrap();
    /// let index_buffer = glium::IndexBuffer::new(&display,
    ///     glium::index_buffer::TrianglesList(vec![0u8, 1, 2, 1, 3, 4, 2, 4, 3]));
    /// # }
    /// ```
    ///
    pub fn new<T: IntoIndexBuffer>(display: &super::Display, data: T) -> IndexBuffer {
        data.into_index_buffer(display)
    }
}

impl GlObject for IndexBuffer {
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

impl IndicesSource for IndexBuffer {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let id = self.buffer.get_id();
        let elems_count = self.buffer.get_elements_count();
        let datatype = self.data_type.clone();
        let primitives = self.primitives.clone();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use std::ptr;

                if state.element_array_buffer_binding != Some(id) {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, id);
                    state.element_array_buffer_binding = Some(id);
                }

                gl.DrawElements(primitives, elems_count as i32, datatype, ptr::null());
            }
        })
    }
}

/// An index from the vertex buffer.
pub trait Index {
    /// Returns the GL_ENUM corresponding to this type.
    fn to_glenum(Option<Self>) -> gl::types::GLenum;
}

impl Index for u8 {
    fn to_glenum(_: Option<u8>) -> gl::types::GLenum {
        gl::UNSIGNED_BYTE
    }
}

impl Index for u16 {
    fn to_glenum(_: Option<u16>) -> gl::types::GLenum {
        gl::UNSIGNED_SHORT
    }
}

impl Index for u32 {
    fn to_glenum(_: Option<u32>) -> gl::types::GLenum {
        gl::UNSIGNED_INT
    }
}

/// Object is convertible to an index buffer.
pub trait IntoIndexBuffer {
    /// Creates a new `IndexBuffer` with the list of indices.
    fn into_index_buffer(self, &super::Display) -> IndexBuffer;
}

/// A list of points stored in RAM.
#[deriving(Clone)]
pub struct PointsList<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for PointsList<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::POINTS,
        }
    }
}

/// A list of lines stored in RAM.
pub struct LinesList<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for LinesList<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::LINES,
        }
    }
}

/// A list of lines with adjacency infos stored in RAM.
pub struct LinesListAdjacency<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for LinesListAdjacency<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::LINES_ADJACENCY,
        }
    }
}

/// A list of lines connected together stored in RAM.
pub struct LineStrip<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for LineStrip<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::LINE_STRIP,
        }
    }
}

/// A list of lines connected together with adjacency infos stored in RAM.
pub struct LineStripAdjacency<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for LineStripAdjacency<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::LINE_STRIP_ADJACENCY,
        }
    }
}

/// A list of triangles stored in RAM.
pub struct TrianglesList<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for TrianglesList<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::TRIANGLES,
        }
    }
}

/// A list of triangles with adjacency infos stored in RAM.
pub struct TrianglesListAdjacency<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for TrianglesListAdjacency<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::TRIANGLES_ADJACENCY,
        }
    }
}

/// A list of triangles connected together stored in RAM.
pub struct TriangleStrip<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for TriangleStrip<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::TRIANGLE_STRIP,
        }
    }
}

/// A list of triangles connected together with adjacency infos stored in RAM.
pub struct TriangleStripAdjacency<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for TriangleStripAdjacency<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::TRIANGLE_STRIP_ADJACENCY,
        }
    }
}

/// A list of triangles stored in RAM.
pub struct TriangleFan<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for TriangleFan<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::TRIANGLE_FAN,
        }
    }
}
<commit_msg>Implement IndicesSource for data types in RAM<commit_after>/*!

*/
use buffer::{mod, Buffer};
use gl;
use GlObject;
use {IndicesSource, IndicesSourceHelper};

/// A list of indices loaded in the graphics card's memory.
#[deriving(Show)]
pub struct IndexBuffer {
    buffer: Buffer,
    data_type: gl::types::GLenum,
    primitives: gl::types::GLenum,
}

impl IndexBuffer {
    /// Builds a new index buffer.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate glium;
    /// # extern crate glutin;
    /// # use glium::DisplayBuild;
    /// # fn main() {
    /// # let display: glium::Display = glutin::HeadlessRendererBuilder::new(1024, 768)
    /// #  .build_glium().unwrap();
    /// let index_buffer = glium::IndexBuffer::new(&display,
    ///     glium::index_buffer::TrianglesList(vec![0u8, 1, 2, 1, 3, 4, 2, 4, 3]));
    /// # }
    /// ```
    ///
    pub fn new<T: IntoIndexBuffer>(display: &super::Display, data: T) -> IndexBuffer {
        data.into_index_buffer(display)
    }
}

impl GlObject for IndexBuffer {
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

impl IndicesSource for IndexBuffer {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let id = self.buffer.get_id();
        let elems_count = self.buffer.get_elements_count();
        let datatype = self.data_type.clone();
        let primitives = self.primitives.clone();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use std::ptr;

                if state.element_array_buffer_binding != Some(id) {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, id);
                    state.element_array_buffer_binding = Some(id);
                }

                gl.DrawElements(primitives, elems_count as i32, datatype, ptr::null());
            }
        })
    }
}

/// An index from the vertex buffer.
pub trait Index {
    /// Returns the GL_ENUM corresponding to this type.
    fn to_glenum(Option<Self>) -> gl::types::GLenum;
}

impl Index for u8 {
    fn to_glenum(_: Option<u8>) -> gl::types::GLenum {
        gl::UNSIGNED_BYTE
    }
}

impl Index for u16 {
    fn to_glenum(_: Option<u16>) -> gl::types::GLenum {
        gl::UNSIGNED_SHORT
    }
}

impl Index for u32 {
    fn to_glenum(_: Option<u32>) -> gl::types::GLenum {
        gl::UNSIGNED_INT
    }
}

/// Object is convertible to an index buffer.
pub trait IntoIndexBuffer {
    /// Creates a new `IndexBuffer` with the list of indices.
    fn into_index_buffer(self, &super::Display) -> IndexBuffer;
}

/// A list of points stored in RAM.
#[deriving(Clone)]
pub struct PointsList<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for PointsList<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::POINTS,
        }
    }
}

impl<T> IndicesSource for PointsList<T> where T: Index + Send + Copy {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let elems_count = self.0.len();
        let data_type = Index::to_glenum(None::<T>);
        let ptr = self.0.as_ptr();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use libc;

                if state.element_array_buffer_binding != None {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
                    state.element_array_buffer_binding = None;
                }

                gl.DrawElements(gl::POINTS, elems_count as i32, data_type,
                                ptr as *const libc::c_void);
            }
        })
    }
}

/// A list of lines stored in RAM.
pub struct LinesList<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for LinesList<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::LINES,
        }
    }
}

impl<T> IndicesSource for LinesList<T> where T: Index + Send + Copy {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let elems_count = self.0.len();
        let data_type = Index::to_glenum(None::<T>);
        let ptr = self.0.as_ptr();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use libc;

                if state.element_array_buffer_binding != None {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
                    state.element_array_buffer_binding = None;
                }

                gl.DrawElements(gl::LINES, elems_count as i32, data_type,
                                ptr as *const libc::c_void);
            }
        })
    }
}

/// A list of lines with adjacency infos stored in RAM.
pub struct LinesListAdjacency<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for LinesListAdjacency<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::LINES_ADJACENCY,
        }
    }
}

impl<T> IndicesSource for LinesListAdjacency<T> where T: Index + Send + Copy {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let elems_count = self.0.len();
        let data_type = Index::to_glenum(None::<T>);
        let ptr = self.0.as_ptr();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use libc;

                if state.element_array_buffer_binding != None {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
                    state.element_array_buffer_binding = None;
                }

                gl.DrawElements(gl::LINES_ADJACENCY, elems_count as i32, data_type,
                                ptr as *const libc::c_void);
            }
        })
    }
}

/// A list of lines connected together stored in RAM.
pub struct LineStrip<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for LineStrip<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::LINE_STRIP,
        }
    }
}

impl<T> IndicesSource for LineStrip<T> where T: Index + Send + Copy {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let elems_count = self.0.len();
        let data_type = Index::to_glenum(None::<T>);
        let ptr = self.0.as_ptr();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use libc;

                if state.element_array_buffer_binding != None {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
                    state.element_array_buffer_binding = None;
                }

                gl.DrawElements(gl::LINE_STRIP, elems_count as i32, data_type,
                                ptr as *const libc::c_void);
            }
        })
    }
}

/// A list of lines connected together with adjacency infos stored in RAM.
pub struct LineStripAdjacency<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for LineStripAdjacency<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::LINE_STRIP_ADJACENCY,
        }
    }
}

impl<T> IndicesSource for LineStripAdjacency<T> where T: Index + Send + Copy {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let elems_count = self.0.len();
        let data_type = Index::to_glenum(None::<T>);
        let ptr = self.0.as_ptr();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use libc;

                if state.element_array_buffer_binding != None {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
                    state.element_array_buffer_binding = None;
                }

                gl.DrawElements(gl::LINE_STRIP_ADJACENCY, elems_count as i32, data_type,
                                ptr as *const libc::c_void);
            }
        })
    }
}

/// A list of triangles stored in RAM.
pub struct TrianglesList<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for TrianglesList<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::TRIANGLES,
        }
    }
}

impl<T> IndicesSource for TrianglesList<T> where T: Index + Send + Copy {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let elems_count = self.0.len();
        let data_type = Index::to_glenum(None::<T>);
        let ptr = self.0.as_ptr();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use libc;

                if state.element_array_buffer_binding != None {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
                    state.element_array_buffer_binding = None;
                }

                gl.DrawElements(gl::TRIANGLES, elems_count as i32, data_type,
                                ptr as *const libc::c_void);
            }
        })
    }
}

/// A list of triangles with adjacency infos stored in RAM.
pub struct TrianglesListAdjacency<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for TrianglesListAdjacency<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::TRIANGLES_ADJACENCY,
        }
    }
}

impl<T> IndicesSource for TrianglesListAdjacency<T> where T: Index + Send + Copy {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let elems_count = self.0.len();
        let data_type = Index::to_glenum(None::<T>);
        let ptr = self.0.as_ptr();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use libc;

                if state.element_array_buffer_binding != None {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
                    state.element_array_buffer_binding = None;
                }

                gl.DrawElements(gl::TRIANGLES_ADJACENCY, elems_count as i32, data_type,
                                ptr as *const libc::c_void);
            }
        })
    }
}

/// A list of triangles connected together stored in RAM.
pub struct TriangleStrip<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for TriangleStrip<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::TRIANGLE_STRIP,
        }
    }
}

impl<T> IndicesSource for TriangleStrip<T> where T: Index + Send + Copy {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let elems_count = self.0.len();
        let data_type = Index::to_glenum(None::<T>);
        let ptr = self.0.as_ptr();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use libc;

                if state.element_array_buffer_binding != None {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
                    state.element_array_buffer_binding = None;
                }

                gl.DrawElements(gl::TRIANGLE_STRIP, elems_count as i32, data_type,
                                ptr as *const libc::c_void);
            }
        })
    }
}

/// A list of triangles connected together with adjacency infos stored in RAM.
pub struct TriangleStripAdjacency<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for TriangleStripAdjacency<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::TRIANGLE_STRIP_ADJACENCY,
        }
    }
}

impl<T> IndicesSource for TriangleStripAdjacency<T> where T: Index + Send + Copy {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let elems_count = self.0.len();
        let data_type = Index::to_glenum(None::<T>);
        let ptr = self.0.as_ptr();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use libc;

                if state.element_array_buffer_binding != None {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
                    state.element_array_buffer_binding = None;
                }

                gl.DrawElements(gl::TRIANGLE_STRIP_ADJACENCY, elems_count as i32, data_type,
                                ptr as *const libc::c_void);
            }
        })
    }
}

/// A list of triangles stored in RAM.
pub struct TriangleFan<T>(pub Vec<T>);

impl<T> IntoIndexBuffer for TriangleFan<T> where T: Index + Send + Copy {
    fn into_index_buffer(self, display: &super::Display) -> IndexBuffer {
        IndexBuffer {
            buffer: Buffer::new::<buffer::ElementArrayBuffer, _>(display, self.0, gl::STATIC_DRAW),
            data_type: Index::to_glenum(None::<T>),
            primitives: gl::TRIANGLE_FAN,
        }
    }
}

impl<T> IndicesSource for TriangleFan<T> where T: Index + Send + Copy {
    fn to_indices_source_helper(&self) -> IndicesSourceHelper {
        let elems_count = self.0.len();
        let data_type = Index::to_glenum(None::<T>);
        let ptr = self.0.as_ptr();

        IndicesSourceHelper(proc(gl, state) {
            unsafe {
                use libc;

                if state.element_array_buffer_binding != None {
                    gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
                    state.element_array_buffer_binding = None;
                }

                gl.DrawElements(gl::TRIANGLE_FAN, elems_count as i32, data_type,
                                ptr as *const libc::c_void);
            }
        })
    }
}
<|endoftext|>


<commit_before>// main.rs
// Main entry point for a dining philosophers,
// a concurrency problem.
//
// taken from the rust-lang tutorial:
// https://doc.rust-lang.org/stable/book/dining-philosophers.html
//
// vim: ft=rust sw=4 ts=4

use std::thread;
use std::sync::{Mutex, Arc};

// a philosopher struct
struct Philosopher {
    name: String,
    left: usize,
    right: usize,
}

impl Philosopher {
    fn new(name: &str, left: usize, right: usize) -> Philosopher {
        Philosopher {
            name: name.to_string(),
            left: left,
            right: right,
        }
    }

    fn eat(&self, table: &Table) {
        let _left = table.forks[self.left].lock().unwrap();
        let _right = table.forks[self.right].lock().unwrap();

        println!("{} has started eating.", self.name);

        thread::sleep_ms(1000);

        println!("{} has finished eating.", self.name);
    }

    fn mult_eat(&self, table: &Table, pause: u32, repeat: u32) {
        for x in 0..repeat {
            thread::sleep_ms(pause);
            println!("{} went to table for {}. time.", self.name, (x+1));
            self.eat(table);
        }
    }
}

struct Table {
    forks: Vec<Mutex<()>>,
}

fn main() {
    let table = Arc::new(Table { forks: vec![
        Mutex::new(()),
        Mutex::new(()),
        Mutex::new(()),
        Mutex::new(()),
        Mutex::new(()),
        ]});

    let philosophers = vec![
        Philosopher::new("Baruch Spinoza", 0, 1),
        Philosopher::new("Gilles Deleuze", 1, 2),
        Philosopher::new("Karl Marx", 2, 3),
        Philosopher::new("Friedich Nietzsche", 3, 4),
        Philosopher::new("Michel Foucault", 0, 4), // swap "hands" to prevent deadlock
        ];

    let handles: Vec<_> = philosophers.into_iter().map(|p| {
        let table = table.clone();

        thread::spawn(move || {
            //p.eat(&table);
            p.mult_eat(&table, 2000, 3);
        })
    }).collect();

    for h in handles {
        h.join().unwrap();
    }
}

<commit_msg>change thread::sleep_ms() to thread::sleep()<commit_after>// main.rs
// Main entry point for a dining philosophers,
// a concurrency problem.
//
// taken from the rust-lang tutorial:
// https://doc.rust-lang.org/stable/book/dining-philosophers.html
//
// vim: ft=rust sw=4 ts=4

use std::thread;
use std::time::Duration;
use std::sync::{Mutex, Arc};

// a philosopher struct
struct Philosopher {
    name: String,
    left: usize,
    right: usize,
}

impl Philosopher {
    fn new(name: &str, left: usize, right: usize) -> Philosopher {
        Philosopher {
            name: name.to_string(),
            left,
            right,
        }
    }

    fn eat(&self, table: &Table) {
        let _left = table.forks[self.left].lock().unwrap();
        let _right = table.forks[self.right].lock().unwrap();

        println!("{} has started eating.", self.name);

        thread::sleep(Duration::from_millis(1000));

        println!("{} has finished eating.", self.name);
    }

    fn mult_eat(&self, table: &Table, pause: u32, repeat: u32) {
        for x in 0..repeat {
            thread::sleep(Duration::from_millis(u64::from(pause)));
            println!("{} went to table for {}. time.", self.name, (x+1));
            self.eat(table);
        }
    }
}

struct Table {
    forks: Vec<Mutex<()>>,
}

fn main() {
    let table = Arc::new(Table { forks: vec![
        Mutex::new(()),
        Mutex::new(()),
        Mutex::new(()),
        Mutex::new(()),
        Mutex::new(()),
        ]});

    let philosophers = vec![
        Philosopher::new("Baruch Spinoza", 0, 1),
        Philosopher::new("Gilles Deleuze", 1, 2),
        Philosopher::new("Karl Marx", 2, 3),
        Philosopher::new("Friedich Nietzsche", 3, 4),
        Philosopher::new("Michel Foucault", 0, 4), // swap "hands" to prevent deadlock
        ];

    let handles: Vec<_> = philosophers.into_iter().map(|p| {
        let table = table.clone();

        thread::spawn(move || {
            //p.eat(&table);
            p.mult_eat(&table, 2000, 3);
        })
    }).collect();

    for h in handles {
        h.join().unwrap();
    }
}

<|endoftext|>


<commit_before>export FontCache, native;
use font::{Font, test_font_bin};

struct FontCache {
    // FIXME: This is a hack to hold onto a boxed reference to
    // the self pointer until explicit self types work on methods.
    // This is a huge space leak.
    mut at_self: Option<@FontCache>,
    native_lib: native::NativeFontCache,

    drop {
        native::destroy_native_lib(&self.native_lib);
    }
}

impl FontCache {
    fn get_font() -> @Font {
        assert self.at_self.is_some();
        match create_font(self.at_self.get(), &self.native_lib) {
          Ok(font) => font,
          Err(*) => /* FIXME */ fail
        }
    }

    fn get_test_font() -> @Font {
        self.get_font()
    }
}

fn FontCache() -> @FontCache {
    let lib = @FontCache {
        mut at_self: None,
        native_lib: native::create_native_lib()
    };

    lib.at_self = Some(lib);
    return lib;
}

fn create_font(lib: @FontCache, native_lib: &native::NativeFontCache) -> Result<@Font, ()> {
    let font_bin = @test_font_bin();
    let native_font = native_font::create(native_lib, font_bin);
    let native_font = if native_font.is_ok() {
        result::unwrap(native_font)
    } else {
        return Err(native_font.get_err());
    };
    let metrics = native_font.get_metrics();
    return Ok(@Font(lib, font_bin, native_font, metrics));
}

#[cfg(target_os = "linux")]
pub mod native {
    use ptr::{null, addr_of};
    use azure::freetype;
    use freetype::{FT_Library, FT_Error};
    use freetype::bindgen::{FT_Init_FreeType, FT_Done_FreeType};

    pub type NativeFontCache = FT_Library;

    pub fn create_native_lib() -> NativeFontCache {
        let lib: FT_Library = null();
        let res = FT_Init_FreeType(addr_of(&lib));
        // FIXME: error handling
        assert res == 0 as FT_Error;
        return lib;
    }

    pub fn destroy_native_lib(native_lib: &NativeFontCache) {
        assert native_lib.is_not_null();
        FT_Done_FreeType(*native_lib);
    }
}

#[cfg(target_os = "macos")]
pub mod native {
    pub type NativeFontCache = ();

    pub fn create_native_lib() -> NativeFontCache { () }
    pub fn destroy_native_lib(_native_lib: &NativeFontCache) { }
}

#[test]
pub fn should_get_fonts() {
    let lib = FontCache();
    lib.get_font();
}
<commit_msg>Remove @self hack from FontCache<commit_after>export FontCache, native;
use font::{Font, test_font_bin};

struct FontCache {
    native_lib: native::NativeFontCache,

    drop {
        native::destroy_native_lib(&self.native_lib);
    }
}

impl FontCache {
    fn get_font(@self) -> @Font {
        match create_font(self, &self.native_lib) {
          Ok(font) => font,
          Err(*) => /* FIXME */ fail
        }
    }

    fn get_test_font(@self) -> @Font {
        self.get_font()
    }
}

fn FontCache() -> @FontCache {
    @FontCache {
        native_lib: native::create_native_lib()
    }
}

fn create_font(lib: @FontCache, native_lib: &native::NativeFontCache) -> Result<@Font, ()> {
    let font_bin = @test_font_bin();
    let native_font = native_font::create(native_lib, font_bin);
    let native_font = if native_font.is_ok() {
        result::unwrap(native_font)
    } else {
        return Err(native_font.get_err());
    };
    let metrics = native_font.get_metrics();
    return Ok(@Font(lib, font_bin, native_font, metrics));
}

#[cfg(target_os = "linux")]
pub mod native {
    use ptr::{null, addr_of};
    use azure::freetype;
    use freetype::{FT_Library, FT_Error};
    use freetype::bindgen::{FT_Init_FreeType, FT_Done_FreeType};

    pub type NativeFontCache = FT_Library;

    pub fn create_native_lib() -> NativeFontCache {
        let lib: FT_Library = null();
        let res = FT_Init_FreeType(addr_of(&lib));
        // FIXME: error handling
        assert res == 0 as FT_Error;
        return lib;
    }

    pub fn destroy_native_lib(native_lib: &NativeFontCache) {
        assert native_lib.is_not_null();
        FT_Done_FreeType(*native_lib);
    }
}

#[cfg(target_os = "macos")]
pub mod native {
    pub type NativeFontCache = ();

    pub fn create_native_lib() -> NativeFontCache { () }
    pub fn destroy_native_lib(_native_lib: &NativeFontCache) { }
}

#[test]
pub fn should_get_fonts() {
    let lib = FontCache();
    lib.get_font();
}
<|endoftext|>


<commit_before>use std::fs::{File, OpenOptions, metadata};
use std::path::{Path, PathBuf};

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, encode_into, decode_from};

use super::Error;
use super::database::Database;
use super::column::Column;
use super::rows::Rows;

use super::super::identifier::Identifier;

pub struct Table<'a> {
    database: &'a Database,
    name: Identifier,
    meta_data: TableMetadata
}

#[derive(Clone, RustcDecodable, RustcEncodable)]
struct TableMetadata {
    engine_id: u8,
    columns: Vec<Column>
}

/// Table representation
impl<'a> Table<'a> {
    /// Create table in database
    pub fn create<'b>(name: &str, engine_id: u8, columns: Vec<Column>, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("creating table: {}", name);

        // TODO: verify if name is a valid identifier

        let metadata = TableMetadata {
            engine_id: engine_id,
            columns: columns
        };

        let mut buf = try!(File::create(db.get_path().clone().join(&name).with_extension("tbl")));

        encode_into(&metadata, &mut buf, SizeLimit::Infinite).unwrap();

        Ok(Table {
            database: &db,
            name: try!(Identifier::new(name)),
            meta_data: metadata.clone()
        })
    }

    /// Load table from database
    pub fn load<'b>(name: &str, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("loading table: {}", &name);
        let path = db.get_path().clone().join(&name).with_extension("tbl");
        if !try!(metadata(&path)).is_dir()
        {
            let mut file = try!(OpenOptions::new()
                        .read(true)
                        .open(&path));

            let metadata: TableMetadata = try!(decode_from(&mut file, SizeLimit::Infinite));
            info!("loaded table: {}", &name);

            Ok(Table {
                database: db,
                name: try!(Identifier::new(name)),
                meta_data: metadata
            })
        }else {
            error!("could not load table: {} at {}", &name, &path.to_str().unwrap());
            Err(Error::LoadTable)
        }
    }

    // TODO: write table delete static function

    /// Returns a vector of the sizes of the columns
    pub fn get_cols_sizes(&self) -> Vec<u32> {
        let mut column_sizes = Vec::<u32>::new();

        for v in &self.meta_data.columns {
            column_sizes.push(v.size());
        }

        column_sizes
    }

    pub fn get_table_header_offset(&self) -> u32 {
        let bytes: Vec<u8> = encode(&self.meta_data, SizeLimit::Infinite).unwrap();
        bytes.len() as u32
    }

    pub fn get_cols_offset(&self) -> u32 {
        let mut size = 0;

        for v in &self.meta_data.columns {
            size += v.size();
        }

        size
    }

    /// Get full file path including filename and ext
    pub fn get_path(&self) -> PathBuf {
        self.database.get_path().clone().join(&self.name.get_name()).with_extension("tbl")
    }

    pub fn get_engine_id(&self) -> u8 {
        self.meta_data.engine_id
    }

}

#[cfg(test)]
mod test {
    use super::Table;
    use super::super::database::*;
    use std::fs::metadata;
    use super::super::column::Column;
    use super::super::types::Types;

    #[test]
    fn create_table() {
        let path = "/tmp/test1/";
        let name = "test_db3";
        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 0, columns, &db).unwrap();

        assert!(!metadata("/tmp/test1/test_db3/test_table1.tbl").unwrap().is_dir());
    }

    #[test]
    fn load_table() {
        let path = "/tmp/test1/";
        let name = "test_db4";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 34, columns, &db).unwrap();

        assert!(!metadata("/tmp/test1/test_db3/test_table1.tbl").unwrap().is_dir());

        let table2 = Table::load("test_table1", &db).unwrap();

        assert_eq!(table.get_engine_id(), table2.get_engine_id());
        assert_eq!(&table.meta_data.columns, &table2.meta_data.columns);
    }

    #[test]
    fn table_offset() {
        let path = "/tmp/test1/";
        let name = "test_db5";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 34, columns, &db).unwrap();

        assert_eq!(table.get_table_header_offset(), 42u64);

    }

}
<commit_msg>fixed test for failing on wrong type<commit_after>use std::fs::{File, OpenOptions, metadata};
use std::path::{Path, PathBuf};

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, encode_into, decode_from};

use super::Error;
use super::database::Database;
use super::column::Column;
use super::rows::Rows;

use super::super::identifier::Identifier;

pub struct Table<'a> {
    database: &'a Database,
    name: Identifier,
    meta_data: TableMetadata
}

#[derive(Clone, RustcDecodable, RustcEncodable)]
struct TableMetadata {
    engine_id: u8,
    columns: Vec<Column>
}

/// Table representation
impl<'a> Table<'a> {
    /// Create table in database
    pub fn create<'b>(name: &str, engine_id: u8, columns: Vec<Column>, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("creating table: {}", name);

        // TODO: verify if name is a valid identifier

        let metadata = TableMetadata {
            engine_id: engine_id,
            columns: columns
        };

        let mut buf = try!(File::create(db.get_path().clone().join(&name).with_extension("tbl")));

        encode_into(&metadata, &mut buf, SizeLimit::Infinite).unwrap();

        Ok(Table {
            database: &db,
            name: try!(Identifier::new(name)),
            meta_data: metadata.clone()
        })
    }

    /// Load table from database
    pub fn load<'b>(name: &str, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("loading table: {}", &name);
        let path = db.get_path().clone().join(&name).with_extension("tbl");
        if !try!(metadata(&path)).is_dir()
        {
            let mut file = try!(OpenOptions::new()
                        .read(true)
                        .open(&path));

            let metadata: TableMetadata = try!(decode_from(&mut file, SizeLimit::Infinite));
            info!("loaded table: {}", &name);

            Ok(Table {
                database: db,
                name: try!(Identifier::new(name)),
                meta_data: metadata
            })
        }else {
            error!("could not load table: {} at {}", &name, &path.to_str().unwrap());
            Err(Error::LoadTable)
        }
    }

    // TODO: write table delete static function

    /// Returns a vector of the sizes of the columns
    pub fn get_cols_sizes(&self) -> Vec<u32> {
        let mut column_sizes = Vec::<u32>::new();

        for v in &self.meta_data.columns {
            column_sizes.push(v.size());
        }

        column_sizes
    }

    pub fn get_table_header_offset(&self) -> u32 {
        let bytes: Vec<u8> = encode(&self.meta_data, SizeLimit::Infinite).unwrap();
        bytes.len() as u32
    }

    pub fn get_cols_offset(&self) -> u32 {
        let mut size = 0;

        for v in &self.meta_data.columns {
            size += v.size();
        }

        size
    }

    /// Get full file path including filename and ext
    pub fn get_path(&self) -> PathBuf {
        self.database.get_path().clone().join(&self.name.get_name()).with_extension("tbl")
    }

    pub fn get_engine_id(&self) -> u8 {
        self.meta_data.engine_id
    }

}

#[cfg(test)]
mod test {
    use super::Table;
    use super::super::database::*;
    use std::fs::metadata;
    use super::super::column::Column;
    use super::super::types::Types;

    #[test]
    fn create_table() {
        let path = "/tmp/test1/";
        let name = "test_db3";
        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 0, columns, &db).unwrap();

        assert!(!metadata("/tmp/test1/test_db3/test_table1.tbl").unwrap().is_dir());
    }

    #[test]
    fn load_table() {
        let path = "/tmp/test1/";
        let name = "test_db4";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 34, columns, &db).unwrap();

        assert!(!metadata("/tmp/test1/test_db3/test_table1.tbl").unwrap().is_dir());

        let table2 = Table::load("test_table1", &db).unwrap();

        assert_eq!(table.get_engine_id(), table2.get_engine_id());
        assert_eq!(&table.meta_data.columns, &table2.meta_data.columns);
    }

    #[test]
    fn table_offset() {
        let path = "/tmp/test1/";
        let name = "test_db5";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 34, columns, &db).unwrap();

        assert_eq!(table.get_table_header_offset(), 42u32);

    }

}
<|endoftext|>


<commit_before>macro_rules! os_required {
    () => {
        panic!("mio must be compiled with `os-poll` to run.")
    };
}

mod selector;
pub(crate) use self::selector::{event, Event, Events, Selector};

mod waker;
pub(crate) use self::waker::Waker;

cfg_tcp! {
    mod tcp;
    pub(crate) use self::tcp::{TcpStream, TcpListener};
}

cfg_udp! {
    mod udp;
    pub(crate) use self::udp::UdpSocket;
}

#[cfg(unix)]
cfg_uds! {
    mod uds;
    pub(crate) use self::uds::{UnixDatagram, UnixListener, UnixStream};
}
<commit_msg>Add shell::IoSourceState<commit_after>macro_rules! os_required {
    () => {
        panic!("mio must be compiled with `os-poll` to run.")
    };
}

mod selector;
pub(crate) use self::selector::{event, Event, Events, Selector};

mod waker;
pub(crate) use self::waker::Waker;

cfg_tcp! {
    mod tcp;
    pub(crate) use self::tcp::{TcpStream, TcpListener};
}

cfg_udp! {
    mod udp;
    pub(crate) use self::udp::UdpSocket;
}

#[cfg(unix)]
cfg_uds! {
    mod uds;
    pub(crate) use self::uds::{UnixDatagram, UnixListener, UnixStream};
}

cfg_net! {
    use std::io;

    pub struct IoSourceState;

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

        pub fn do_io<T, F, R>(&self, f: F, io: &T) -> io::Result<R>
        where
            F: FnOnce(&T) -> io::Result<R>,
        {
            // We don't hold state, so we can just call the function and
            // return.
            f(io)
        }
    }
}
<|endoftext|>


<commit_before>extern crate termion;

use self::termion::event;
use self::termion::raw::{RawTerminal, IntoRawMode};
use self::termion::screen::AlternateScreen;
use self::termion::input::TermRead;
use self::termion::cursor;
use self::termion::color;
use std::io::{self, Write};
use std::iter;

use super::base::*;

macro_rules! decode_color {
    ($x:expr, $c:expr) => {{
        match $c {
            Color::Reset => format!("{}", $x(color::Reset)),
            Color::Black => format!("{}", $x(color::Black)),
            Color::White => format!("{}", $x(color::White)),
            Color::Grey => format!("{}", $x(color::LightBlack)),
        }
    }}
}

impl From<event::Key> for Key {
    fn from(k: event::Key) -> Key {
        match k {
            event::Key::Backspace => Key::Backspace,
            event::Key::Left => Key::Left,
            event::Key::Right => Key::Right,
            event::Key::Up => Key::Up,
            event::Key::Down => Key::Down,
            event::Key::Home => Key::Home,
            event::Key::End => Key::End,
            event::Key::PageUp => Key::PageUp,
            event::Key::PageDown => Key::PageDown,
            event::Key::Delete => Key::Delete,
            event::Key::Insert => Key::Insert,
            event::Key::F(n) => Key::F(n),
            event::Key::Char(c) => Key::Char(c),
            event::Key::Alt(c) => Key::Alt(Box::new(Key::Char(c))),
            event::Key::Ctrl(c) => Key::Ctrl(Box::new(Key::Char(c))),
            event::Key::Null => Key::Null,
            event::Key::Esc => Key::Esc,
            event::Key::__IsNotComplete => panic!("got a weird key from termios"),
        }
    }
}

impl From<event::MouseEvent> for MouseEvent {
    fn from(e: event::MouseEvent) -> MouseEvent {
        match e {
            event::MouseEvent::Press(b, x, y) => MouseEvent::Press(MouseButton::from(b), x as i32, y as i32),
            event::MouseEvent::Release(x, y) => MouseEvent::Release(x as i32, y as i32),
            event::MouseEvent::Hold(x, y) => MouseEvent::Hold(x as i32, y as i32),
        }
    }
}

impl From<event::MouseButton> for MouseButton {
    fn from(b: event::MouseButton) -> MouseButton {
        match b {
            event::MouseButton::Left => MouseButton::Left,
            event::MouseButton::Right => MouseButton::Right,
            event::MouseButton::Middle => MouseButton::Middle,
            event::MouseButton::WheelUp => MouseButton::WheelUp,
            event::MouseButton::WheelDown => MouseButton::WheelDown,
        }
    }
}

impl From<event::Event> for Event {
    fn from(e: event::Event) -> Event {
        match e {
            event::Event::Key(k) => Event::Key(k.into()),
            event::Event::Mouse(m) => Event::Mouse(m.into()),
            event::Event::Unsupported(v) => Event::Unsupported(v.iter().map(|x| *x as u32).collect()),
        }
    }
}

pub struct Terminal {
    out: AlternateScreen<RawTerminal<io::Stdout>>,
}

impl Terminal {
    pub fn keys(&mut self) -> iter::Map<termion::input::Events<io::Stdin>, fn(io::Result<event::Event>) -> Event> {
        fn extract(e: io::Result<event::Event>) -> Event { Event::from(e.unwrap()) }
        io::stdin().events().map(extract)
    }
}

impl Write for Terminal {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        self.out.write(data)
    }

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

impl Default for Terminal {
    fn default() -> Terminal {
        Terminal {
            out: AlternateScreen::from(io::stdout().into_raw_mode().unwrap()),
        }
    }
}

impl TermImpl for Terminal {
    fn get_size(&self) -> (i32, i32) {
        let (x, y) = termion::terminal_size().unwrap();
        (x as i32, y as i32)
    }

    fn goto(&mut self, (x, y): (i32, i32)) {
        write!(self.out, "{}", cursor::Goto(x as u16, y as u16)).unwrap();
    }

    fn set_color_fg(&mut self, c: Color) {
        write!(self.out, "{}", decode_color!(color::Fg, c)).unwrap();
    }

    fn set_color_bg(&mut self, c: Color) {
        write!(self.out, "{}", decode_color!(color::Bg, c)).unwrap();
    }

    fn clear(&mut self) {
        write!(self.out, "{}", termion::clear::All).unwrap();
    }
}
<commit_msg>Fix shift+navigation on Unix systems<commit_after>extern crate termion;

use self::termion::event;
use self::termion::raw::{RawTerminal, IntoRawMode};
use self::termion::screen::AlternateScreen;
use self::termion::input::TermRead;
use self::termion::cursor;
use self::termion::color;
use std::io::{self, Write};
use std::iter;

use super::base::*;

macro_rules! decode_color {
    ($x:expr, $c:expr) => {{
        match $c {
            Color::Reset => format!("{}", $x(color::Reset)),
            Color::Black => format!("{}", $x(color::Black)),
            Color::White => format!("{}", $x(color::White)),
            Color::Grey => format!("{}", $x(color::LightBlack)),
        }
    }}
}

impl From<event::Key> for Key {
    fn from(k: event::Key) -> Key {
        match k {
            event::Key::Backspace => Key::Backspace,
            event::Key::Left => Key::Left,
            event::Key::Right => Key::Right,
            event::Key::Up => Key::Up,
            event::Key::Down => Key::Down,
            event::Key::Home => Key::Home,
            event::Key::End => Key::End,
            event::Key::PageUp => Key::PageUp,
            event::Key::PageDown => Key::PageDown,
            event::Key::Delete => Key::Delete,
            event::Key::Insert => Key::Insert,
            event::Key::F(n) => Key::F(n),
            event::Key::Char(c) => Key::Char(c),
            event::Key::Alt(c) => Key::Alt(Box::new(Key::Char(c))),
            event::Key::Ctrl(c) => Key::Ctrl(Box::new(Key::Char(c))),
            event::Key::Null => Key::Null,
            event::Key::Esc => Key::Esc,
            event::Key::__IsNotComplete => panic!("got a weird key from termios"),
        }
    }
}

impl From<event::MouseEvent> for MouseEvent {
    fn from(e: event::MouseEvent) -> MouseEvent {
        match e {
            event::MouseEvent::Press(b, x, y) => MouseEvent::Press(MouseButton::from(b), x as i32, y as i32),
            event::MouseEvent::Release(x, y) => MouseEvent::Release(x as i32, y as i32),
            event::MouseEvent::Hold(x, y) => MouseEvent::Hold(x as i32, y as i32),
        }
    }
}

impl From<event::MouseButton> for MouseButton {
    fn from(b: event::MouseButton) -> MouseButton {
        match b {
            event::MouseButton::Left => MouseButton::Left,
            event::MouseButton::Right => MouseButton::Right,
            event::MouseButton::Middle => MouseButton::Middle,
            event::MouseButton::WheelUp => MouseButton::WheelUp,
            event::MouseButton::WheelDown => MouseButton::WheelDown,
        }
    }
}

impl From<event::Event> for Event {
    fn from(e: event::Event) -> Event {
        match e {
            event::Event::Key(k) => Event::Key(k.into()),
            event::Event::Mouse(m) => Event::Mouse(m.into()),
            event::Event::Unsupported(v) => {
                let vals = v.iter().map(|x| *x as u32).collect();
                if vals == [27, 91, 49, 59, 50, 65] {
                    Event::Key(Key::Shift(Box::new(Key::Up)))
                } else if vals == [27, 91, 49, 59, 50, 66] {
                    Event::Key(Key::Shift(Box::new(Key::Down)))
                } else if vals == [27, 91, 49, 59, 50, 67] {
                    Event::Key(Key::Shift(Box::new(Key::Right)))
                } else if vals == [27, 91, 49, 59, 50, 68] {
                    Event::Key(Key::Shift(Box::new(Key::Left)))
                } else {
                    Event::Unsupported(vals)
                }
            }
        }
    }
}

pub struct Terminal {
    out: AlternateScreen<RawTerminal<io::Stdout>>,
}

impl Terminal {
    pub fn keys(&mut self) -> iter::Map<termion::input::Events<io::Stdin>, fn(io::Result<event::Event>) -> Event> {
        fn extract(e: io::Result<event::Event>) -> Event { Event::from(e.unwrap()) }
        io::stdin().events().map(extract)
    }
}

impl Write for Terminal {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        self.out.write(data)
    }

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

impl Default for Terminal {
    fn default() -> Terminal {
        Terminal {
            out: AlternateScreen::from(io::stdout().into_raw_mode().unwrap()),
        }
    }
}

impl TermImpl for Terminal {
    fn get_size(&self) -> (i32, i32) {
        let (x, y) = termion::terminal_size().unwrap();
        (x as i32, y as i32)
    }

    fn goto(&mut self, (x, y): (i32, i32)) {
        write!(self.out, "{}", cursor::Goto(x as u16, y as u16)).unwrap();
    }

    fn set_color_fg(&mut self, c: Color) {
        write!(self.out, "{}", decode_color!(color::Fg, c)).unwrap();
    }

    fn set_color_bg(&mut self, c: Color) {
        write!(self.out, "{}", decode_color!(color::Bg, c)).unwrap();
    }

    fn clear(&mut self) {
        write!(self.out, "{}", termion::clear::All).unwrap();
    }
}
<|endoftext|>


<commit_before>use std::iter;
use rustwlc::{Geometry, Size};
use std::fmt::{self, Debug};
use std::cmp::{Eq, PartialEq};
use cairo::{Context, ImageSurface, Format, Operator, Status, SolidPattern};

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Color {
    red: u32,
    green: u32,
    blue: u32
}

#[derive(Clone)]
/// A border for a container.
pub struct Border {
    context: Context,
    thickness: u32,
    color: Color,
    geometry: Geometry
}

/// All the borders of a container (top, bottom, left, right)
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Borders {
    top: Option<Border>,
    bottom: Option<Border>,
    right: Option<Border>,
    left: Option<Border>
}

impl Color {
    pub fn new(red: u32, green: u32, blue: u32) -> Self {
        Color { red: red, green: green, blue: blue}
    }
}

impl Border {
    pub fn new(geometry: Geometry, thickness: u32, color: Color) -> Self {
        let Size { w, h } = geometry.size;
        let h = h as i32;
        let w = w as i32;
        let stride = calculate_stride(w as u32) as i32;
        let data: Vec<u8> = iter::repeat(0).take(w as usize * stride as usize).collect();
        let buffer = data.into_boxed_slice();
        let surface = ImageSurface::create_for_data(buffer, drop_data, Format::ARgb32, h, w, stride);
        let context = Context::new(&surface);
        context.set_operator(Operator::Source);
        match context.status() {
            Status::Success => {},
            err => {
                panic!("Cairo context failed with {:#?}", err);
            }
        }
        Border {
            context: context,
            thickness: thickness,
            color: color,
            geometry: geometry
        }
    }

    /// Renders a line, starting from (x, y) to (x + width, y + height).
    pub fn render(&self, mut x: f64, mut y: f64) {
        let Color { red, green, blue} = self.color;
        let Size { w, h } = self.geometry.size;
        let mut w = w as f64;
        let mut h = h as f64;
        let pattern = SolidPattern::from_rgb(red as f64 / 255.0,
                                             green as f64 / 255.0,
                                             blue as f64 / 255.0);
        self.context.set_source(&pattern);
        if w > 1.0 && h > 1.0 {
            self.context.rectangle(x, y, w, h);
            self.context.fill();
        } else {
            if w == 1.0 {
                x += 0.5;
                h += y;
                w = x;
            }

            if h == 1.0 {
                y += 0.5;
                w += x;
                h = y;
            }

            self.context.move_to(x, y);
            self.context.set_line_width(1.0);
            self.context.line_to(w, h);
            self.context.stroke();
        }
    }
}

impl Debug for Border {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Debug")
            .field("thickness", &self.thickness as &Debug)
            .field("color", &self.color as &Debug)
            .finish()
    }
}

impl PartialEq for Border {
    fn eq(&self, other: &Border) -> bool {
        (self.thickness == other.thickness && self.color == other.color
         && self.geometry == other.geometry)
    }
}

impl Eq for Border {}

unsafe impl Send for Border {}
unsafe impl Sync for Border {}

impl Borders {
    pub fn new(top: Option<Border>, bottom: Option<Border>,
               left: Option<Border>, right: Option<Border>) -> Self {
        Borders {
            top: top,
            bottom: bottom,
            left: left,
            right: right
        }
    }

    /// Renders each border at their respective geometries.
    pub fn render(&self) {
        let borders = vec![&self.top, &self.bottom, &self.left, &self.right];
        for border in borders.iter().flat_map(|maybe_g| maybe_g.into_iter()) {
        }
    }
}

/// Calculates the stride for ARgb32 encoded buffers
fn calculate_stride(width: u32) -> u32 {
    // function stolen from CAIRO_STRIDE_FOR_WIDTH macro in cairoint.h
    // Can be found in the most recent version of the cairo source
    (32 * width + 7) / 8 + 4 & !4
}

fn drop_data(_: Box<[u8]>) {}

#[cfg(tests)]
mod tests {
    use super::calculate_stride;

    #[test]
    fn test_calculate_stride() {
        let test_data = [
            (100, 400),
            (200, 800),
            (300, 1200),
            (400, 1600),
            (500, 2000),
            (600, 2400),
            (700, 2800),
            (800, 3200),
            (900, 3600)
        ];
        for &(width, stride) in test_data.iter() {
            assert_eq!(calculate_stride(width), stride);
        }
    }
}
<commit_msg>Switched over to new trait-based system<commit_after>use std::iter;
use std::fmt::{self, Debug};
use std::cmp::{Eq, PartialEq};
use std::ops::{Deref, DerefMut};
use rustwlc::{Geometry, Size};
use cairo::{Context, ImageSurface, Format, Operator, Status, SolidPattern};

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Color {
    red: u32,
    green: u32,
    blue: u32
}

pub trait Border {
    /// Renders the border around the geometry of a view.
    fn render(&self, view_g: Geometry);

    fn get_color(&self) -> Color;

    fn get_context(&self) -> &Context;

    /// Draws the line from (x, y) to (x+width,y+height) where width/height.
    ///
    /// You should just use the default implementation in most cases.
    fn draw_line(&self, mut x: f64, mut y: f64, mut w: f64, mut h: f64) {
        let Color { red, green, blue} = self.get_color();
        let pattern = SolidPattern::from_rgb(red as f64 / 255.0,
                                             green as f64 / 255.0,
                                             blue as f64 / 255.0);
        let context = self.get_context();
        context.set_source(&pattern);
        if w > 1.0 && h > 1.0 {
            context.rectangle(x, y, w, h);
            context.fill();
        } else {
            if w == 1.0 {
                x += 0.5;
                h += y;
                w = x;
            }

            if h == 1.0 {
                y += 0.5;
                w += x;
                h = y;
            }

            context.move_to(x, y);
            context.set_line_width(1.0);
            context.line_to(w, h);
            context.stroke();
        }
    }
}

#[derive(Clone)]
/// A border for a container.
pub struct BaseBorder {
    context: Context,
    thickness: u32,
    color: Color,
    geometry: Geometry
}

impl Border for BottomBorder {
    fn render(&self, view_g: Geometry) {}

    fn get_context(&self) -> &Context {
        &self.context
    }

    fn get_color(&self) -> Color {
        self.color
    }
}
impl Border for TopBorder {
    fn render(&self, view_g: Geometry) {}

    fn get_context(&self) -> &Context {
        &self.context
    }

    fn get_color(&self) -> Color {
        self.color
    }
}

impl Border for RightBorder {
    fn render(&self, view_g: Geometry) {}

    fn get_context(&self) -> &Context {
        &self.context
    }

    fn get_color(&self) -> Color {
        self.color
    }
}

impl Border for LeftBorder {
    fn render(&self, view_g: Geometry) {}

    fn get_context(&self) -> &Context {
        &self.context
    }

    fn get_color(&self) -> Color {
        self.color
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TopBorder {
    border: BaseBorder
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BottomBorder {
    border: BaseBorder
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RightBorder {
    border: BaseBorder
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LeftBorder {
    border: BaseBorder
}

impl Deref for TopBorder {
    type Target = BaseBorder;

    fn deref(&self) -> &BaseBorder {
        &self.border
    }
}

impl Deref for BottomBorder {
    type Target = BaseBorder;

    fn deref(&self) -> &BaseBorder {
        &self.border
    }
}
impl Deref for RightBorder {
    type Target = BaseBorder;

    fn deref(&self) -> &BaseBorder {
        &self.border
    }
}
impl Deref for LeftBorder {
    type Target = BaseBorder;

    fn deref(&self) -> &BaseBorder {
        &self.border
    }
}

/// All the borders of a container (top, bottom, left, right)
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Borders {
    top: Option<TopBorder>,
    bottom: Option<BottomBorder>,
    right: Option<RightBorder>,
    left: Option<LeftBorder>
}

impl Color {
    pub fn new(red: u32, green: u32, blue: u32) -> Self {
        Color { red: red, green: green, blue: blue}
    }
}

impl BaseBorder {
    pub fn new(geometry: Geometry, thickness: u32, color: Color) -> Self {
        let Size { w, h } = geometry.size;
        let h = h as i32;
        let w = w as i32;
        let stride = calculate_stride(w as u32) as i32;
        let data: Vec<u8> = iter::repeat(0).take(w as usize * stride as usize).collect();
        let buffer = data.into_boxed_slice();
        let surface = ImageSurface::create_for_data(buffer, drop_data, Format::ARgb32, h, w, stride);
        let context = Context::new(&surface);
        context.set_operator(Operator::Source);
        match context.status() {
            Status::Success => {},
            err => {
                panic!("Cairo context failed with {:#?}", err);
            }
        }
        BaseBorder {
            context: context,
            thickness: thickness,
            color: color,
            geometry: geometry
        }
    }

    /// Renders a line, starting from (x, y) to (x + width, y + height).
    pub fn render(&self, mut x: f64, mut y: f64) {
    }
}

impl Debug for BaseBorder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Debug")
            .field("thickness", &self.thickness as &Debug)
            .field("color", &self.color as &Debug)
            .finish()
    }
}

impl PartialEq for BaseBorder {
    fn eq(&self, other: &BaseBorder) -> bool {
        (self.thickness == other.thickness && self.color == other.color
         && self.geometry == other.geometry)
    }
}

impl Eq for BaseBorder {}

unsafe impl Send for BaseBorder {}
unsafe impl Sync for BaseBorder {}

impl Borders {
    pub fn new(top: Option<TopBorder>, bottom: Option<BottomBorder>,
               left: Option<LeftBorder>, right: Option<RightBorder>) -> Self {
        Borders {
            top: top,
            bottom: bottom,
            left: left,
            right: right
        }
    }

    /// Renders each border at their respective geometries.
    pub fn render(&self, view_g: Geometry) {
        let borders = vec![self.top.as_ref().map(|g| g as &Border),
                           self.bottom.as_ref().map(|g| g as &Border),
                           self.left.as_ref().map(|g| g as &Border),
                           self.right.as_ref().map(|g| g as &Border)];
        for border in borders.iter().flat_map(|maybe_g| maybe_g.into_iter()){
            let foo = border.render(view_g);
        }
    }
}

/// Calculates the stride for ARgb32 encoded buffers
fn calculate_stride(width: u32) -> u32 {
    // function stolen from CAIRO_STRIDE_FOR_WIDTH macro in cairoint.h
    // Can be found in the most recent version of the cairo source
    (32 * width + 7) / 8 + 4 & !4
}

fn drop_data(_: Box<[u8]>) {}

#[cfg(tests)]
mod tests {
    use super::calculate_stride;

    #[test]
    fn test_calculate_stride() {
        let test_data = [
            (100, 400),
            (200, 800),
            (300, 1200),
            (400, 1600),
            (500, 2000),
            (600, 2400),
            (700, 2800),
            (800, 3200),
            (900, 3600)
        ];
        for &(width, stride) in test_data.iter() {
            assert_eq!(calculate_stride(width), stride);
        }
    }
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate regex;
extern crate toml;

use self::chrono::{Duration, NaiveTime};
use self::regex::Regex;
use self::toml::Value as Toml;

use constant::CONFIG_FILE_NAME;
use error::{CannotHappenError, CliError, ConfigError, ConfigErrorKind};
use lib::io::*;
use std::borrow::Borrow;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::{Error as IoError, Read};
use std::path::PathBuf;
use std::str::FromStr;

pub enum ConfigKey {
    BurnAfter,
    SweepPeriod,
    SweepTime,
}

impl ConfigKey {
    pub fn from<S: AsRef<str>>(key: S) -> Result<ConfigKey, ConfigError> {
        match key.as_ref().trim() {
            "burn.after"   => Ok(ConfigKey::BurnAfter),
            "sweep.period" => Ok(ConfigKey::SweepPeriod),
            "sweep.time"   => Ok(ConfigKey::SweepTime),
            _              => Err(ConfigError::new(ConfigErrorKind::InvalidKey)),
        }
    }

    fn to_str(&self) -> &str {
        match *self {
            ConfigKey::BurnAfter   => "burn.after",
            ConfigKey::SweepPeriod => "sweep.period",
            ConfigKey::SweepTime   => "sweep.time",
        }
    }

    fn to_pair(&self) -> (&str, &str) {
        let key = self
            .to_str()
            .split('.')
            .collect::<Vec<&str>>();
        (key[0], key[1]) // unsafe!
    }
}

type EditableTomlCore = BTreeMap<String, BTreeMap<String, String>>;

struct EditableToml(EditableTomlCore);

impl EditableToml {
    fn from(toml: Toml) -> Result<Self, ConfigError> {
        toml::decode::<EditableTomlCore>(toml)
            .map(|c| EditableToml(c))
            .ok_or(ConfigError::new(ConfigErrorKind::Something))
    }

    fn overwrite<CK: Borrow<ConfigKey>>(&mut self, key: CK, value: String) {
        let &mut EditableToml(ref mut core) = self;

        let (first, second) = key.borrow().to_pair();
        let second          = second.to_string();

        if core.contains_key(first) {
            core.get_mut(first).map(|e| e.insert(second, value));
        } else {
            let mut entry = BTreeMap::new();
            entry.insert(second, value);

            core.insert(first.to_string(), entry);
        }
    }

    fn to_toml(self) -> Toml {
        let EditableToml(core) = self;
        toml::encode(&core)
    }
}

pub struct Config {
    toml: Toml,
}

impl Config {
    fn path() -> PathBuf {
        path_buf![super::working_dir(), CONFIG_FILE_NAME]
    }

    pub fn exist() -> bool {
        Self::path().is_file()
    }

    fn to_string(&self) -> String {
        toml::encode_str(&self.toml)
    }

    pub fn create(&self) -> Result<(), IoError> {
        print_with_tag(Tag::Info, format!("Create \"{}\" file", CONFIG_FILE_NAME));

        super::create_setting_file(Self::path(), self.to_string())
    }

    fn _new(toml: Toml) -> Self {
        Config { toml: toml }
    }

    pub fn default() -> Self {
        let mut editable = EditableToml(BTreeMap::new());
        editable.overwrite(ConfigKey::BurnAfter  , "2 weeks".to_string());
        editable.overwrite(ConfigKey::SweepPeriod, "daily"  .to_string());
        editable.overwrite(ConfigKey::SweepTime  , "00:00"  .to_string());

        Self::_new(editable.to_toml())
    }

    pub fn read() -> Result<Self, CliError> {
        print_with_tag(Tag::Info, format!("Read \"{}\" file", CONFIG_FILE_NAME));

        let mut f = try!(File::open(Self::path()));

        let mut contents = String::new();
        try!(f.read_to_string(&mut contents));

        let result = contents
            .parse()
            .map_err(|e: Vec<_>| e.into_iter().next());
        let toml = match result {
            Ok(toml)    => toml,
            Err(option) => match option {
                Some(e) => return Err(From::from(e)),
                None    => return Err(From::from(CannotHappenError)),
            },
        };

        Ok(Self::_new(toml))
    }

    pub fn get<CK: Borrow<ConfigKey>>(&self, key: CK) -> Result<String, CliError> {
        let key = key.borrow();

        let result = self.toml
            .lookup(key.to_str())
            .ok_or(ConfigError::new(match *key {
                ConfigKey::BurnAfter   => ConfigErrorKind::NotFoundBurnAfter,
                ConfigKey::SweepPeriod => unimplemented!(),
                ConfigKey::SweepTime   => unimplemented!(),
            }));
        let value = try!(result);

        value
            .as_str()
            .ok_or(From::from(ConfigError::new(ConfigErrorKind::NonStringValue)))
            .and_then(|s| Self::validate(key, s))
    }

    pub fn to_duration(value: String) -> Result<Duration, CliError> {
        let mut value   = value.split(' ');
        let (num, unit) = match (value.next(), value.next()) {
            (Some(num), Some(unit)) => (num, unit),
            _                       => return Err(From::from(CannotHappenError)),
        };
        let num = try!(num.parse::<u32>()) as i64;

        let duration = match unit {
            "day"  | "days"  => Duration::days(num),
            "week" | "weeks" => Duration::weeks(num),
            _                => return Err(From::from(CannotHappenError)),
        };

        Ok(duration)
    }

    pub fn set<CK: Borrow<ConfigKey>>(mut self, key: CK, value: String) -> Result<Self, ConfigError> {
        let mut editable = try!(EditableToml::from(self.toml));

        editable.overwrite(key, value);

        self.toml = editable.to_toml();

        Ok(self)
    }

    pub fn validate<CK: Borrow<ConfigKey>, S: AsRef<str>>(key: CK, value: S) -> Result<String, CliError> {
        let value = value.as_ref().trim();

        match *key.borrow() {
            ConfigKey::BurnAfter => {
                let pair = try!(Regex::new(r"^(?P<num>\d+)\s?(?P<unit>days?|weeks?)$"))
                    .captures(value)
                    .map_or((None, None), |caps| (caps.name("num"), caps.name("unit")));
                let (num, unit) = match pair {
                    (Some(num), Some(unit)) => (num, unit),
                    _                       => return Err(From::from(ConfigError::new(ConfigErrorKind::BurnAfter))),
                };
                Ok(format!("{} {}", num, unit))
            },
            ConfigKey::SweepPeriod => {
                match value {
                    "daily" | "weekly" => Ok(value.to_string()),
                    _                  => Err(From::from(ConfigError::new(ConfigErrorKind::SweepPeriod))),
                }
            },
            ConfigKey::SweepTime => {
                match NaiveTime::from_str(format!("{}:00", value).as_ref()) {
                    Ok(_)  => Ok(value.to_string()),
                    // should set Err(e) to Error::cause()
                    Err(_) => Err(From::from(ConfigError::new(ConfigErrorKind::SweepTime))),
                }
            },
        }
    }
}

#[test]
fn overwrite_should_add_value {
}

#[test]
fn default_should_return_config() {
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn get_should_return_ok() {
    }
    #[test]
    fn get_should_return_err() {
    }

    #[test]
    fn set_should_return_ok() {
    }
    #[test]
    fn set_should_retrun_err() {
    }

    #[test]
    fn to_duration_should_return_ok {
    }
    #[test]
    fn to_duration_should_return_err {
    }

    #[test]
    fn validate_should_return_ok() {
    }
    #[test]
    fn validate_should_return_err() {
    }
}
<commit_msg>[Test] Create test for EditableToml.overwrite()<commit_after>extern crate chrono;
extern crate regex;
extern crate toml;

use self::chrono::{Duration, NaiveTime};
use self::regex::Regex;
use self::toml::Value as Toml;

use constant::CONFIG_FILE_NAME;
use error::{CannotHappenError, CliError, ConfigError, ConfigErrorKind};
use lib::io::*;
use std::borrow::Borrow;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::{Error as IoError, Read};
use std::path::PathBuf;
use std::str::FromStr;

pub enum ConfigKey {
    BurnAfter,
    SweepPeriod,
    SweepTime,
}

impl ConfigKey {
    pub fn from<S: AsRef<str>>(key: S) -> Result<ConfigKey, ConfigError> {
        match key.as_ref().trim() {
            "burn.after"   => Ok(ConfigKey::BurnAfter),
            "sweep.period" => Ok(ConfigKey::SweepPeriod),
            "sweep.time"   => Ok(ConfigKey::SweepTime),
            _              => Err(ConfigError::new(ConfigErrorKind::InvalidKey)),
        }
    }

    fn to_str(&self) -> &str {
        match *self {
            ConfigKey::BurnAfter   => "burn.after",
            ConfigKey::SweepPeriod => "sweep.period",
            ConfigKey::SweepTime   => "sweep.time",
        }
    }

    fn to_pair(&self) -> (&str, &str) {
        let key = self
            .to_str()
            .split('.')
            .collect::<Vec<&str>>();
        (key[0], key[1]) // unsafe!
    }
}

type EditableTomlCore = BTreeMap<String, BTreeMap<String, String>>;

#[derive(Clone)]
struct EditableToml(EditableTomlCore);

impl EditableToml {
    fn from(toml: Toml) -> Result<Self, ConfigError> {
        toml::decode::<EditableTomlCore>(toml)
            .map(|c| EditableToml(c))
            .ok_or(ConfigError::new(ConfigErrorKind::Something))
    }

    fn overwrite<CK: Borrow<ConfigKey>>(&mut self, key: CK, value: String) {
        let &mut EditableToml(ref mut core) = self;

        let (first, second) = key.borrow().to_pair();
        let second          = second.to_string();

        if core.contains_key(first) {
            core.get_mut(first).map(|e| e.insert(second, value));
        } else {
            let mut entry = BTreeMap::new();
            entry.insert(second, value);

            core.insert(first.to_string(), entry);
        }
    }

    fn to_toml(self) -> Toml {
        let EditableToml(core) = self;
        toml::encode(&core)
    }
}

pub struct Config {
    toml: Toml,
}

impl Config {
    fn path() -> PathBuf {
        path_buf![super::working_dir(), CONFIG_FILE_NAME]
    }

    pub fn exist() -> bool {
        Self::path().is_file()
    }

    fn to_string(&self) -> String {
        toml::encode_str(&self.toml)
    }

    pub fn create(&self) -> Result<(), IoError> {
        print_with_tag(Tag::Info, format!("Create \"{}\" file", CONFIG_FILE_NAME));

        super::create_setting_file(Self::path(), self.to_string())
    }

    fn _new(toml: Toml) -> Self {
        Config { toml: toml }
    }

    pub fn default() -> Self {
        let mut editable = EditableToml(BTreeMap::new());
        editable.overwrite(ConfigKey::BurnAfter  , "2 weeks".to_string());
        editable.overwrite(ConfigKey::SweepPeriod, "daily"  .to_string());
        editable.overwrite(ConfigKey::SweepTime  , "00:00"  .to_string());

        Self::_new(editable.to_toml())
    }

    pub fn read() -> Result<Self, CliError> {
        print_with_tag(Tag::Info, format!("Read \"{}\" file", CONFIG_FILE_NAME));

        let mut f = try!(File::open(Self::path()));

        let mut contents = String::new();
        try!(f.read_to_string(&mut contents));

        let result = contents
            .parse()
            .map_err(|e: Vec<_>| e.into_iter().next());
        let toml = match result {
            Ok(toml)    => toml,
            Err(option) => match option {
                Some(e) => return Err(From::from(e)),
                None    => return Err(From::from(CannotHappenError)),
            },
        };

        Ok(Self::_new(toml))
    }

    pub fn get<CK: Borrow<ConfigKey>>(&self, key: CK) -> Result<String, CliError> {
        let key = key.borrow();

        let result = self.toml
            .lookup(key.to_str())
            .ok_or(ConfigError::new(match *key {
                ConfigKey::BurnAfter   => ConfigErrorKind::NotFoundBurnAfter,
                ConfigKey::SweepPeriod => unimplemented!(),
                ConfigKey::SweepTime   => unimplemented!(),
            }));
        let value = try!(result);

        value
            .as_str()
            .ok_or(From::from(ConfigError::new(ConfigErrorKind::NonStringValue)))
            .and_then(|s| Self::validate(key, s))
    }

    pub fn to_duration(value: String) -> Result<Duration, CliError> {
        let mut value   = value.split(' ');
        let (num, unit) = match (value.next(), value.next()) {
            (Some(num), Some(unit)) => (num, unit),
            _                       => return Err(From::from(CannotHappenError)),
        };
        let num = try!(num.parse::<u32>()) as i64;

        let duration = match unit {
            "day"  | "days"  => Duration::days(num),
            "week" | "weeks" => Duration::weeks(num),
            _                => return Err(From::from(CannotHappenError)),
        };

        Ok(duration)
    }

    pub fn set<CK: Borrow<ConfigKey>>(mut self, key: CK, value: String) -> Result<Self, ConfigError> {
        let mut editable = try!(EditableToml::from(self.toml));

        editable.overwrite(key, value);

        self.toml = editable.to_toml();

        Ok(self)
    }

    pub fn validate<CK: Borrow<ConfigKey>, S: AsRef<str>>(key: CK, value: S) -> Result<String, CliError> {
        let value = value.as_ref().trim();

        match *key.borrow() {
            ConfigKey::BurnAfter => {
                let pair = try!(Regex::new(r"^(?P<num>\d+)\s?(?P<unit>days?|weeks?)$"))
                    .captures(value)
                    .map_or((None, None), |caps| (caps.name("num"), caps.name("unit")));
                let (num, unit) = match pair {
                    (Some(num), Some(unit)) => (num, unit),
                    _                       => return Err(From::from(ConfigError::new(ConfigErrorKind::BurnAfter))),
                };
                Ok(format!("{} {}", num, unit))
            },
            ConfigKey::SweepPeriod => {
                match value {
                    "daily" | "weekly" => Ok(value.to_string()),
                    _                  => Err(From::from(ConfigError::new(ConfigErrorKind::SweepPeriod))),
                }
            },
            ConfigKey::SweepTime => {
                match NaiveTime::from_str(format!("{}:00", value).as_ref()) {
                    Ok(_)  => Ok(value.to_string()),
                    // should set Err(e) to Error::cause()
                    Err(_) => Err(From::from(ConfigError::new(ConfigErrorKind::SweepTime))),
                }
            },
        }
    }
}

#[test]
fn config_key_from_should_return_ok() {
}
#[test]
fn config_key_from_should_return_err() {
}

#[test]
fn config_key_to_str_should_return_correct_str() {
}

#[test]
fn config_key_to_pair_should_return_pair() {
}

#[test]
fn editable_toml_overwrite_should_add_value() {
    let b_tree_map: EditableTomlCore = BTreeMap::new();
    let mut correct                  = b_tree_map.clone();
    let mut editable                 = EditableToml(b_tree_map);

    let v1 = "value1".to_string();

    let mut entry         = BTreeMap::new();
    let key1              = ConfigKey::BurnAfter;
    let (first1, second1) = key1.to_pair();
    entry.insert(second1.to_string(), v1.clone());
    correct.insert(first1.to_string(), entry);

    editable.overwrite(ConfigKey::BurnAfter, v1);
    let EditableToml(calculated) = editable.clone();

    assert_eq!(&correct, &calculated);

    let v2 = "value2".to_string();
    let v3 = "value3".to_string();

    let mut entry         = BTreeMap::new();
    let key2              = ConfigKey::SweepPeriod;
    let (first2, second2) = key2.to_pair();
    let key3              = ConfigKey::SweepTime;
    let (_, second3)      = key3.to_pair();
    entry.insert(second2.to_string(), v2.clone());
    entry.insert(second3.to_string(), v3.clone());
    correct.insert(first2.to_string(), entry);

    editable.overwrite(ConfigKey::SweepPeriod, v2);
    editable.overwrite(ConfigKey::SweepTime  , v3);
    let &EditableToml(ref calculated) = &editable;

    assert_eq!(&correct, calculated);
}

#[test]
fn default_should_return_config() {
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn get_should_return_ok() {
    }
    #[test]
    fn get_should_return_err() {
    }

    #[test]
    fn set_should_return_ok() {
    }
    #[test]
    fn set_should_retrun_err() {
    }

    #[test]
    fn to_duration_should_return_ok() {
    }
    #[test]
    fn to_duration_should_return_err() {
    }

    #[test]
    fn validate_should_return_ok() {
    }
    #[test]
    fn validate_should_return_err() {
    }
}
<|endoftext|>


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

//! Implementation of Rust panics via process aborts
//!
//! When compared to the implementation via unwinding, this crate is *much*
//! simpler! That being said, it's not quite as versatile, but here goes!

#![no_std]
#![unstable(feature = "panic_abort", issue = "32837")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
#![panic_runtime]
#![allow(unused_features)]

#![feature(core_intrinsics)]
#![feature(libc)]
#![feature(nll)]
#![feature(panic_runtime)]
#![feature(staged_api)]
#![feature(rustc_attrs)]

// Rust's "try" function, but if we're aborting on panics we just call the
// function as there's nothing else we need to do here.
#[rustc_std_internal_symbol]
pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8),
                                              data: *mut u8,
                                              _data_ptr: *mut usize,
                                              _vtable_ptr: *mut usize) -> u32 {
    f(data);
    0
}

// "Leak" the payload and shim to the relevant abort on the platform in
// question.
//
// For Unix we just use `abort` from libc as it'll trigger debuggers, core
// dumps, etc, as one might expect. On Windows, however, the best option we have
// is the `__fastfail` intrinsics, but that's unfortunately not defined in LLVM,
// and the `RaiseFailFastException` function isn't available until Windows 7
// which would break compat with XP. For now just use `intrinsics::abort` which
// will kill us with an illegal instruction, which will do a good enough job for
// now hopefully.
#[rustc_std_internal_symbol]
pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 {
    abort();

    #[cfg(any(unix, target_os = "cloudabi"))]
    unsafe fn abort() -> ! {
        extern crate libc;
        libc::abort();
    }

    #[cfg(any(target_os = "redox",
              windows,
              all(target_arch = "wasm32", not(target_os = "emscripten"))))]
    unsafe fn abort() -> ! {
        core::intrinsics::abort();
    }
}

// This... is a bit of an oddity. The tl;dr; is that this is required to link
// correctly, the longer explanation is below.
//
// Right now the binaries of libcore/libstd that we ship are all compiled with
// `-C panic=unwind`. This is done to ensure that the binaries are maximally
// compatible with as many situations as possible. The compiler, however,
// requires a "personality function" for all functions compiled with `-C
// panic=unwind`. This personality function is hardcoded to the symbol
// `rust_eh_personality` and is defined by the `eh_personality` lang item.
//
// So... why not just define that lang item here? Good question! The way that
// panic runtimes are linked in is actually a little subtle in that they're
// "sort of" in the compiler's crate store, but only actually linked if another
// isn't actually linked. This ends up meaning that both this crate and the
// panic_unwind crate can appear in the compiler's crate store, and if both
// define the `eh_personality` lang item then that'll hit an error.
//
// To handle this the compiler only requires the `eh_personality` is defined if
// the panic runtime being linked in is the unwinding runtime, and otherwise
// it's not required to be defined (rightfully so). In this case, however, this
// library just defines this symbol so there's at least some personality
// somewhere.
//
// Essentially this symbol is just defined to get wired up to libcore/libstd
// binaries, but it should never be called as we don't link in an unwinding
// runtime at all.
pub mod personalities {
    #[no_mangle]
    #[cfg(not(any(
        target_arch = "wasm32",
        all(
            target_os = "windows",
            target_env = "gnu",
            target_arch = "x86_64",
        ),
    )))]
    pub extern fn rust_eh_personality() {}

    // On x86_64-pc-windows-gnu we use our own personality function that needs
    // to return `ExceptionContinueSearch` as we're passing on all our frames.
    #[no_mangle]
    #[cfg(all(target_os = "windows",
              target_env = "gnu",
              target_arch = "x86_64"))]
    pub extern fn rust_eh_personality(_record: usize,
                                      _frame: usize,
                                      _context: usize,
                                      _dispatcher: usize) -> u32 {
        1 // `ExceptionContinueSearch`
    }

    // Similar to above, this corresponds to the `eh_unwind_resume` lang item
    // that's only used on Windows currently.
    //
    // Note that we don't execute landing pads, so this is never called, so it's
    // body is empty.
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu"))]
    pub extern fn rust_eh_unwind_resume() {}

    // These two are called by our startup objects on i686-pc-windows-gnu, but
    // they don't need to do anything so the bodies are nops.
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern fn rust_eh_register_frames() {}
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern fn rust_eh_unregister_frames() {}
}
<commit_msg>Rollup merge of #55774 - CryZe:patch-5, r=alexcrichton<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of Rust panics via process aborts
//!
//! When compared to the implementation via unwinding, this crate is *much*
//! simpler! That being said, it's not quite as versatile, but here goes!

#![no_std]
#![unstable(feature = "panic_abort", issue = "32837")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
#![panic_runtime]
#![allow(unused_features)]

#![feature(core_intrinsics)]
#![feature(libc)]
#![feature(nll)]
#![feature(panic_runtime)]
#![feature(staged_api)]
#![feature(rustc_attrs)]

// Rust's "try" function, but if we're aborting on panics we just call the
// function as there's nothing else we need to do here.
#[rustc_std_internal_symbol]
pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8),
                                              data: *mut u8,
                                              _data_ptr: *mut usize,
                                              _vtable_ptr: *mut usize) -> u32 {
    f(data);
    0
}

// "Leak" the payload and shim to the relevant abort on the platform in
// question.
//
// For Unix we just use `abort` from libc as it'll trigger debuggers, core
// dumps, etc, as one might expect. On Windows, however, the best option we have
// is the `__fastfail` intrinsics, but that's unfortunately not defined in LLVM,
// and the `RaiseFailFastException` function isn't available until Windows 7
// which would break compat with XP. For now just use `intrinsics::abort` which
// will kill us with an illegal instruction, which will do a good enough job for
// now hopefully.
#[rustc_std_internal_symbol]
pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 {
    abort();

    #[cfg(any(unix, target_os = "cloudabi"))]
    unsafe fn abort() -> ! {
        extern crate libc;
        libc::abort();
    }

    #[cfg(any(target_os = "redox",
              windows,
              all(target_arch = "wasm32", not(target_os = "emscripten"))))]
    unsafe fn abort() -> ! {
        core::intrinsics::abort();
    }
}

// This... is a bit of an oddity. The tl;dr; is that this is required to link
// correctly, the longer explanation is below.
//
// Right now the binaries of libcore/libstd that we ship are all compiled with
// `-C panic=unwind`. This is done to ensure that the binaries are maximally
// compatible with as many situations as possible. The compiler, however,
// requires a "personality function" for all functions compiled with `-C
// panic=unwind`. This personality function is hardcoded to the symbol
// `rust_eh_personality` and is defined by the `eh_personality` lang item.
//
// So... why not just define that lang item here? Good question! The way that
// panic runtimes are linked in is actually a little subtle in that they're
// "sort of" in the compiler's crate store, but only actually linked if another
// isn't actually linked. This ends up meaning that both this crate and the
// panic_unwind crate can appear in the compiler's crate store, and if both
// define the `eh_personality` lang item then that'll hit an error.
//
// To handle this the compiler only requires the `eh_personality` is defined if
// the panic runtime being linked in is the unwinding runtime, and otherwise
// it's not required to be defined (rightfully so). In this case, however, this
// library just defines this symbol so there's at least some personality
// somewhere.
//
// Essentially this symbol is just defined to get wired up to libcore/libstd
// binaries, but it should never be called as we don't link in an unwinding
// runtime at all.
pub mod personalities {
    #[no_mangle]
    #[cfg(not(any(
        all(
            target_arch = "wasm32",
            not(target_os = "emscripten"),
        ),
        all(
            target_os = "windows",
            target_env = "gnu",
            target_arch = "x86_64",
        ),
    )))]
    pub extern fn rust_eh_personality() {}

    // On x86_64-pc-windows-gnu we use our own personality function that needs
    // to return `ExceptionContinueSearch` as we're passing on all our frames.
    #[no_mangle]
    #[cfg(all(target_os = "windows",
              target_env = "gnu",
              target_arch = "x86_64"))]
    pub extern fn rust_eh_personality(_record: usize,
                                      _frame: usize,
                                      _context: usize,
                                      _dispatcher: usize) -> u32 {
        1 // `ExceptionContinueSearch`
    }

    // Similar to above, this corresponds to the `eh_unwind_resume` lang item
    // that's only used on Windows currently.
    //
    // Note that we don't execute landing pads, so this is never called, so it's
    // body is empty.
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu"))]
    pub extern fn rust_eh_unwind_resume() {}

    // These two are called by our startup objects on i686-pc-windows-gnu, but
    // they don't need to do anything so the bodies are nops.
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern fn rust_eh_register_frames() {}
    #[no_mangle]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern fn rust_eh_unregister_frames() {}
}
<|endoftext|>


<commit_before>use crate::builder::OsStr;

/// Operations to perform on argument values
///
/// These do not apply to [`ValueSource::DefaultValue`][crate::parser::ValueSource::DefaultValue]
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "unstable-v4", non_exhaustive)]
pub enum ArgPredicate {
    /// Is the argument present?
    IsPresent,
    /// Does the argument match the specified value?
    Equals(OsStr),
}

impl<S: Into<OsStr>> From<S> for ArgPredicate {
    fn from(other: S) -> Self {
        Self::Equals(other.into())
    }
}
<commit_msg>fix: Correctly refer to unstable-v5<commit_after>use crate::builder::OsStr;

/// Operations to perform on argument values
///
/// These do not apply to [`ValueSource::DefaultValue`][crate::parser::ValueSource::DefaultValue]
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "unstable-v5", non_exhaustive)]
pub enum ArgPredicate {
    /// Is the argument present?
    IsPresent,
    /// Does the argument match the specified value?
    Equals(OsStr),
}

impl<S: Into<OsStr>> From<S> for ArgPredicate {
    fn from(other: S) -> Self {
        Self::Equals(other.into())
    }
}
<|endoftext|>