<commit_before>
extern crate byteorder;

use byteorder::{LittleEndian, ReadBytesExt};
use std::fs::{File};
use std::io::*;
use std::path::{Path};

#[derive(Debug)]
pub struct Header {
    pub i : char,
    pub b : char,
    pub s : char,
    pub p : char
}

#[derive(Debug)]
pub struct DirEntry {
    pub offset: i32,
    pub length : i32
}

#[derive(Debug)]
pub struct Entity {
    pub entities: String
}

#[derive(Debug)]
pub struct Texture {
    pub name : String,
    pub flags : i32,
    pub contents : i32
}
#[derive(Debug)]
pub struct Plane {
    pub normal: [f32; 3],
    pub dist : f32
}

#[derive(Debug)]
pub struct BSP {
    pub header : Header,
    pub dir_entries : Vec<DirEntry>,
    pub entities : Entity,
    pub textures : Vec<Texture>,
    pub planes : Vec<Plane>,
}

fn read_header(cursor : &mut Cursor<Vec<u8>>) -> Result<Header> {
    let i = cursor.read_u8()? as char;
    let b = cursor.read_u8()? as char;
    let s = cursor.read_u8()? as char;
    let p = cursor.read_u8()? as char;
    Ok(Header {i : i, b : b, s : s, p : p})
}

fn read_version(cursor : &mut Cursor<Vec<u8>>) -> Result<i32> {
    cursor.read_i32::<LittleEndian>()
}

fn read_directories(cursor : &mut Cursor<Vec<u8>>) -> Result<Vec<DirEntry>> {
    let mut dir_entries = Vec::new();
    for _ in 0 .. 16 {
        let offset = cursor.read_i32::<LittleEndian>()?;
        let length = cursor.read_i32::<LittleEndian>()?;
        dir_entries.push( DirEntry { offset : offset, length : length });
    }
    Ok(dir_entries)
}

fn read_entities(cursor : &mut Cursor<Vec<u8>>, dir_entry : &DirEntry) -> Result<Entity> {
    let mut entities = Vec::with_capacity(dir_entry.length as usize);
    cursor.set_position(dir_entry.offset as u64);
    for _ in 0 .. dir_entry.length {
        let data = cursor.read_u8()?;
        entities.push(data);
    }

    let entities = String::from_utf8(entities).unwrap();

    Ok (Entity { entities : entities})
}

fn read_entry<F, T>(cursor : &mut Cursor<Vec<u8>>, dir_entry : &DirEntry, mut f : F ) -> Result<Vec<T>> where F : FnMut(&mut Cursor<Vec<u8>>) -> Result<T> {
    let mut entries = Vec::new();
    cursor.set_position(dir_entry.offset as u64);
    let end_pos = (dir_entry.offset + dir_entry.length) as u64;
    while cursor.position() < end_pos {
        let entry = f(cursor)?;
        entries.push(entry);
    }
    Ok (entries)
}

fn read_texture(cursor : &mut Cursor<Vec<u8>>) -> Result<Texture> {
    let mut texture = Vec::new();
    for _ in 0 .. 64 {
        let data = cursor.read_u8()?;
        if data != 0u8 {
            texture.push(data);
        }
    }
    let texture_name = String::from_utf8(texture).unwrap();
    let flags = cursor.read_i32::<LittleEndian>()?;
    let contents = cursor.read_i32::<LittleEndian>()?;
    Ok (Texture { name : texture_name, flags : flags, contents : contents })
}

fn read_plane(cursor : &mut Cursor<Vec<u8>>) -> Result<Plane> {
    let x = cursor.read_f32::<LittleEndian>()?;
    let y = cursor.read_f32::<LittleEndian>()?;
    let z = cursor.read_f32::<LittleEndian>()?;
    let dist = cursor.read_f32::<LittleEndian>()?;
    let plane = Plane { normal : [x,y,z], dist : dist };
    Ok (plane)
}

pub fn read_bsp(filename : &str) -> Result<BSP> {
    let path = Path::new(filename);
    let mut file = File::open(path).unwrap();
    let mut bytes = Vec::new();
    file.read_to_end(&mut bytes).unwrap();
    let mut cursor = Cursor::new(bytes);
    let header = read_header(&mut cursor)?;
    let version = read_version(&mut cursor)?;
    assert_eq!(version, 0x2e);
    let dir_entries = read_directories(&mut cursor)?;
    let entities = read_entities(&mut cursor, &dir_entries[0])?;
    let textures = read_entry(&mut cursor, &dir_entries[1], read_texture)?; //read_textures(&mut cursor, &dir_entries[1])?;
    let planes = read_entry(&mut cursor, &dir_entries[2], read_plane)?;
    Ok ({ BSP { header : header,
                dir_entries : dir_entries,
                entities : entities,
                textures : textures,
                planes : planes }})
}
<commit_msg>added most of the q3 bsp format<commit_after>extern crate byteorder;

use byteorder::{LittleEndian, ReadBytesExt};
use std::io::*;

#[derive(Debug)]
pub struct Header {
    pub i: char,
    pub b: char,
    pub s: char,
    pub p: char,
}

fn read_header(cursor: &mut Cursor<Vec<u8>>) -> Result<Header> {
    let i = cursor.read_u8()? as char;
    let b = cursor.read_u8()? as char;
    let s = cursor.read_u8()? as char;
    let p = cursor.read_u8()? as char;
    Ok(Header {
        i: i,
        b: b,
        s: s,
        p: p,
    })
}

fn read_version(cursor: &mut Cursor<Vec<u8>>) -> Result<i32> {
    cursor.read_i32::<LittleEndian>()
}

#[derive(Debug)]
pub struct DirEntry {
    pub offset: i32,
    pub length: i32,
}

fn read_directories(cursor: &mut Cursor<Vec<u8>>) -> Result<Vec<DirEntry>> {
    let mut dir_entries = Vec::new();
    for _ in 0..16 {
        let offset = cursor.read_i32::<LittleEndian>()?;
        let length = cursor.read_i32::<LittleEndian>()?;
        dir_entries.push(DirEntry {
            offset: offset,
            length: length,
        });
    }
    Ok(dir_entries)
}

#[derive(Debug)]
pub struct Entity {
    pub entities: String,
}

fn read_entities(cursor: &mut Cursor<Vec<u8>>, dir_entry: &DirEntry) -> Result<Entity> {
    let mut entities = Vec::with_capacity(dir_entry.length as usize);
    cursor.set_position(dir_entry.offset as u64);
    for _ in 0..dir_entry.length {
        let data = cursor.read_u8()?;
        entities.push(data);
    }
    let entities = String::from_utf8(entities).unwrap();
    Ok(Entity { entities: entities })
}

fn read_entry<F, T>(cursor: &mut Cursor<Vec<u8>>, dir_entry: &DirEntry, mut f: F) -> Result<Vec<T>>
    where F: FnMut(&mut Cursor<Vec<u8>>) -> Result<T>
{
    let mut entries = Vec::new();
    cursor.set_position(dir_entry.offset as u64);
    let end_pos = (dir_entry.offset + dir_entry.length) as u64;
    while cursor.position() < end_pos {
        let entry = f(cursor)?;
        entries.push(entry);
    }
    Ok(entries)
}

#[derive(Debug)]
pub struct Texture {
    pub name: String,
    pub flags: i32,
    pub contents: i32,
}

fn read_texture(cursor: &mut Cursor<Vec<u8>>) -> Result<Texture> {
    let mut texture = Vec::new();
    for _ in 0..64 {
        let data = cursor.read_u8()?;
        if data != 0u8 {
            texture.push(data);
        }
    }
    let texture_name = String::from_utf8(texture).unwrap();
    let flags = cursor.read_i32::<LittleEndian>()?;
    let contents = cursor.read_i32::<LittleEndian>()?;
    Ok(Texture {
        name: texture_name,
        flags: flags,
        contents: contents,
    })
}

#[derive(Debug)]
pub struct Plane {
    pub normal: [f32; 3],
    pub dist: f32,
}

fn read_plane(cursor: &mut Cursor<Vec<u8>>) -> Result<Plane> {
    let x = cursor.read_f32::<LittleEndian>()?;
    let y = cursor.read_f32::<LittleEndian>()?;
    let z = cursor.read_f32::<LittleEndian>()?;
    let dist = cursor.read_f32::<LittleEndian>()?;
    let plane = Plane {
        normal: [x, y, z],
        dist: dist,
    };
    Ok(plane)
}

#[derive(Debug)]
pub struct Node {
    pub plane: i32,
    pub children: [i32; 2],
    pub mins: [i32; 3],
    pub maxs: [i32; 3],
}

fn read_node(cursor: &mut Cursor<Vec<u8>>) -> Result<Node> {
    let plane = cursor.read_i32::<LittleEndian>()?;
    let children = [cursor.read_i32::<LittleEndian>()?, cursor.read_i32::<LittleEndian>()?];
    let mins = [cursor.read_i32::<LittleEndian>()?,
                cursor.read_i32::<LittleEndian>()?,
                cursor.read_i32::<LittleEndian>()?];
    let maxs = [cursor.read_i32::<LittleEndian>()?,
                cursor.read_i32::<LittleEndian>()?,
                cursor.read_i32::<LittleEndian>()?];
    let node = Node {
        plane: plane,
        children: children,
        mins: mins,
        maxs: maxs,
    };
    Ok(node)
}

#[derive(Debug)]
pub struct Leaf {
    pub cluster: i32,
    pub area: i32,
    pub mins: [i32; 3],
    pub maxs: [i32; 3],
    pub leaf_face: i32,
    pub num_leaf_faces: i32,
    pub leaf_brush: i32,
    pub num_leaf_brushes: i32,
}

fn read_leaf(cursor: &mut Cursor<Vec<u8>>) -> Result<Leaf> {
    let cluster = cursor.read_i32::<LittleEndian>()?;
    let area = cursor.read_i32::<LittleEndian>()?;
    let mins = [cursor.read_i32::<LittleEndian>()?,
                cursor.read_i32::<LittleEndian>()?,
                cursor.read_i32::<LittleEndian>()?];
    let maxs = [cursor.read_i32::<LittleEndian>()?,
                cursor.read_i32::<LittleEndian>()?,
                cursor.read_i32::<LittleEndian>()?];
    let leaf_face = cursor.read_i32::<LittleEndian>()?;
    let num_leaf_faces = cursor.read_i32::<LittleEndian>()?;
    let leaf_brush = cursor.read_i32::<LittleEndian>()?;
    let num_leaf_brushes = cursor.read_i32::<LittleEndian>()?;
    let leaf = Leaf {
        cluster: cluster,
        area: area,
        mins: mins,
        maxs: maxs,
        leaf_face: leaf_face,
        num_leaf_faces: num_leaf_faces,
        leaf_brush: leaf_brush,
        num_leaf_brushes: num_leaf_brushes,
    };
    Ok(leaf)
}

#[derive(Debug)]
pub struct LeafFace {
    pub face: i32,
}

fn read_leaf_face(cursor: &mut Cursor<Vec<u8>>) -> Result<LeafFace> {
    let face = cursor.read_i32::<LittleEndian>()?;
    let leaf_face = LeafFace { face: face };
    Ok(leaf_face)
}

#[derive(Debug)]
pub struct LeafBrush {
    pub brush: i32,
}

fn read_leaf_brush(cursor: &mut Cursor<Vec<u8>>) -> Result<LeafBrush> {
    let brush = cursor.read_i32::<LittleEndian>()?;
    let leaf_brush = LeafBrush { brush: brush };
    Ok(leaf_brush)
}

#[derive(Debug)]
pub struct Model {
    pub mins: [f32; 3],
    pub maxs: [f32; 3],
    pub face: i32,
    pub num_faces: i32,
    pub brush: i32,
    pub num_brushes: i32,
}

fn read_model(cursor: &mut Cursor<Vec<u8>>) -> Result<Model> {
    let mins = [cursor.read_f32::<LittleEndian>()?,
                cursor.read_f32::<LittleEndian>()?,
                cursor.read_f32::<LittleEndian>()?];
    let maxs = [cursor.read_f32::<LittleEndian>()?,
                cursor.read_f32::<LittleEndian>()?,
                cursor.read_f32::<LittleEndian>()?];
    let face = cursor.read_i32::<LittleEndian>()?;
    let num_faces = cursor.read_i32::<LittleEndian>()?;
    let brush = cursor.read_i32::<LittleEndian>()?;
    let num_brushes = cursor.read_i32::<LittleEndian>()?;
    let model = Model {
        mins: mins,
        maxs: maxs,
        face: face,
        num_faces: num_faces,
        brush: brush,
        num_brushes: num_brushes,
    };
    Ok(model)
}

#[derive(Debug)]
pub struct Brush {
    pub brush_side: i32,
    pub num_brush_sides: i32,
    pub texture: i32,
}

fn read_brush(cursor: &mut Cursor<Vec<u8>>) -> Result<Brush> {
    let brush_side = cursor.read_i32::<LittleEndian>()?;
    let num_brush_sides = cursor.read_i32::<LittleEndian>()?;
    let texture = cursor.read_i32::<LittleEndian>()?;
    let brush = Brush {
        brush_side: brush_side,
        num_brush_sides: num_brush_sides,
        texture: texture,
    };
    Ok(brush)
}

#[derive(Debug)]
pub struct BrushSide {
    pub plane: i32,
    pub texture: i32,
}

fn read_brush_side(cursor: &mut Cursor<Vec<u8>>) -> Result<BrushSide> {
    let plane = cursor.read_i32::<LittleEndian>()?;
    let texture = cursor.read_i32::<LittleEndian>()?;
    let brush_side = BrushSide {
        plane: plane,
        texture: texture,
    };
    Ok(brush_side)
}

#[derive(Debug)]
pub struct Vertex {
    pub position: [f32; 3],
    pub tex_coord1: [f32; 2],
    pub tex_coord2: [f32; 2],
    pub normal: [f32; 3],
    pub color: [u8; 4],
}

fn read_vertex(cursor: &mut Cursor<Vec<u8>>) -> Result<Vertex> {
    let position = [cursor.read_f32::<LittleEndian>()?,
                    cursor.read_f32::<LittleEndian>()?,
                    cursor.read_f32::<LittleEndian>()?];
    let tex_coord1 = [cursor.read_f32::<LittleEndian>()?, cursor.read_f32::<LittleEndian>()?];
    let tex_coord2 = [cursor.read_f32::<LittleEndian>()?, cursor.read_f32::<LittleEndian>()?];
    let normal = [cursor.read_f32::<LittleEndian>()?,
                  cursor.read_f32::<LittleEndian>()?,
                  cursor.read_f32::<LittleEndian>()?];
    let color = [cursor.read_u8()?, cursor.read_u8()?, cursor.read_u8()?, cursor.read_u8()?];
    let vertex = Vertex {
        position: position,
        tex_coord1: tex_coord1,
        tex_coord2: tex_coord2,
        normal: normal,
        color: color,
    };
    Ok(vertex)
}

#[derive(Debug)]
pub struct MeshVert {
    pub offset: i32,
}

fn read_mesh_vert(cursor: &mut Cursor<Vec<u8>>) -> Result<MeshVert> {
    let offset = cursor.read_i32::<LittleEndian>()?;
    let mesh_vert = MeshVert { offset: offset };
    Ok(mesh_vert)
}

#[derive(Debug)]
pub struct BSP {
    pub header: Header,
    pub dir_entries: Vec<DirEntry>,
    pub entities: Entity,
    pub textures: Vec<Texture>,
    pub planes: Vec<Plane>,
    pub nodes: Vec<Node>,
    pub leafs: Vec<Leaf>,
    pub leaf_faces: Vec<LeafFace>,
    pub leaf_brushes: Vec<LeafBrush>,
    pub models: Vec<Model>,
    pub brushes: Vec<Brush>,
    pub brush_sides: Vec<BrushSide>,
    pub vertexes: Vec<Vertex>,
    pub mesh_verts: Vec<MeshVert>,
}

pub fn read_bsp(bytes: Vec<u8>) -> Result<BSP> {
    let mut cursor = Cursor::new(bytes);
    let header = read_header(&mut cursor)?;
    let version = read_version(&mut cursor)?;
    assert_eq!(version, 0x2e);
    let dir_entries = read_directories(&mut cursor)?;
    let entities = read_entities(&mut cursor, &dir_entries[0])?;
    let textures = read_entry(&mut cursor, &dir_entries[1], read_texture)?;
    let planes = read_entry(&mut cursor, &dir_entries[2], read_plane)?;
    let nodes = read_entry(&mut cursor, &dir_entries[3], read_node)?;
    let leafs = read_entry(&mut cursor, &dir_entries[4], read_leaf)?;
    let leaf_faces = read_entry(&mut cursor, &dir_entries[5], read_leaf_face)?;
    let leaf_brushes = read_entry(&mut cursor, &dir_entries[6], read_leaf_brush)?;
    let models = read_entry(&mut cursor, &dir_entries[7], read_model)?;
    let brushes = read_entry(&mut cursor, &dir_entries[8], read_brush)?;
    let brush_sides = read_entry(&mut cursor, &dir_entries[9], read_brush_side)?;
    let vertexes = read_entry(&mut cursor, &dir_entries[10], read_vertex)?;
    let mesh_verts = read_entry(&mut cursor, &dir_entries[11], read_mesh_vert)?;
    Ok({
        BSP {
            header: header,
            dir_entries: dir_entries,
            entities: entities,
            textures: textures,
            planes: planes,
            nodes: nodes,
            leafs: leafs,
            leaf_faces: leaf_faces,
            leaf_brushes: leaf_brushes,
            models: models,
            brushes: brushes,
            brush_sides: brush_sides,
            vertexes: vertexes,
            mesh_verts: mesh_verts,
        }
    })
}
<|endoftext|>


<commit_before>//
// yaml.rs
// Nothing to see here yet
//

#![crate_id="yaml"]

use std::iter::Iterator;
use std::option::Option;

pub struct Scanner<'a> {
    reader: Box<Reader + 'a>,
}

impl <'a>Scanner<'a> {
    pub fn new<T: Reader + 'a>(reader: Box<T>) -> Scanner<'a> {
        Scanner { reader: reader }
    }
}

#[derive(PartialEq, Copy, Show)]
pub enum Token {
    Character,
    Other,
}

impl <'a>Iterator for Scanner<'a> {

    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        Option::Some(Token::Character)
    }
}

mod test {

    use std::io::MemReader;
    use std::vec;

    use super::{Scanner, Token};

    #[test]
    fn test_scanner() {
        let stream = "---";
        let mut reader = MemReader::new(stream.bytes().collect());
        let mut scanner = Scanner::new(Box::new(reader));
        for token in scanner.take(5) {
            assert!(token == Token::Character);
        }
    }
}
<commit_msg>Iterate over the reader<commit_after>//
// yaml.rs
// Nothing to see here yet
//

#![crate_id="yaml"]

use std::iter::Iterator;
use std::option::Option;

pub struct Scanner<'a> {
    reader: Box<Reader + 'a>,
    done: bool,
}

impl <'a>Scanner<'a> {
    pub fn new<T: Reader + 'a>(reader: Box<T>) -> Scanner<'a> {
        Scanner { reader: reader, done: false }
    }

    pub fn get_next_token(&mut self) -> Option<Token> {
        loop {
            match self.reader.read_byte() {
                Err(error) => {
                    self.done = true;
                    return Some(Token::Eof);
                },
                Ok(byte) => {
                    return Some(Token::Character);
                }
            }
        }
    }
}

#[derive(PartialEq, Copy, Show)]
pub enum Token {
    Character,
    Eof,
}

impl <'a>Iterator for Scanner<'a> {

    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        if self.done {
            return None;
        }
        self.get_next_token()
    }
}

mod test {

    use std::io::MemReader;
    use std::vec;

    use super::{Scanner, Token};

    #[test]
    fn test_scanner() {
        let stream = "---";
        let mut reader = MemReader::new(stream.bytes().collect());
        let mut scanner = Scanner::new(Box::new(reader));
        let tokens: Vec<Token> = scanner.collect();
        let expected = vec!(Token::Character, Token::Character, Token::Character, Token::Eof);
        assert!(tokens == expected);
    }
}
<|endoftext|>


<commit_before>/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

Metadata (such as doc comments) is allowed on each ref.

# Semantic

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.

Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.

# Example

Using the macro:

```rust
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access. On stable Rust, the macro may need to allocate each static on the heap.

*/

#![cfg_attr(feature="nightly", feature(const_fn, allow_internal_unstable, core_intrinsics))]

#![no_std]

#[cfg(not(feature="nightly"))]
pub mod lazy;

#[cfg(all(feature="nightly", not(feature="spin_no_std")))]
#[path="nightly_lazy.rs"]
pub mod lazy;

#[cfg(all(feature="nightly", feature="spin_no_std"))]
#[path="core_lazy.rs"]
pub mod lazy;

pub use core::ops::Deref as __Deref;

#[macro_export]
#[cfg_attr(feature="nightly", allow_internal_unstable)]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    (@$VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@MAKE TY, $VIS, $(#[$attr])*, $N);
        impl $crate::__Deref for $N {
            type Target = $T;
            #[allow(unsafe_code)]
            fn deref<'a>(&'a self) -> &'a $T {
                unsafe {
                    #[inline(always)]
                    fn __static_ref_initialize() -> $T { $e }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        __lazy_static_create!(LAZY, $T);
                        LAZY.get(__static_ref_initialize)
                    }
                    __stability()
                }
            }
        }
        lazy_static!($($t)*);
    };
    (@MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (@MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<commit_msg>Note in the docs that initialization cycles can lead to deadlocks<commit_after>/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

Metadata (such as doc comments) is allowed on each ref.

# Semantic

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object. Note that this can lead to deadlocks
if you have multiple lazy statics that depend on each other in their initialization.

Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.

# Example

Using the macro:

```rust
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access. On stable Rust, the macro may need to allocate each static on the heap.

*/

#![cfg_attr(feature="nightly", feature(const_fn, allow_internal_unstable, core_intrinsics))]

#![no_std]

#[cfg(not(feature="nightly"))]
pub mod lazy;

#[cfg(all(feature="nightly", not(feature="spin_no_std")))]
#[path="nightly_lazy.rs"]
pub mod lazy;

#[cfg(all(feature="nightly", feature="spin_no_std"))]
#[path="core_lazy.rs"]
pub mod lazy;

pub use core::ops::Deref as __Deref;

#[macro_export]
#[cfg_attr(feature="nightly", allow_internal_unstable)]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    (@$VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@MAKE TY, $VIS, $(#[$attr])*, $N);
        impl $crate::__Deref for $N {
            type Target = $T;
            #[allow(unsafe_code)]
            fn deref<'a>(&'a self) -> &'a $T {
                unsafe {
                    #[inline(always)]
                    fn __static_ref_initialize() -> $T { $e }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        __lazy_static_create!(LAZY, $T);
                        LAZY.get(__static_ref_initialize)
                    }
                    __stability()
                }
            }
        }
        lazy_static!($($t)*);
    };
    (@MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (@MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<|endoftext|>


<commit_before>#![feature(str_char)]

pub mod atom;
pub mod sexp;
pub mod parser;
pub mod token;

pub use atom::Atom;
pub use sexp::Sexp;
<commit_msg>Add ToSexp trait<commit_after>#![feature(str_char)]

pub mod atom;
pub mod sexp;
pub mod parser;
pub mod token;

pub use atom::Atom;
pub use sexp::Sexp;

/// Convert self into a S-expression.
pub trait ToSexp {
    fn to_sexp(&self) -> Sexp;
}
<|endoftext|>


<commit_before>use std::process::Command;
use std::fs;
use std::convert::AsRef;
use std::path::Path;
mod lsb_release;

///A list of supported operating system types
#[derive(Debug)]
#[derive(PartialEq)]
pub enum OSType {
    Unknown,
    Redhat,
    OSX,
    Ubuntu,
    Debian,
    Windows
}

fn file_exists<P: AsRef<Path>>(path: P) -> bool {
    let metadata = fs::metadata(path);

    match metadata {
        Ok(md) => md.is_dir() || md.is_file(),
        Err(_) => false
    }
}

fn is_windows() -> bool {
    if cfg!(target_os="windows") {
        return true;
    } else {
        return false;
    }
}

fn is_os_x() -> bool {
    match Command::new("sw_vers").output() {
        Ok(output) => output.status.success(),
        Err(_) => false
    }
}

fn lsb_release() -> OSType {
    match lsb_release::retrieve() {
        Some(release) => {
            if release.distro == Some("Ubuntu".to_string()) {
                OSType::Ubuntu
            }
            else if release.distro == Some("Debian".to_string()) {
                OSType::Debian
            }
            else {
                OSType::Unknown
            }
        },
        None => OSType::Unknown
    }

}

///Returns the current operating system type
///
///#Example
///
///```
///use os_type;
///let os = os_type::current_platform();
///```
pub fn current_platform() -> OSType {
    if is_os_x() {
        OSType::OSX
    }
    else if is_windows() {
        OSType::Windows
    }
    else if lsb_release::is_available() {
        lsb_release()
    }
    else if file_exists("/etc/redhat-release") || file_exists("/etc/centos-release") {
        OSType::Redhat
    }
    else {
        OSType::Unknown
    }
}
<commit_msg>include windows_ver module<commit_after>use std::process::Command;
use std::fs;
use std::convert::AsRef;
use std::path::Path;
mod lsb_release;
mod windows_ver;

///A list of supported operating system types
#[derive(Debug)]
#[derive(PartialEq)]
pub enum OSType {
    Unknown,
    Redhat,
    OSX,
    Ubuntu,
    Debian,
    Windows
}

fn file_exists<P: AsRef<Path>>(path: P) -> bool {
    let metadata = fs::metadata(path);

    match metadata {
        Ok(md) => md.is_dir() || md.is_file(),
        Err(_) => false
    }
}

fn is_windows() -> bool {
    if cfg!(target_os="windows") {
        return true;
    } else {
        return false;
    }
}

fn is_os_x() -> bool {
    match Command::new("sw_vers").output() {
        Ok(output) => output.status.success(),
        Err(_) => false
    }
}

fn lsb_release() -> OSType {
    match lsb_release::retrieve() {
        Some(release) => {
            if release.distro == Some("Ubuntu".to_string()) {
                OSType::Ubuntu
            }
            else if release.distro == Some("Debian".to_string()) {
                OSType::Debian
            }
            else {
                OSType::Unknown
            }
        },
        None => OSType::Unknown
    }

}

///Returns the current operating system type
///
///#Example
///
///```
///use os_type;
///let os = os_type::current_platform();
///```
pub fn current_platform() -> OSType {
    if is_os_x() {
        OSType::OSX
    }
    else if is_windows() {
        OSType::Windows
    }
    else if lsb_release::is_available() {
        lsb_release()
    }
    else if file_exists("/etc/redhat-release") || file_exists("/etc/centos-release") {
        OSType::Redhat
    }
    else {
        OSType::Unknown
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(test, feature(test))]

extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt};

use std::collections::HashMap;
use std::io::{self, Read, Seek, SeekFrom, BufRead, BufReader};
use std::fs::File;
use std::cell::RefCell;

pub mod errors;
use errors::ReadError;

pub struct BigArchive<T: Read + Seek> {
    pub format: Format,
    pub size: u32,

    _buf_reader: RefCell<BufReader<T>>,
    _entries: HashMap<String, BigEntry>,
}

impl BigArchive<File> {
    pub fn new_from_path(path: &str) -> Result<Self, ReadError> {
        let f = try!(File::open(&path));
        let br = BufReader::new(f);
        Ok(try!(BigArchive::new(br)))
    }
}

impl<T: Read + Seek> BigArchive<T> {
    pub fn new(mut data: BufReader<T>) -> Result<Self, ReadError> {
        let format = try!(read_format(&mut data));

        if let Format::Unknown(bytes) = format {
            return Err(ReadError::UnknownArchiveFormat(bytes));
        }

        let size = try!(data.read_u32::<BigEndian>());
        let num_entries = try!(data.read_u32::<BigEndian>());

        // Offset to the first entry, I think.
        let _ = data.read_u32::<BigEndian>();

        let mut entries = HashMap::new();

        for i in 0..num_entries {
            let offset = try!(data.read_u32::<BigEndian>());
            let size = try!(data.read_u32::<BigEndian>());

            let mut buf = Vec::new();
            data.read_until(b'\0', &mut buf)
                .expect(&format!("Failed to read name for entry {}", i + 1));

            // Remove the trailing \0
            let name = String::from_utf8_lossy(&buf[..buf.len() - 1]);

            let entry = BigEntry {
                offset: offset,
                size: size,
                name: name.to_string(),
            };

            entries.insert(entry.name.clone(), entry);
        }

        Ok(BigArchive {
            format: format,
            size: size,
            _buf_reader: RefCell::new(data),
            _entries: entries,
        })
    }

    /// TODO: Don't return owned data, instead give the caller back a slice
    pub fn read_entry(&self, entry_name: &str) -> Option<Vec<u8>> {
        if let Some(entry) = self._entries.get(entry_name) {
            let br = &mut self._buf_reader.borrow_mut();

            if br.seek(SeekFrom::Start((*entry).offset as u64)).is_err() {
                return None;
            }

            let mut buf = vec![0; entry.size as usize];
            if br.read_exact(&mut buf).is_err() {
                return None;
            }

            Some(buf)
        } else {
            None
        }
    }

    pub fn contains(&self, entry_name: &str) -> bool {
        self._entries.contains_key(entry_name)
    }

    pub fn get_entry(&self, entry_name: &str) -> Option<&BigEntry> {
        self._entries.get(entry_name)
    }

    pub fn get_entry_mut(&mut self, entry_name: &str) -> Option<&mut BigEntry> {
        self._entries.get_mut(entry_name)
    }

    pub fn get_all_entry_names(&self) -> std::collections::hash_map::Keys<String, BigEntry> {
        self._entries.keys()
    }
}

#[derive(Debug)]
pub struct BigEntry {
    pub offset: u32,
    pub size: u32,
    pub name: String,
}

#[derive(Debug, PartialEq)]
pub enum Format {
    Unknown(Vec<u8>),
    Big4,
    BigF,
}

impl<'a> From<&'a mut BufRead> for Format {
    fn from(data: &'a mut BufRead) -> Self {
        let mut buf = [0; 4];
        let _ = data.read_exact(&mut buf);
        match &buf {
            b"BIG4" => Format::Big4,
            b"BIGF" => Format::BigF,
            _ => Format::Unknown(Vec::from(&buf[..])),
        }
    }
}

fn read_format(data: &mut BufRead) -> Result<Format, io::Error> {
    Ok(Format::from(data))
}

#[cfg(test)]
mod tests_bytes {
    const TEST_BYTES: &'static [u8] = include_bytes!("../test.big");
    use std::io::{BufReader, Cursor};
    use super::{Format, BigArchive};

    #[test]
    fn is_big4() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        assert_eq!(archive.format, Format::Big4);
    }

    #[test]
    fn has_two_entries() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        assert_eq!(archive.get_all_entry_names().len(), 2);
    }

    #[test]
    fn contains_art_slash_image_dot_txt() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        assert!(archive.contains("art/image.txt"));
    }

    #[test]
    fn contains_data_slash_test_dot_ini() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        assert!(archive.contains("data/test.ini"));
    }

    #[test]
    fn read_entry_art_slash_image_dot_txt() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        let data = archive.read_entry("art/image.txt").unwrap();
        assert_eq!(data, vec![98, 108, 97, 98, 108, 98, 97]);
    }

    #[test]
    fn read_entry_data_slash_test_dot_ini() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        let data = archive.read_entry("data/test.ini").unwrap();
        assert_eq!(data,
                   vec![84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 105, 109, 112, 108,
                        101, 32, 116, 101, 115, 116, 32, 102, 105, 108, 101]);
    }

    mod benches {
        extern crate test;
        use self::test::Bencher;

        #[bench]
        fn is_big4(b: &mut Bencher) {
            b.iter(|| super::is_big4());
        }

        #[bench]
        fn has_two_entries(b: &mut Bencher) {
            b.iter(|| super::has_two_entries());
        }

        #[bench]
        fn contains_art_slash_image_dot_txt(b: &mut Bencher) {
            b.iter(|| super::contains_art_slash_image_dot_txt());
        }

        #[bench]
        fn contains_data_slash_test_dot_ini(b: &mut Bencher) {
            b.iter(|| super::contains_data_slash_test_dot_ini());
        }

        #[bench]
        fn read_entry_art_slash_image_dot_txt(b: &mut Bencher) {
            b.iter(|| super::read_entry_art_slash_image_dot_txt());
        }

        #[bench]
        fn read_entry_data_slash_test_dot_ini(b: &mut Bencher) {
            b.iter(|| super::read_entry_data_slash_test_dot_ini());
        }
    }
}

#[cfg(test)]
mod tests_file {
    use super::{Format, BigArchive};
    const ARCHIVE_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/test.big");

    #[test]
    fn is_big4() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        assert_eq!(archive.format, Format::Big4);
    }

    #[test]
    fn has_two_entries() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        assert_eq!(archive.get_all_entry_names().len(), 2);
    }

    #[test]
    fn contains_art_slash_image_dot_txt() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        assert!(archive.contains("art/image.txt"));
    }

    #[test]
    fn contains_data_slash_test_dot_ini() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        assert!(archive.contains("data/test.ini"));
    }

    #[test]
    fn read_entry_art_slash_image_dot_txt() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        let data = archive.read_entry("art/image.txt").unwrap();
        assert_eq!(data, vec![98, 108, 97, 98, 108, 98, 97]);
    }

    #[test]
    fn read_entry_data_slash_test_dot_ini() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        let data = archive.read_entry("data/test.ini").unwrap();
        assert_eq!(data,
                   vec![84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 105, 109, 112, 108,
                        101, 32, 116, 101, 115, 116, 32, 102, 105, 108, 101]);
    }

    mod benches {
        extern crate test;
        use self::test::Bencher;

        #[bench]
        fn is_big4(b: &mut Bencher) {
            b.iter(|| super::is_big4());
        }

        #[bench]
        fn has_two_entries(b: &mut Bencher) {
            b.iter(|| super::has_two_entries());
        }

        #[bench]
        fn contains_art_slash_image_dot_txt(b: &mut Bencher) {
            b.iter(|| super::contains_art_slash_image_dot_txt());
        }

        #[bench]
        fn contains_data_slash_test_dot_ini(b: &mut Bencher) {
            b.iter(|| super::contains_data_slash_test_dot_ini());
        }

        #[bench]
        fn read_entry_art_slash_image_dot_txt(b: &mut Bencher) {
            b.iter(|| super::read_entry_art_slash_image_dot_txt());
        }

        #[bench]
        fn read_entry_data_slash_test_dot_ini(b: &mut Bencher) {
            b.iter(|| super::read_entry_data_slash_test_dot_ini());
        }
    }
}
<commit_msg>Read archive size correctly (it is LittleEndian)<commit_after>#![cfg_attr(test, feature(test))]

extern crate byteorder;
use byteorder::{LittleEndian, BigEndian, ReadBytesExt};

use std::collections::HashMap;
use std::io::{self, Read, Seek, SeekFrom, BufRead, BufReader};
use std::fs::File;
use std::cell::RefCell;

pub mod errors;
use errors::ReadError;

pub struct BigArchive<T: Read + Seek> {
    pub format: Format,
    pub size: u32,

    _buf_reader: RefCell<BufReader<T>>,
    _entries: HashMap<String, BigEntry>,
}

impl BigArchive<File> {
    pub fn new_from_path(path: &str) -> Result<Self, ReadError> {
        let f = try!(File::open(&path));
        let br = BufReader::new(f);
        Ok(try!(BigArchive::new(br)))
    }
}

impl<T: Read + Seek> BigArchive<T> {
    pub fn new(mut data: BufReader<T>) -> Result<Self, ReadError> {
        let format = try!(read_format(&mut data));

        if let Format::Unknown(bytes) = format {
            return Err(ReadError::UnknownArchiveFormat(bytes));
        }

        let size = try!(data.read_u32::<LittleEndian>());
        let num_entries = try!(data.read_u32::<BigEndian>());

        // Offset to the first entry, I think.
        let _ = data.read_u32::<BigEndian>();

        let mut entries = HashMap::new();

        for i in 0..num_entries {
            let offset = try!(data.read_u32::<BigEndian>());
            let size = try!(data.read_u32::<BigEndian>());

            let mut buf = Vec::new();
            data.read_until(b'\0', &mut buf)
                .expect(&format!("Failed to read name for entry {}", i + 1));

            // Remove the trailing \0
            let name = String::from_utf8_lossy(&buf[..buf.len() - 1]);

            let entry = BigEntry {
                offset: offset,
                size: size,
                name: name.to_string(),
            };

            entries.insert(entry.name.clone(), entry);
        }

        Ok(BigArchive {
            format: format,
            size: size,
            _buf_reader: RefCell::new(data),
            _entries: entries,
        })
    }

    /// TODO: Don't return owned data, instead give the caller back a slice
    pub fn read_entry(&self, entry_name: &str) -> Option<Vec<u8>> {
        if let Some(entry) = self._entries.get(entry_name) {
            let br = &mut self._buf_reader.borrow_mut();

            if br.seek(SeekFrom::Start((*entry).offset as u64)).is_err() {
                return None;
            }

            let mut buf = vec![0; entry.size as usize];
            if br.read_exact(&mut buf).is_err() {
                return None;
            }

            Some(buf)
        } else {
            None
        }
    }

    pub fn contains(&self, entry_name: &str) -> bool {
        self._entries.contains_key(entry_name)
    }

    pub fn get_entry(&self, entry_name: &str) -> Option<&BigEntry> {
        self._entries.get(entry_name)
    }

    pub fn get_entry_mut(&mut self, entry_name: &str) -> Option<&mut BigEntry> {
        self._entries.get_mut(entry_name)
    }

    pub fn get_all_entry_names(&self) -> std::collections::hash_map::Keys<String, BigEntry> {
        self._entries.keys()
    }
}

#[derive(Debug)]
pub struct BigEntry {
    pub offset: u32,
    pub size: u32,
    pub name: String,
}

#[derive(Debug, PartialEq)]
pub enum Format {
    Unknown(Vec<u8>),
    Big4,
    BigF,
}

impl<'a> From<&'a mut BufRead> for Format {
    fn from(data: &'a mut BufRead) -> Self {
        let mut buf = [0; 4];
        let _ = data.read_exact(&mut buf);
        match &buf {
            b"BIG4" => Format::Big4,
            b"BIGF" => Format::BigF,
            _ => Format::Unknown(Vec::from(&buf[..])),
        }
    }
}

fn read_format(data: &mut BufRead) -> Result<Format, io::Error> {
    Ok(Format::from(data))
}

#[cfg(test)]
mod tests_bytes {
    const TEST_BYTES: &'static [u8] = include_bytes!("../test.big");
    use std::io::{BufReader, Cursor};
    use super::{Format, BigArchive};

    #[test]
    fn is_big4() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        assert_eq!(archive.format, Format::Big4);
    }

    #[test]
    fn has_two_entries() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        assert_eq!(archive.get_all_entry_names().len(), 2);
    }

    #[test]
    fn contains_art_slash_image_dot_txt() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        assert!(archive.contains("art/image.txt"));
    }

    #[test]
    fn contains_data_slash_test_dot_ini() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        assert!(archive.contains("data/test.ini"));
    }

    #[test]
    fn read_entry_art_slash_image_dot_txt() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        let data = archive.read_entry("art/image.txt").unwrap();
        assert_eq!(data, vec![98, 108, 97, 98, 108, 98, 97]);
    }

    #[test]
    fn read_entry_data_slash_test_dot_ini() {
        let c = Cursor::new(TEST_BYTES);
        let br = BufReader::new(c);
        let archive = BigArchive::new(br).unwrap();
        let data = archive.read_entry("data/test.ini").unwrap();
        assert_eq!(data,
                   vec![84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 105, 109, 112, 108,
                        101, 32, 116, 101, 115, 116, 32, 102, 105, 108, 101]);
    }

    mod benches {
        extern crate test;
        use self::test::Bencher;

        #[bench]
        fn is_big4(b: &mut Bencher) {
            b.iter(|| super::is_big4());
        }

        #[bench]
        fn has_two_entries(b: &mut Bencher) {
            b.iter(|| super::has_two_entries());
        }

        #[bench]
        fn contains_art_slash_image_dot_txt(b: &mut Bencher) {
            b.iter(|| super::contains_art_slash_image_dot_txt());
        }

        #[bench]
        fn contains_data_slash_test_dot_ini(b: &mut Bencher) {
            b.iter(|| super::contains_data_slash_test_dot_ini());
        }

        #[bench]
        fn read_entry_art_slash_image_dot_txt(b: &mut Bencher) {
            b.iter(|| super::read_entry_art_slash_image_dot_txt());
        }

        #[bench]
        fn read_entry_data_slash_test_dot_ini(b: &mut Bencher) {
            b.iter(|| super::read_entry_data_slash_test_dot_ini());
        }
    }
}

#[cfg(test)]
mod tests_file {
    use super::{Format, BigArchive};
    const ARCHIVE_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/test.big");

    #[test]
    fn is_big4() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        assert_eq!(archive.format, Format::Big4);
    }

    #[test]
    fn has_two_entries() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        assert_eq!(archive.get_all_entry_names().len(), 2);
    }

    #[test]
    fn contains_art_slash_image_dot_txt() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        assert!(archive.contains("art/image.txt"));
    }

    #[test]
    fn contains_data_slash_test_dot_ini() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        assert!(archive.contains("data/test.ini"));
    }

    #[test]
    fn read_entry_art_slash_image_dot_txt() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        let data = archive.read_entry("art/image.txt").unwrap();
        assert_eq!(data, vec![98, 108, 97, 98, 108, 98, 97]);
    }

    #[test]
    fn read_entry_data_slash_test_dot_ini() {
        let archive = BigArchive::new_from_path(&ARCHIVE_PATH).unwrap();
        let data = archive.read_entry("data/test.ini").unwrap();
        assert_eq!(data,
                   vec![84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 105, 109, 112, 108,
                        101, 32, 116, 101, 115, 116, 32, 102, 105, 108, 101]);
    }

    mod benches {
        extern crate test;
        use self::test::Bencher;

        #[bench]
        fn is_big4(b: &mut Bencher) {
            b.iter(|| super::is_big4());
        }

        #[bench]
        fn has_two_entries(b: &mut Bencher) {
            b.iter(|| super::has_two_entries());
        }

        #[bench]
        fn contains_art_slash_image_dot_txt(b: &mut Bencher) {
            b.iter(|| super::contains_art_slash_image_dot_txt());
        }

        #[bench]
        fn contains_data_slash_test_dot_ini(b: &mut Bencher) {
            b.iter(|| super::contains_data_slash_test_dot_ini());
        }

        #[bench]
        fn read_entry_art_slash_image_dot_txt(b: &mut Bencher) {
            b.iter(|| super::read_entry_art_slash_image_dot_txt());
        }

        #[bench]
        fn read_entry_data_slash_test_dot_ini(b: &mut Bencher) {
            b.iter(|| super::read_entry_data_slash_test_dot_ini());
        }
    }
}
<|endoftext|>


<commit_before>//! # Rushell - shell script in rust.
//!
//! Rushell is a helper library for std::process::Command, which allows you to
//! write a shell script helps you to write a shell script in rust.
//!
//! ## cmd! macro
//!
//! You can easiliy create Command instance by using cmd! macro.
//!
//! ```
//! #[macro_use] extern crate shell;
//! fn main() {
//!   let command = cmd!("echo test");
//! }
//! ```
//!
//! You can specify an argument by using rust value as well.
//!
//! ```
//! #[macro_use] extern crate shell;
//! # fn main() {
//!   let name = "John";
//!   let command = cmd!("echo My name is {}.", name);
//! # }
//! ```
//!
//! ## Running command
//!
//! Rushell adds run() method to Command, which returns ShellResult.  Because
//! ShellResult regards exit code 0 is Ok and others are Err, you can easily
//! check an error with try operator (?).
//!
//!
//! ```
//! #[macro_use] extern crate shell;
//! # use shell::ShellResult;
//! # use shell::JobSpec;
//! fn my_shell_script() -> ShellResult {
//!   cmd!("echo test").run()?;
//!   cmd!("echo test").run()?;
//!   Ok(())
//! }
//! # fn main() {
//! #   my_shell_script().unwrap();
//! # }
//! ```
//!
//! ## Output string
//!
//! output_utf8() and error_utf8() can be used to run command and returns
//! String.
//!
//! ## Async control
//!
//! If you would like to run a command asynchronously, call async() instead of
//! run(). async() returns JobHandler which you can use to kill or wait the
//! running process. JobHandler automatically invokes wait() when it's dropped.
//! So you will not get a zombi process. You can explicitly detach a process
//! from job handler by calling detach() if you want to.
//!
//! ```test
//! #[macro_use] extern crate shell;
//! # use shell::JobSpec;
//! # use shell::ShellResult;
//! # fn main() {
//! # fn body() -> ShellResult {
//! let job = cmd!("sleep 100").spawn()?;
//! job.wait();
//! # Ok(())
//! # }
//! # body();
//! # }
//! ```
//!
//! # Subshell
//!
//! You can create a subshell which is a separated process to run shell
//! command by using subshell() function. subshell() returns a command so
//! that you can call run(), async() as well as a normal external command.
//!
//! ```
//! #[macro_use] extern crate shell;
//! # use shell::JobSpec;
//! # fn main() {
//! shell::subshell(|| {
//!     // Running in a separated process so changing current directory does
//!     // not affect a parante process.
//!     std::env::set_current_dir("./src")?;
//!     std::env::set_var("ENV_NAME", "HOGE");
//!     cmd!("echo test").run()?;
//!     Ok(())
//! }).run().unwrap();
//! # }
//! ```
//!

extern crate libc;
extern crate errno;

use std::io::Error;
use std::process::Command;
use errno::Errno;
use errno::errno;
use std::os::unix::process::CommandExt;

#[derive(Debug)]
pub enum ShellError {
    Code(u8),
    Signaled(i32),
    OtherError(Error),
    Errno(&'static str, Errno),
}

impl std::convert::From<std::io::Error> for ShellError {
    fn from(error: std::io::Error) -> ShellError {
        ShellError::OtherError(error)
    }
}

pub type ShellResult = std::result::Result<(), ShellError>;

fn check_errno(name: &'static str,
               result: libc::c_int) -> Result<libc::c_int, ShellError> {
    if result != -1 {
        Ok(result)
    } else {
        Err(ShellError::Errno(name, errno()))
    }
}

trait ShellResultExt {
    fn code(&self) -> u8;
}

impl ShellResultExt for ShellResult {
    fn code(&self) -> u8 {
        match self {
            &Ok(_) => 0,
            &Err(ShellError::Code(code)) => code,
            &Err(_) => 1
        }
    }
}

pub fn subshell<F>(func: F) ->
        SubShell where F: FnMut() -> ShellResult + 'static {
    SubShell(Box::new(func))
}

/// Something which can be used as a command
pub trait JobSpec where Self: Sized {
    fn exec(self) -> !;

    fn spawn(self) -> Result<JobHandle, ShellError> {
        self.spawn_internal(false)
    }

    fn spawn_internal(self, foreground: bool) -> Result<JobHandle, ShellError> {
        unsafe {
            let foreground = foreground && libc::tcgetpgrp(0) == libc::getpid();
            let pid = check_errno("fork", libc::fork())?;
            // Call setpgid in both processes to avoid race.
            check_errno("setpgid", libc::setpgid(pid, 0)).unwrap();
            if pid == 0 {
                self.exec()
                // Process replaced
            }
            if foreground {
                check_errno("tcsetpgrp", libc::tcsetpgrp(0, pid));
            }
            Ok(JobHandle { pid: pid })
        }
    }

    fn run(self) -> ShellResult {
        self.spawn_internal(true)?.wait()
    }
}

/// Single Command
pub struct ShellCommand(Command);

impl ShellCommand {
    pub fn new(format: &str, args: &[&str]) -> ShellCommand {
        let mut i = 0;
        let mut vec = format.split(" ").collect::<Vec<_>>();
        for s in vec.iter_mut() {
            if *s == "{}" {
                *s = args[i];
                i += 1;
            }
        }
        let mut command = Command::new(vec[0]);
        command.args(&vec.as_slice()[1..]);
        ShellCommand(command)
    }
}

impl JobSpec for ShellCommand {
    fn exec(mut self) -> ! {
        self.0.exec();
        std::process::exit(1);
    }
}

#[macro_export]
macro_rules! cmd {
    ($format:expr) => ($crate::ShellCommand::new($format, &[]));
    ($format:expr, $($arg:expr),+) =>
        ($crate::ShellCommand::new($format, &[$($arg),+]));
}

/// Block
/// TODO: Change FnMut to FnOnce after fnbox is resolved.
pub struct SubShell(Box<FnMut() -> ShellResult + 'static>);

impl JobSpec for SubShell {
    fn exec(mut self) -> ! {
        let result = self.0();
        if let Err(ref err) = result {
            eprintln!("{:?}", err);
        }
        std::process::exit(result.code() as i32);
    }
}

/// Job which is a process leader.
pub struct JobHandle { pid: i32 }

impl JobHandle {
    /// Sends a SIGTERM to a process group, then wait a process leader.
    pub fn terminate(self) -> ShellResult {
        assert_ne!(self.pid, 0);
        unsafe {
            check_errno("kill", libc::kill(-self.pid, libc::SIGTERM))?;
            match self.wait() {
                Ok(()) | Err(ShellError::Code(_))
                    | Err(ShellError::Signaled(_)) => Ok(()),
                err => err
            }
        }
    }

    /// Wait for termination of the process.
    pub fn wait(mut self) -> ShellResult {
        self.wait_mut()
    }

    fn wait_mut(&mut self) -> ShellResult {
        if self.pid == 0 {
            return Ok(());
        }
        let pid = self.pid;
        self.pid = 0;
        loop {
            unsafe {
                let mut status: libc::c_int = 0;
                check_errno("waitpid", libc::waitpid(
                        pid, &mut status as *mut i32, 0))?;

                if libc::WIFEXITED(status) {
                    let code = libc::WEXITSTATUS(status);
                    if code == 0 {
                        return Ok(());
                    } else {
                        return Err(ShellError::Signaled(code));
                    }
                } else if libc::WIFSIGNALED(status) {
                    let signal = libc::WTERMSIG(status);
                    return Err(ShellError::Signaled(signal));
                }
            }
        }
    }
}

impl Drop for JobHandle {
    fn drop(&mut self) {
        self.wait_mut().unwrap();
    }
}

pub fn try<F>(f: F) -> ShellResult where F: FnOnce() -> ShellResult {
    f()
}

pub fn watch_for_rerun() -> SubShell {
    SubShell(Box::new(move || {
        loop {
            let bin = "foo";
            cmd!("inotifywait -e close_write -r src").run()?;
            if cmd!("cargo build {}", bin).run().is_ok()  {
                break;
            }
        }

        Ok(())
    }))
}

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

    #[test]
    fn test_command_run() {
        ::try(|| {
            cmd!("test 0 = 0").run()?;
            Ok(())
        }).unwrap();
    }

    #[test]
    fn test_subshell_terminate() {
        ::try(|| {
            let job = ::subshell(|| {
                println!("Start child");
                ::subshell(|| {
                    println!("Start sleeping");
                    ::std::thread::sleep(::std::time::Duration::from_secs(10));
                    println!("Stop sleeping");
                    Ok(())
                }).spawn()?;
                Ok(())
            }).spawn()?;
            ::std::thread::sleep(::std::time::Duration::from_secs(1));
            job.terminate()?;
            Ok(())
        }).unwrap();
    }
}

<commit_msg>check error of tcsetpgrp<commit_after>//! # Rushell - shell script in rust.
//!
//! Rushell is a helper library for std::process::Command, which allows you to
//! write a shell script helps you to write a shell script in rust.
//!
//! ## cmd! macro
//!
//! You can easiliy create Command instance by using cmd! macro.
//!
//! ```
//! #[macro_use] extern crate shell;
//! fn main() {
//!   let command = cmd!("echo test");
//! }
//! ```
//!
//! You can specify an argument by using rust value as well.
//!
//! ```
//! #[macro_use] extern crate shell;
//! # fn main() {
//!   let name = "John";
//!   let command = cmd!("echo My name is {}.", name);
//! # }
//! ```
//!
//! ## Running command
//!
//! Rushell adds run() method to Command, which returns ShellResult.  Because
//! ShellResult regards exit code 0 is Ok and others are Err, you can easily
//! check an error with try operator (?).
//!
//!
//! ```
//! #[macro_use] extern crate shell;
//! # use shell::ShellResult;
//! # use shell::JobSpec;
//! fn my_shell_script() -> ShellResult {
//!   cmd!("echo test").run()?;
//!   cmd!("echo test").run()?;
//!   Ok(())
//! }
//! # fn main() {
//! #   my_shell_script().unwrap();
//! # }
//! ```
//!
//! ## Output string
//!
//! output_utf8() and error_utf8() can be used to run command and returns
//! String.
//!
//! ## Async control
//!
//! If you would like to run a command asynchronously, call async() instead of
//! run(). async() returns JobHandler which you can use to kill or wait the
//! running process. JobHandler automatically invokes wait() when it's dropped.
//! So you will not get a zombi process. You can explicitly detach a process
//! from job handler by calling detach() if you want to.
//!
//! ```test
//! #[macro_use] extern crate shell;
//! # use shell::JobSpec;
//! # use shell::ShellResult;
//! # fn main() {
//! # fn body() -> ShellResult {
//! let job = cmd!("sleep 100").spawn()?;
//! job.wait();
//! # Ok(())
//! # }
//! # body();
//! # }
//! ```
//!
//! # Subshell
//!
//! You can create a subshell which is a separated process to run shell
//! command by using subshell() function. subshell() returns a command so
//! that you can call run(), async() as well as a normal external command.
//!
//! ```
//! #[macro_use] extern crate shell;
//! # use shell::JobSpec;
//! # fn main() {
//! shell::subshell(|| {
//!     // Running in a separated process so changing current directory does
//!     // not affect a parante process.
//!     std::env::set_current_dir("./src")?;
//!     std::env::set_var("ENV_NAME", "HOGE");
//!     cmd!("echo test").run()?;
//!     Ok(())
//! }).run().unwrap();
//! # }
//! ```
//!

extern crate libc;
extern crate errno;

use std::io::Error;
use std::process::Command;
use errno::Errno;
use errno::errno;
use std::os::unix::process::CommandExt;

#[derive(Debug)]
pub enum ShellError {
    Code(u8),
    Signaled(i32),
    OtherError(Error),
    Errno(&'static str, Errno),
}

impl std::convert::From<std::io::Error> for ShellError {
    fn from(error: std::io::Error) -> ShellError {
        ShellError::OtherError(error)
    }
}

pub type ShellResult = std::result::Result<(), ShellError>;

fn check_errno(name: &'static str,
               result: libc::c_int) -> Result<libc::c_int, ShellError> {
    if result != -1 {
        Ok(result)
    } else {
        Err(ShellError::Errno(name, errno()))
    }
}

trait ShellResultExt {
    fn code(&self) -> u8;
}

impl ShellResultExt for ShellResult {
    fn code(&self) -> u8 {
        match self {
            &Ok(_) => 0,
            &Err(ShellError::Code(code)) => code,
            &Err(_) => 1
        }
    }
}

pub fn subshell<F>(func: F) ->
        SubShell where F: FnMut() -> ShellResult + 'static {
    SubShell(Box::new(func))
}

/// Something which can be used as a command
pub trait JobSpec where Self: Sized {
    fn exec(self) -> !;

    fn spawn(self) -> Result<JobHandle, ShellError> {
        self.spawn_internal(false)
    }

    fn spawn_internal(self, foreground: bool) -> Result<JobHandle, ShellError> {
        unsafe {
            let foreground = foreground && libc::tcgetpgrp(0) == libc::getpid();
            let pid = check_errno("fork", libc::fork())?;
            // Call setpgid in both processes to avoid race.
            check_errno("setpgid", libc::setpgid(pid, 0)).unwrap();
            if pid == 0 {
                self.exec()
                // Process replaced
            }
            if foreground {
                check_errno("tcsetpgrp", libc::tcsetpgrp(0, pid)).unwrap();
            }
            Ok(JobHandle { pid: pid })
        }
    }

    fn run(self) -> ShellResult {
        self.spawn_internal(true)?.wait()
    }
}

/// Single Command
pub struct ShellCommand(Command);

impl ShellCommand {
    pub fn new(format: &str, args: &[&str]) -> ShellCommand {
        let mut i = 0;
        let mut vec = format.split(" ").collect::<Vec<_>>();
        for s in vec.iter_mut() {
            if *s == "{}" {
                *s = args[i];
                i += 1;
            }
        }
        let mut command = Command::new(vec[0]);
        command.args(&vec.as_slice()[1..]);
        ShellCommand(command)
    }
}

impl JobSpec for ShellCommand {
    fn exec(mut self) -> ! {
        self.0.exec();
        std::process::exit(1);
    }
}

#[macro_export]
macro_rules! cmd {
    ($format:expr) => ($crate::ShellCommand::new($format, &[]));
    ($format:expr, $($arg:expr),+) =>
        ($crate::ShellCommand::new($format, &[$($arg),+]));
}

/// Block
/// TODO: Change FnMut to FnOnce after fnbox is resolved.
pub struct SubShell(Box<FnMut() -> ShellResult + 'static>);

impl JobSpec for SubShell {
    fn exec(mut self) -> ! {
        let result = self.0();
        if let Err(ref err) = result {
            eprintln!("{:?}", err);
        }
        std::process::exit(result.code() as i32);
    }
}

/// Job which is a process leader.
pub struct JobHandle { pid: i32 }

impl JobHandle {
    /// Sends a SIGTERM to a process group, then wait a process leader.
    pub fn terminate(self) -> ShellResult {
        assert_ne!(self.pid, 0);
        unsafe {
            check_errno("kill", libc::kill(-self.pid, libc::SIGTERM))?;
            match self.wait() {
                Ok(()) | Err(ShellError::Code(_))
                    | Err(ShellError::Signaled(_)) => Ok(()),
                err => err
            }
        }
    }

    /// Wait for termination of the process.
    pub fn wait(mut self) -> ShellResult {
        self.wait_mut()
    }

    fn wait_mut(&mut self) -> ShellResult {
        if self.pid == 0 {
            return Ok(());
        }
        let pid = self.pid;
        self.pid = 0;
        loop {
            unsafe {
                let mut status: libc::c_int = 0;
                check_errno("waitpid", libc::waitpid(
                        pid, &mut status as *mut i32, 0))?;

                if libc::WIFEXITED(status) {
                    let code = libc::WEXITSTATUS(status);
                    if code == 0 {
                        return Ok(());
                    } else {
                        return Err(ShellError::Signaled(code));
                    }
                } else if libc::WIFSIGNALED(status) {
                    let signal = libc::WTERMSIG(status);
                    return Err(ShellError::Signaled(signal));
                }
            }
        }
    }
}

impl Drop for JobHandle {
    fn drop(&mut self) {
        self.wait_mut().unwrap();
    }
}

pub fn try<F>(f: F) -> ShellResult where F: FnOnce() -> ShellResult {
    f()
}

pub fn watch_for_rerun() -> SubShell {
    SubShell(Box::new(move || {
        loop {
            let bin = "foo";
            cmd!("inotifywait -e close_write -r src").run()?;
            if cmd!("cargo build {}", bin).run().is_ok()  {
                break;
            }
        }

        Ok(())
    }))
}

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

    #[test]
    fn test_command_run() {
        ::try(|| {
            cmd!("test 0 = 0").run()?;
            Ok(())
        }).unwrap();
    }

    #[test]
    fn test_subshell_terminate() {
        ::try(|| {
            let job = ::subshell(|| {
                println!("Start child");
                ::subshell(|| {
                    println!("Start sleeping");
                    ::std::thread::sleep(::std::time::Duration::from_secs(10));
                    println!("Stop sleeping");
                    Ok(())
                }).spawn()?;
                Ok(())
            }).spawn()?;
            ::std::thread::sleep(::std::time::Duration::from_secs(1));
            job.terminate()?;
            Ok(())
        }).unwrap();
    }
}

<|endoftext|>


<commit_before>//! The `neon` crate provides the entire [Neon](https://www.neon-bindings.com/) API.

extern crate neon_runtime;
extern crate cslice;
extern crate semver;

#[cfg(test)]
extern crate rustc_version;

#[cfg(test)]
#[macro_use]
extern crate lazy_static;

pub mod mem;
pub mod vm;
pub mod scope;
pub mod js;
pub mod task;
pub mod meta;

#[doc(hidden)]
pub mod macro_internal;

/// Register the current crate as a Node module, providing startup
/// logic for initializing the module object at runtime.
///
/// Example:
///
/// ```rust,ignore
/// register_module!(m, {
///     m.export("foo", foo)?;
///     m.export("bar", bar)?;
///     m.export("baz", baz)?;
///     Ok(())
/// });
/// ```
#[macro_export]
macro_rules! register_module {
    ($module:ident, $init:block) => {
        // Mark this function as a global constructor (like C++).
        #[allow(improper_ctypes)]
        #[cfg_attr(target_os = "linux", link_section = ".ctors")]
        #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
        #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
        pub static __LOAD_NEON_MODULE: extern "C" fn() = {
            fn __init_neon_module(mut $module: $crate::vm::Module) -> $crate::vm::VmResult<()> $init

            extern "C" fn __load_neon_module() {
                // Put everything else in the ctor fn so the user fn can't see it.
                #[repr(C)]
                struct __NodeModule {
                    version: i32,
                    flags: u32,
                    dso_handle: *mut u8,
                    filename: *const u8,
                    register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8)>,
                    context_register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8, *mut u8)>,
                    modname: *const u8,
                    priv_data: *mut u8,
                    link: *mut __NodeModule
                }

                static mut __NODE_MODULE: __NodeModule = __NodeModule {
                    version: 0,
                    flags: 0,
                    dso_handle: 0 as *mut _,
                    filename: b"neon_source.rs\0" as *const u8,
                    register_func: Some(__register_neon_module),
                    context_register_func: None,
                    modname: b"neon_module\0" as *const u8,
                    priv_data: 0 as *mut _,
                    link: 0 as *mut _
                };

                extern "C" fn __register_neon_module(
                        m: $crate::mem::Handle<$crate::js::JsObject>, _: *mut u8, _: *mut u8) {
                    $crate::vm::Module::initialize(m, __init_neon_module);
                }

                extern "C" {
                    fn node_module_register(module: *mut __NodeModule);
                }

                // Suppress the default Rust panic hook, which prints diagnostics to stderr.
                ::std::panic::set_hook(::std::boxed::Box::new(|_| { }));

                unsafe {
                    // Set the ABI version based on the NODE_MODULE_VERSION constant provided by the current node headers.
                    __NODE_MODULE.version = $crate::macro_internal::runtime::module::get_version();
                    node_module_register(&mut __NODE_MODULE);
                }
            }

            __load_neon_module
        };
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! class_definition {
    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; init($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          {
                              fn _______allocator_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsUndefined>) -> $crate::vm::VmResult<$typ> {
                                  $body
                              }

                              $crate::macro_internal::AllocateKernel::new(_______allocator_rust_y_u_no_hygienic_items_______)
                          } ;
                          $call_ctor ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; ($($mname:tt)*) ; ($($mdef:tt)*) ; method $name:ident($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          $new_ctor ;
                          ($($mname)* $name) ;
                          ($($mdef)* {
                              fn _______method_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::MethodKernel::new(_______method_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; constructor($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          ({
                              fn _______constructor_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::VmResult<Option<$crate::mem::Handle<$crate::js::JsObject>>> {
                                  $body
                              }

                              $crate::macro_internal::ConstructKernel::new(_______constructor_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; call($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          ({
                              fn _______call_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsValue>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::ConstructorCallKernel::new(_______call_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:block ; ($($call_ctor:block)*) ; ($($new_ctor:block)*) ; ($($mname:ident)*) ; ($($mdef:block)*) ; $($rest:tt)* ) => {
        impl $crate::js::class::Class for $cls {
            type Internals = $typ;

            fn setup<'a, T: $crate::scope::Scope<'a>>(_: &mut T) -> $crate::vm::VmResult<$crate::js::class::ClassDescriptor<'a, Self>> {
                ::std::result::Result::Ok(Self::describe(stringify!($cname), $allocator)
                                             $(.construct($new_ctor))*
                                             $(.call($call_ctor))*
                                             $(.method(stringify!($mname), $mdef))*)
            }
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! impl_managed {
    ($cls:ident) => {
        impl $crate::mem::Managed for $cls {
            fn to_raw(self) -> $crate::macro_internal::runtime::raw::Local {
                let $cls(raw) = self;
                raw
            }

            fn from_raw(raw: $crate::macro_internal::runtime::raw::Local) -> Self {
                $cls(raw)
            }
        }
    }
}

/// Declare custom native JavaScript types with Rust implementations.
///
/// Example:
///
/// ```rust,ignore
/// pub struct Greeter {
///     greeting: String
/// }
///
/// declare_types! {
///
///     /// A class for generating greeting strings.
///     pub class JsGreeter for Greeter {
///         init(call) {
///             let scope = call.scope;
///             let greeting = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             Ok(Greeter {
///                 greeting: greeting
///             })
///         }
///
///         method hello(call) {
///             let scope = call.scope;
///             let name = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             let msg = vm::lock(call.arguments.this(scope), |greeter| {
///                 format!("{}, {}!", greeter.greeting, name)
///             });
///             Ok(JsString::new_or_throw(scope, &msg[..])?.upcast())
///         }
///     }
///
/// }
/// ```
#[macro_export]
macro_rules! declare_types {
    { $(#[$attr:meta])* pub class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* pub class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* pub class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        pub struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { } => { };
}

#[cfg(all(windows, not(neon_profile = "release")))]
compile_error!("Neon only builds with --release. For tests, try `cargo test --release`.");

#[cfg(test)]
mod tests {
    use std::path::{Path, PathBuf};
    use std::process::Command;
    use std::sync::Mutex;

    use rustc_version::{version_meta, Channel};

    // Create a mutex to enforce sequential running of the tests.
    lazy_static! {
        static ref TEST_MUTEX: Mutex<()> = Mutex::new(());
    }

    fn project_root() -> PathBuf {
        Path::new(env!("CARGO_MANIFEST_DIR")).to_path_buf()
    }

    fn run(cmd: &str, dir: &Path) {
        let (shell, command_flag) = if cfg!(windows) {
            ("cmd", "/C")
        } else {
            ("sh", "-c")
        };

        assert!(Command::new(&shell)
                        .current_dir(dir)
                        .args(&[&command_flag, cmd])
                        .status()
                        .expect("failed to execute test command")
                        .success());
    }

    #[test]
    fn cli_test() {
        let _guard = TEST_MUTEX.lock();

        let cli = project_root().join("cli");
        run("npm install", &cli);
        run("npm run transpile", &cli);

        let test_cli = project_root().join("test").join("cli");
        run("npm install", &test_cli);
        run("npm run transpile", &test_cli);
        run("npm test", &test_cli);
    }

    #[test]
    fn static_test() {
        let _guard = TEST_MUTEX.lock();

        if version_meta().unwrap().channel != Channel::Nightly {
            return;
        }

        run("cargo test --release", &project_root().join("test").join("static"));
    }

    #[test]
    fn dynamic_test() {
        let _guard = TEST_MUTEX.lock();

        let cli = project_root().join("cli");
        run("npm install", &cli);
        run("npm run transpile", &cli);

        let test_dynamic = project_root().join("test").join("dynamic");
        run("npm install", &test_dynamic);
        run("npm test", &test_dynamic);
    }
}
<commit_msg>disable static tests in Windows; seems like recent compiletest_rs may not be working in windows<commit_after>//! The `neon` crate provides the entire [Neon](https://www.neon-bindings.com/) API.

extern crate neon_runtime;
extern crate cslice;
extern crate semver;

#[cfg(test)]
extern crate rustc_version;

#[cfg(test)]
#[macro_use]
extern crate lazy_static;

pub mod mem;
pub mod vm;
pub mod scope;
pub mod js;
pub mod task;
pub mod meta;

#[doc(hidden)]
pub mod macro_internal;

/// Register the current crate as a Node module, providing startup
/// logic for initializing the module object at runtime.
///
/// Example:
///
/// ```rust,ignore
/// register_module!(m, {
///     m.export("foo", foo)?;
///     m.export("bar", bar)?;
///     m.export("baz", baz)?;
///     Ok(())
/// });
/// ```
#[macro_export]
macro_rules! register_module {
    ($module:ident, $init:block) => {
        // Mark this function as a global constructor (like C++).
        #[allow(improper_ctypes)]
        #[cfg_attr(target_os = "linux", link_section = ".ctors")]
        #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
        #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
        pub static __LOAD_NEON_MODULE: extern "C" fn() = {
            fn __init_neon_module(mut $module: $crate::vm::Module) -> $crate::vm::VmResult<()> $init

            extern "C" fn __load_neon_module() {
                // Put everything else in the ctor fn so the user fn can't see it.
                #[repr(C)]
                struct __NodeModule {
                    version: i32,
                    flags: u32,
                    dso_handle: *mut u8,
                    filename: *const u8,
                    register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8)>,
                    context_register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8, *mut u8)>,
                    modname: *const u8,
                    priv_data: *mut u8,
                    link: *mut __NodeModule
                }

                static mut __NODE_MODULE: __NodeModule = __NodeModule {
                    version: 0,
                    flags: 0,
                    dso_handle: 0 as *mut _,
                    filename: b"neon_source.rs\0" as *const u8,
                    register_func: Some(__register_neon_module),
                    context_register_func: None,
                    modname: b"neon_module\0" as *const u8,
                    priv_data: 0 as *mut _,
                    link: 0 as *mut _
                };

                extern "C" fn __register_neon_module(
                        m: $crate::mem::Handle<$crate::js::JsObject>, _: *mut u8, _: *mut u8) {
                    $crate::vm::Module::initialize(m, __init_neon_module);
                }

                extern "C" {
                    fn node_module_register(module: *mut __NodeModule);
                }

                // Suppress the default Rust panic hook, which prints diagnostics to stderr.
                ::std::panic::set_hook(::std::boxed::Box::new(|_| { }));

                unsafe {
                    // Set the ABI version based on the NODE_MODULE_VERSION constant provided by the current node headers.
                    __NODE_MODULE.version = $crate::macro_internal::runtime::module::get_version();
                    node_module_register(&mut __NODE_MODULE);
                }
            }

            __load_neon_module
        };
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! class_definition {
    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; init($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          {
                              fn _______allocator_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsUndefined>) -> $crate::vm::VmResult<$typ> {
                                  $body
                              }

                              $crate::macro_internal::AllocateKernel::new(_______allocator_rust_y_u_no_hygienic_items_______)
                          } ;
                          $call_ctor ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; ($($mname:tt)*) ; ($($mdef:tt)*) ; method $name:ident($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          $new_ctor ;
                          ($($mname)* $name) ;
                          ($($mdef)* {
                              fn _______method_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::MethodKernel::new(_______method_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; constructor($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          ({
                              fn _______constructor_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::VmResult<Option<$crate::mem::Handle<$crate::js::JsObject>>> {
                                  $body
                              }

                              $crate::macro_internal::ConstructKernel::new(_______constructor_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; call($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          ({
                              fn _______call_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsValue>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::ConstructorCallKernel::new(_______call_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:block ; ($($call_ctor:block)*) ; ($($new_ctor:block)*) ; ($($mname:ident)*) ; ($($mdef:block)*) ; $($rest:tt)* ) => {
        impl $crate::js::class::Class for $cls {
            type Internals = $typ;

            fn setup<'a, T: $crate::scope::Scope<'a>>(_: &mut T) -> $crate::vm::VmResult<$crate::js::class::ClassDescriptor<'a, Self>> {
                ::std::result::Result::Ok(Self::describe(stringify!($cname), $allocator)
                                             $(.construct($new_ctor))*
                                             $(.call($call_ctor))*
                                             $(.method(stringify!($mname), $mdef))*)
            }
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! impl_managed {
    ($cls:ident) => {
        impl $crate::mem::Managed for $cls {
            fn to_raw(self) -> $crate::macro_internal::runtime::raw::Local {
                let $cls(raw) = self;
                raw
            }

            fn from_raw(raw: $crate::macro_internal::runtime::raw::Local) -> Self {
                $cls(raw)
            }
        }
    }
}

/// Declare custom native JavaScript types with Rust implementations.
///
/// Example:
///
/// ```rust,ignore
/// pub struct Greeter {
///     greeting: String
/// }
///
/// declare_types! {
///
///     /// A class for generating greeting strings.
///     pub class JsGreeter for Greeter {
///         init(call) {
///             let scope = call.scope;
///             let greeting = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             Ok(Greeter {
///                 greeting: greeting
///             })
///         }
///
///         method hello(call) {
///             let scope = call.scope;
///             let name = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             let msg = vm::lock(call.arguments.this(scope), |greeter| {
///                 format!("{}, {}!", greeter.greeting, name)
///             });
///             Ok(JsString::new_or_throw(scope, &msg[..])?.upcast())
///         }
///     }
///
/// }
/// ```
#[macro_export]
macro_rules! declare_types {
    { $(#[$attr:meta])* pub class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* pub class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* pub class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        pub struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { } => { };
}

#[cfg(all(windows, not(neon_profile = "release")))]
compile_error!("Neon only builds with --release. For tests, try `cargo test --release`.");

#[cfg(test)]
mod tests {
    use std::path::{Path, PathBuf};
    use std::process::Command;
    use std::sync::Mutex;

    use rustc_version::{version_meta, Channel};

    // Create a mutex to enforce sequential running of the tests.
    lazy_static! {
        static ref TEST_MUTEX: Mutex<()> = Mutex::new(());
    }

    fn project_root() -> PathBuf {
        Path::new(env!("CARGO_MANIFEST_DIR")).to_path_buf()
    }

    fn run(cmd: &str, dir: &Path) {
        let (shell, command_flag) = if cfg!(windows) {
            ("cmd", "/C")
        } else {
            ("sh", "-c")
        };

        assert!(Command::new(&shell)
                        .current_dir(dir)
                        .args(&[&command_flag, cmd])
                        .status()
                        .expect("failed to execute test command")
                        .success());
    }

    #[test]
    fn cli_test() {
        let _guard = TEST_MUTEX.lock();

        let cli = project_root().join("cli");
        run("npm install", &cli);
        run("npm run transpile", &cli);

        let test_cli = project_root().join("test").join("cli");
        run("npm install", &test_cli);
        run("npm run transpile", &test_cli);
        run("npm test", &test_cli);
    }

    #[cfg(not(windows))]
    #[test]
    fn static_test() {
        let _guard = TEST_MUTEX.lock();

        if version_meta().unwrap().channel != Channel::Nightly {
            return;
        }

        run("cargo test --release", &project_root().join("test").join("static"));
    }

    #[test]
    fn dynamic_test() {
        let _guard = TEST_MUTEX.lock();

        let cli = project_root().join("cli");
        run("npm install", &cli);
        run("npm run transpile", &cli);

        let test_dynamic = project_root().join("test").join("dynamic");
        run("npm install", &test_dynamic);
        run("npm test", &test_dynamic);
    }
}
<|endoftext|>


<commit_before>pub struct Nil;
pub struct Cons<H, T>(pub H, pub T);

/// Used as an index into an `HList`.
///
/// `Here` is 0, pointing to the head of the HList.
///
/// Users should normally allow type inference to deal with this type
#[allow(dead_code)]
pub enum Here {}

/// Used as an index into an `HList`.
///
/// `There<T>` is 1 + `T`.
///
/// Users should normally allow type inference to deal with this type.
#[allow(dead_code)]
pub struct There<T>(std::marker::PhantomData<T>);

impl Nil {
    pub fn push<N>(self, item: N) -> Cons<N, Self> {
        Cons(item, self)
    }
}

impl<H, T> Cons<H, T> {
    pub fn push<N>(self, item: N) -> Cons<N, Self> {
        Cons(item, self)
    }
}

pub trait Find<T, I> {
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;
}

impl<T, Tail> Find<T, Here> for Cons<T, Tail> {
    fn get(&self) -> &T {
        &self.0
    }
    fn get_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<Head, T, Tail, TailIndex> Find<T, There<TailIndex>> for Cons<Head, Tail>
    where Tail: Find<T, TailIndex> {
    fn get(&self) -> &T {
        self.1.get()
    }
    fn get_mut(&mut self) -> &mut T {
        self.1.get_mut()
    }
}

#[test]
fn test_get() {
    let list = Nil.push(5i32).push("Foo");
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 5i32);
    assert!(b == "Foo");
}

#[test]
fn test_get_mut() {
    let mut list = Nil.push(5i32).push("Foo");
    *list.get_mut() = 6i32;
    *list.get_mut() = "Bar";
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 6i32);
    assert!(b == "Bar");
}

#[test]
fn test_index_as_type_parameter() {
    fn foo<I, L: Find<i32, I>>(list: &L) -> i32 {
        *list.get()
    }
    let list = Nil.push("foo").push(5i32).push("bar");
    assert!(foo(&list) == 5);
}
<commit_msg>Make `HList` trait, and move .push() to it.<commit_after>pub struct Nil;
pub struct Cons<H, T>(pub H, pub T);

pub trait HList: Sized {
    fn push<N>(self, item: N) -> Cons<N, Self> {
        Cons(item, self)
    }
}

impl HList for Nil {}
impl<H, T> HList for Cons<H, T> {}

/// Used as an index into an `HList`.
///
/// `Here` is 0, pointing to the head of the HList.
///
/// Users should normally allow type inference to deal with this type
#[allow(dead_code)]
pub enum Here {}

/// Used as an index into an `HList`.
///
/// `There<T>` is 1 + `T`.
///
/// Users should normally allow type inference to deal with this type.
#[allow(dead_code)]
pub struct There<T>(std::marker::PhantomData<T>);

pub trait Find<T, I> {
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;
}

impl<T, Tail> Find<T, Here> for Cons<T, Tail> {
    fn get(&self) -> &T {
        &self.0
    }
    fn get_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<Head, T, Tail, TailIndex> Find<T, There<TailIndex>> for Cons<Head, Tail>
    where Tail: Find<T, TailIndex> {
    fn get(&self) -> &T {
        self.1.get()
    }
    fn get_mut(&mut self) -> &mut T {
        self.1.get_mut()
    }
}

#[test]
fn test_get() {
    let list = Nil.push(5i32).push("Foo");
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 5i32);
    assert!(b == "Foo");
}

#[test]
fn test_get_mut() {
    let mut list = Nil.push(5i32).push("Foo");
    *list.get_mut() = 6i32;
    *list.get_mut() = "Bar";
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 6i32);
    assert!(b == "Bar");
}

#[test]
fn test_index_as_type_parameter() {
    fn foo<I, L: Find<i32, I>>(list: &L) -> i32 {
        *list.get()
    }
    let list = Nil.push("foo").push(5i32).push("bar");
    assert!(foo(&list) == 5);
}
<|endoftext|>