<commit_before>use sdl::Rect;
use sdl::video;

const SCALE: isize = 20;

pub struct Display
{
    gfx: [[u8; 64]; 32],
    draw_flag: bool,
    screen: video::Surface,
}

impl Display
{
    pub fn new() -> Display
    {
        Display {
            gfx: [[0; 64]; 32],
            draw_flag: true,
            screen: video::set_video_mode(64 * SCALE,
                                          32 * SCALE,
                                          8,
                                          &[video::SurfaceFlag::HWSurface],
                                          &[video::VideoFlag::DoubleBuf])
                    .unwrap(),
        }
    }

    pub fn clear(&mut self)
    {
        self.gfx = [[0; 64]; 32];
        self.draw_flag = true;
    }

    pub fn draw(&mut self, x: usize, y: usize, sprite: &[u8]) -> u8
    {
        let mut collision = 0u8;
        let n = sprite.len() as usize;
        let mut yj: usize;
        let mut xi: usize;

        for j in 0..n
        {
            for i in 0..8
            {
                yj = (y + j) % 32;
                xi = (x + i) % 64;

                if (sprite[j] & (0x80 >> i)) != 0
                {
                    if self.gfx[yj][xi] == 1
                    {
                        collision = 1
                    }
                    self.gfx[yj][xi] ^= 1;
                }
            }
        }

        self.draw_flag = true;
        collision
    }

    pub fn draw_screen(&mut self)
    {
        if !self.draw_flag
        {
            return;
        }
        let mut pixel: u8;
        let sc = SCALE as u16;
        fn pt(p: usize) -> i16
        {
            (p as i16) * (SCALE as i16)
        }

        for y in 0..32
        {
            for x in 0..64
            {
                pixel = if self.gfx[y][x] != 0 { 255 } else { 0 };
                self.screen.fill_rect(Some(Rect {
                                               x: pt(x),
                                               y: pt(y),
                                               w: sc,
                                               h: sc,
                                           }),
                                      video::RGB(pixel, pixel, pixel));
            }
        }

        self.screen.flip();
        self.draw_flag = false;
    }
}
<commit_msg>Use constants instead of magic numbers.<commit_after>use sdl::Rect;
use sdl::video;

const SCALE: usize = 20;
const HEIGHT_BASE: usize = 32;
const WIDTH_BASE: usize = 64;

pub struct Display
{
    gfx: [[u8; WIDTH_BASE]; HEIGHT_BASE],
    draw_flag: bool,
    screen: video::Surface,
}

impl Display
{
    pub fn new() -> Display
    {
        Display {
            gfx: [[0; WIDTH_BASE]; HEIGHT_BASE],
            draw_flag: true,
            screen: video::set_video_mode((WIDTH_BASE * SCALE) as isize,
                                          (HEIGHT_BASE * SCALE) as isize,
                                          8,
                                          &[video::SurfaceFlag::HWSurface],
                                          &[video::VideoFlag::DoubleBuf])
                    .unwrap(),
        }
    }

    pub fn clear(&mut self)
    {
        self.gfx = [[0; WIDTH_BASE]; HEIGHT_BASE];
        self.draw_flag = true;
    }

    pub fn draw(&mut self, x: usize, y: usize, sprite: &[u8]) -> u8
    {
        let mut collision = 0u8;
        let n = sprite.len() as usize;
        let mut yj: usize;
        let mut xi: usize;

        for j in 0..n
        {
            for i in 0..8
            {
                yj = (y + j) % HEIGHT_BASE;
                xi = (x + i) % WIDTH_BASE;

                if (sprite[j] & (0x80 >> i)) != 0
                {
                    if self.gfx[yj][xi] == 1
                    {
                        collision = 1
                    }
                    self.gfx[yj][xi] ^= 1;
                }
            }
        }

        self.draw_flag = true;
        collision
    }

    pub fn draw_screen(&mut self)
    {
        if !self.draw_flag
        {
            return;
        }
        let mut pixel: u8;
        let sc = SCALE as u16;
        fn pt(p: usize) -> i16
        {
            (p as i16) * (SCALE as i16)
        }

        for y in 0..HEIGHT_BASE
        {
            for x in 0..WIDTH_BASE
            {
                pixel = if self.gfx[y][x] != 0 { 255 } else { 0 };
                self.screen.fill_rect(Some(Rect {
                                               x: pt(x),
                                               y: pt(y),
                                               w: sc,
                                               h: sc,
                                           }),
                                      video::RGB(pixel, pixel, pixel));
            }
        }

        self.screen.flip();
        self.draw_flag = false;
    }
}
<|endoftext|>


<commit_before>use std::mem;

macro_rules! boxed {
    [$($x:expr),*] => (Box::new([$($x),*]));
}

macro_rules! collect {
    ($x:expr, $y:ty) => ($x.collect::<Vec<$y>>().into_boxed_slice());
}

type Element = Box<[usize]>;

#[derive(Debug)]
pub struct Polytope<V> {
    dimensions: usize,
    vertices: Box<[V]>,
    elements: Box<[Box<[Element]>]>,
}

impl<V: Default> Polytope<V> {
    pub fn new() -> Self {
        Polytope::<V> {
            dimensions: 0,
            vertices: boxed![V::default()],
            elements: boxed![],
        }
    }
}

impl<V> Polytope<V> {
    pub fn extrude<F1, F2>(&self, pull_in: F1, push_out: F2) -> Self
            where F1: Fn(&V) -> V,
                  F2: Fn(&V) -> V {
        // Vertices are a special case: Create a promoted pair of each and linked the pairs.
        let mut new_vertices = Vec::<V>::new();
        let mut new_edges = Vec::<Element>::new();
        for v in self.vertices.iter() {
            // Pulled in and pushed out copies.
            let i = new_vertices.len();
            new_vertices.push(pull_in(v));
            let j = new_vertices.len();
            new_vertices.push(push_out(v));

            // Linkage element.
            new_edges.push(boxed![i, j]);
        }

        // For the rest of the dimensions, create a pair of each element and linked them via a
        // higher dimensional element.
        let mut linkage_offset = 0;
        let mut new_elements = Vec::<Vec<Element>>::new();
        let mut new_elems_this = new_edges;
        let mut new_elems_next = Vec::<Element>::new();
        for elems_this in self.elements.iter() {
            let next_linkage_offset = new_elems_this.len();
            for e in elems_this.iter() {
                // Pulled in and pushed out copies.
                let i = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 0), usize));
                let j = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 1), usize));

                // Linkage element.
                new_elems_next.push(collect!(e.iter().chain([i, j].iter()).cloned(), usize));
            }
            linkage_offset = next_linkage_offset;
            // Reference-safe way of doing
            //   new_elements.push(new_elems_this);
            //   new_elems_this = new_elems_next;
            //   new_elems_next = vec![];
            new_elements.push(
                mem::replace(&mut new_elems_this,
                             mem::replace(&mut new_elems_next, vec![])));
        }
        // Don't forget the final dimension.
        new_elements.push(new_elems_this);

        let new_vertices = new_vertices.into_boxed_slice();
        let new_elements = collect!(new_elements.drain(..).map(
            |mut elements_of_this_dimension|
            collect!(elements_of_this_dimension.drain(..), Element)
        ), Box<[Element]>);
        Polytope::<V> {
            dimensions: self.dimensions + 1,
            vertices: new_vertices,
            elements: new_elements,
        }
    }

    pub fn cone<F1, F2>(&self, tip: V, pull_in: F1, push_out: F2) -> Self
            where F1: Fn(&V) -> V,
                  F2: Fn(&V) -> V {
        // Create a promoted pair of each vertex and linked all of them to the tip.
        let mut new_vertices = Vec::<V>::new();
        let mut new_edges = Vec::<Element>::new();
        let tip_index = self.vertices.len() * 2;
        for v in self.vertices.iter() {
            // Pulled in and pushed out copies.
            let i = new_vertices.len();
            new_vertices.push(pull_in(v));
            let j = new_vertices.len();
            new_vertices.push(push_out(v));

            // Linkage elements.
            new_edges.push(boxed![i, tip_index]);
            new_edges.push(boxed![j, tip_index]);
        }
        new_vertices.push(tip);

        // For the rest of the dimensions, create a pair of each element and linked them to the tip.
        let mut linkage_offset = 0;
        let mut new_elements = Vec::<Vec<Element>>::new();
        let mut new_elems_this = new_edges;
        let mut new_elems_next = Vec::<Element>::new();
        for elems_this in self.elements.iter() {
            let next_linkage_offset = new_elems_this.len();
            for e in elems_this.iter() {
                // Pulled in and pushed out copies.
                let i = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 0), usize));
                let j = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 1), usize));

                // Linkage elements.
                new_elems_next.push(collect!(
                    e.iter().map(|b| b * 2 + 0).chain([i].iter().cloned()), usize));
                new_elems_next.push(collect!(
                    e.iter().map(|b| b * 2 + 1).chain([j].iter().cloned()), usize));
            }
            linkage_offset = next_linkage_offset;
            // Reference-safe way of doing
            //   new_elements.push(new_elems_this);
            //   new_elems_this = new_elems_next;
            //   new_elems_next = vec![];
            new_elements.push(
                mem::replace(&mut new_elems_this,
                             mem::replace(&mut new_elems_next, vec![])));
        }
        // Don't forget the final dimension.
        new_elements.push(new_elems_this);

        let new_vertices = new_vertices.into_boxed_slice();
        let new_elements = collect!(new_elements.drain(..).map(
            |mut elements_of_this_dimension|
            collect!(elements_of_this_dimension.drain(..), Element)
        ), Box<[Element]>);
        Polytope::<V> {
            dimensions: self.dimensions + 1,
            vertices: new_vertices,
            elements: new_elements,
        }
    }
}

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

    #[derive(Debug)]
    struct MyVertex {
        coords: Box<[f64]>,
    }

    impl Default for MyVertex {
        fn default() -> Self {
            MyVertex {
                coords: Box::new([]),
            }
        }
    }

    impl MyVertex {
        fn promote(&self, h: f64) -> Self {
            MyVertex {
                coords: collect!(self.coords.iter().chain([h].iter()).map(|&x| x), f64),
            }
        }
    }

    #[test]
    fn polytope_new() {
        let p = Polytope::<MyVertex>::new();
        assert_eq!(p.dimensions, 0);
        assert_eq!(p.vertices.len(), 1);
        assert_eq!(p.elements.len(), 0);
    }

    #[test]
    fn extrude_point() {
        let p = Polytope::<MyVertex>::new();
        let q = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        assert_eq!(q.dimensions, 1);
        assert_eq!(q.vertices.len(), 2);
        assert!(q.vertices[0].coords == Box::new([-1.0]));
        assert!(q.vertices[1].coords == Box::new([ 1.0]));
        assert_eq!(q.elements.len(), 1);
        assert!(q.elements[0] == Box::new([Box::new([0, 1])]));
    }

    #[test]
    fn extrude_line() {
        let p = Polytope::<MyVertex>::new();
        let p = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        let q = p.extrude(|v| v.promote(-2.0), |v| v.promote(2.0));
        assert_eq!(q.dimensions, 2);
        assert_eq!(q.vertices.len(), 4);
        assert!(q.vertices[0].coords == Box::new([-1.0, -2.0]));
        assert!(q.vertices[1].coords == Box::new([-1.0,  2.0]));
        assert!(q.vertices[2].coords == Box::new([ 1.0, -2.0]));
        assert!(q.vertices[3].coords == Box::new([ 1.0,  2.0]));
        assert_eq!(q.elements.len(), 2);
        assert!(q.elements[0] == Box::new([
            Box::new([0, 1]),
            Box::new([2, 3]),
            Box::new([0, 2]),
            Box::new([1, 3]),
        ]));
        assert!(q.elements[1] == Box::new([Box::new([0, 1, 2, 3])]));
    }

    #[test]
    fn cone_line() {
        let p = Polytope::<MyVertex>::new();
        let p = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        let q = p.cone(MyVertex { coords: boxed![0.0, 0.0] },
                       |v| v.promote(-2.0), |v| v.promote(2.0));
        assert_eq!(q.dimensions, 2);
        assert_eq!(q.vertices.len(), 5);
        assert!(q.vertices[0].coords == Box::new([-1.0, -2.0]));
        assert!(q.vertices[1].coords == Box::new([-1.0,  2.0]));
        assert!(q.vertices[2].coords == Box::new([ 1.0, -2.0]));
        assert!(q.vertices[3].coords == Box::new([ 1.0,  2.0]));
        assert!(q.vertices[4].coords == Box::new([ 0.0,  0.0]));
        assert_eq!(q.elements.len(), 2);
        assert!(q.elements[0] == Box::new([
            Box::new([0, 4]),
            Box::new([1, 4]),
            Box::new([2, 4]),
            Box::new([3, 4]),
            Box::new([0, 2]),
            Box::new([1, 3]),
        ]));
        assert!(q.elements[1] == Box::new([
            Box::new([0, 2, 4]),
            Box::new([1, 3, 5]),
        ]));
    }
}
<commit_msg>Get rid of Default trait for Polytope::new().<commit_after>use std::mem;

macro_rules! boxed {
    [$($x:expr),*] => (Box::new([$($x),*]));
}

macro_rules! collect {
    ($x:expr, $y:ty) => ($x.collect::<Vec<$y>>().into_boxed_slice());
}

type Element = Box<[usize]>;

#[derive(Debug)]
pub struct Polytope<V> {
    dimensions: usize,
    vertices: Box<[V]>,
    elements: Box<[Box<[Element]>]>,
}

impl<V> Polytope<V> {
    pub fn new(dimensionless: V) -> Self {
        Polytope::<V> {
            dimensions: 0,
            vertices: boxed![dimensionless],
            elements: boxed![],
        }
    }
}

impl<V> Polytope<V> {
    pub fn extrude<F1, F2>(&self, pull_in: F1, push_out: F2) -> Self
            where F1: Fn(&V) -> V,
                  F2: Fn(&V) -> V {
        // Vertices are a special case: Create a promoted pair of each and linked the pairs.
        let mut new_vertices = Vec::<V>::new();
        let mut new_edges = Vec::<Element>::new();
        for v in self.vertices.iter() {
            // Pulled in and pushed out copies.
            let i = new_vertices.len();
            new_vertices.push(pull_in(v));
            let j = new_vertices.len();
            new_vertices.push(push_out(v));

            // Linkage element.
            new_edges.push(boxed![i, j]);
        }

        // For the rest of the dimensions, create a pair of each element and linked them via a
        // higher dimensional element.
        let mut linkage_offset = 0;
        let mut new_elements = Vec::<Vec<Element>>::new();
        let mut new_elems_this = new_edges;
        let mut new_elems_next = Vec::<Element>::new();
        for elems_this in self.elements.iter() {
            let next_linkage_offset = new_elems_this.len();
            for e in elems_this.iter() {
                // Pulled in and pushed out copies.
                let i = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 0), usize));
                let j = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 1), usize));

                // Linkage element.
                new_elems_next.push(collect!(e.iter().chain([i, j].iter()).cloned(), usize));
            }
            linkage_offset = next_linkage_offset;
            // Reference-safe way of doing
            //   new_elements.push(new_elems_this);
            //   new_elems_this = new_elems_next;
            //   new_elems_next = vec![];
            new_elements.push(
                mem::replace(&mut new_elems_this,
                             mem::replace(&mut new_elems_next, vec![])));
        }
        // Don't forget the final dimension.
        new_elements.push(new_elems_this);

        let new_vertices = new_vertices.into_boxed_slice();
        let new_elements = collect!(new_elements.drain(..).map(
            |mut elements_of_this_dimension|
            collect!(elements_of_this_dimension.drain(..), Element)
        ), Box<[Element]>);
        Polytope::<V> {
            dimensions: self.dimensions + 1,
            vertices: new_vertices,
            elements: new_elements,
        }
    }

    pub fn cone<F1, F2>(&self, tip: V, pull_in: F1, push_out: F2) -> Self
            where F1: Fn(&V) -> V,
                  F2: Fn(&V) -> V {
        // Create a promoted pair of each vertex and linked all of them to the tip.
        let mut new_vertices = Vec::<V>::new();
        let mut new_edges = Vec::<Element>::new();
        let tip_index = self.vertices.len() * 2;
        for v in self.vertices.iter() {
            // Pulled in and pushed out copies.
            let i = new_vertices.len();
            new_vertices.push(pull_in(v));
            let j = new_vertices.len();
            new_vertices.push(push_out(v));

            // Linkage elements.
            new_edges.push(boxed![i, tip_index]);
            new_edges.push(boxed![j, tip_index]);
        }
        new_vertices.push(tip);

        // For the rest of the dimensions, create a pair of each element and linked them to the tip.
        let mut linkage_offset = 0;
        let mut new_elements = Vec::<Vec<Element>>::new();
        let mut new_elems_this = new_edges;
        let mut new_elems_next = Vec::<Element>::new();
        for elems_this in self.elements.iter() {
            let next_linkage_offset = new_elems_this.len();
            for e in elems_this.iter() {
                // Pulled in and pushed out copies.
                let i = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 0), usize));
                let j = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 1), usize));

                // Linkage elements.
                new_elems_next.push(collect!(
                    e.iter().map(|b| b * 2 + 0).chain([i].iter().cloned()), usize));
                new_elems_next.push(collect!(
                    e.iter().map(|b| b * 2 + 1).chain([j].iter().cloned()), usize));
            }
            linkage_offset = next_linkage_offset;
            // Reference-safe way of doing
            //   new_elements.push(new_elems_this);
            //   new_elems_this = new_elems_next;
            //   new_elems_next = vec![];
            new_elements.push(
                mem::replace(&mut new_elems_this,
                             mem::replace(&mut new_elems_next, vec![])));
        }
        // Don't forget the final dimension.
        new_elements.push(new_elems_this);

        let new_vertices = new_vertices.into_boxed_slice();
        let new_elements = collect!(new_elements.drain(..).map(
            |mut elements_of_this_dimension|
            collect!(elements_of_this_dimension.drain(..), Element)
        ), Box<[Element]>);
        Polytope::<V> {
            dimensions: self.dimensions + 1,
            vertices: new_vertices,
            elements: new_elements,
        }
    }
}

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

    #[derive(Debug)]
    struct MyVertex {
        coords: Box<[f64]>,
    }

    impl Default for MyVertex {
        fn default() -> Self {
            MyVertex {
                coords: Box::new([]),
            }
        }
    }

    impl MyVertex {
        fn promote(&self, h: f64) -> Self {
            MyVertex {
                coords: collect!(self.coords.iter().chain([h].iter()).map(|&x| x), f64),
            }
        }
    }

    #[test]
    fn polytope_new() {
        let p = Polytope::<MyVertex>::new(Default::default());
        assert_eq!(p.dimensions, 0);
        assert_eq!(p.vertices.len(), 1);
        assert_eq!(p.elements.len(), 0);
    }

    #[test]
    fn extrude_point() {
        let p = Polytope::<MyVertex>::new(Default::default());
        let q = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        assert_eq!(q.dimensions, 1);
        assert_eq!(q.vertices.len(), 2);
        assert!(q.vertices[0].coords == Box::new([-1.0]));
        assert!(q.vertices[1].coords == Box::new([ 1.0]));
        assert_eq!(q.elements.len(), 1);
        assert!(q.elements[0] == Box::new([Box::new([0, 1])]));
    }

    #[test]
    fn extrude_line() {
        let p = Polytope::<MyVertex>::new(Default::default());
        let p = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        let q = p.extrude(|v| v.promote(-2.0), |v| v.promote(2.0));
        assert_eq!(q.dimensions, 2);
        assert_eq!(q.vertices.len(), 4);
        assert!(q.vertices[0].coords == Box::new([-1.0, -2.0]));
        assert!(q.vertices[1].coords == Box::new([-1.0,  2.0]));
        assert!(q.vertices[2].coords == Box::new([ 1.0, -2.0]));
        assert!(q.vertices[3].coords == Box::new([ 1.0,  2.0]));
        assert_eq!(q.elements.len(), 2);
        assert!(q.elements[0] == Box::new([
            Box::new([0, 1]),
            Box::new([2, 3]),
            Box::new([0, 2]),
            Box::new([1, 3]),
        ]));
        assert!(q.elements[1] == Box::new([Box::new([0, 1, 2, 3])]));
    }

    #[test]
    fn cone_line() {
        let p = Polytope::<MyVertex>::new(Default::default());
        let p = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        let q = p.cone(MyVertex { coords: boxed![0.0, 0.0] },
                       |v| v.promote(-2.0), |v| v.promote(2.0));
        assert_eq!(q.dimensions, 2);
        assert_eq!(q.vertices.len(), 5);
        assert!(q.vertices[0].coords == Box::new([-1.0, -2.0]));
        assert!(q.vertices[1].coords == Box::new([-1.0,  2.0]));
        assert!(q.vertices[2].coords == Box::new([ 1.0, -2.0]));
        assert!(q.vertices[3].coords == Box::new([ 1.0,  2.0]));
        assert!(q.vertices[4].coords == Box::new([ 0.0,  0.0]));
        assert_eq!(q.elements.len(), 2);
        assert!(q.elements[0] == Box::new([
            Box::new([0, 4]),
            Box::new([1, 4]),
            Box::new([2, 4]),
            Box::new([3, 4]),
            Box::new([0, 2]),
            Box::new([1, 3]),
        ]));
        assert!(q.elements[1] == Box::new([
            Box::new([0, 2, 4]),
            Box::new([1, 3, 5]),
        ]));
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Parsing and loading Executable and Linkable Format (ELF) 32- and 64-bit
//! binaries.
//!
//! For more information on the ELF format, refer to:
//!  - [Wikipedia](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
//!  - The [OS Dev Wiki](http://wiki.osdev.org/ELF)
//!  - The [ELF Format Specification](http://www.skyfree.org/linux/references/ELF_Format.pdf)
use core::mem;
use core::intrinsics;
use core::slice;

pub mod section;
pub mod file;

pub type Section<'a> = section::Header<'a>;
pub type FileHeader = file::Header;

pub struct Binary<'a> {
    pub header: &'a FileHeader
  , binary: &'a [u8]
}

unsafe fn extract_from_slice<'a, T: Sized>( data: &'a [u8]
                                          , offset: usize
                                          , n: usize)
                                          -> &'a [T] {
    assert!( data.len() - offset >= mem::size_of::<T>() * n
           , "Slice too short to contain {} objects of type {}"
           , n
           , intrinsics::type_name::<T>()
           );
    slice::from_raw_parts(data[offset..].as_ptr() as *const T, n)
}
<commit_msg>[elf] Remove elided explicit lifetime<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Parsing and loading Executable and Linkable Format (ELF) 32- and 64-bit
//! binaries.
//!
//! For more information on the ELF format, refer to:
//!  - [Wikipedia](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
//!  - The [OS Dev Wiki](http://wiki.osdev.org/ELF)
//!  - The [ELF Format Specification](http://www.skyfree.org/linux/references/ELF_Format.pdf)
use core::mem;
use core::intrinsics;
use core::slice;

pub mod section;
pub mod file;

pub type Section<'a> = section::Header<'a>;
pub type FileHeader = file::Header;

pub struct Binary<'a> {
    pub header: &'a FileHeader
  , binary: &'a [u8]
}

unsafe fn extract_from_slice<T: Sized>( data: &[u8]
                                      , offset: usize
                                      , n: usize)
                                      -> &[T] {
    assert!( data.len() - offset >= mem::size_of::<T>() * n
           , "Slice too short to contain {} objects of type {}"
           , n
           , intrinsics::type_name::<T>()
           );
    slice::from_raw_parts(data[offset..].as_ptr() as *const T, n)
}
<|endoftext|>


<commit_before>// Copyright © 2014 - 2015 by Optimal Computing Limited (of New Zealand)
// This code is licensed under the MIT license (see LICENSE-MIT for details)

use std::fmt;
use std::ops::Deref;
use std::error::Error as StdError;

use postgres::types::{ToSql, FromSql, Type, IsNull, TEXT};

/// A key issued at storage, used to retrieve your file
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
pub struct FileKey(pub String);

impl ToSql for FileKey {
    fn to_sql(&self, ty: &Type, out: &mut Vec<u8>)
              -> Result<IsNull, Box<StdError + Sync + Send>>
        where Self: Sized
    {
        // use the inner type
        self.0.to_sql(ty,out)
    }

    accepts!(TEXT);

    fn to_sql_checked(&self, ty: &Type, out: &mut Vec<u8>)
                      -> Result<IsNull, Box<StdError + Sync + Send>>
        where Self: Sized
    {
        // use the inner type
        self.0.to_sql_checked(ty,out)
    }
}

impl FromSql for FileKey {
    fn from_sql(ty: &Type, raw: &[u8])
                -> Result<Self, Box<StdError + Sync + Send>>
    {
        // use the inner type
        let s = <String>::from_sql(ty, raw)?;
        Ok(FileKey(s))
    }

    accepts!(TEXT);
}

impl fmt::Display for FileKey
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        write!(f, "{}", &*self)
    }
}

impl Deref for FileKey {
    type Target = str;

    fn deref(&self) -> &str {
        &*self.0
    }
}

// inner error for building postgres conversion errors
#[cfg(feature = "postgres")]
#[derive(Debug)]
pub struct WrongType(pub ::postgres::types::Type);

#[cfg(feature = "postgres")]
impl fmt::Display for WrongType {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt,
               "cannot convert to or from a Postgres value of type `{}`",
               self.0)
    }
}

#[cfg(feature = "postgres")]
impl ::std::error::Error for WrongType {
    fn description(&self) -> &str {
        "cannot convert to or from a Postgres value"
    }
}

#[cfg(feature = "postgres")]
impl WrongType {
    pub fn new(ty: ::postgres::types::Type) -> WrongType {
        WrongType(ty)
    }
}
<commit_msg>Use dyn keyword where needed<commit_after>// Copyright © 2014 - 2015 by Optimal Computing Limited (of New Zealand)
// This code is licensed under the MIT license (see LICENSE-MIT for details)

use std::fmt;
use std::ops::Deref;
use std::error::Error as StdError;

use postgres::types::{ToSql, FromSql, Type, IsNull, TEXT};

/// A key issued at storage, used to retrieve your file
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
pub struct FileKey(pub String);

impl ToSql for FileKey {
    fn to_sql(&self, ty: &Type, out: &mut Vec<u8>)
              -> Result<IsNull, Box<dyn StdError + Sync + Send>>
        where Self: Sized
    {
        // use the inner type
        self.0.to_sql(ty,out)
    }

    accepts!(TEXT);

    fn to_sql_checked(&self, ty: &Type, out: &mut Vec<u8>)
                      -> Result<IsNull, Box<dyn StdError + Sync + Send>>
        where Self: Sized
    {
        // use the inner type
        self.0.to_sql_checked(ty,out)
    }
}

impl FromSql for FileKey {
    fn from_sql(ty: &Type, raw: &[u8])
                -> Result<Self, Box<dyn StdError + Sync + Send>>
    {
        // use the inner type
        let s = <String>::from_sql(ty, raw)?;
        Ok(FileKey(s))
    }

    accepts!(TEXT);
}

impl fmt::Display for FileKey
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        write!(f, "{}", &*self)
    }
}

impl Deref for FileKey {
    type Target = str;

    fn deref(&self) -> &str {
        &*self.0
    }
}

// inner error for building postgres conversion errors
#[cfg(feature = "postgres")]
#[derive(Debug)]
pub struct WrongType(pub ::postgres::types::Type);

#[cfg(feature = "postgres")]
impl fmt::Display for WrongType {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt,
               "cannot convert to or from a Postgres value of type `{}`",
               self.0)
    }
}

#[cfg(feature = "postgres")]
impl ::std::error::Error for WrongType {
    fn description(&self) -> &str {
        "cannot convert to or from a Postgres value"
    }
}

#[cfg(feature = "postgres")]
impl WrongType {
    pub fn new(ty: ::postgres::types::Type) -> WrongType {
        WrongType(ty)
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 Chris Liebert

// Frustum extracting and testing algorithm used from
// http://www.racer.nl/reference/vfc_markmorley.htm

/// `Frustum`
///
/// A data structure for six planes of the view frustum
///
#[derive(Debug)]
pub struct Frustum {
    // right left bottom top near and far planes
    planes: [[f32; 4]; 6],
}

impl Frustum {
    /// Create a frustum from 1-dimensional modelview and projection float arrays
	///
    pub fn create_from_1d_array(modl: &[f32; 16], proj: &[f32; 16]) -> Frustum {

        // Combine the two matrices (multiply projection by modelview)
        let clip: [f32; 16] =
            [modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] + modl[3] * proj[12],
             modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] + modl[3] * proj[13],
             modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] + modl[3] * proj[14],
             modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] + modl[3] * proj[15],
             modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] + modl[7] * proj[12],
             modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] + modl[7] * proj[13],
             modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] + modl[7] * proj[14],
             modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] + modl[7] * proj[15],
             modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] + modl[11] * proj[12],
             modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] + modl[11] * proj[13],
             modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] + modl[11] * proj[14],
             modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] + modl[11] * proj[15],
             modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] + modl[15] * proj[12],
             modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] + modl[15] * proj[13],
             modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] + modl[15] * proj[14],
             modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] + modl[15] * proj[15]];

        // Extract the numbers for the RIGHT plane
        let rdx: f32 = clip[3] - clip[0];
        let rdy: f32 = clip[7] - clip[4];
        let rdz: f32 = clip[11] - clip[8];
        let rdw: f32 = clip[15] - clip[12];

        // Divisor to normilize right plane
        let rd: f32 = (rdx.powi(2) + rdy.powi(2) + rdz.powi(2)).sqrt();

        // Extract the numbers for the LEFT plane
        let ldx: f32 = clip[3] + clip[0];
        let ldy: f32 = clip[7] + clip[4];
        let ldz: f32 = clip[11] + clip[8];
        let ldw: f32 = clip[15] + clip[12];

        // Divisor to normilize left plane
        let ld: f32 = (ldx.powi(2) + ldy.powi(2) + ldz.powi(2)).sqrt();

        // Extract the BOTTOM plane
        let bdx: f32 = clip[3] + clip[1];
        let bdy: f32 = clip[7] + clip[5];
        let bdz: f32 = clip[11] + clip[9];
        let bdw: f32 = clip[15] + clip[13];

        // Divisor to normilize bottom plane
        let bd: f32 = (bdx.powi(2) + bdy.powi(2) + bdz.powi(2)).sqrt();

        // Extract the TOP plane
        let tdx: f32 = clip[3] - clip[1];
        let tdy: f32 = clip[7] - clip[5];
        let tdz: f32 = clip[11] - clip[9];
        let tdw: f32 = clip[15] - clip[13];

        // Divisor to normilize top plane
        let td: f32 = (tdx.powi(2) + tdy.powi(2) + tdz.powi(2)).sqrt();

        // Extract the FAR plane
        let fdx: f32 = clip[3] - clip[2];
        let fdy: f32 = clip[7] - clip[6];
        let fdz: f32 = clip[11] - clip[10];
        let fdw: f32 = clip[15] - clip[14];

        // Divisor to normilize far plane
        let fd: f32 = (fdx.powi(2) + fdy.powi(2) + fdz.powi(2)).sqrt();

        // Extract the NEAR plane
        let ndx: f32 = clip[3] + clip[2];
        let ndy: f32 = clip[7] + clip[6];
        let ndz: f32 = clip[11] + clip[10];
        let ndw: f32 = clip[15] + clip[14];

        // Divisor to normilize near plane
        let nd: f32 = (ndx.powi(2) + ndy.powi(2) + ndz.powi(2)).sqrt();

        Frustum {
            planes: [[rdx / rd, rdy / rd, rdz / rd, rdw / rd],
                     [ldx / ld, ldy / ld, ldz / ld, ldw / ld],
                     [bdx / bd, bdy / bd, bdz / bd, bdw / bd],
                     [tdx / td, tdy / td, tdz / td, tdw / td],
                     [fdx / fd, fdy / fd, fdz / fd, fdw / fd],
                     [ndx / nd, ndy / nd, ndz / nd, ndw / nd]],
        }
    }

	/// Create a frustum from 2-dimensional modelview and projection float arrays
	///
    pub fn create_from_2d_array(modl: &[[f32; 4]; 4], proj: &[[f32; 4]; 4]) -> Frustum {
        let modl_1d: [f32; 16] = [
            modl[0][0],
            modl[0][1],
            modl[0][2],
            modl[0][3],
                modl[1][0],
                modl[1][1],
                modl[1][2],
                modl[1][3],
                    modl[2][0],
                    modl[2][1],
                    modl[2][2],
                    modl[2][3],
                        modl[3][0],
                        modl[3][1],
                        modl[3][2],
                        modl[3][3],
        ];
        let proj_1d: [f32; 16] = [
            proj[0][0],
            proj[0][1],
            proj[0][2],
            proj[0][3],
                proj[1][0],
                proj[1][1],
                proj[1][2],
                proj[1][3],
                    proj[2][0],
                    proj[2][1],
                    proj[2][2],
                    proj[2][3],
                        proj[3][0],
                        proj[3][1],
                        proj[3][2],
                        proj[3][3]
        ];

        return Frustum::create_from_1d_array(&modl_1d, &proj_1d);
    }

    /// A cube is intersecting the renderable region of the frustum
	///
    pub fn cube_intersecting(&self, x: &f32, y: &f32, z: &f32, size: &f32) -> bool {
        for p in 0..6 {
            if !((self.planes[p][0] * (x - size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32)) {
                return false;
            }
        }
        true
    }

	/// A point is intersecting the renderable region of the frustum
	///
    pub fn point_intersecting(&self, x: &f32, y: &f32, z: &f32) -> bool {
        for p in 0..6 {
            if (self.planes[p][0] * x + self.planes[p][1] * y + self.planes[p][2] * z + self.planes[p][3]) <= 0.0f32 {
                return false;
            }
        }
        true
    }

	/// A sphere is intersecting the renderable region of the frustum
	///
    pub fn sphere_intersecting(&self, x: &f32, y: &f32, z: &f32, r: &f32) -> bool {
        for p in 0..6 {
            if self.planes[p][0] * x + self.planes[p][1] * y + self.planes[p][2] * z + self.planes[p][3] <= (0.0f32 - r) {
                return false;
            }
        }
        true
    }
}
<commit_msg>whitespace update<commit_after>// Copyright (C) 2016 Chris Liebert

// Frustum extracting and testing algorithm used from
// http://www.racer.nl/reference/vfc_markmorley.htm

/// `Frustum`
///
/// A data structure for six planes of the view frustum
///
#[derive(Debug)]
pub struct Frustum {
    // right left bottom top near and far planes
    planes: [[f32; 4]; 6],
}

impl Frustum {
    /// Create a frustum from 1-dimensional modelview and projection float arrays
    ///
    pub fn create_from_1d_array(modl: &[f32; 16], proj: &[f32; 16]) -> Frustum {

        // Combine the two matrices (multiply projection by modelview)
        let clip: [f32; 16] =
            [modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] + modl[3] * proj[12],
             modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] + modl[3] * proj[13],
             modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] + modl[3] * proj[14],
             modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] + modl[3] * proj[15],
             modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] + modl[7] * proj[12],
             modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] + modl[7] * proj[13],
             modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] + modl[7] * proj[14],
             modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] + modl[7] * proj[15],
             modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] + modl[11] * proj[12],
             modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] + modl[11] * proj[13],
             modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] + modl[11] * proj[14],
             modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] + modl[11] * proj[15],
             modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] + modl[15] * proj[12],
             modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] + modl[15] * proj[13],
             modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] + modl[15] * proj[14],
             modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] + modl[15] * proj[15]];

        // Extract the numbers for the RIGHT plane
        let rdx: f32 = clip[3] - clip[0];
        let rdy: f32 = clip[7] - clip[4];
        let rdz: f32 = clip[11] - clip[8];
        let rdw: f32 = clip[15] - clip[12];

        // Divisor to normilize right plane
        let rd: f32 = (rdx.powi(2) + rdy.powi(2) + rdz.powi(2)).sqrt();

        // Extract the numbers for the LEFT plane
        let ldx: f32 = clip[3] + clip[0];
        let ldy: f32 = clip[7] + clip[4];
        let ldz: f32 = clip[11] + clip[8];
        let ldw: f32 = clip[15] + clip[12];

        // Divisor to normilize left plane
        let ld: f32 = (ldx.powi(2) + ldy.powi(2) + ldz.powi(2)).sqrt();

        // Extract the BOTTOM plane
        let bdx: f32 = clip[3] + clip[1];
        let bdy: f32 = clip[7] + clip[5];
        let bdz: f32 = clip[11] + clip[9];
        let bdw: f32 = clip[15] + clip[13];

        // Divisor to normilize bottom plane
        let bd: f32 = (bdx.powi(2) + bdy.powi(2) + bdz.powi(2)).sqrt();

        // Extract the TOP plane
        let tdx: f32 = clip[3] - clip[1];
        let tdy: f32 = clip[7] - clip[5];
        let tdz: f32 = clip[11] - clip[9];
        let tdw: f32 = clip[15] - clip[13];

        // Divisor to normilize top plane
        let td: f32 = (tdx.powi(2) + tdy.powi(2) + tdz.powi(2)).sqrt();

        // Extract the FAR plane
        let fdx: f32 = clip[3] - clip[2];
        let fdy: f32 = clip[7] - clip[6];
        let fdz: f32 = clip[11] - clip[10];
        let fdw: f32 = clip[15] - clip[14];

        // Divisor to normilize far plane
        let fd: f32 = (fdx.powi(2) + fdy.powi(2) + fdz.powi(2)).sqrt();

        // Extract the NEAR plane
        let ndx: f32 = clip[3] + clip[2];
        let ndy: f32 = clip[7] + clip[6];
        let ndz: f32 = clip[11] + clip[10];
        let ndw: f32 = clip[15] + clip[14];

        // Divisor to normilize near plane
        let nd: f32 = (ndx.powi(2) + ndy.powi(2) + ndz.powi(2)).sqrt();

        Frustum {
            planes: [[rdx / rd, rdy / rd, rdz / rd, rdw / rd],
                     [ldx / ld, ldy / ld, ldz / ld, ldw / ld],
                     [bdx / bd, bdy / bd, bdz / bd, bdw / bd],
                     [tdx / td, tdy / td, tdz / td, tdw / td],
                     [fdx / fd, fdy / fd, fdz / fd, fdw / fd],
                     [ndx / nd, ndy / nd, ndz / nd, ndw / nd]],
        }
    }

    /// Create a frustum from 2-dimensional modelview and projection float arrays
    ///
    pub fn create_from_2d_array(modl: &[[f32; 4]; 4], proj: &[[f32; 4]; 4]) -> Frustum {
        let modl_1d: [f32; 16] = [
            modl[0][0],
            modl[0][1],
            modl[0][2],
            modl[0][3],
                modl[1][0],
                modl[1][1],
                modl[1][2],
                modl[1][3],
                    modl[2][0],
                    modl[2][1],
                    modl[2][2],
                    modl[2][3],
                        modl[3][0],
                        modl[3][1],
                        modl[3][2],
                        modl[3][3],
        ];
        let proj_1d: [f32; 16] = [
            proj[0][0],
            proj[0][1],
            proj[0][2],
            proj[0][3],
                proj[1][0],
                proj[1][1],
                proj[1][2],
                proj[1][3],
                    proj[2][0],
                    proj[2][1],
                    proj[2][2],
                    proj[2][3],
                        proj[3][0],
                        proj[3][1],
                        proj[3][2],
                        proj[3][3]
        ];

        return Frustum::create_from_1d_array(&modl_1d, &proj_1d);
    }

    /// A cube is intersecting the renderable region of the frustum
    ///
    pub fn cube_intersecting(&self, x: &f32, y: &f32, z: &f32, size: &f32) -> bool {
        for p in 0..6 {
            if !((self.planes[p][0] * (x - size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32)) {
                return false;
            }
        }
        true
    }

    /// A point is intersecting the renderable region of the frustum
    ///
    pub fn point_intersecting(&self, x: &f32, y: &f32, z: &f32) -> bool {
        for p in 0..6 {
            if (self.planes[p][0] * x + self.planes[p][1] * y + self.planes[p][2] * z + self.planes[p][3]) <= 0.0f32 {
                return false;
            }
        }
        true
    }

    /// A sphere is intersecting the renderable region of the frustum
    ///
    pub fn sphere_intersecting(&self, x: &f32, y: &f32, z: &f32, r: &f32) -> bool {
        for p in 0..6 {
            if self.planes[p][0] * x + self.planes[p][1] * y + self.planes[p][2] * z + self.planes[p][3] <= (0.0f32 - r) {
                return false;
            }
        }
        true
    }
}
<|endoftext|>


<commit_before>// Copyright 2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use libc;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::ffi::{CStr, CString, OsStr};
use std::fmt;
use std::hash;
use std::ops::Deref;
use std::os::raw::c_char;
use std::ptr;
use std::slice;
use std::string::String;
use translate::*;
use types::{StaticType, Type};

use glib_sys;
use gobject_sys;
use value::{FromValueOptional, SetValue, SetValueOptional, Value};

#[derive(Debug)]
pub struct GString(Inner);

#[derive(Debug)]
enum Inner {
    Native(Option<CString>),
    Foreign(*mut c_char, usize),
}

unsafe impl Send for GString {}
unsafe impl Sync for GString {}

impl GString {
    pub unsafe fn new(ptr: *mut c_char) -> Self {
        assert!(!ptr.is_null());
        GString(Inner::Foreign(ptr, libc::strlen(ptr)))
    }

    pub unsafe fn new_borrowed(ptr: *const c_char) -> Borrowed<Self> {
        assert!(!ptr.is_null());
        Borrowed::new(GString(Inner::Foreign(ptr as *mut _, libc::strlen(ptr))))
    }

    pub fn as_str(&self) -> &str {
        let cstr = match self {
            GString(Inner::Foreign(ptr, length)) => unsafe {
                let bytes = slice::from_raw_parts(*ptr as *const u8, length + 1);
                CStr::from_bytes_with_nul_unchecked(bytes)
            },
            GString(Inner::Native(cstring)) => cstring
                .as_ref()
                .expect("Native shouldn't be empty")
                .as_c_str(),
        };
        cstr.to_str().unwrap()
    }
}

impl Drop for GString {
    fn drop(&mut self) {
        if let GString(Inner::Foreign(ptr, _len)) = self {
            unsafe {
                glib_sys::g_free(*ptr as *mut _);
            }
        }
    }
}

impl fmt::Display for GString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

impl hash::Hash for GString {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        let bytes = match self {
            GString(Inner::Foreign(ptr, length)) => unsafe {
                slice::from_raw_parts(*ptr as *const u8, length + 1)
            },
            GString(Inner::Native(cstring)) => cstring
                .as_ref()
                .expect("Native shouldn't be empty")
                .as_bytes(),
        };
        state.write(bytes);
    }
}

impl Borrow<str> for GString {
    fn borrow(&self) -> &str {
        self.as_str()
    }
}

impl Ord for GString {
    fn cmp(&self, other: &GString) -> Ordering {
        self.as_str().cmp(other.as_str())
    }
}

impl PartialOrd for GString {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for GString {
    fn eq(&self, other: &GString) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<GString> for String {
    fn eq(&self, other: &GString) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<str> for GString {
    fn eq(&self, other: &str) -> bool {
        self.as_str() == other
    }
}

impl<'a> PartialEq<&'a str> for GString {
    fn eq(&self, other: &&'a str) -> bool {
        self.as_str() == *other
    }
}

impl<'a> PartialEq<GString> for &'a str {
    fn eq(&self, other: &GString) -> bool {
        *self == other.as_str()
    }
}

impl PartialEq<String> for GString {
    fn eq(&self, other: &String) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<GString> for str {
    fn eq(&self, other: &GString) -> bool {
        self == other.as_str()
    }
}

impl PartialOrd<GString> for String {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(&String::from(other.as_str())))
    }
}

impl PartialOrd<String> for GString {
    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
        Some(self.as_str().cmp(other.as_str()))
    }
}

impl PartialOrd<GString> for str {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(&other))
    }
}

impl PartialOrd<str> for GString {
    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
        Some(self.as_str().cmp(other))
    }
}

impl Eq for GString {}

impl AsRef<str> for GString {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl AsRef<OsStr> for GString {
    fn as_ref(&self) -> &OsStr {
        OsStr::new(self.as_str())
    }
}

impl Deref for GString {
    type Target = str;

    fn deref(&self) -> &str {
        self.as_str()
    }
}

impl From<GString> for String {
    #[inline]
    fn from(mut s: GString) -> Self {
        if let GString(Inner::Native(ref mut cstring)) = s {
            if let Ok(s) = cstring
                .take()
                .expect("Native shouldn't be empty")
                .into_string()
            {
                return s;
            }
        }
        String::from(s.as_str())
    }
}

impl From<GString> for Box<str> {
    #[inline]
    fn from(s: GString) -> Self {
        let st: String = s.into();
        st.into_boxed_str()
    }
}

impl From<String> for GString {
    #[inline]
    fn from(s: String) -> Self {
        s.into_bytes().into()
    }
}

impl From<Box<str>> for GString {
    #[inline]
    fn from(s: Box<str>) -> Self {
        s.as_bytes().to_vec().into()
    }
}

impl<'a> From<&'a str> for GString {
    #[inline]
    fn from(s: &'a str) -> Self {
        s.as_bytes().to_vec().into()
    }
}

impl From<Vec<u8>> for GString {
    #[inline]
    fn from(s: Vec<u8>) -> Self {
        let cstring = CString::new(s).expect("CString::new failed");
        cstring.into()
    }
}

impl From<CString> for GString {
    #[inline]
    fn from(s: CString) -> Self {
        GString(Inner::Native(Some(s)))
    }
}

impl<'a> From<&'a CStr> for GString {
    #[inline]
    fn from(c: &'a CStr) -> Self {
        CString::from(c).into()
    }
}

#[doc(hidden)]
impl FromGlibPtrFull<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *const c_char) -> Self {
        GString::new(ptr as *mut _)
    }
}

#[doc(hidden)]
impl FromGlibPtrFull<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut u8) -> Self {
        GString::new(ptr as *mut _)
    }
}

#[doc(hidden)]
impl FromGlibPtrFull<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut i8) -> Self {
        GString::new(ptr as *mut _)
    }
}

#[doc(hidden)]
impl FromGlibPtrNone<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *const c_char) -> Self {
        let cstr = CStr::from_ptr(ptr);
        cstr.into()
    }
}

#[doc(hidden)]
impl FromGlibPtrNone<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut u8) -> Self {
        let cstr = CStr::from_ptr(ptr as *mut _);
        cstr.into()
    }
}

#[doc(hidden)]
impl FromGlibPtrNone<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut i8) -> Self {
        let cstr = CStr::from_ptr(ptr as *mut _);
        cstr.into()
    }
}

#[doc(hidden)]
impl FromGlibPtrBorrow<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *const c_char) -> Borrowed<Self> {
        GString::new_borrowed(ptr)
    }
}

#[doc(hidden)]
impl FromGlibPtrBorrow<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut u8) -> Borrowed<Self> {
        GString::new_borrowed(ptr as *const c_char)
    }
}

#[doc(hidden)]
impl FromGlibPtrBorrow<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut i8) -> Borrowed<Self> {
        GString::new_borrowed(ptr as *const c_char)
    }
}

#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *const c_char> for GString {
    type Storage = &'a Self;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
        Stash(self.as_ptr() as *const _, self)
    }

    #[inline]
    fn to_glib_full(&self) -> *const c_char {
        unsafe {
            glib_sys::g_strndup(self.as_ptr() as *const c_char, self.len() as libc::size_t)
                as *const c_char
        }
    }
}

#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *mut c_char> for GString {
    type Storage = &'a Self;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
        Stash(self.as_ptr() as *mut _, self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut c_char {
        unsafe {
            glib_sys::g_strndup(self.as_ptr() as *const c_char, self.len() as libc::size_t)
                as *mut c_char
        }
    }
}

impl GlibPtrDefault for GString {
    type GlibType = *const c_char;
}

impl StaticType for GString {
    fn static_type() -> Type {
        String::static_type()
    }
}

impl StaticType for Vec<GString> {
    fn static_type() -> Type {
        unsafe { from_glib(glib_sys::g_strv_get_type()) }
    }
}

impl<'a> FromValueOptional<'a> for GString {
    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
        let val = value.to_glib_none().0;
        if val.is_null() {
            None
        } else {
            let ptr = gobject_sys::g_value_dup_string(val);
            Some(GString::new(ptr))
        }
    }
}

impl SetValue for GString {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl SetValueOptional for GString {
    unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
        gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl_from_glib_container_as_vec_string!(GString, *const c_char);
impl_from_glib_container_as_vec_string!(GString, *mut c_char);

#[cfg(test)]
#[allow(clippy::blacklisted_name)]
mod tests {
    use glib_sys;
    use gstring::GString;
    use std::ffi::CString;

    #[test]
    fn test_gstring() {
        let data = CString::new("foo").unwrap();
        let ptr = data.as_ptr();

        unsafe {
            let ptr_copy = glib_sys::g_strdup(ptr);
            let gstring = GString::new(ptr_copy);
            assert_eq!(gstring.as_str(), "foo");
            let foo: Box<str> = gstring.into();
            assert_eq!(foo.as_ref(), "foo");
        }
    }

    #[test]
    fn test_owned_glib_string() {
        let data = CString::new("foo").unwrap();
        let ptr = data.as_ptr();
        unsafe {
            let ptr_copy = glib_sys::g_strdup(ptr);
            let gstr = GString::new(ptr_copy);
            assert_eq!(gstr, "foo");
        }
    }

    #[test]
    fn test_gstring_from_str() {
        let gstring: GString = "foo".into();
        assert_eq!(gstring.as_str(), "foo");
        let foo: Box<str> = gstring.into();
        assert_eq!(foo.as_ref(), "foo");
    }

    #[test]
    fn test_gstring_from_cstring() {
        let cstr = CString::new("foo").unwrap();
        let gstring = GString::from(cstr);
        assert_eq!(gstring.as_str(), "foo");
        let foo: Box<str> = gstring.into();
        assert_eq!(foo.as_ref(), "foo");
    }

    #[test]
    fn test_string_from_gstring() {
        let cstr = CString::new("foo").unwrap();
        let gstring = GString::from(cstr);
        assert_eq!(gstring.as_str(), "foo");
        let s = String::from(gstring);
        assert_eq!(s, "foo");
    }

    #[test]
    fn test_vec_u8_to_gstring() {
        let v = "foo".as_bytes();
        let s: GString = Vec::from(v).into();
        assert_eq!(s.as_str(), "foo");
    }

    #[test]
    fn test_hashmap() {
        use std::collections::HashMap;

        let cstr = CString::new("foo").unwrap();
        let gstring = GString::from(cstr);
        assert_eq!(gstring.as_str(), "foo");
        let mut h: HashMap<GString, i32> = HashMap::new();
        h.insert(gstring, 42);
        let gstring: GString = "foo".into();
        assert!(h.contains_key(&gstring));
    }
}
<commit_msg>clippy: Use byte literals<commit_after>// Copyright 2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use libc;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::ffi::{CStr, CString, OsStr};
use std::fmt;
use std::hash;
use std::ops::Deref;
use std::os::raw::c_char;
use std::ptr;
use std::slice;
use std::string::String;
use translate::*;
use types::{StaticType, Type};

use glib_sys;
use gobject_sys;
use value::{FromValueOptional, SetValue, SetValueOptional, Value};

#[derive(Debug)]
pub struct GString(Inner);

#[derive(Debug)]
enum Inner {
    Native(Option<CString>),
    Foreign(*mut c_char, usize),
}

unsafe impl Send for GString {}
unsafe impl Sync for GString {}

impl GString {
    pub unsafe fn new(ptr: *mut c_char) -> Self {
        assert!(!ptr.is_null());
        GString(Inner::Foreign(ptr, libc::strlen(ptr)))
    }

    pub unsafe fn new_borrowed(ptr: *const c_char) -> Borrowed<Self> {
        assert!(!ptr.is_null());
        Borrowed::new(GString(Inner::Foreign(ptr as *mut _, libc::strlen(ptr))))
    }

    pub fn as_str(&self) -> &str {
        let cstr = match self {
            GString(Inner::Foreign(ptr, length)) => unsafe {
                let bytes = slice::from_raw_parts(*ptr as *const u8, length + 1);
                CStr::from_bytes_with_nul_unchecked(bytes)
            },
            GString(Inner::Native(cstring)) => cstring
                .as_ref()
                .expect("Native shouldn't be empty")
                .as_c_str(),
        };
        cstr.to_str().unwrap()
    }
}

impl Drop for GString {
    fn drop(&mut self) {
        if let GString(Inner::Foreign(ptr, _len)) = self {
            unsafe {
                glib_sys::g_free(*ptr as *mut _);
            }
        }
    }
}

impl fmt::Display for GString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

impl hash::Hash for GString {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        let bytes = match self {
            GString(Inner::Foreign(ptr, length)) => unsafe {
                slice::from_raw_parts(*ptr as *const u8, length + 1)
            },
            GString(Inner::Native(cstring)) => cstring
                .as_ref()
                .expect("Native shouldn't be empty")
                .as_bytes(),
        };
        state.write(bytes);
    }
}

impl Borrow<str> for GString {
    fn borrow(&self) -> &str {
        self.as_str()
    }
}

impl Ord for GString {
    fn cmp(&self, other: &GString) -> Ordering {
        self.as_str().cmp(other.as_str())
    }
}

impl PartialOrd for GString {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for GString {
    fn eq(&self, other: &GString) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<GString> for String {
    fn eq(&self, other: &GString) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<str> for GString {
    fn eq(&self, other: &str) -> bool {
        self.as_str() == other
    }
}

impl<'a> PartialEq<&'a str> for GString {
    fn eq(&self, other: &&'a str) -> bool {
        self.as_str() == *other
    }
}

impl<'a> PartialEq<GString> for &'a str {
    fn eq(&self, other: &GString) -> bool {
        *self == other.as_str()
    }
}

impl PartialEq<String> for GString {
    fn eq(&self, other: &String) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<GString> for str {
    fn eq(&self, other: &GString) -> bool {
        self == other.as_str()
    }
}

impl PartialOrd<GString> for String {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(&String::from(other.as_str())))
    }
}

impl PartialOrd<String> for GString {
    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
        Some(self.as_str().cmp(other.as_str()))
    }
}

impl PartialOrd<GString> for str {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(&other))
    }
}

impl PartialOrd<str> for GString {
    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
        Some(self.as_str().cmp(other))
    }
}

impl Eq for GString {}

impl AsRef<str> for GString {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl AsRef<OsStr> for GString {
    fn as_ref(&self) -> &OsStr {
        OsStr::new(self.as_str())
    }
}

impl Deref for GString {
    type Target = str;

    fn deref(&self) -> &str {
        self.as_str()
    }
}

impl From<GString> for String {
    #[inline]
    fn from(mut s: GString) -> Self {
        if let GString(Inner::Native(ref mut cstring)) = s {
            if let Ok(s) = cstring
                .take()
                .expect("Native shouldn't be empty")
                .into_string()
            {
                return s;
            }
        }
        String::from(s.as_str())
    }
}

impl From<GString> for Box<str> {
    #[inline]
    fn from(s: GString) -> Self {
        let st: String = s.into();
        st.into_boxed_str()
    }
}

impl From<String> for GString {
    #[inline]
    fn from(s: String) -> Self {
        s.into_bytes().into()
    }
}

impl From<Box<str>> for GString {
    #[inline]
    fn from(s: Box<str>) -> Self {
        s.as_bytes().to_vec().into()
    }
}

impl<'a> From<&'a str> for GString {
    #[inline]
    fn from(s: &'a str) -> Self {
        s.as_bytes().to_vec().into()
    }
}

impl From<Vec<u8>> for GString {
    #[inline]
    fn from(s: Vec<u8>) -> Self {
        let cstring = CString::new(s).expect("CString::new failed");
        cstring.into()
    }
}

impl From<CString> for GString {
    #[inline]
    fn from(s: CString) -> Self {
        GString(Inner::Native(Some(s)))
    }
}

impl<'a> From<&'a CStr> for GString {
    #[inline]
    fn from(c: &'a CStr) -> Self {
        CString::from(c).into()
    }
}

#[doc(hidden)]
impl FromGlibPtrFull<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *const c_char) -> Self {
        GString::new(ptr as *mut _)
    }
}

#[doc(hidden)]
impl FromGlibPtrFull<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut u8) -> Self {
        GString::new(ptr as *mut _)
    }
}

#[doc(hidden)]
impl FromGlibPtrFull<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut i8) -> Self {
        GString::new(ptr as *mut _)
    }
}

#[doc(hidden)]
impl FromGlibPtrNone<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *const c_char) -> Self {
        let cstr = CStr::from_ptr(ptr);
        cstr.into()
    }
}

#[doc(hidden)]
impl FromGlibPtrNone<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut u8) -> Self {
        let cstr = CStr::from_ptr(ptr as *mut _);
        cstr.into()
    }
}

#[doc(hidden)]
impl FromGlibPtrNone<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut i8) -> Self {
        let cstr = CStr::from_ptr(ptr as *mut _);
        cstr.into()
    }
}

#[doc(hidden)]
impl FromGlibPtrBorrow<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *const c_char) -> Borrowed<Self> {
        GString::new_borrowed(ptr)
    }
}

#[doc(hidden)]
impl FromGlibPtrBorrow<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut u8) -> Borrowed<Self> {
        GString::new_borrowed(ptr as *const c_char)
    }
}

#[doc(hidden)]
impl FromGlibPtrBorrow<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut i8) -> Borrowed<Self> {
        GString::new_borrowed(ptr as *const c_char)
    }
}

#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *const c_char> for GString {
    type Storage = &'a Self;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
        Stash(self.as_ptr() as *const _, self)
    }

    #[inline]
    fn to_glib_full(&self) -> *const c_char {
        unsafe {
            glib_sys::g_strndup(self.as_ptr() as *const c_char, self.len() as libc::size_t)
                as *const c_char
        }
    }
}

#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *mut c_char> for GString {
    type Storage = &'a Self;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
        Stash(self.as_ptr() as *mut _, self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut c_char {
        unsafe {
            glib_sys::g_strndup(self.as_ptr() as *const c_char, self.len() as libc::size_t)
                as *mut c_char
        }
    }
}

impl GlibPtrDefault for GString {
    type GlibType = *const c_char;
}

impl StaticType for GString {
    fn static_type() -> Type {
        String::static_type()
    }
}

impl StaticType for Vec<GString> {
    fn static_type() -> Type {
        unsafe { from_glib(glib_sys::g_strv_get_type()) }
    }
}

impl<'a> FromValueOptional<'a> for GString {
    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
        let val = value.to_glib_none().0;
        if val.is_null() {
            None
        } else {
            let ptr = gobject_sys::g_value_dup_string(val);
            Some(GString::new(ptr))
        }
    }
}

impl SetValue for GString {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl SetValueOptional for GString {
    unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
        gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl_from_glib_container_as_vec_string!(GString, *const c_char);
impl_from_glib_container_as_vec_string!(GString, *mut c_char);

#[cfg(test)]
#[allow(clippy::blacklisted_name)]
mod tests {
    use glib_sys;
    use gstring::GString;
    use std::ffi::CString;

    #[test]
    fn test_gstring() {
        let data = CString::new("foo").unwrap();
        let ptr = data.as_ptr();

        unsafe {
            let ptr_copy = glib_sys::g_strdup(ptr);
            let gstring = GString::new(ptr_copy);
            assert_eq!(gstring.as_str(), "foo");
            let foo: Box<str> = gstring.into();
            assert_eq!(foo.as_ref(), "foo");
        }
    }

    #[test]
    fn test_owned_glib_string() {
        let data = CString::new("foo").unwrap();
        let ptr = data.as_ptr();
        unsafe {
            let ptr_copy = glib_sys::g_strdup(ptr);
            let gstr = GString::new(ptr_copy);
            assert_eq!(gstr, "foo");
        }
    }

    #[test]
    fn test_gstring_from_str() {
        let gstring: GString = "foo".into();
        assert_eq!(gstring.as_str(), "foo");
        let foo: Box<str> = gstring.into();
        assert_eq!(foo.as_ref(), "foo");
    }

    #[test]
    fn test_gstring_from_cstring() {
        let cstr = CString::new("foo").unwrap();
        let gstring = GString::from(cstr);
        assert_eq!(gstring.as_str(), "foo");
        let foo: Box<str> = gstring.into();
        assert_eq!(foo.as_ref(), "foo");
    }

    #[test]
    fn test_string_from_gstring() {
        let cstr = CString::new("foo").unwrap();
        let gstring = GString::from(cstr);
        assert_eq!(gstring.as_str(), "foo");
        let s = String::from(gstring);
        assert_eq!(s, "foo");
    }

    #[test]
    fn test_vec_u8_to_gstring() {
        let v: &[u8] = b"foo";
        let s: GString = Vec::from(v).into();
        assert_eq!(s.as_str(), "foo");
    }

    #[test]
    fn test_hashmap() {
        use std::collections::HashMap;

        let cstr = CString::new("foo").unwrap();
        let gstring = GString::from(cstr);
        assert_eq!(gstring.as_str(), "foo");
        let mut h: HashMap<GString, i32> = HashMap::new();
        h.insert(gstring, 42);
        let gstring: GString = "foo".into();
        assert!(h.contains_key(&gstring));
    }
}
<|endoftext|>


<commit_before>#![crate_name = "hiredis"]
#![crate_type = "lib"]
#![feature(globs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]

extern crate libc;

use std::mem::transmute;

pub mod api;

pub struct Reply {
    head:  bool,
    reply: *const api::Reply
}

pub enum ReplyCode {
    String = 1,
    Array,
    Integer,
    Nil,
    Status,
    Error,
    Unknown
}

impl Reply {
    /**
     * Creates a new Reply wrapper.
     *
     * This wraps an already existing Reply returned from hiredis, it will
     * automatically free the data when the reply goes out of scope. Note that
     * this method cannot be invoked outside of the crate.
     */
    fn new(reply: *const api::Reply) -> Reply {
        Reply {
            head:  true,
            reply: reply
        }
    }

    /**
     * Redis replies with the type of data being sent, this method allows
     * peaking into it.
     *
     * TODO: Create a nicer wrapper enum that encodes the data directly with
     * Vectors and so on.
     */
    pub fn typename(&self) -> uint {
        unsafe {
            //match (*self.reply)._type {
            //    1 => String,
            //    2 => Array,
            //    3 => Integer,
            //    4 => Nil,
            //    5 => Status,
            //    6 => Error,
            //    v => {
            //        println!("Unknown Error: {}", v);
            //        Unknown
            //    }
            //}
        }

        unsafe { (*self.reply)._type as uint }
    }

    pub fn string<'r>(&'r self) -> Option<&'r [u8]> {
        None
        //match self.typename() {
        //    String => {
        //        unsafe {
        //            let data = std::c_vec::CVec::new(
        //                (*self.reply)._str as *mut u8,
        //                (*self.reply).len as uint
        //            ).as_mut_slice() as *mut [u8];

        //            Some(&*data)
        //        }
        //    }

        //    _ => {
        //        None
        //    }
        //}
    }
}

impl Drop for Reply {
    fn drop(&mut self) {
        unsafe {
            /* When Redis returns a Reply object, we wrap it in our own Reply
             * object. However, if redis returns an array, the Reply object
             * contains an array of sub Reply objects. These get wrapped too,
             * but should not be freed, as freeing the head object frees the
             * children too. This check prevents us accidentally freeing replies
             * that shouldn't be freed.
             */
            if self.head {
                api::freeReplyObject(transmute(self.reply))
            }
        }
    }
}

pub struct Redis {
    context: *const api::Context
}

impl Redis {
    /**
     * Creates a new connection to a Redis instance.
     *
     * TODO: Deal with the other redisConnect* variants, not yet sure how to
     * design this API.
     */
    pub fn new(ip: &str, port: i32) -> Redis {
        unsafe {
            Redis {
                context: api::redisConnect(
                    ip.to_c_str().as_ptr(),
                    port
                )
            }
        }
    }

    /**
     * Sends a single command to be executed, and returns the reply immediately.
     * If further replies are expected the `receive` function exists to expect
     * them. This function doesn't handle complex spaces in messages, and so the
     * `execf` function exists and uses hiredis's formatting instead.
     *
     * TODO: Move to IoResult using context.err
     */
    pub fn command(&self, command: &str) -> Option<Reply> {
        command.with_c_str(|v| {
            unsafe {
                /* This is the library call, returns (void*)0 on failure. */
                let result = api::redisCommand(self.context, v);

                /* Fail if the command errored for some reason. */
                if result == 0 as *const ::libc::c_void {
                    return None;
                }

                /* Otherwise cast the pointer to the actual struct type being
                 * returned and store it to be returned. */
                Some(Reply::new(result as *const api::Reply))
            }
        })
    }

    /**
     * Appends a command to the output buffer, allowing for pipelining.
     *
     * TODO: This needs to return a status code.
     */
    pub fn append_command(&self, command: &str) {
        command.with_c_str(|v| {
            unsafe {
                api::redisAppendCommand(self.context, v);
            }
        });
    }

    /**
     * Attempts to read a message from the input buffer. Blocking in this
     * context depends on how the connection was created.
     */
    pub fn receive(&self) -> Option<Reply> {
        unsafe {
            let reply: Reply = std::mem::uninitialized();
            let result       = api::redisGetReply(self.context, transmute(&reply));

            Some(reply)
        }
    }
}

impl Drop for Redis {
    /**
     * When a Redis instance goes out of scope, the connection needs to be
     * closed. Redis has a function for this that both closes the connection and
     * frees any resources used.
     */
    fn drop(&mut self) {
        unsafe {
            api::redisFree(self.context)
        }
    }
}
<commit_msg>Revert to Basic<commit_after>#![crate_name = "hiredis"]
#![crate_type = "lib"]
#![feature(globs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]

extern crate libc;

use std::mem::transmute;

pub mod api;

pub struct Reply {
    head:  bool,
    reply: *const api::Reply
}

pub enum ReplyCode {
    String = 1,
    Array,
    Integer,
    Nil,
    Status,
    Error,
    Unknown
}

impl Reply {
    /**
     * Creates a new Reply wrapper.
     *
     * This wraps an already existing Reply returned from hiredis, it will
     * automatically free the data when the reply goes out of scope. Note that
     * this method cannot be invoked outside of the crate.
     */
    fn new(reply: *const api::Reply) -> Reply {
        Reply {
            head:  true,
            reply: reply
        }
    }

    /**
     * Redis replies with the type of data being sent, this method allows
     * peaking into it.
     *
     * TODO: Create a nicer wrapper enum that encodes the data directly with
     * Vectors and so on.
     */
    pub fn typename(&self) -> ReplyCode {
        unsafe {
            match (*self.reply)._type {
                1 => String,
                2 => Array,
                3 => Integer,
                4 => Nil,
                5 => Status,
                6 => Error,
                _ => Unknown
            }
        }
    }

    pub fn string<'r>(&'r self) -> Option<&'r [u8]> {
        match self.typename() {
            String => {
                unsafe {
                    let data = std::c_vec::CVec::new(
                        (*self.reply)._str as *mut u8,
                        (*self.reply).len as uint
                    ).as_mut_slice() as *mut [u8];

                    Some(&*data)
                }
            }

            _ => {
                None
            }
        }
    }
}

impl Drop for Reply {
    fn drop(&mut self) {
        unsafe {
            /* When Redis returns a Reply object, we wrap it in our own Reply
             * object. However, if redis returns an array, the Reply object
             * contains an array of sub Reply objects. These get wrapped too,
             * but should not be freed, as freeing the head object frees the
             * children too. This check prevents us accidentally freeing replies
             * that shouldn't be freed.
             */
            if self.head {
                api::freeReplyObject(transmute(self.reply))
            }
        }
    }
}

pub struct Redis {
    context: *const api::Context
}

impl Redis {
    /**
     * Creates a new connection to a Redis instance.
     *
     * TODO: Deal with the other redisConnect* variants, not yet sure how to
     * design this API.
     */
    pub fn new(ip: &str, port: i32) -> Redis {
        unsafe {
            Redis {
                context: api::redisConnect(
                    ip.to_c_str().as_ptr(),
                    port
                )
            }
        }
    }

    /**
     * Sends a single command to be executed, and returns the reply immediately.
     * If further replies are expected the `receive` function exists to expect
     * them. This function doesn't handle complex spaces in messages, and so the
     * `execf` function exists and uses hiredis's formatting instead.
     *
     * TODO: Move to IoResult using context.err
     */
    pub fn command(&self, command: &str) -> Option<Reply> {
        command.with_c_str(|v| {
            unsafe {
                /* This is the library call, returns (void*)0 on failure. */
                let result = api::redisCommand(self.context, v);

                /* Fail if the command errored for some reason. */
                if result == 0 as *const ::libc::c_void {
                    return None;
                }

                /* Otherwise cast the pointer to the actual struct type being
                 * returned and store it to be returned. */
                Some(Reply::new(result as *const api::Reply))
            }
        })
    }

    /**
     * Appends a command to the output buffer, allowing for pipelining.
     *
     * TODO: This needs to return a status code.
     */
    pub fn append_command(&self, command: &str) {
        command.with_c_str(|v| {
            unsafe {
                api::redisAppendCommand(self.context, v);
            }
        });
    }

    /**
     * Attempts to read a message from the input buffer. Blocking in this
     * context depends on how the connection was created.
     */
    pub fn receive(&self) -> Option<Reply> {
        unsafe {
            let reply: Reply = std::mem::uninitialized();
            let result       = api::redisGetReply(self.context, transmute(&reply));

            Some(reply)
        }
    }
}

impl Drop for Redis {
    /**
     * When a Redis instance goes out of scope, the connection needs to be
     * closed. Redis has a function for this that both closes the connection and
     * frees any resources used.
     */
    fn drop(&mut self) {
        unsafe {
            api::redisFree(self.context)
        }
    }
}
<|endoftext|>


<commit_before>use ffi::{pk11, sec};
use std::{ptr, mem};

pub enum Mode
{
    Encrypt,
    Decrypt,
}

impl Mode
{
    fn to_ffi(&self) -> pk11::CK_ATTRIBUTE_TYPE
    {
        match *self
        {
            Encrypt => pk11::CKA_ENCRYPT,
            Decrypt => pk11::CKA_DECRYPT,
        }
    }
}

#[allow(non_camel_case_types)]
pub enum Type
{
    AES_128_ECB,
    AES_128_CBC,
}

impl Type
{
    fn to_ffi(&self, pad: bool) -> Option<pk11::CK_MECHANISM_TYPE>
    {
        match (*self, pad)
        {
            (AES_128_ECB, false) => Some(pk11::CKM_AES_ECB),
            (AES_128_CBC, false) => Some(pk11::CKM_AES_CBC),
            (AES_128_CBC, true) => Some(pk11::CKM_AES_CBC_PAD),
            _ => None,
        }
    }
}

pub struct Crypter
{
    mechanism: pk11::CK_MECHANISM_TYPE,
    context: Option<*mut pk11::PK11Context>,
}

impl Crypter
{
    pub fn new(t: Type, pad: bool) -> Result<Crypter, String>
    {
        let mechanism = match t.to_ffi(pad)
        {
            Some(m) => m,
            None => return Err("Unsupported type/padding combination".to_string()),
        };
        Ok(Crypter
           {
               mechanism: mechanism,
               context: None,
           })
    }

    fn free_context(&mut self)
    {
        let context = mem::replace(&mut self.context, None);
        match context
        {
            None => {},
            Some(c) => unsafe { pk11::PK11_DestroyContext(c, true); },
        }
    }

    pub fn init(&mut self, mode: Mode, key: &[u8], iv: &[u8]) -> Result<(), String>
    {
        self.free_context();
        unsafe
        {
            let mut key_item = sec::SECItem::new(sec::siBuffer, key);
            let mut iv_item = sec::SECItem::new(sec::siBuffer, iv);

            let slot = try_ptr!(pk11::PK11_GetBestSlot(self.mechanism, ptr::null_mut()));
            let sym_key = try_ptr!(pk11::PK11_ImportSymKey(slot, self.mechanism, pk11::OriginUnwrap, mode.to_ffi(), &mut key_item, ptr::null_mut()));
            let sec_param = try_ptr!(pk11::PK11_ParamFromIV(self.mechanism, &mut iv_item));
            let context = try_ptr!(pk11::PK11_CreateContextBySymKey(self.mechanism, mode.to_ffi(), sym_key, sec_param));

            self.context = Some(context);

            sec::SECItem::free(sec_param);
            pk11::PK11_FreeSymKey(sym_key);
            pk11::PK11_FreeSlot(slot);

            Ok(())
        }
    }

    pub fn update(&mut self, in_buf: &[u8]) -> Result<Vec<u8>, String>
    {
        let context = match self.context
        {
            None => return Err("Not initialized".to_string()),
            Some(c) => c,
        };
        let mut out_buf = Vec::with_capacity(in_buf.len() + 128);
        unsafe
        {
            let mut outlen = 0;
            let status = pk11::PK11_CipherOp(context, out_buf.as_mut_ptr(), &mut outlen, out_buf.capacity() as ::libc::c_int, in_buf.as_ptr(), in_buf.len() as ::libc::c_int);
            try!(status.to_result());
            out_buf.set_len(outlen as uint);
        }
        Ok(out_buf)
    }

    pub fn final(&mut self) -> Result<Vec<u8>, String>
    {
        let context = match self.context
        {
            None => return Err("Not initialized".to_string()),
            Some(c) => c,
        };
        let mut out_buf = Vec::with_capacity(2048);
        unsafe
        {
            let mut outlen = 0;
            let status = pk11::PK11_DigestFinal(context, out_buf.as_mut_ptr(), &mut outlen, out_buf.capacity() as ::libc::c_uint);
            try!(status.to_result());
            out_buf.set_len(outlen as uint);
        }
        Ok(out_buf)
    }
}

impl Drop for Crypter
{
    fn drop(&mut self)
    {
        self.free_context();
    }
}
<commit_msg>Add key length information to symm::Type<commit_after>use ffi::{pk11, sec};
use std::{ptr, mem};

pub enum Mode
{
    Encrypt,
    Decrypt,
}

impl Mode
{
    fn to_ffi(&self) -> pk11::CK_ATTRIBUTE_TYPE
    {
        match *self
        {
            Encrypt => pk11::CKA_ENCRYPT,
            Decrypt => pk11::CKA_DECRYPT,
        }
    }
}

#[allow(non_camel_case_types)]
pub enum Type
{
    AES_128_ECB,
    AES_128_CBC,
}

impl Type
{
    fn to_ffi(&self, pad: bool) -> Option<pk11::CK_MECHANISM_TYPE>
    {
        match (*self, pad)
        {
            (AES_128_ECB, false) => Some(pk11::CKM_AES_ECB),
            (AES_128_CBC, false) => Some(pk11::CKM_AES_CBC),
            (AES_128_CBC, true) => Some(pk11::CKM_AES_CBC_PAD),
            _ => None,
        }
    }

    pub fn key_len(&self) -> uint
    {
        match *self
        {
            AES_128_ECB
            | AES_128_CBC => 16
        }
    }
}

pub struct Crypter
{
    pad: bool,
    typ: Type,
    context: Option<*mut pk11::PK11Context>,
}

impl Crypter
{
    pub fn new(t: Type, pad: bool) -> Result<Crypter, String>
    {
        match t.to_ffi(pad)
        {
            Some(..) => {},
            None => return Err("Unsupported type/padding combination".to_string()),
        };
        Ok(Crypter
           {
               pad: pad,
               typ: t,
               context: None,
           })
    }

    fn mech(&self) -> pk11::CK_MECHANISM_TYPE
    {
        self.typ.to_ffi(self.pad).unwrap()
    }

    fn free_context(&mut self)
    {
        let context = mem::replace(&mut self.context, None);
        match context
        {
            None => {},
            Some(c) => unsafe { pk11::PK11_DestroyContext(c, true); },
        }
    }

    pub fn init(&mut self, mode: Mode, key: &[u8], iv: &[u8]) -> Result<(), String>
    {
        self.free_context();

        let needed_key_len = self.typ.key_len();
        if key.len() != needed_key_len
        {
            return Err(format!("Invalid key length. Should be {} bytes.", needed_key_len));
        }

        unsafe
        {
            let mut key_item = sec::SECItem::new(sec::siBuffer, key);
            let mut iv_item = sec::SECItem::new(sec::siBuffer, iv);

            let slot = try_ptr!(pk11::PK11_GetBestSlot(self.mech(), ptr::null_mut()));
            let sym_key = try_ptr!(pk11::PK11_ImportSymKey(slot, self.mech(), pk11::OriginUnwrap, mode.to_ffi(), &mut key_item, ptr::null_mut()));
            let sec_param = try_ptr!(pk11::PK11_ParamFromIV(self.mech(), &mut iv_item));
            let context = try_ptr!(pk11::PK11_CreateContextBySymKey(self.mech(), mode.to_ffi(), sym_key, sec_param));

            self.context = Some(context);

            sec::SECItem::free(sec_param);
            pk11::PK11_FreeSymKey(sym_key);
            pk11::PK11_FreeSlot(slot);

            Ok(())
        }
    }

    pub fn update(&mut self, in_buf: &[u8]) -> Result<Vec<u8>, String>
    {
        let context = match self.context
        {
            None => return Err("Not initialized".to_string()),
            Some(c) => c,
        };
        let mut out_buf = Vec::with_capacity(in_buf.len() + 128);
        unsafe
        {
            let mut outlen = 0;
            let status = pk11::PK11_CipherOp(context, out_buf.as_mut_ptr(), &mut outlen, out_buf.capacity() as ::libc::c_int, in_buf.as_ptr(), in_buf.len() as ::libc::c_int);
            try!(status.to_result());
            out_buf.set_len(outlen as uint);
        }
        Ok(out_buf)
    }

    pub fn final(&mut self) -> Result<Vec<u8>, String>
    {
        let context = match self.context
        {
            None => return Err("Not initialized".to_string()),
            Some(c) => c,
        };
        let mut out_buf = Vec::with_capacity(2048);
        unsafe
        {
            let mut outlen = 0;
            let status = pk11::PK11_DigestFinal(context, out_buf.as_mut_ptr(), &mut outlen, out_buf.capacity() as ::libc::c_uint);
            try!(status.to_result());
            out_buf.set_len(outlen as uint);
        }
        Ok(out_buf)
    }
}

impl Drop for Crypter
{
    fn drop(&mut self)
    {
        self.free_context();
    }
}
<|endoftext|>


<commit_before>//! Reimplements core logic and types from `std::io` in an `alloc`-friendly
//! fashion.

use lib::*;

pub enum ErrorKind {
    InvalidData,
    WriteZero,
    Other,
    UnexpectedEof,
}

pub struct Error {
    repr: Repr,
}

enum Repr {
    Custom(ErrorKind, Box<dyn Display + Send + Sync>),
}

impl Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        match &self.repr {
            Repr::Custom(_, msg) => write!(fmt, "{}", msg),
        }
    }
}

impl Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        Display::fmt(self, fmt)
    }
}

impl serde::de::StdError for Error {}

impl Error {
    pub(crate) fn new<E>(kind: ErrorKind, error: E) -> Error
    where
        E: Display + Send + Sync + 'static,
    {
        Error {
            repr: Repr::Custom(kind, Box::new(error)),
        }
    }
}

pub type Result<T> = result::Result<T, Error>;

pub trait Write {
    fn write(&mut self, buf: &[u8]) -> Result<usize>;

    fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
        while !buf.is_empty() {
            match self.write(buf) {
                Ok(0) => {
                    return Err(Error::new(
                        ErrorKind::WriteZero,
                        "failed to write whole buffer",
                    ))
                }
                Ok(n) => buf = &buf[n..],
                Err(e) => return Err(e),
            }
        }
        Ok(())
    }

    fn flush(&mut self) -> Result<()>;
}

impl<W: Write> Write for &mut W {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        (*self).write(buf)
    }

    #[inline]
    fn write_all(&mut self, buf: &[u8]) -> Result<()> {
        (*self).write_all(buf)
    }

    #[inline]
    fn flush(&mut self) -> Result<()> {
        (*self).flush()
    }
}

impl Write for Vec<u8> {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.extend_from_slice(buf);
        Ok(buf.len())
    }

    #[inline]
    fn write_all(&mut self, buf: &[u8]) -> Result<()> {
        self.extend_from_slice(buf);
        Ok(())
    }

    #[inline]
    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}

pub trait Read {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
    fn bytes(self) -> Bytes<Self>
    where
        Self: Sized,
    {
        Bytes { inner: self }
    }
}

pub struct Bytes<R> {
    inner: R,
}

impl<R: Read> Iterator for Bytes<R> {
    type Item = Result<u8>;

    fn next(&mut self) -> Option<Result<u8>> {
        let mut byte = 0;
        match self.inner.read(slice::from_mut(&mut byte)) {
            Ok(0) => None,
            Ok(..) => Some(Ok(byte)),
            Err(e) => Some(Err(e)),
        }
    }
}
<commit_msg>Remove unused ErrorKind from io error repr<commit_after>//! Reimplements core logic and types from `std::io` in an `alloc`-friendly
//! fashion.

use lib::*;

pub enum ErrorKind {
    InvalidData,
    WriteZero,
    Other,
    UnexpectedEof,
}

pub struct Error {
    repr: Box<dyn Display + Send + Sync>,
}

impl Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        Display::fmt(self.repr.as_ref(), fmt)
    }
}

impl Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        Display::fmt(self, fmt)
    }
}

impl serde::de::StdError for Error {}

impl Error {
    pub(crate) fn new<E>(kind: ErrorKind, error: E) -> Error
    where
        E: Display + Send + Sync + 'static,
    {
        let _ = kind;
        Error {
            repr: Box::new(error),
        }
    }
}

pub type Result<T> = result::Result<T, Error>;

pub trait Write {
    fn write(&mut self, buf: &[u8]) -> Result<usize>;

    fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
        while !buf.is_empty() {
            match self.write(buf) {
                Ok(0) => {
                    return Err(Error::new(
                        ErrorKind::WriteZero,
                        "failed to write whole buffer",
                    ))
                }
                Ok(n) => buf = &buf[n..],
                Err(e) => return Err(e),
            }
        }
        Ok(())
    }

    fn flush(&mut self) -> Result<()>;
}

impl<W: Write> Write for &mut W {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        (*self).write(buf)
    }

    #[inline]
    fn write_all(&mut self, buf: &[u8]) -> Result<()> {
        (*self).write_all(buf)
    }

    #[inline]
    fn flush(&mut self) -> Result<()> {
        (*self).flush()
    }
}

impl Write for Vec<u8> {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.extend_from_slice(buf);
        Ok(buf.len())
    }

    #[inline]
    fn write_all(&mut self, buf: &[u8]) -> Result<()> {
        self.extend_from_slice(buf);
        Ok(())
    }

    #[inline]
    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}

pub trait Read {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
    fn bytes(self) -> Bytes<Self>
    where
        Self: Sized,
    {
        Bytes { inner: self }
    }
}

pub struct Bytes<R> {
    inner: R,
}

impl<R: Read> Iterator for Bytes<R> {
    type Item = Result<u8>;

    fn next(&mut self) -> Option<Result<u8>> {
        let mut byte = 0;
        match self.inner.read(slice::from_mut(&mut byte)) {
            Ok(0) => None,
            Ok(..) => Some(Ok(byte)),
            Err(e) => Some(Err(e)),
        }
    }
}
<|endoftext|>