<commit_before>extern crate image;

mod obj_load;
pub mod camera;
pub use self::camera::Camera;

use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;
use std::vec::Vec;

use glium::{IndexBuffer, VertexBuffer, Program, Surface, DrawParameters};
use glium::backend::Facade;
use glium::index::PrimitiveType;
use glium::texture::{RawImage2d, Texture2d};

use cgmath::prelude::*;
use cgmath::Matrix4;
use cgmath::conv::*;

#[derive(Copy, Clone, Debug)]
pub struct Vertex {
    pub position: [f32; 3],
    pub normal: [f32; 3],
    pub tex_coords: [f32; 2]
}

implement_vertex!(Vertex, position, normal, tex_coords);

#[derive(Debug)]
pub struct Material {
    pub diffuse: Option<[f32; 3]>,
    pub has_diffuse: bool,
    pub diffuse_texture: Texture2d
}

impl Material {
    fn new<F: Facade>(facade: &F, obj_mat: obj_load::Material) -> Material {
        let (diffuse_texture, has_diffuse)  = match obj_mat.map_Kd {
            Some(tex_path) => {
                let tex_image = Material::load_texture(&tex_path);
                (Texture2d::new(facade, tex_image).expect("Failed to create texture!"), true)
            }
            None => (Texture2d::empty(facade, 0, 0).expect("Failed to create empty texture!"), false)
        };
        Material {
            diffuse: obj_mat.Kd,
            has_diffuse: has_diffuse,
            diffuse_texture: diffuse_texture
        }
    }

    fn load_texture(tex_path: &Path) -> RawImage2d<u8> {
        let tex_reader = BufReader::new(File::open(tex_path).expect("Failed to open texture!"));
        let image = image::load(tex_reader, image::PNG).expect("Failed to load image!").to_rgba();
        let image_dim = image.dimensions();
        println!("texture {:?} loaded", tex_path);
        RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dim)
    }
}

#[derive(Debug)]
pub struct Mesh {
    pub vertices: Vec<Vertex>,
    pub indices: Vec<u32>,
    pub material: Material,
    pub local_to_world: Matrix4<f32>,
    pub vertex_buffer: Option<VertexBuffer<Vertex>>,
    pub index_buffer: Option<IndexBuffer<u32>>
}

impl Mesh {
    fn new<F: Facade>(facade: &F, obj_mat: obj_load::Material) -> Mesh {
        Mesh { vertices: Vec::new(),
               indices: Vec::new(),
               material: Material::new(facade, obj_mat),
               local_to_world: Matrix4::identity(),
               vertex_buffer: None,
               index_buffer: None
        }
    }

    fn create_buffers<F: Facade>(&mut self, facade: &F) {
        self.vertex_buffer = Some(VertexBuffer::new(facade, &self.vertices)
                                  .expect("Failed to create vertex buffer!"));
        self.index_buffer = Some(IndexBuffer::new(facade, PrimitiveType::TrianglesList, &self.indices)
                                 .expect("Failed to create index buffer!"));
    }

    pub fn draw<S: Surface>(&self, target: &mut S, program: &Program, draw_parameters: &DrawParameters,
                            world_to_clip: Matrix4<f32>) {
        let uniforms = uniform! {
            local_to_world: array4x4(self.local_to_world),
            world_to_clip: array4x4(world_to_clip),
            u_light: [-1.0, 0.4, 0.9f32],
            u_color: self.material.diffuse.expect("No diffuse color!"),
            u_has_diffuse: self.material.has_diffuse,
            diffuse_texture: &self.material.diffuse_texture
        };
        target.draw(self.vertex_buffer.as_ref().expect("No vertex buffer!"),
                    self.index_buffer.as_ref().expect("No index buffer!"),
                    &program, &uniforms, &draw_parameters).unwrap();
    }
}

pub struct Scene {
    pub meshes: Vec<Mesh>
}

pub fn load_scene<F: Facade>(scene_path: &Path, facade: &F) -> Scene {
    let mut scene = Scene { meshes: vec!() };
    let obj = obj_load::load_obj(scene_path).expect("Failed to load.");
    for range in obj.material_ranges {
        let obj_mat = obj.materials.get(&range.name)
            .expect(&::std::fmt::format(format_args!("Couldn't find material {}!", range.name)));
        let mut mesh = Mesh::new(facade, obj_mat.clone());
        let mut vertex_map = HashMap::new();
        for polygon in obj.polygons[range.start_i..range.end_i].iter() {
            let default_normal = [0.0; 3];
            let default_tex_coords= [0.0; 2];
            for index_vertex in &polygon.index_vertices {
                match vertex_map.get(index_vertex) {
                    Some(&i) => mesh.indices.push(i),
                    None => {
                        vertex_map.insert(index_vertex, mesh.vertices.len() as u32);
                        let pos = obj.positions[index_vertex[0] - 1];

                        let tex_coords;
                        let tex_coords_i = index_vertex[1];
                        if tex_coords_i > 0 {
                            tex_coords = obj.tex_coords[tex_coords_i - 1];
                        } else {
                            tex_coords = default_tex_coords;
                        }

                        let normal;
                        let normal_i = index_vertex[2];
                        if normal_i > 0 {
                            normal = obj.normals[normal_i - 1];
                        } else {
                            normal = default_normal;
                        }

                        mesh.indices.push(mesh.vertices.len() as u32);
                        mesh.vertices.push(Vertex { position: pos, normal: normal, tex_coords: tex_coords });
                    }
                }
            }
        }
        mesh.create_buffers(facade);
        scene.meshes.push(mesh);
    }
    scene
}
<commit_msg>Fix texture naming<commit_after>extern crate image;

mod obj_load;
pub mod camera;
pub use self::camera::Camera;

use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;
use std::vec::Vec;

use glium::{IndexBuffer, VertexBuffer, Program, Surface, DrawParameters};
use glium::backend::Facade;
use glium::index::PrimitiveType;
use glium::texture::{RawImage2d, SrgbTexture2d};

use cgmath::prelude::*;
use cgmath::Matrix4;
use cgmath::conv::*;

#[derive(Copy, Clone, Debug)]
pub struct Vertex {
    pub position: [f32; 3],
    pub normal: [f32; 3],
    pub tex_coords: [f32; 2]
}

implement_vertex!(Vertex, position, normal, tex_coords);

#[derive(Debug)]
pub struct Material {
    pub diffuse: Option<[f32; 3]>,
    pub has_diffuse: bool,
    pub diffuse_texture: SrgbTexture2d
}

impl Material {
    fn new<F: Facade>(facade: &F, obj_mat: obj_load::Material) -> Material {
        let (diffuse_texture, has_diffuse)  = match obj_mat.map_Kd {
            Some(tex_path) => {
                let tex_image = Material::load_texture(&tex_path);
                (SrgbTexture2d::new(facade, tex_image).expect("Failed to create texture!"), true)
            }
            None => (SrgbTexture2d::empty(facade, 0, 0).expect("Failed to create empty texture!"), false)
        };
        Material {
            diffuse: obj_mat.Kd,
            has_diffuse: has_diffuse,
            diffuse_texture: diffuse_texture
        }
    }

    fn load_texture(tex_path: &Path) -> RawImage2d<u8> {
        let tex_reader = BufReader::new(File::open(tex_path).expect("Failed to open texture!"));
        let image = image::load(tex_reader, image::PNG).expect("Failed to load image!").to_rgba();
        let image_dim = image.dimensions();
        RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dim)
    }
}

#[derive(Debug)]
pub struct Mesh {
    pub vertices: Vec<Vertex>,
    pub indices: Vec<u32>,
    pub material: Material,
    pub local_to_world: Matrix4<f32>,
    pub vertex_buffer: Option<VertexBuffer<Vertex>>,
    pub index_buffer: Option<IndexBuffer<u32>>
}

impl Mesh {
    fn new<F: Facade>(facade: &F, obj_mat: obj_load::Material) -> Mesh {
        Mesh { vertices: Vec::new(),
               indices: Vec::new(),
               material: Material::new(facade, obj_mat),
               local_to_world: Matrix4::identity(),
               vertex_buffer: None,
               index_buffer: None
        }
    }

    fn create_buffers<F: Facade>(&mut self, facade: &F) {
        self.vertex_buffer = Some(VertexBuffer::new(facade, &self.vertices)
                                  .expect("Failed to create vertex buffer!"));
        self.index_buffer = Some(IndexBuffer::new(facade, PrimitiveType::TrianglesList, &self.indices)
                                 .expect("Failed to create index buffer!"));
    }

    pub fn draw<S: Surface>(&self, target: &mut S, program: &Program, draw_parameters: &DrawParameters,
                            world_to_clip: Matrix4<f32>) {
        let uniforms = uniform! {
            local_to_world: array4x4(self.local_to_world),
            world_to_clip: array4x4(world_to_clip),
            u_light: [-1.0, 0.4, 0.9f32],
            u_color: self.material.diffuse.expect("No diffuse color!"),
            u_has_diffuse: self.material.has_diffuse,
            tex_diffuse: &self.material.diffuse_texture
        };
        target.draw(self.vertex_buffer.as_ref().expect("No vertex buffer!"),
                    self.index_buffer.as_ref().expect("No index buffer!"),
                    &program, &uniforms, &draw_parameters).unwrap();
    }
}

pub struct Scene {
    pub meshes: Vec<Mesh>
}

pub fn load_scene<F: Facade>(scene_path: &Path, facade: &F) -> Scene {
    let mut scene = Scene { meshes: vec!() };
    let obj = obj_load::load_obj(scene_path).expect("Failed to load.");
    for range in obj.material_ranges {
        let obj_mat = obj.materials.get(&range.name)
            .expect(&::std::fmt::format(format_args!("Couldn't find material {}!", range.name)));
        let mut mesh = Mesh::new(facade, obj_mat.clone());
        let mut vertex_map = HashMap::new();
        for polygon in obj.polygons[range.start_i..range.end_i].iter() {
            let default_normal = [0.0; 3];
            let default_tex_coords= [0.0; 2];
            for index_vertex in &polygon.index_vertices {
                match vertex_map.get(index_vertex) {
                    Some(&i) => mesh.indices.push(i),
                    None => {
                        vertex_map.insert(index_vertex, mesh.vertices.len() as u32);
                        let pos = obj.positions[index_vertex[0] - 1];

                        let tex_coords;
                        let tex_coords_i = index_vertex[1];
                        if tex_coords_i > 0 {
                            tex_coords = obj.tex_coords[tex_coords_i - 1];
                        } else {
                            tex_coords = default_tex_coords;
                        }

                        let normal;
                        let normal_i = index_vertex[2];
                        if normal_i > 0 {
                            normal = obj.normals[normal_i - 1];
                        } else {
                            normal = default_normal;
                        }

                        mesh.indices.push(mesh.vertices.len() as u32);
                        mesh.vertices.push(Vertex { position: pos, normal: normal, tex_coords: tex_coords });
                    }
                }
            }
        }
        mesh.create_buffers(facade);
        scene.meshes.push(mesh);
    }
    scene
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::collections::HashMap;

mod response;
mod cursor;
mod from_json;

pub use common::response::*;
pub use common::cursor::*;
pub use common::from_json::*;

///Convenience type used to hold parameters to an API call.
pub type ParamList<'a> = HashMap<Cow<'a, str>, Cow<'a, str>>;

///Convenience function to add a key/value parameter to a ParamList.
pub fn add_param<'a, K, V>(list: &mut ParamList<'a>, key: K, value: V) -> Option<Cow<'a, str>>
    where K: Into<Cow<'a, str>>,
          V: Into<Cow<'a, str>>
{
    list.insert(key.into(), value.into())
}

pub fn add_name_param<'a>(list: &mut ParamList<'a>, id: &UserID<'a>) -> Option<Cow<'a, str>> {
    match id {
        &UserID::ID(id) => add_param(list, "user_id", id.to_string()),
        &UserID::ScreenName(name) => add_param(list, "screen_name", name),
    }
}

///Convenience enum to generalize between referring to an account by numeric ID or by screen name.
pub enum UserID<'a> {
    ///Referring via the account's numeric ID.
    ID(i64),
    ///Referring via the account's screen name.
    ScreenName(&'a str),
}

impl<'a> From<i64> for UserID<'a> {
    fn from(id: i64) -> UserID<'a> {
        UserID::ID(id)
    }
}

impl<'a> From<&'a str> for UserID<'a> {
    fn from(name: &'a str) -> UserID<'a> {
        UserID::ScreenName(name)
    }
}
<commit_msg>impl From<&String> for UserID<commit_after>use std::borrow::Cow;
use std::collections::HashMap;

mod response;
mod cursor;
mod from_json;

pub use common::response::*;
pub use common::cursor::*;
pub use common::from_json::*;

///Convenience type used to hold parameters to an API call.
pub type ParamList<'a> = HashMap<Cow<'a, str>, Cow<'a, str>>;

///Convenience function to add a key/value parameter to a ParamList.
pub fn add_param<'a, K, V>(list: &mut ParamList<'a>, key: K, value: V) -> Option<Cow<'a, str>>
    where K: Into<Cow<'a, str>>,
          V: Into<Cow<'a, str>>
{
    list.insert(key.into(), value.into())
}

pub fn add_name_param<'a>(list: &mut ParamList<'a>, id: &UserID<'a>) -> Option<Cow<'a, str>> {
    match id {
        &UserID::ID(id) => add_param(list, "user_id", id.to_string()),
        &UserID::ScreenName(name) => add_param(list, "screen_name", name),
    }
}

///Convenience enum to generalize between referring to an account by numeric ID or by screen name.
pub enum UserID<'a> {
    ///Referring via the account's numeric ID.
    ID(i64),
    ///Referring via the account's screen name.
    ScreenName(&'a str),
}

impl<'a> From<i64> for UserID<'a> {
    fn from(id: i64) -> UserID<'a> {
        UserID::ID(id)
    }
}

impl<'a> From<&'a str> for UserID<'a> {
    fn from(name: &'a str) -> UserID<'a> {
        UserID::ScreenName(name)
    }
}

impl<'a> From<&'a String> for UserID<'a> {
    fn from(name: &'a String) -> UserID<'a> {
        UserID::ScreenName(name.as_str())
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::str::FromStr;

use num::NumCast;

use super::{File, Value};

/// An interface for converting from `Value` variants.
pub trait FromValue {
    /// Returns `Some` if the conversion was successful, `None` otherwise.
    fn from_value(value: &Value) -> Option<Self>;
}

impl FromValue for Value {
    fn from_value(value: &Value) -> Option<Self> {
        Some(value.clone())
    }
}

macro_rules! num_from_value {
    ($ty:ty) => {
        /// Casts from any of the numeric variants (`I64`, `U64`, `F64`) and converts from the
        /// `String` variant using `std::str::FromStr`.
        impl FromValue for $ty {
            fn from_value(value: &Value) -> Option<$ty> {
                match *value {
                    Value::I64(value) => NumCast::from(value),
                    Value::U64(value) => NumCast::from(value),
                    Value::F64(value) => NumCast::from(value),
                    Value::String(ref value) => FromStr::from_str(value).ok(),
                    _ => None,
                }
            }
        }
    }
}

num_from_value!(u8);
num_from_value!(u16);
num_from_value!(u32);
num_from_value!(u64);
num_from_value!(usize);
num_from_value!(i8);
num_from_value!(i16);
num_from_value!(i32);
num_from_value!(i64);
num_from_value!(isize);
num_from_value!(f32);
num_from_value!(f64);

/// Converts from any of the flat variants (`Null`, `Boolean`, `I64`, `U64`, `F64`, `String`).
///
/// `Null` is converted to an empty string. All other variants make use of `std::string::ToString`,
/// so the respective `Display` formatted results are used. For example, `Boolean` values are
/// converted into either `"false"` or `"true"`.
impl FromValue for String {
    fn from_value(value: &Value) -> Option<String> {
        match *value {
            Value::Null => Some(String::new()),
            Value::Boolean(value) => Some(value.to_string()),
            Value::I64(value) => Some(value.to_string()),
            Value::U64(value) => Some(value.to_string()),
            Value::F64(value) => Some(value.to_string()),
            Value::String(ref value) => Some(value.clone()),
            _ => None,
        }
    }
}

static FALSE_STRINGS: &'static [&'static str] = &["0", "f", "F", "false", "FALSE", "off", "OFF"];
static TRUE_STRINGS: &'static [&'static str] = &["1", "t", "T", "true", "TRUE", "on", "ON"];

/// Converts from common representations of `false` and `true`.
///
/// * `Boolean` values are mapped directly.
/// * `I64` and `U64` map `0` and `1` to `false` and `true` respectively.
/// * `String` maps `"0"`, `"f"`, `"F"`, `"false"`, `"FALSE"`, `"off"`, and `"OFF"` to `false`.
/// * `String` maps `"1"`, `"t"`, `"T"`, `"true"`, `"TRUE"`, `"on"`, and `"ON"` to `true`.
/// * All other variants return `None`.
impl FromValue for bool {
    fn from_value(value: &Value) -> Option<bool> {
        match *value {
            Value::Boolean(value) => Some(value),
            Value::I64(value) if value == 0 => Some(false),
            Value::I64(value) if value == 1 => Some(true),
            Value::U64(value) if value == 0 => Some(false),
            Value::U64(value) if value == 1 => Some(true),
            Value::String(ref value) if FALSE_STRINGS.contains(&&value[..]) => Some(false),
            Value::String(ref value) if TRUE_STRINGS.contains(&&value[..]) => Some(true),
            _ => None,
        }
    }
}

/// Extracts from `File` variant.
impl FromValue for File {
    fn from_value(value: &Value) -> Option<File> {
        match *value {
            Value::File(ref file) => Some(file.clone()),
            _ => None,
        }
    }
}

/// Converts the `Null` variant to `None` and delegates any other variants to `T::from_value`.
impl<T: FromValue> FromValue for Option<T> {
    fn from_value(value: &Value) -> Option<Option<T>> {
        match *value {
            Value::Null => Some(None),
            _ => T::from_value(value).map(|result| Some(result)),
        }
    }
}

/// Converts from `Array` variant.
impl<T: FromValue> FromValue for Vec<T> {
    fn from_value(value: &Value) -> Option<Vec<T>> {
        match *value {
            Value::Array(ref array) => {
                let mut vec = Vec::with_capacity(array.len());
                for value in array {
                    match T::from_value(value) {
                        Some(value) => vec.push(value),
                        None => return None,
                    }
                }
                Some(vec)
            },
            _ => None,
        }
    }
}

/// Converts using `Map::to_strict_map` if the variant is `Map`, returns `None` otherwise.
impl<T: FromValue> FromValue for BTreeMap<String, T> {
    fn from_value(value: &Value) -> Option<BTreeMap<String, T>> {
        match *value {
            Value::Map(ref map) => map.to_strict_map(),
            _ => None,
        }
    }
}
<commit_msg>Require `Sized` for `FromValue`<commit_after>use std::collections::BTreeMap;
use std::str::FromStr;

use num::NumCast;

use super::{File, Value};

/// An interface for converting from `Value` variants.
pub trait FromValue: Sized {
    /// Returns `Some` if the conversion was successful, `None` otherwise.
    fn from_value(value: &Value) -> Option<Self>;
}

impl FromValue for Value {
    fn from_value(value: &Value) -> Option<Self> {
        Some(value.clone())
    }
}

macro_rules! num_from_value {
    ($ty:ty) => {
        /// Casts from any of the numeric variants (`I64`, `U64`, `F64`) and converts from the
        /// `String` variant using `std::str::FromStr`.
        impl FromValue for $ty {
            fn from_value(value: &Value) -> Option<$ty> {
                match *value {
                    Value::I64(value) => NumCast::from(value),
                    Value::U64(value) => NumCast::from(value),
                    Value::F64(value) => NumCast::from(value),
                    Value::String(ref value) => FromStr::from_str(value).ok(),
                    _ => None,
                }
            }
        }
    }
}

num_from_value!(u8);
num_from_value!(u16);
num_from_value!(u32);
num_from_value!(u64);
num_from_value!(usize);
num_from_value!(i8);
num_from_value!(i16);
num_from_value!(i32);
num_from_value!(i64);
num_from_value!(isize);
num_from_value!(f32);
num_from_value!(f64);

/// Converts from any of the flat variants (`Null`, `Boolean`, `I64`, `U64`, `F64`, `String`).
///
/// `Null` is converted to an empty string. All other variants make use of `std::string::ToString`,
/// so the respective `Display` formatted results are used. For example, `Boolean` values are
/// converted into either `"false"` or `"true"`.
impl FromValue for String {
    fn from_value(value: &Value) -> Option<String> {
        match *value {
            Value::Null => Some(String::new()),
            Value::Boolean(value) => Some(value.to_string()),
            Value::I64(value) => Some(value.to_string()),
            Value::U64(value) => Some(value.to_string()),
            Value::F64(value) => Some(value.to_string()),
            Value::String(ref value) => Some(value.clone()),
            _ => None,
        }
    }
}

static FALSE_STRINGS: &'static [&'static str] = &["0", "f", "F", "false", "FALSE", "off", "OFF"];
static TRUE_STRINGS: &'static [&'static str] = &["1", "t", "T", "true", "TRUE", "on", "ON"];

/// Converts from common representations of `false` and `true`.
///
/// * `Boolean` values are mapped directly.
/// * `I64` and `U64` map `0` and `1` to `false` and `true` respectively.
/// * `String` maps `"0"`, `"f"`, `"F"`, `"false"`, `"FALSE"`, `"off"`, and `"OFF"` to `false`.
/// * `String` maps `"1"`, `"t"`, `"T"`, `"true"`, `"TRUE"`, `"on"`, and `"ON"` to `true`.
/// * All other variants return `None`.
impl FromValue for bool {
    fn from_value(value: &Value) -> Option<bool> {
        match *value {
            Value::Boolean(value) => Some(value),
            Value::I64(value) if value == 0 => Some(false),
            Value::I64(value) if value == 1 => Some(true),
            Value::U64(value) if value == 0 => Some(false),
            Value::U64(value) if value == 1 => Some(true),
            Value::String(ref value) if FALSE_STRINGS.contains(&&value[..]) => Some(false),
            Value::String(ref value) if TRUE_STRINGS.contains(&&value[..]) => Some(true),
            _ => None,
        }
    }
}

/// Extracts from `File` variant.
impl FromValue for File {
    fn from_value(value: &Value) -> Option<File> {
        match *value {
            Value::File(ref file) => Some(file.clone()),
            _ => None,
        }
    }
}

/// Converts the `Null` variant to `None` and delegates any other variants to `T::from_value`.
impl<T: FromValue> FromValue for Option<T> {
    fn from_value(value: &Value) -> Option<Option<T>> {
        match *value {
            Value::Null => Some(None),
            _ => T::from_value(value).map(|result| Some(result)),
        }
    }
}

/// Converts from `Array` variant.
impl<T: FromValue> FromValue for Vec<T> {
    fn from_value(value: &Value) -> Option<Vec<T>> {
        match *value {
            Value::Array(ref array) => {
                let mut vec = Vec::with_capacity(array.len());
                for value in array {
                    match T::from_value(value) {
                        Some(value) => vec.push(value),
                        None => return None,
                    }
                }
                Some(vec)
            },
            _ => None,
        }
    }
}

/// Converts using `Map::to_strict_map` if the variant is `Map`, returns `None` otherwise.
impl<T: FromValue> FromValue for BTreeMap<String, T> {
    fn from_value(value: &Value) -> Option<BTreeMap<String, T>> {
        match *value {
            Value::Map(ref map) => map.to_strict_map(),
            _ => None,
        }
    }
}
<|endoftext|>


<commit_before>use crate::actually_private::Private;
use alloc::borrow::Cow;
use alloc::string::String;
use core::fmt::{self, Debug, Display};
use core::marker::{PhantomData, PhantomPinned};
use core::mem::MaybeUninit;
use core::pin::Pin;
use core::slice;
use core::str::{self, Utf8Error};

extern "C" {
    #[link_name = "cxxbridge1$cxx_string$init"]
    fn string_init(this: &mut MaybeUninit<CxxString>, ptr: *const u8, len: usize);
    #[link_name = "cxxbridge1$cxx_string$destroy"]
    fn string_destroy(this: &mut MaybeUninit<CxxString>);
    #[link_name = "cxxbridge1$cxx_string$data"]
    fn string_data(this: &CxxString) -> *const u8;
    #[link_name = "cxxbridge1$cxx_string$length"]
    fn string_length(this: &CxxString) -> usize;
    #[link_name = "cxxbridge1$cxx_string$push"]
    fn string_push(this: Pin<&mut CxxString>, ptr: *const u8, len: usize);
}

/// Binding to C++ `std::string`.
///
/// # Invariants
///
/// As an invariant of this API and the static analysis of the cxx::bridge
/// macro, in Rust code we can never obtain a `CxxString` by value. C++'s string
/// requires a move constructor and may hold internal pointers, which is not
/// compatible with Rust's move behavior. Instead in Rust code we will only ever
/// look at a CxxString through a reference or smart pointer, as in `&CxxString`
/// or `UniquePtr<CxxString>`.
#[repr(C)]
pub struct CxxString {
    _private: [u8; 0],
    _pinned: PhantomData<PhantomPinned>,
}

/// Construct a C++ std::string on the Rust stack.
///
/// # Syntax
///
/// In statement position:
///
/// ```
/// # use cxx::let_cxx_string;
/// # let expression = "";
/// let_cxx_string!(var = expression);
/// ```
///
/// The `expression` may have any type that implements `AsRef<[u8]>`. Commonly
/// it will be a string literal, but for example `&[u8]` and `String` would work
/// as well.
///
/// The macro expands to something resembling `let $var: Pin<&mut CxxString> =
/// /*???*/;`. The resulting [`Pin`] can be deref'd to `&CxxString` as needed.
///
/// # Example
///
/// ```
/// use cxx::{let_cxx_string, CxxString};
///
/// fn f(s: &CxxString) {/* ... */}
///
/// fn main() {
///     let_cxx_string!(s = "example");
///     f(&s);
/// }
/// ```
#[macro_export]
macro_rules! let_cxx_string {
    ($var:ident = $value:expr $(,)?) => {
        let mut $var = $crate::private::StackString::new();
        #[allow(unused_mut, unused_unsafe)]
        let mut $var = match $value {
            let_cxx_string => unsafe { $var.init(let_cxx_string) },
        };
    };
}

impl CxxString {
    /// `CxxString` is not constructible via `new`. Instead, use the
    /// [`let_cxx_string!`] macro.
    pub fn new<T: Private>() -> Self {
        unreachable!()
    }

    /// Returns the length of the string in bytes.
    ///
    /// Matches the behavior of C++ [std::string::size][size].
    ///
    /// [size]: https://en.cppreference.com/w/cpp/string/basic_string/size
    pub fn len(&self) -> usize {
        unsafe { string_length(self) }
    }

    /// Returns true if `self` has a length of zero bytes.
    ///
    /// Matches the behavior of C++ [std::string::empty][empty].
    ///
    /// [empty]: https://en.cppreference.com/w/cpp/string/basic_string/empty
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a byte slice of this string's contents.
    pub fn as_bytes(&self) -> &[u8] {
        let data = self.as_ptr();
        let len = self.len();
        unsafe { slice::from_raw_parts(data, len) }
    }

    /// Produces a pointer to the first character of the string.
    ///
    /// Matches the behavior of C++ [std::string::data][data].
    ///
    /// Note that the return type may look like `const char *` but is not a
    /// `const char *` in the typical C sense, as C++ strings may contain
    /// internal null bytes. As such, the returned pointer only makes sense as a
    /// string in combination with the length returned by [`len()`][len].
    ///
    /// [data]: https://en.cppreference.com/w/cpp/string/basic_string/data
    /// [len]: #method.len
    pub fn as_ptr(&self) -> *const u8 {
        unsafe { string_data(self) }
    }

    /// Validates that the C++ string contains UTF-8 data and produces a view of
    /// it as a Rust &str, otherwise an error.
    pub fn to_str(&self) -> Result<&str, Utf8Error> {
        str::from_utf8(self.as_bytes())
    }

    /// If the contents of the C++ string are valid UTF-8, this function returns
    /// a view as a Cow::Borrowed &str. Otherwise replaces any invalid UTF-8
    /// sequences with the U+FFFD [replacement character] and returns a
    /// Cow::Owned String.
    ///
    /// [replacement character]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html
    pub fn to_string_lossy(&self) -> Cow<str> {
        String::from_utf8_lossy(self.as_bytes())
    }

    /// Appends a given string slice onto the end of this C++ string.
    pub fn push_str(self: Pin<&mut Self>, s: &str) {
        self.push_bytes(s.as_bytes());
    }

    /// Appends arbitrary bytes onto the end of this C++ string.
    pub fn push_bytes(self: Pin<&mut Self>, bytes: &[u8]) {
        unsafe { string_push(self, bytes.as_ptr(), bytes.len()) }
    }
}

impl Display for CxxString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(self.to_string_lossy().as_ref(), f)
    }
}

impl Debug for CxxString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self.to_string_lossy().as_ref(), f)
    }
}

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

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

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

#[doc(hidden)]
#[repr(C)]
pub struct StackString {
    // Static assertions in cxx.cc validate that this is large enough and
    // aligned enough.
    space: MaybeUninit<[usize; 8]>,
}

impl StackString {
    pub fn new() -> Self {
        StackString {
            space: MaybeUninit::uninit(),
        }
    }

    pub unsafe fn init(&mut self, value: impl AsRef<[u8]>) -> Pin<&mut CxxString> {
        let value = value.as_ref();
        let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
        string_init(this, value.as_ptr(), value.len());
        Pin::new_unchecked(&mut *this.as_mut_ptr())
    }
}

impl Drop for StackString {
    fn drop(&mut self) {
        unsafe {
            let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
            string_destroy(this);
        }
    }
}
<commit_msg>Avoid bringing let_cxx_string's variable name into scope too early<commit_after>use crate::actually_private::Private;
use alloc::borrow::Cow;
use alloc::string::String;
use core::fmt::{self, Debug, Display};
use core::marker::{PhantomData, PhantomPinned};
use core::mem::MaybeUninit;
use core::pin::Pin;
use core::slice;
use core::str::{self, Utf8Error};

extern "C" {
    #[link_name = "cxxbridge1$cxx_string$init"]
    fn string_init(this: &mut MaybeUninit<CxxString>, ptr: *const u8, len: usize);
    #[link_name = "cxxbridge1$cxx_string$destroy"]
    fn string_destroy(this: &mut MaybeUninit<CxxString>);
    #[link_name = "cxxbridge1$cxx_string$data"]
    fn string_data(this: &CxxString) -> *const u8;
    #[link_name = "cxxbridge1$cxx_string$length"]
    fn string_length(this: &CxxString) -> usize;
    #[link_name = "cxxbridge1$cxx_string$push"]
    fn string_push(this: Pin<&mut CxxString>, ptr: *const u8, len: usize);
}

/// Binding to C++ `std::string`.
///
/// # Invariants
///
/// As an invariant of this API and the static analysis of the cxx::bridge
/// macro, in Rust code we can never obtain a `CxxString` by value. C++'s string
/// requires a move constructor and may hold internal pointers, which is not
/// compatible with Rust's move behavior. Instead in Rust code we will only ever
/// look at a CxxString through a reference or smart pointer, as in `&CxxString`
/// or `UniquePtr<CxxString>`.
#[repr(C)]
pub struct CxxString {
    _private: [u8; 0],
    _pinned: PhantomData<PhantomPinned>,
}

/// Construct a C++ std::string on the Rust stack.
///
/// # Syntax
///
/// In statement position:
///
/// ```
/// # use cxx::let_cxx_string;
/// # let expression = "";
/// let_cxx_string!(var = expression);
/// ```
///
/// The `expression` may have any type that implements `AsRef<[u8]>`. Commonly
/// it will be a string literal, but for example `&[u8]` and `String` would work
/// as well.
///
/// The macro expands to something resembling `let $var: Pin<&mut CxxString> =
/// /*???*/;`. The resulting [`Pin`] can be deref'd to `&CxxString` as needed.
///
/// # Example
///
/// ```
/// use cxx::{let_cxx_string, CxxString};
///
/// fn f(s: &CxxString) {/* ... */}
///
/// fn main() {
///     let_cxx_string!(s = "example");
///     f(&s);
/// }
/// ```
#[macro_export]
macro_rules! let_cxx_string {
    ($var:ident = $value:expr $(,)?) => {
        let mut cxx_stack_string = $crate::private::StackString::new();
        #[allow(unused_mut, unused_unsafe)]
        let mut $var = match $value {
            let_cxx_string => unsafe { cxx_stack_string.init(let_cxx_string) },
        };
    };
}

impl CxxString {
    /// `CxxString` is not constructible via `new`. Instead, use the
    /// [`let_cxx_string!`] macro.
    pub fn new<T: Private>() -> Self {
        unreachable!()
    }

    /// Returns the length of the string in bytes.
    ///
    /// Matches the behavior of C++ [std::string::size][size].
    ///
    /// [size]: https://en.cppreference.com/w/cpp/string/basic_string/size
    pub fn len(&self) -> usize {
        unsafe { string_length(self) }
    }

    /// Returns true if `self` has a length of zero bytes.
    ///
    /// Matches the behavior of C++ [std::string::empty][empty].
    ///
    /// [empty]: https://en.cppreference.com/w/cpp/string/basic_string/empty
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a byte slice of this string's contents.
    pub fn as_bytes(&self) -> &[u8] {
        let data = self.as_ptr();
        let len = self.len();
        unsafe { slice::from_raw_parts(data, len) }
    }

    /// Produces a pointer to the first character of the string.
    ///
    /// Matches the behavior of C++ [std::string::data][data].
    ///
    /// Note that the return type may look like `const char *` but is not a
    /// `const char *` in the typical C sense, as C++ strings may contain
    /// internal null bytes. As such, the returned pointer only makes sense as a
    /// string in combination with the length returned by [`len()`][len].
    ///
    /// [data]: https://en.cppreference.com/w/cpp/string/basic_string/data
    /// [len]: #method.len
    pub fn as_ptr(&self) -> *const u8 {
        unsafe { string_data(self) }
    }

    /// Validates that the C++ string contains UTF-8 data and produces a view of
    /// it as a Rust &str, otherwise an error.
    pub fn to_str(&self) -> Result<&str, Utf8Error> {
        str::from_utf8(self.as_bytes())
    }

    /// If the contents of the C++ string are valid UTF-8, this function returns
    /// a view as a Cow::Borrowed &str. Otherwise replaces any invalid UTF-8
    /// sequences with the U+FFFD [replacement character] and returns a
    /// Cow::Owned String.
    ///
    /// [replacement character]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html
    pub fn to_string_lossy(&self) -> Cow<str> {
        String::from_utf8_lossy(self.as_bytes())
    }

    /// Appends a given string slice onto the end of this C++ string.
    pub fn push_str(self: Pin<&mut Self>, s: &str) {
        self.push_bytes(s.as_bytes());
    }

    /// Appends arbitrary bytes onto the end of this C++ string.
    pub fn push_bytes(self: Pin<&mut Self>, bytes: &[u8]) {
        unsafe { string_push(self, bytes.as_ptr(), bytes.len()) }
    }
}

impl Display for CxxString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(self.to_string_lossy().as_ref(), f)
    }
}

impl Debug for CxxString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self.to_string_lossy().as_ref(), f)
    }
}

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

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

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

#[doc(hidden)]
#[repr(C)]
pub struct StackString {
    // Static assertions in cxx.cc validate that this is large enough and
    // aligned enough.
    space: MaybeUninit<[usize; 8]>,
}

impl StackString {
    pub fn new() -> Self {
        StackString {
            space: MaybeUninit::uninit(),
        }
    }

    pub unsafe fn init(&mut self, value: impl AsRef<[u8]>) -> Pin<&mut CxxString> {
        let value = value.as_ref();
        let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
        string_init(this, value.as_ptr(), value.len());
        Pin::new_unchecked(&mut *this.as_mut_ptr())
    }
}

impl Drop for StackString {
    fn drop(&mut self) {
        unsafe {
            let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
            string_destroy(this);
        }
    }
}
<|endoftext|>


<commit_before>// Based on the original C++ farmhashna.cc
use platform::*;
use farmhashna_shared::*;
use farmhashcc_shared;
use std::mem;

// renamed from hash64 to make it clearer elsewhere which is being called
pub fn na_hash64(mut s: &[u8]) -> u64 {
    let len = s.len() as usize;
    const SEED: u64 = 81;
    if len <= 32 {
        if len <= 16 {
            return hash_len_0_to_16(s);
        } else {
            return hash_len_17_to_32(s);
        }
    } else if len <= 64{
        return hash_len_33_to_64(s);
    }
    // For strings over 64 bytes we loop.  Internal state consists of
    // 56 bytes: v, w, x, y, and z.
    let mut x = SEED;
    let mut y: u64 = 2480279821605975764; // y := (seed*k1) + 113
    let mut z = shift_mix(y.wrapping_mul(K2).wrapping_add(113)).wrapping_mul(K2);
    let mut v = Uint128 {first:0, second:0};
    let mut w = Uint128 {first:0, second:0};

    x = x.wrapping_mul(K2).wrapping_add(fetch64(s));

    let last64 = &s[len - 64..];
    while {
        x = rotate64(x.wrapping_add(y).wrapping_add(v.first).wrapping_add(fetch64(&s[8..])), 37).wrapping_mul(K1);
        y = rotate64(y.wrapping_add(v.second).wrapping_add(fetch64(&s[48..])), 42).wrapping_mul(K1);
        x ^= w.second;
        y = y.wrapping_add(v.first).wrapping_add(fetch64(&s[40..]));
        z = rotate64(z.wrapping_add(w.first), 33).wrapping_mul(K1);
        v = farmhashcc_shared::weak_hash_len_32_with_seeds_bytes(&s,v.second.wrapping_mul(K1), x.wrapping_add(w.first));
        w = farmhashcc_shared::weak_hash_len_32_with_seeds_bytes(&s[32..],z.wrapping_add(w.second), y.wrapping_add(fetch64(&s[16..])));

        mem::swap(&mut z, &mut x);
        s = &s[64..];
        s.len() >= 64
    } {}

    let mul = K1 + ((z & 0xff) << 1);

    // Make s point to the last 64 bytes of input.
    s = last64;
    w.first = w.first.wrapping_add(((len as u64 - 1) & 63));
    v.first = v.first.wrapping_add(w.first);
    w.first = w.first.wrapping_add(v.first);
    x = rotate64(x.wrapping_add(y)
        .wrapping_add(v.first.wrapping_add(fetch64(&s[8..]))), 37).wrapping_mul(mul);
    y = rotate64(y.wrapping_add(v.second).wrapping_add(fetch64(&s[48..])), 42).wrapping_mul(mul);
    x ^= w.second.wrapping_mul(9);
    y = y.wrapping_add(v.first.wrapping_mul(9).wrapping_add(fetch64(&s[40..])));
    z = rotate64(z.wrapping_add(w.first), 33).wrapping_mul(mul);
    v = farmhashcc_shared::weak_hash_len_32_with_seeds_bytes(&s, v.second.wrapping_mul(mul),
        x.wrapping_add(w.first));
    w = farmhashcc_shared::weak_hash_len_32_with_seeds_bytes(&s[32..], z.wrapping_add(w.second),
        y.wrapping_add(fetch64(&s[16..])));
    mem::swap(&mut z, &mut x);
    return hash_len_16_mul(hash_len_16_mul(v.first, w.first, mul).wrapping_add(shift_mix(y).wrapping_mul(K0).wrapping_add(z)),
        hash_len_16_mul(v.second, w.second, mul).wrapping_add(x),
        mul)
}

pub fn na_hash64_with_seed(s: &[u8], seed: u64) -> u64 {
    return na_hash64_with_seeds(s, K2, seed)
}

pub fn na_hash64_with_seeds(s: &[u8], seed0: u64, seed1: u64) -> u64 {
    return hash_len_16(na_hash64(s)-seed0, seed1)
}
<commit_msg>Prevent errors in debug builds by using one wrapping_sub call.<commit_after>// Based on the original C++ farmhashna.cc
use platform::*;
use farmhashna_shared::*;
use farmhashcc_shared;
use std::mem;

// renamed from hash64 to make it clearer elsewhere which is being called
pub fn na_hash64(mut s: &[u8]) -> u64 {
    let len = s.len() as usize;
    const SEED: u64 = 81;
    if len <= 32 {
        if len <= 16 {
            return hash_len_0_to_16(s);
        } else {
            return hash_len_17_to_32(s);
        }
    } else if len <= 64{
        return hash_len_33_to_64(s);
    }
    // For strings over 64 bytes we loop.  Internal state consists of
    // 56 bytes: v, w, x, y, and z.
    let mut x = SEED;
    let mut y: u64 = 2480279821605975764; // y := (seed*k1) + 113
    let mut z = shift_mix(y.wrapping_mul(K2).wrapping_add(113)).wrapping_mul(K2);
    let mut v = Uint128 {first:0, second:0};
    let mut w = Uint128 {first:0, second:0};

    x = x.wrapping_mul(K2).wrapping_add(fetch64(s));

    let last64 = &s[len - 64..];
    while {
        x = rotate64(x.wrapping_add(y).wrapping_add(v.first).wrapping_add(fetch64(&s[8..])), 37).wrapping_mul(K1);
        y = rotate64(y.wrapping_add(v.second).wrapping_add(fetch64(&s[48..])), 42).wrapping_mul(K1);
        x ^= w.second;
        y = y.wrapping_add(v.first).wrapping_add(fetch64(&s[40..]));
        z = rotate64(z.wrapping_add(w.first), 33).wrapping_mul(K1);
        v = farmhashcc_shared::weak_hash_len_32_with_seeds_bytes(&s,v.second.wrapping_mul(K1), x.wrapping_add(w.first));
        w = farmhashcc_shared::weak_hash_len_32_with_seeds_bytes(&s[32..],z.wrapping_add(w.second), y.wrapping_add(fetch64(&s[16..])));

        mem::swap(&mut z, &mut x);
        s = &s[64..];
        s.len() >= 64
    } {}

    let mul = K1 + ((z & 0xff) << 1);

    // Make s point to the last 64 bytes of input.
    s = last64;
    w.first = w.first.wrapping_add(((len as u64 - 1) & 63));
    v.first = v.first.wrapping_add(w.first);
    w.first = w.first.wrapping_add(v.first);
    x = rotate64(x.wrapping_add(y)
        .wrapping_add(v.first.wrapping_add(fetch64(&s[8..]))), 37).wrapping_mul(mul);
    y = rotate64(y.wrapping_add(v.second).wrapping_add(fetch64(&s[48..])), 42).wrapping_mul(mul);
    x ^= w.second.wrapping_mul(9);
    y = y.wrapping_add(v.first.wrapping_mul(9).wrapping_add(fetch64(&s[40..])));
    z = rotate64(z.wrapping_add(w.first), 33).wrapping_mul(mul);
    v = farmhashcc_shared::weak_hash_len_32_with_seeds_bytes(&s, v.second.wrapping_mul(mul),
        x.wrapping_add(w.first));
    w = farmhashcc_shared::weak_hash_len_32_with_seeds_bytes(&s[32..], z.wrapping_add(w.second),
        y.wrapping_add(fetch64(&s[16..])));
    mem::swap(&mut z, &mut x);
    return hash_len_16_mul(hash_len_16_mul(v.first, w.first, mul).wrapping_add(shift_mix(y).wrapping_mul(K0).wrapping_add(z)),
        hash_len_16_mul(v.second, w.second, mul).wrapping_add(x),
        mul)
}

pub fn na_hash64_with_seed(s: &[u8], seed: u64) -> u64 {
    return na_hash64_with_seeds(s, K2, seed)
}

pub fn na_hash64_with_seeds(s: &[u8], seed0: u64, seed1: u64) -> u64 {
    return hash_len_16(na_hash64(s).wrapping_sub(seed0), seed1)
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::fs::File;
use std::error::Error;
use std::fs;
use std::fmt;
use std::io::{Seek, Read, SeekFrom};
use std::collections::HashMap;

#[derive(Debug)]
pub enum FsError {
    FileNotFound,
    InvalidDirectory
}
impl Error for FsError {
    fn description(&self) -> &str {
        match *self {
            FsError::FileNotFound => "the folder does not exist or cannot be read from",
            FsError::InvalidDirectory => "the specified directory is not a valid directory",
        }
    }
}
impl fmt::Display for FsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FsError::FileNotFound => write!(f, "the folder specified could not be found or read from"),
            FsError::InvalidDirectory => write!(f, "the specified directory is not a valid directory"),
        }
    }
}

#[derive(Debug)]
pub struct FileSystem {
    path: PathBuf,
    mainfile: MainFile,
    indices: HashMap<u32, IndexFile>
}

#[derive(Debug)]
pub struct MainFile {
    file: Option<File>
}

#[derive(Debug)]
pub struct IndexFile {
    file: File
}

#[derive(Debug,Clone)]
pub struct IndexEntry {
    id: u32,
    size: u32,
    offset: u64
}

impl IndexEntry {
    pub fn id(&self) -> u32 {
        self.id
    }
    pub fn size(&self) -> u32 {
        self.size
    }
    pub fn offset(&self) -> u64 {
        self.offset
    }
}

impl IndexFile {
    pub fn last_entry(&self) -> u64 {
         self.file.metadata().unwrap().len() / 6u64
    }

    pub fn entry(&mut self, id: u32) -> Option<IndexEntry> {
        let ref mut file = self.file;
        let mut tmp: [u8; 6] = [0; 6];

        // Seek to the proper position and read into the temp buffer
        // TODO this must be done safer.. what if it doesn't exist?
        file.seek(SeekFrom::Start(id as u64 * 6u64));
        file.read(&mut tmp);

        // Decode the size and offset from the temp buffer
        let size: u32 = ((tmp[0] as u32) << 16) | ((tmp[1] as u32) << 8) | (tmp[2] as u32);
        let offset: u64 = ((tmp[3] as u64) << 16) | ((tmp[4] as u64) << 8) | (tmp[5] as u64);

        Some(IndexEntry {id: id, size: size, offset: offset * 520u64})
    }
}

impl FileSystem {
    pub fn new(string: &'static str) -> Result<FileSystem, FsError> {
        // Declare some nice variables!!!
        let path = PathBuf::from(string);
        let metadata = fs::metadata(&path);

        // Make sure the folder exists
        if !metadata.is_ok() {
            return Err(FsError::FileNotFound);
        }

        // Make sure it is a directory
        if !metadata.unwrap().is_dir() {
            return Err(FsError::InvalidDirectory);
        }

        // Create mainfile path
        let mut mainfile_path = PathBuf::from(string);
        mainfile_path.push("main_file_cache.dat2");

        // Find all valid index files
        let mut indices: HashMap<u32, IndexFile> = HashMap::new();
        let entries = fs::read_dir(&path).unwrap();
        for entry in entries {
            let e = entry.unwrap();
            let fname = e.file_name().into_string().unwrap();

            // Is this an index?
            if fname.starts_with("main_file_cache.idx") {
                // Parse the index id into an integer
                let idx = fname[19..].parse::<u32>().unwrap();

                // Add the index file to our map with indices
                indices.insert(idx, IndexFile {file: File::open(e.path()).unwrap()});
            }
        }

        // Create the filesystem object and return it
        let file = File::open(mainfile_path).ok();
        let mainfile = MainFile{file: file};

        Ok(FileSystem {path: path, mainfile: mainfile, indices: indices})
    }

    /// Gets the mainfile, that is, the main_file_cache.dat2 entry in the folder
    /// that holds the actual binary data of the filesystem entries.
    pub fn mainfile(&mut self) -> &mut MainFile {
        &mut self.mainfile
    }

    /// Gets an index with a specific id if it exists. The index can only exist if the file exists
    /// on the file system.
    pub fn index(&mut self, index: u32) -> Option<&mut IndexFile> {
        self.indices.get_mut(&index)
    }
}

impl MainFile {
    /// Checks if the file exists.
    pub fn exists(&self) -> bool {
        self.file.is_some()
    }

    /// Gets the backing file, if existant. Returns a new instance with a fresh seek pointer.
    pub fn file(&mut self) -> Option<&mut File> {
        self.file.as_mut()
    }

    /// Calculates the number of data blocks in the mainfile (if existant). This is done by
    /// taking the file size and dividing that by 520 (rouding up), because each block
    /// takes up 520 bytes of data.
    pub fn num_blocks(&self) -> Option<u64> {
        match self.file {
            Some(ref x) => Some((x.metadata().unwrap().len() + 519u64) / 520u64),
            None => None
        }
    }

    /// Reads a block of data, specified by the block id. The data is read at 520 * block_id
    /// and is exactly 520 bytes big. It is not guaranteed all 520 bytes are occupied if the
    /// block is the last one, thus possible to be trimmed.
    pub fn read_block(&mut self, block: u32) -> Option<[u8; 520]> {
        // Do we have a valid file?
        if self.file.is_none() {
            return None;
        }

        let mut data: [u8; 520] = [0; 520];
        let file = self.file().unwrap();

        // Seek to the right position and read the data
        file.seek(SeekFrom::Start(block as u64 * 520u64));
        file.read(&mut data);

        return Some(data);
    }
}
<commit_msg>Document methods of indexinfo<commit_after>use std::path::PathBuf;
use std::fs::File;
use std::error::Error;
use std::fs;
use std::fmt;
use std::io::{Seek, Read, SeekFrom};
use std::collections::HashMap;

#[derive(Debug)]
pub enum FsError {
    FileNotFound,
    InvalidDirectory
}
impl Error for FsError {
    fn description(&self) -> &str {
        match *self {
            FsError::FileNotFound => "the folder does not exist or cannot be read from",
            FsError::InvalidDirectory => "the specified directory is not a valid directory",
        }
    }
}
impl fmt::Display for FsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FsError::FileNotFound => write!(f, "the folder specified could not be found or read from"),
            FsError::InvalidDirectory => write!(f, "the specified directory is not a valid directory"),
        }
    }
}

#[derive(Debug)]
pub struct FileSystem {
    path: PathBuf,
    mainfile: MainFile,
    indices: HashMap<u32, IndexFile>
}

#[derive(Debug)]
pub struct MainFile {
    file: Option<File>
}

#[derive(Debug)]
pub struct IndexFile {
    file: File
}

#[derive(Debug,Clone)]
pub struct IndexEntry {
    id: u32,
    size: u32,
    offset: u64
}

impl IndexEntry {
    /// Gets the id of this block.
    pub fn id(&self) -> u32 {
        self.id
    }

    /// Gets the absolute size of the entry data, not counting the 8-10
    /// byte header in the blocks.
    pub fn size(&self) -> u32 {
        self.size
    }

    /// Gets the absolute offset of the very first 520-byte block of this
    /// entry in the main data file.
    pub fn offset(&self) -> u64 {
        self.offset
    }
}

impl IndexFile {
    pub fn last_entry(&self) -> u64 {
         self.file.metadata().unwrap().len() / 6u64
    }

    pub fn entry(&mut self, id: u32) -> Option<IndexEntry> {
        let ref mut file = self.file;
        let mut tmp: [u8; 6] = [0; 6];

        // Seek to the proper position and read into the temp buffer
        // TODO this must be done safer.. what if it doesn't exist?
        file.seek(SeekFrom::Start(id as u64 * 6u64));
        file.read(&mut tmp);

        // Decode the size and offset from the temp buffer
        let size: u32 = ((tmp[0] as u32) << 16) | ((tmp[1] as u32) << 8) | (tmp[2] as u32);
        let offset: u64 = ((tmp[3] as u64) << 16) | ((tmp[4] as u64) << 8) | (tmp[5] as u64);

        Some(IndexEntry {id: id, size: size, offset: offset * 520u64})
    }
}

impl FileSystem {
    pub fn new(string: &'static str) -> Result<FileSystem, FsError> {
        // Declare some nice variables!!!
        let path = PathBuf::from(string);
        let metadata = fs::metadata(&path);

        // Make sure the folder exists
        if !metadata.is_ok() {
            return Err(FsError::FileNotFound);
        }

        // Make sure it is a directory
        if !metadata.unwrap().is_dir() {
            return Err(FsError::InvalidDirectory);
        }

        // Create mainfile path
        let mut mainfile_path = PathBuf::from(string);
        mainfile_path.push("main_file_cache.dat2");

        // Find all valid index files
        let mut indices: HashMap<u32, IndexFile> = HashMap::new();
        let entries = fs::read_dir(&path).unwrap();
        for entry in entries {
            let e = entry.unwrap();
            let fname = e.file_name().into_string().unwrap();

            // Is this an index?
            if fname.starts_with("main_file_cache.idx") {
                // Parse the index id into an integer
                let idx = fname[19..].parse::<u32>().unwrap();

                // Add the index file to our map with indices
                indices.insert(idx, IndexFile {file: File::open(e.path()).unwrap()});
            }
        }

        // Create the filesystem object and return it
        let file = File::open(mainfile_path).ok();
        let mainfile = MainFile{file: file};

        Ok(FileSystem {path: path, mainfile: mainfile, indices: indices})
    }

    /// Gets the mainfile, that is, the main_file_cache.dat2 entry in the folder
    /// that holds the actual binary data of the filesystem entries.
    pub fn mainfile(&mut self) -> &mut MainFile {
        &mut self.mainfile
    }

    /// Gets an index with a specific id if it exists. The index can only exist if the file exists
    /// on the file system.
    pub fn index(&mut self, index: u32) -> Option<&mut IndexFile> {
        self.indices.get_mut(&index)
    }
}

impl MainFile {
    /// Checks if the file exists.
    pub fn exists(&self) -> bool {
        self.file.is_some()
    }

    /// Gets the backing file, if existant. Returns a new instance with a fresh seek pointer.
    pub fn file(&mut self) -> Option<&mut File> {
        self.file.as_mut()
    }

    /// Calculates the number of data blocks in the mainfile (if existant). This is done by
    /// taking the file size and dividing that by 520 (rouding up), because each block
    /// takes up 520 bytes of data.
    pub fn num_blocks(&self) -> Option<u64> {
        match self.file {
            Some(ref x) => Some((x.metadata().unwrap().len() + 519u64) / 520u64),
            None => None
        }
    }

    /// Reads a block of data, specified by the block id. The data is read at 520 * block_id
    /// and is exactly 520 bytes big. It is not guaranteed all 520 bytes are occupied if the
    /// block is the last one, thus possible to be trimmed.
    pub fn read_block(&mut self, block: u32) -> Option<[u8; 520]> {
        // Do we have a valid file?
        if self.file.is_none() {
            return None;
        }

        let mut data: [u8; 520] = [0; 520];
        let file = self.file().unwrap();

        // Seek to the right position and read the data
        file.seek(SeekFrom::Start(block as u64 * 520u64));
        file.read(&mut data);

        return Some(data);
    }
}
<|endoftext|>


<commit_before>// Generators
use std::marker::PhantomData;
use std::mem::size_of;

use data::*;

pub struct BoolGenerator;
pub struct IntGenerator<N>(PhantomData<N>);
pub struct VecGenerator<G>(G);

pub struct Filtered<G, F>(G, F);
pub struct Const<V>(V);

pub trait Generator {
    type Item;
    fn generate(&self, source: &mut InfoTap) -> Maybe<Self::Item>;

    fn filter<F: Fn(&Self::Item) -> bool>(self, pred: F) -> Filtered<Self, F>
    where
        Self: Sized,
    {
        Filtered(self, pred)
    }
}

pub fn booleans() -> BoolGenerator {
    BoolGenerator
}
pub fn u8s() -> IntGenerator<u8> {
    IntGenerator(PhantomData)
}
pub fn vecs<G>(inner: G) -> VecGenerator<G> {
    VecGenerator(inner)
}

pub fn consts<V>(val: V) -> Const<V> {
    Const(val)
}

impl<G: Generator> Generator for VecGenerator<G> {
    type Item = Vec<G::Item>;
    fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
        let mut result = Vec::new();
        let bs = booleans();
        while bs.generate(src)? {
            let item = self.0.generate(src)?;
            result.push(item)
        }

        Ok(result)
    }
}

impl Generator for BoolGenerator {
    type Item = bool;
    fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
        src.next_byte().map(|next| next >= 0x80)
    }
}

impl Generator for IntGenerator<u8> {
    type Item = u8;
    fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
        assert!(size_of::<u8>() == 1);
        let nbytes = size_of::<u8>() / size_of::<u8>();
        let mut val: u8 = 0;
        for _ in 0..nbytes {
            val = val.wrapping_shl(8) | src.next_byte()?;
        }
        // src.next_byte().map(|next| next >= 0x80)
        Ok(val)
    }
}

impl<G: Generator, F: Fn(&G::Item) -> bool> Generator for Filtered<G, F> {
    type Item = G::Item;
    fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
        let &Filtered(ref gen, ref pred) = self;
        let val = gen.generate(src)?;
        if pred(&val) {
            Ok(val)
        } else {
            Err(DataError::SkipItem)
        }
    }
}

impl<V: Clone> Generator for Const<V> {
    type Item = V;
    fn generate(&self, _: &mut InfoTap) -> Maybe<Self::Item> {
        Ok(self.0.clone())
    }
}

pub fn find_minimal<G: Generator, F: Fn(G::Item) -> bool>(
    gen: &G,
    pool: InfoPool,
    check: F,
) -> InfoPool {
    minimize(&pool, &|mut t| {
        gen.generate(&mut t).map(|v| check(v)).unwrap_or(false)
    }).unwrap_or(pool)
}

#[cfg(test)]
mod tests {
    extern crate env_logger;
    use rand::random;
    use std::iter;
    use std::fmt;
    use super::*;
    use data::InfoPool;
    const SHORT_VEC_SIZE: usize = 256;

    fn gen_random_vec() -> Vec<u8> {
        (0..SHORT_VEC_SIZE).map(|_| random()).collect::<Vec<u8>>()
    }

    fn should_generate_same_output_given_same_input<G: Generator>(gen: G)
    where
        G::Item: fmt::Debug + PartialEq,
    {
        for (p0, p1, v0, v1) in iter::repeat(())
            .map(|_| gen_random_vec())
            .map(|v0| (InfoPool::of_vec(v0.clone()), InfoPool::of_vec(v0)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (p0, p1, v0, v1))
                })
            })
            .take(100)
        {
            assert!(v0 == v1, "({:?} == {:?}) -> ({:?} == {:?})", p0, p1, v0, v1);
        }
    }

    fn usually_generates_different_output_for_different_inputs<G: Generator>(gen: G)
    where
        G::Item: PartialEq,
    {
        let nitems = 100;
        let differing = iter::repeat(())
            .map(|_| (gen_random_vec(), gen_random_vec()))
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .map(|(v0, v1)| (InfoPool::of_vec(v0), InfoPool::of_vec(v1)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (v0, v1))
                })
            })
            .take(nitems)
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .count();
        assert!(differing > 0, "Differing items:{} > 0", differing);

    }

    // Mostly only useful for scalar quantities. For collections, we basically say:
    // `while booleans() { elemnt() }`
    // So because booleans are imprecisly generated (ie: a pool of [0xff] ~ [0x80]),
    // the source and result can have a differing ordering.
    fn should_partially_order_same_as_source<G: Generator>(gen: G)
    where
        G::Item: PartialOrd + fmt::Debug,
    {
        let nitems = 100;
        for (p0, p1, v0, v1) in iter::repeat(())
            .map(|_| (gen_random_vec(), gen_random_vec()))
            .filter(|&(ref v0, ref v1)| v0 < v1)
            .map(|(v0, v1)| (InfoPool::of_vec(v0), InfoPool::of_vec(v1)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (p0, p1, v0, v1))
                })
            })
            .take(nitems)
        {
            assert!(v0 <= v1, "({:?} == {:?}) -> ({:?} == {:?})", p0, p1, v0, v1);
        }
    }

    #[test]
    fn consts_should_generate_same_values() {
        let v1 = gen_random_vec();
        let gen = consts("fourty two");
        assert_eq!(
            gen.generate(&mut InfoPool::of_vec(v1).tap()),
            Ok("fourty two")
        );
    }

    // If only I had some kind of property testing library.
    #[test]
    fn bools_should_generate_false_booleans_from_zeros() {
        let v1 = vec![0];
        let bools = booleans();
        assert_eq!(bools.generate(&mut InfoPool::of_vec(v1).tap()), Ok(false));
    }

    #[test]
    fn bools_should_generate_true_booleans_from_saturated_values() {
        let v1 = vec![0xff];
        let bools = booleans();
        assert_eq!(bools.generate(&mut InfoPool::of_vec(v1).tap()), Ok(true));
    }

    fn should_minimize_to<G: Generator>(gen: G, expected: G::Item)
    where
        G::Item: fmt::Debug + PartialEq,
    {
        let mut p;
        loop {
            p = InfoPool::random_of_size(SHORT_VEC_SIZE);
            match gen.generate(&mut p.tap()) {
                Ok(_) => break,
                Err(DataError::SkipItem) => (),
                Err(DataError::PoolExhausted) => panic!("Not enough pool to generate data"),
            }
        }
        debug!("Before: {:?}", p);
        let p = find_minimal(&gen, p, |_| true);
        debug!("After: {:?}", p);

        let val = gen.generate(&mut p.tap()).expect("generated value");
        assert_eq!(val, expected);

    }
    #[test]
    fn bools_should_generate_same_output_given_same_input() {
        should_generate_same_output_given_same_input(booleans())
    }

    // These really need to be proper statistical tests.
    #[test]
    fn bools_usually_generates_different_output_for_different_inputs() {
        usually_generates_different_output_for_different_inputs(booleans())
    }

    #[test]
    fn bools_minimize_to_false() {
        should_minimize_to(booleans(), false)
    }

    #[test]
    fn bools_should_partially_order_same_as_source() {
        should_partially_order_same_as_source(booleans())
    }

    #[test]
    fn vecs_should_generate_same_output_given_same_input() {
        should_generate_same_output_given_same_input(vecs(booleans()));
    }

    #[test]
    fn vecs_usually_generates_different_output_for_different_inputs() {
        usually_generates_different_output_for_different_inputs(vecs(booleans()))
    }

    #[test]
    fn vec_bools_minimize_to_empty() {
        env_logger::init().unwrap_or(());
        should_minimize_to(vecs(booleans()), vec![])
    }

    #[test]
    fn vec_bools_can_minimise_with_predicate() {
        env_logger::init().unwrap_or(());
        should_minimize_to(
            vecs(booleans()).filter(|v| v.len() > 2),
            vec![false, false, false],
        );
    }

    #[test]
    fn u8s_should_generate_same_output_given_same_input() {
        should_generate_same_output_given_same_input(u8s())
    }

    // These really need to be proper statistical tests.
    #[test]
    fn u8s_usually_generates_different_output_for_different_inputs() {
        usually_generates_different_output_for_different_inputs(u8s());
    }

    #[test]
    fn u8s_minimize_to_zero() {
        should_minimize_to(u8s(), 0);
    }

    #[test]
    fn u8s_should_partially_order_same_as_source() {
        should_partially_order_same_as_source(u8s());
    }

    #[test]
    fn filter_should_pass_through_when_true() {
        let gen = consts(()).filter(|&_| true);
        let p = InfoPool::random_of_size(4);
        assert_eq!(gen.generate(&mut p.tap()), Ok(()));
    }

    #[test]
    fn filter_should_skip_when_false() {
        let gen = consts(()).filter(|&_| false);
        let p = InfoPool::random_of_size(4);
        assert_eq!(gen.generate(&mut p.tap()), Err(DataError::SkipItem));
    }

}
<commit_msg>Macros for unsigned integer generators.<commit_after>// Generators
use std::marker::PhantomData;
use std::mem::size_of;

use data::*;

pub struct BoolGenerator;
pub struct IntGenerator<N>(PhantomData<N>);
pub struct VecGenerator<G>(G);

pub struct Filtered<G, F>(G, F);
pub struct Const<V>(V);

pub trait Generator {
    type Item;
    fn generate(&self, source: &mut InfoTap) -> Maybe<Self::Item>;

    fn filter<F: Fn(&Self::Item) -> bool>(self, pred: F) -> Filtered<Self, F>
    where
        Self: Sized,
    {
        Filtered(self, pred)
    }
}

pub fn booleans() -> BoolGenerator {
    BoolGenerator
}

pub fn vecs<G>(inner: G) -> VecGenerator<G> {
    VecGenerator(inner)
}

pub fn consts<V>(val: V) -> Const<V> {
    Const(val)
}

impl<G: Generator> Generator for VecGenerator<G> {
    type Item = Vec<G::Item>;
    fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
        let mut result = Vec::new();
        let bs = booleans();
        while bs.generate(src)? {
            let item = self.0.generate(src)?;
            result.push(item)
        }

        Ok(result)
    }
}

impl Generator for BoolGenerator {
    type Item = bool;
    fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
        src.next_byte().map(|next| next >= 0x80)
    }
}

macro_rules! integer_gen {
    ($name:ident, $ty:ty) => {
        pub fn $name() -> IntGenerator<$ty> {
            IntGenerator(PhantomData)
        }

        impl Generator for IntGenerator<$ty> {
            type Item = $ty;
            fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
                assert!(size_of::<u8>() == 1);
                let nbytes = size_of::<$ty>() / size_of::<u8>();
                let mut val: $ty = 0;
                for _ in 0..nbytes {
                    val = val.wrapping_shl(8) | src.next_byte()? as $ty;
                }
                // src.next_byte().map(|next| next >= 0x80)
                Ok(val)
            }
        }
    }
}

integer_gen!(u8s, u8);
integer_gen!(u16s, u16);
integer_gen!(u32s, u32);
integer_gen!(u64s, u64);

impl<G: Generator, F: Fn(&G::Item) -> bool> Generator for Filtered<G, F> {
    type Item = G::Item;
    fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
        let &Filtered(ref gen, ref pred) = self;
        let val = gen.generate(src)?;
        if pred(&val) {
            Ok(val)
        } else {
            Err(DataError::SkipItem)
        }
    }
}

impl<V: Clone> Generator for Const<V> {
    type Item = V;
    fn generate(&self, _: &mut InfoTap) -> Maybe<Self::Item> {
        Ok(self.0.clone())
    }
}

pub fn find_minimal<G: Generator, F: Fn(G::Item) -> bool>(
    gen: &G,
    pool: InfoPool,
    check: F,
) -> InfoPool {
    minimize(&pool, &|mut t| {
        gen.generate(&mut t).map(|v| check(v)).unwrap_or(false)
    }).unwrap_or(pool)
}

#[cfg(test)]
mod tests {
    extern crate env_logger;
    use rand::random;
    use std::iter;
    use std::fmt;
    use super::*;
    use data::InfoPool;
    const SHORT_VEC_SIZE: usize = 256;

    fn gen_random_vec() -> Vec<u8> {
        (0..SHORT_VEC_SIZE).map(|_| random()).collect::<Vec<u8>>()
    }

    fn should_generate_same_output_given_same_input<G: Generator>(gen: G)
    where
        G::Item: fmt::Debug + PartialEq,
    {
        for (p0, p1, v0, v1) in iter::repeat(())
            .map(|_| gen_random_vec())
            .map(|v0| (InfoPool::of_vec(v0.clone()), InfoPool::of_vec(v0)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (p0, p1, v0, v1))
                })
            })
            .take(100)
        {
            assert!(v0 == v1, "({:?} == {:?}) -> ({:?} == {:?})", p0, p1, v0, v1);
        }
    }

    fn usually_generates_different_output_for_different_inputs<G: Generator>(gen: G)
    where
        G::Item: PartialEq,
    {
        let nitems = 100;
        let differing = iter::repeat(())
            .map(|_| (gen_random_vec(), gen_random_vec()))
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .map(|(v0, v1)| (InfoPool::of_vec(v0), InfoPool::of_vec(v1)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (v0, v1))
                })
            })
            .take(nitems)
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .count();
        assert!(differing > 0, "Differing items:{} > 0", differing);

    }

    // Mostly only useful for scalar quantities. For collections, we basically say:
    // `while booleans() { elemnt() }`
    // So because booleans are imprecisly generated (ie: a pool of [0xff] ~ [0x80]),
    // the source and result can have a differing ordering.
    fn should_partially_order_same_as_source<G: Generator>(gen: G)
    where
        G::Item: PartialOrd + fmt::Debug,
    {
        let nitems = 100;
        for (p0, p1, v0, v1) in iter::repeat(())
            .map(|_| (gen_random_vec(), gen_random_vec()))
            .filter(|&(ref v0, ref v1)| v0 < v1)
            .map(|(v0, v1)| (InfoPool::of_vec(v0), InfoPool::of_vec(v1)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (p0, p1, v0, v1))
                })
            })
            .take(nitems)
        {
            assert!(v0 <= v1, "({:?} == {:?}) -> ({:?} == {:?})", p0, p1, v0, v1);
        }
    }

    #[test]
    fn consts_should_generate_same_values() {
        let v1 = gen_random_vec();
        let gen = consts("fourty two");
        assert_eq!(
            gen.generate(&mut InfoPool::of_vec(v1).tap()),
            Ok("fourty two")
        );
    }

    // If only I had some kind of property testing library.
    #[test]
    fn bools_should_generate_false_booleans_from_zeros() {
        let v1 = vec![0];
        let bools = booleans();
        assert_eq!(bools.generate(&mut InfoPool::of_vec(v1).tap()), Ok(false));
    }

    #[test]
    fn bools_should_generate_true_booleans_from_saturated_values() {
        let v1 = vec![0xff];
        let bools = booleans();
        assert_eq!(bools.generate(&mut InfoPool::of_vec(v1).tap()), Ok(true));
    }

    fn should_minimize_to<G: Generator>(gen: G, expected: G::Item)
    where
        G::Item: fmt::Debug + PartialEq,
    {
        let mut p;
        loop {
            p = InfoPool::random_of_size(SHORT_VEC_SIZE);
            match gen.generate(&mut p.tap()) {
                Ok(_) => break,
                Err(DataError::SkipItem) => (),
                Err(DataError::PoolExhausted) => panic!("Not enough pool to generate data"),
            }
        }
        debug!("Before: {:?}", p);
        let p = find_minimal(&gen, p, |_| true);
        debug!("After: {:?}", p);

        let val = gen.generate(&mut p.tap()).expect("generated value");
        assert_eq!(val, expected);

    }
    #[test]
    fn bools_should_generate_same_output_given_same_input() {
        should_generate_same_output_given_same_input(booleans())
    }

    // These really need to be proper statistical tests.
    #[test]
    fn bools_usually_generates_different_output_for_different_inputs() {
        usually_generates_different_output_for_different_inputs(booleans())
    }

    #[test]
    fn bools_minimize_to_false() {
        should_minimize_to(booleans(), false)
    }

    #[test]
    fn bools_should_partially_order_same_as_source() {
        should_partially_order_same_as_source(booleans())
    }

    #[test]
    fn vecs_should_generate_same_output_given_same_input() {
        should_generate_same_output_given_same_input(vecs(booleans()));
    }

    #[test]
    fn vecs_usually_generates_different_output_for_different_inputs() {
        usually_generates_different_output_for_different_inputs(vecs(booleans()))
    }

    #[test]
    fn vec_bools_minimize_to_empty() {
        env_logger::init().unwrap_or(());
        should_minimize_to(vecs(booleans()), vec![])
    }

    #[test]
    fn vec_bools_can_minimise_with_predicate() {
        env_logger::init().unwrap_or(());
        should_minimize_to(
            vecs(booleans()).filter(|v| v.len() > 2),
            vec![false, false, false],
        );
    }

    #[test]
    fn u8s_should_generate_same_output_given_same_input() {
        should_generate_same_output_given_same_input(u8s())
    }

    // These really need to be proper statistical tests.
    #[test]
    fn u8s_usually_generates_different_output_for_different_inputs() {
        usually_generates_different_output_for_different_inputs(u8s());
    }

    #[test]
    fn u8s_minimize_to_zero() {
        should_minimize_to(u8s(), 0);
    }

    #[test]
    fn u8s_should_partially_order_same_as_source() {
        should_partially_order_same_as_source(u8s());
    }

    #[test]
    fn u64s_should_generate_same_output_given_same_input() {
        should_generate_same_output_given_same_input(u64s())
    }

    // These really need to be proper statistical tests.
    #[test]
    fn u64s_usually_generates_different_output_for_different_inputs() {
        usually_generates_different_output_for_different_inputs(u64s());
    }

    #[test]
    fn u64s_minimize_to_zero() {
        should_minimize_to(u64s(), 0);
    }

    #[test]
    fn u64s_should_partially_order_same_as_source() {
        should_partially_order_same_as_source(u64s());
    }

    #[test]
    fn filter_should_pass_through_when_true() {
        let gen = consts(()).filter(|&_| true);
        let p = InfoPool::random_of_size(4);
        assert_eq!(gen.generate(&mut p.tap()), Ok(()));
    }

    #[test]
    fn filter_should_skip_when_false() {
        let gen = consts(()).filter(|&_| false);
        let p = InfoPool::random_of_size(4);
        assert_eq!(gen.generate(&mut p.tap()), Err(DataError::SkipItem));
    }

}
<|endoftext|>


<commit_before>
type InterruptHandlerFn = unsafe extern "C" fn() -> !;

use dispatch_table::{DispatchTable, DispatchFn};
use spin::RwLock;

#[derive(Default)]
#[repr(packed)]
struct IDTEntry {
    base_low: u16,
    selector: u16,
    always0: u8,
    flags: u8,
    base_high: u16,
    base_highest: u32,
    _reserved: u32,
}

#[derive(Default)]
pub struct IDT([IDTEntry; 20]);

lazy_static! {
    static ref INTERRUPT_TABLE: RwLock<DispatchTable<u64>> = RwLock::new(DispatchTable::new(256));
    static ref DESCRIPTOR_TABLE: RwLock<IDT> = RwLock::new(Default::default());
}

impl IDT {
    fn set_entry(&mut self, num: usize, base: u64, selector: u16, flags: u8) {
        self.0[num].base_low = (base & 0xffff) as u16;
        self.0[num].base_high = ((base >> 16) & 0xffff) as u16;
        self.0[num].base_highest = (base >> 32) as u32;
        self.0[num].always0 = 0;
        self.0[num].selector = selector;
        self.0[num].flags = flags;
    }
}

#[repr(C)]
pub struct InterruptCPUState {
	ds: u64,
	r15: u64,
	r14: u64,
	r13: u64,
	r12: u64,
	r11: u64,
	r10: u64,
	r9: u64,
	r8: u64,
	rdi: u64,
	rsi: u64,
	rbp: u64,
	rdx: u64,
	rcx: u64,
	rbx: u64,
	rax: u64,
	interrupt_number: u64,
	error_code: u64,
	rip: u64,
	cs: u64,
	rflags: u64,
	rsp: u64,
	ss: u64,
}

pub fn register_interrupt_handler(interrupt: u64, stub: InterruptHandlerFn, handler: DispatchFn<u64>) {
    INTERRUPT_TABLE.write().register(interrupt, handler);
    DESCRIPTOR_TABLE.write().set_entry(interrupt as usize, stub as u64, 0x08, 0x8e);
}

pub fn unregister_interrupt_handler(interrupt: u64) {
    INTERRUPT_TABLE.write().unregister(interrupt);
}

#[no_mangle]
pub extern "C" fn dispatch_interrupt(state: &mut InterruptCPUState) {
    INTERRUPT_TABLE.read().dispatch(&state.interrupt_number);
}

fn default_handler(_interrupt_number: &u64) -> bool {
    true
}

extern "C" {
    fn _isr0() -> !;
    fn _isr1() -> !;
    fn _isr2() -> !;
    fn _isr3() -> !;
    fn _isr4() -> !;
    fn _isr5() -> !;
    fn _isr6() -> !;
    fn _isr7() -> !;
    fn _isr8() -> !;
    fn _isr9() -> !;
    fn _isr10() -> !;
    fn _isr11() -> !;
    fn _isr12() -> !;
    fn _isr13() -> !;
    fn _isr14() -> !;
    fn _isr15() -> !;
    fn _isr16() -> !;
    fn _isr17() -> !;
    fn _isr18() -> !;
    fn _isr19() -> !;
}

const ISR: [InterruptHandlerFn; 20] = [_isr0, _isr1, _isr2, _isr3, _isr4, _isr5, _isr6, _isr7, _isr8, _isr9, _isr10, _isr11, _isr12, _isr13, _isr14, _isr15, _isr16, _isr17, _isr18, _isr19];

pub fn init_interrupt_handlers() {
    for i in 0..20 {
        register_interrupt_handler(i, ISR[i as usize], default_handler);
    }
}

#[cfg(feature = "runtime_tests")]
pub mod runtime_tests {

    use interrupts;
    use vmx;

}
<commit_msg>Create host IDT descriptor<commit_after>
type InterruptHandlerFn = unsafe extern "C" fn() -> !;

use dispatch_table::{DispatchTable, DispatchFn};
use spin::RwLock;
use vmx;
use core::mem;

#[derive(Default)]
#[repr(packed)]
struct IDTEntry {
    base_low: u16,
    selector: u16,
    always0: u8,
    flags: u8,
    base_high: u16,
    base_highest: u32,
    _reserved: u32,
}

fn new_host_idt_descriptor() -> vmx::CPUTableDescriptor {
    let base = (*DESCRIPTOR_TABLE.write()).0.as_ptr() as u64;
    vmx::CPUTableDescriptor{
        base: base,
        limit: (mem::size_of::<IDT>() - 1) as u16,
    }
}

#[derive(Default)]
pub struct IDT([IDTEntry; 20]);

lazy_static! {
    static ref INTERRUPT_TABLE: RwLock<DispatchTable<u64>> = RwLock::new(DispatchTable::new(256));
    static ref DESCRIPTOR_TABLE: RwLock<IDT> = RwLock::new(Default::default());
}

impl IDT {
    fn set_entry(&mut self, num: usize, base: u64, selector: u16, flags: u8) {
        self.0[num].base_low = (base & 0xffff) as u16;
        self.0[num].base_high = ((base >> 16) & 0xffff) as u16;
        self.0[num].base_highest = (base >> 32) as u32;
        self.0[num].always0 = 0;
        self.0[num].selector = selector;
        self.0[num].flags = flags;
    }
}

#[repr(C)]
pub struct InterruptCPUState {
	ds: u64,
	r15: u64,
	r14: u64,
	r13: u64,
	r12: u64,
	r11: u64,
	r10: u64,
	r9: u64,
	r8: u64,
	rdi: u64,
	rsi: u64,
	rbp: u64,
	rdx: u64,
	rcx: u64,
	rbx: u64,
	rax: u64,
	interrupt_number: u64,
	error_code: u64,
	rip: u64,
	cs: u64,
	rflags: u64,
	rsp: u64,
	ss: u64,
}

pub fn register_interrupt_handler(interrupt: u64, stub: InterruptHandlerFn, handler: DispatchFn<u64>) {
    INTERRUPT_TABLE.write().register(interrupt, handler);
    DESCRIPTOR_TABLE.write().set_entry(interrupt as usize, stub as u64, 0x08, 0x8e);
}

pub fn unregister_interrupt_handler(interrupt: u64) {
    INTERRUPT_TABLE.write().unregister(interrupt);
}

#[no_mangle]
pub extern "C" fn dispatch_interrupt(state: &mut InterruptCPUState) {
    INTERRUPT_TABLE.read().dispatch(&state.interrupt_number);
}

fn default_handler(_interrupt_number: &u64) -> bool {
    true
}

extern "C" {
    fn _isr0() -> !;
    fn _isr1() -> !;
    fn _isr2() -> !;
    fn _isr3() -> !;
    fn _isr4() -> !;
    fn _isr5() -> !;
    fn _isr6() -> !;
    fn _isr7() -> !;
    fn _isr8() -> !;
    fn _isr9() -> !;
    fn _isr10() -> !;
    fn _isr11() -> !;
    fn _isr12() -> !;
    fn _isr13() -> !;
    fn _isr14() -> !;
    fn _isr15() -> !;
    fn _isr16() -> !;
    fn _isr17() -> !;
    fn _isr18() -> !;
    fn _isr19() -> !;
}

const ISR: [InterruptHandlerFn; 20] = [_isr0, _isr1, _isr2, _isr3, _isr4, _isr5, _isr6, _isr7, _isr8, _isr9, _isr10, _isr11, _isr12, _isr13, _isr14, _isr15, _isr16, _isr17, _isr18, _isr19];

pub fn init_interrupt_handlers() {
    for i in 0..20 {
        register_interrupt_handler(i, ISR[i as usize], default_handler);
    }
}

#[cfg(feature = "runtime_tests")]
pub mod runtime_tests {

    use interrupts;
    use vmx;

}
<|endoftext|>