<commit_before>//! Layout handling

use rustwlc::handle::{WlcView, WlcOutput};
use std::rc::{Rc, Weak};

#[derive(PartialEq, Clone, Copy)]
pub enum ContainerType {
    Root,        /* Root container, only one exists */
    Output,      /* Output, like a monitor or head */
    Workspace,   /* A workspace */
    View         /* A view (aka a window) */
}

/// Types of container
enum ContainerTypes {
    /// Root container, only one exists
    Root,
    /// WlcOutput/monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Layout mode for a container
enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Vec<Weak<Box<Containable>>>;

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(&self);

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Finds a parent container with the given type, if there is any
    fn get_parent_by_type(&self, type_: ContainerType) -> Option<&Containable> {
        let mut container = self.get_parent();
        while container.is_some() && container.unwrap().get_type() != type_ {
            container = container.unwrap().get_parent();
        }
        container
    }
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Returns true if this view is a parent is an ancestor of the child
    fn is_parent_of<T: Containable>(&self, child: T) -> bool;

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of<T: Containable>(&self, parent: T) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace<T: Containable>(&self) -> T;
}

struct Container {
    handle: Option<WlcOutput>,

    parent: Box<Containable>,
    children: Vec<Rc<Box<Containable>>>,
    type_: ContainerType,
    layout: Layout,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for Container {

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable> {
        match self.type_ {
            ContainerType::Root => None,
            _ => Some(&*self.parent),
        }
    }
    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Vec<Weak<Box<Containable>>> {
        self.children.iter().map(|child| Rc::downgrade(&child)).collect()
    }

    fn get_type(&self) -> ContainerType {
        self.type_
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) {
        for child in self.get_children() {
            if let Some(child) = child.upgrade() {
                if let Ok(child) = Rc::try_unwrap(child) {
                    child.remove_container();
                    drop(child);
                }
            }
        }
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X (width) and Y (height) dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }

}

struct View {
    handle: Option<WlcView>,
    parent: Box<Containable>,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for View {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable> {
        Some(&*self.parent)
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Vec<Weak<Box<Containable>>> {
        unimplemented!();
    }

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType {
        ContainerType::View
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) {
        unimplemented!();
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }
}
<commit_msg>get_children now returns an Option, and remove_container returns a result<commit_after>//! Layout handling

use rustwlc::handle::{WlcView, WlcOutput};
use std::rc::{Rc, Weak};

#[derive(PartialEq, Clone, Copy)]
pub enum ContainerType {
    Root,        /* Root container, only one exists */
    Output,      /* Output, like a monitor or head */
    Workspace,   /* A workspace */
    View         /* A view (aka a window) */
}

/// Types of container
enum ContainerTypes {
    /// Root container, only one exists
    Root,
    /// WlcOutput/monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Layout mode for a container
enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Box<Containable>>>>;

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str>;

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Finds a parent container with the given type, if there is any
    fn get_parent_by_type(&self, type_: ContainerType) -> Option<&Containable> {
        let mut container = self.get_parent();
        while container.is_some() && container.unwrap().get_type() != type_ {
            container = container.unwrap().get_parent();
        }
        container
    }
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Returns true if this view is a parent is an ancestor of the child
    fn is_parent_of<T: Containable>(&self, child: T) -> bool;

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of<T: Containable>(&self, parent: T) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace<T: Containable>(&self) -> T;
}

struct Container {
    handle: Option<WlcOutput>,

    parent: Box<Containable>,
    children: Vec<Rc<Box<Containable>>>,
    type_: ContainerType,
    layout: Layout,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for Container {

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable> {
        match self.type_ {
            ContainerType::Root => None,
            _ => Some(&*self.parent),
        }
    }
    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Box<Containable>>>> {
        if self.children.len() == 0 {
            None
        } else {
            Some(self.children.iter().map(|child| Rc::downgrade(&child)).collect())
        }
    }

    fn get_type(&self) -> ContainerType {
        self.type_
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        for child in self.get_children().expect("No children") {
            if let Some(child) = child.upgrade() {
                if let Ok(child) = Rc::try_unwrap(child) {
                    child.remove_container();
                    drop(child);
                }
            }
        }
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X (width) and Y (height) dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }

}

struct View {
    handle: Option<WlcView>,
    parent: Box<Containable>,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for View {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable> {
        Some(&*self.parent)
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Box<Containable>>>> {
        None
    }

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType {
        ContainerType::View
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        unimplemented!();
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }
}
<|endoftext|>


<commit_before>extern crate primus_polygoni;
extern crate image;
extern crate time;

use std::f32::consts::PI;
use primus_polygoni::rand::{self, Rng};
use primus_polygoni::gfx;
use primus_polygoni::gfx_app;
use primus_polygoni::winit;
use primus_polygoni::nalgebra::{self, Vector2, Vector3, UnitQuaternion};
use time::precise_time_s;

use primus_polygoni::{Vertex, Instance, Locals, Camera};

const SCENE_SPHERES: usize = 20;
const SCENE_RADIUS: f32 = (SCENE_SPHERES as f32 * 3.0) / (2.0 * PI);

struct App<R: gfx::Resources> {
    bundle: gfx::Bundle<R, primus_polygoni::pipe::Data<R>>,
    camera: Camera,
    aspect_ratio: f32,
    mouse: Vector2<f32>,
    head_spinning: bool,
    going_left: bool,
    going_right: bool,
    marker: f32,
    init: bool,
}

fn fill_instances<R, C>(encoder: &mut gfx::Encoder<R, C>,
                        instances: &gfx::handle::Buffer<R, Instance>)
    where R: gfx::Resources, C: gfx::CommandBuffer<R>
{
    let mut vec = Vec::with_capacity(SCENE_SPHERES);
    let mut rng = rand::thread_rng();

    for i in 0..SCENE_SPHERES {
        let angle = i as f32 / SCENE_SPHERES as f32 * (2.0 * PI);
        let position = Vector3::new(
            angle.cos() * SCENE_RADIUS,
            0.0,
            angle.sin() * SCENE_RADIUS);

        let scale = 1.0;

        let transform = nalgebra::Similarity3::from_parts(
            nalgebra::Translation3::from_vector(position),
            nalgebra::one(),
            scale).to_homogeneous();
        let transform = transform.as_slice();

        let line = |l: &[f32]| [l[0], l[1], l[2], l[3]];

        vec.push(Instance {
            t1: line(&transform[0..4]),
            t2: line(&transform[4..8]),
            t3: line(&transform[8..12]),
            t4: line(&transform[12..16]),
        });
    }
    encoder.update_buffer(instances, &vec[..], 0).unwrap();
}

impl<R: gfx::Resources> gfx_app::Application<R> for App<R> {
    fn new<F: gfx::Factory<R>>(factory: &mut F,
                               backend: gfx_app::shade::Backend,
                               targets: gfx_app::WindowTargets<R>) -> Self {
        use gfx::traits::FactoryExt;

        let pso = primus_polygoni::create_pipeline(factory, backend);

        let (vertex_data, index_data) = primus_polygoni::generate_icosphere(4);
        let (vertices, mut slice) = factory
            .create_vertex_buffer_with_slice(&vertex_data[..], &index_data[..]);
        slice.instances = Some((SCENE_SPHERES as u32, 0));

        let size = 1024;
        let (w, h) = (size * 2, size);
        let mut texels: Vec<_> = (0..(w * h)).map(|_| [0; 4]).collect();
        primus_polygoni::generate_texture(&mut texels, size);

        let (_, texture_view) =
            factory.create_texture_immutable::<gfx::format::Rgba8>(
                gfx::texture::Kind::D2(w as gfx::texture::Size,
                                       h as gfx::texture::Size,
                                       gfx::texture::AaMode::Single),
                &[&texels]
            ).unwrap();

        let sinfo = gfx::texture::SamplerInfo::new(
            gfx::texture::FilterMethod::Bilinear,
            gfx::texture::WrapMode::Clamp);

        let data = primus_polygoni::pipe::Data {
            vertices: vertices,
            instances: factory.create_buffer(SCENE_SPHERES, gfx::buffer::Role::Vertex,
                                             gfx::memory::Usage::Dynamic, gfx::Bind::empty()).unwrap(),
            locals: factory.create_constant_buffer(1),
            color: (texture_view, factory.create_sampler(sinfo)),
            color_target: targets.color,
            depth_target: targets.depth,
        };

        App {
            bundle: gfx::Bundle::new(slice, pso, data),
            camera: Camera::new(SCENE_RADIUS),
            aspect_ratio: targets.aspect_ratio,
            mouse: Vector2::new(0., 0.),
            head_spinning: false,
            going_left: false,
            going_right: false,
            marker: precise_time_s() as f32,
            init: false,
        }
    }

    fn render<C: gfx::CommandBuffer<R>>(&mut self, encoder: &mut gfx::Encoder<R, C>) {

        let now = precise_time_s() as f32;
        let delta = now - self.marker;
        self.marker = now;

        if !self.init {
            fill_instances(encoder, &self.bundle.data.instances);
            self.init = true;
        }

        if self.head_spinning {
            let max_rotation = 2.0 * PI * delta;
            self.camera.rotate(UnitQuaternion::new(
                Vector3::y() * (-self.mouse.x * max_rotation)
            ));
            self.camera.pitch(self.mouse.y * max_rotation);
        }

        let speed = (2.0 * PI) / SCENE_SPHERES as f32;
        if self.going_left { self.camera.move_left(speed * delta); }
        if self.going_right { self.camera.move_right(speed * delta); }

        self.camera.update(self.aspect_ratio);
        let locals = Locals {
            transform: self.camera.gpu_transform()
        };
        encoder.update_constant_buffer(&self.bundle.data.locals, &locals);

        encoder.clear(&self.bundle.data.color_target, [0.1, 0.2, 0.3, 1.0]);
        encoder.clear_depth(&self.bundle.data.depth_target, 1.0);
        self.bundle.encode(encoder);
    }

    fn on_resize(&mut self, targets: gfx_app::WindowTargets<R>) {
        self.bundle.data.color_target = targets.color;
        self.bundle.data.depth_target = targets.depth;
        self.aspect_ratio = targets.aspect_ratio;
    }

    fn on(&mut self, event: winit::Event) {
        use winit::Event::*;
        use winit::ElementState::*;
        use winit::MouseButton::*;
        match event {
            KeyboardInput(state, _, Some(key)) => {
                use winit::VirtualKeyCode::*;
                match key {
                    Q | Left => self.going_left = state == Pressed,
                    D | Right => self.going_right = state == Pressed,
                    _ => {}
                }
            },
            MouseMoved(x, y) => {
                let (w, h, _, _) = self.bundle.data.color_target.get_dimensions();
                self.mouse = Vector2::new((x as f32 / w as f32) - 0.5,
                                          0.5 - (y as f32 / h as f32));
            }
            MouseWheel(_delta, _) => {

            }
            MouseInput(state, Left) => self.head_spinning = state == Pressed,
            _ => {}
        }
    }
}

fn main() {
    let wb = winit::WindowBuilder::new().with_title("Primus Polygoni");
    gfx_app::launch_gl3::<gfx_app::Wrap<_,_,App<_>>>(wb);
}
<commit_msg>simple scene<commit_after>extern crate primus_polygoni;
extern crate image;
extern crate time;

use std::f32::consts::PI;
use primus_polygoni::rand;
use primus_polygoni::rand::distributions::{IndependentSample, Range};

use primus_polygoni::gfx;
use primus_polygoni::gfx_app;
use primus_polygoni::winit;
use primus_polygoni::nalgebra::{self, Vector2, Vector3, UnitQuaternion};
use time::precise_time_s;

use primus_polygoni::{Vertex, Instance, Locals, Camera};

const SCENE_SPHERES: usize = 100;
const SCENE_RADIUS: f32 = (SCENE_SPHERES as f32 * 4.0) / (2.0 * PI);

struct App<R: gfx::Resources> {
    bundle: gfx::Bundle<R, primus_polygoni::pipe::Data<R>>,
    camera: Camera,
    aspect_ratio: f32,
    mouse: Vector2<f32>,
    head_spinning: bool,
    going_left: bool,
    going_right: bool,
    marker: f32,
    init: bool,
}

fn fill_instances<R, C>(encoder: &mut gfx::Encoder<R, C>,
                        instances: &gfx::handle::Buffer<R, Instance>)
    where R: gfx::Resources, C: gfx::CommandBuffer<R>
{
    let mut vec = Vec::with_capacity(SCENE_SPHERES);
    let mut rng = rand::thread_rng();

    for i in 0..SCENE_SPHERES {
        let angle = i as f32 / SCENE_SPHERES as f32 * (2.0 * PI);
        let position = Vector3::new(
            angle.cos() * SCENE_RADIUS,
            0.0,
            angle.sin() * SCENE_RADIUS);

        let radius = Range::new(0.5, 1.5).ind_sample(&mut rng);
        let remaining = 2.0 - radius;

        let range = Range::new(-remaining, remaining);
        let displacement = Vector3::new(
            range.ind_sample(&mut rng),
            range.ind_sample(&mut rng),
            range.ind_sample(&mut rng),
        );

        let transform = nalgebra::Similarity3::from_parts(
            nalgebra::Translation3::from_vector(position + displacement),
            nalgebra::one(),
            radius).to_homogeneous();
        let transform = transform.as_slice();

        let line = |l: &[f32]| [l[0], l[1], l[2], l[3]];

        vec.push(Instance {
            t1: line(&transform[0..4]),
            t2: line(&transform[4..8]),
            t3: line(&transform[8..12]),
            t4: line(&transform[12..16]),
        });
    }
    encoder.update_buffer(instances, &vec[..], 0).unwrap();
}

impl<R: gfx::Resources> gfx_app::Application<R> for App<R> {
    fn new<F: gfx::Factory<R>>(factory: &mut F,
                               backend: gfx_app::shade::Backend,
                               targets: gfx_app::WindowTargets<R>) -> Self {
        use gfx::traits::FactoryExt;

        let pso = primus_polygoni::create_pipeline(factory, backend);

        let (vertex_data, index_data) = primus_polygoni::generate_icosphere(4);
        let (vertices, mut slice) = factory
            .create_vertex_buffer_with_slice(&vertex_data[..], &index_data[..]);
        slice.instances = Some((SCENE_SPHERES as u32, 0));

        let size = 1024;
        let (w, h) = (size * 2, size);
        let mut texels: Vec<_> = (0..(w * h)).map(|_| [0; 4]).collect();
        primus_polygoni::generate_texture(&mut texels, size);

        let (_, texture_view) =
            factory.create_texture_immutable::<gfx::format::Rgba8>(
                gfx::texture::Kind::D2(w as gfx::texture::Size,
                                       h as gfx::texture::Size,
                                       gfx::texture::AaMode::Single),
                &[&texels]
            ).unwrap();

        let sinfo = gfx::texture::SamplerInfo::new(
            gfx::texture::FilterMethod::Bilinear,
            gfx::texture::WrapMode::Clamp);

        let data = primus_polygoni::pipe::Data {
            vertices: vertices,
            instances: factory.create_buffer(SCENE_SPHERES, gfx::buffer::Role::Vertex,
                                             gfx::memory::Usage::Dynamic, gfx::Bind::empty()).unwrap(),
            locals: factory.create_constant_buffer(1),
            color: (texture_view, factory.create_sampler(sinfo)),
            color_target: targets.color,
            depth_target: targets.depth,
        };

        App {
            bundle: gfx::Bundle::new(slice, pso, data),
            camera: Camera::new(SCENE_RADIUS),
            aspect_ratio: targets.aspect_ratio,
            mouse: Vector2::new(0., 0.),
            head_spinning: false,
            going_left: false,
            going_right: false,
            marker: precise_time_s() as f32,
            init: false,
        }
    }

    fn render<C: gfx::CommandBuffer<R>>(&mut self, encoder: &mut gfx::Encoder<R, C>) {

        let now = precise_time_s() as f32;
        let delta = now - self.marker;
        self.marker = now;

        if !self.init {
            fill_instances(encoder, &self.bundle.data.instances);
            self.init = true;
        }

        if self.head_spinning {
            let max_rotation = 2.0 * PI * delta;
            self.camera.rotate(UnitQuaternion::new(
                Vector3::y() * (-self.mouse.x * max_rotation)
            ));
            self.camera.pitch(self.mouse.y * max_rotation);
        }

        let speed = 0.5 * PI;
        if self.going_left { self.camera.move_left(speed * delta); }
        if self.going_right { self.camera.move_right(speed * delta); }

        self.camera.update(self.aspect_ratio);
        let locals = Locals {
            transform: self.camera.gpu_transform()
        };
        encoder.update_constant_buffer(&self.bundle.data.locals, &locals);

        encoder.clear(&self.bundle.data.color_target, [0.1, 0.2, 0.3, 1.0]);
        encoder.clear_depth(&self.bundle.data.depth_target, 1.0);
        self.bundle.encode(encoder);
    }

    fn on_resize(&mut self, targets: gfx_app::WindowTargets<R>) {
        self.bundle.data.color_target = targets.color;
        self.bundle.data.depth_target = targets.depth;
        self.aspect_ratio = targets.aspect_ratio;
    }

    fn on(&mut self, event: winit::Event) {
        use winit::Event::*;
        use winit::ElementState::*;
        use winit::MouseButton::*;
        match event {
            KeyboardInput(state, _, Some(key)) => {
                use winit::VirtualKeyCode::*;
                match key {
                    Q | Left => self.going_left = state == Pressed,
                    D | Right => self.going_right = state == Pressed,
                    _ => {}
                }
            },
            MouseMoved(x, y) => {
                let (w, h, _, _) = self.bundle.data.color_target.get_dimensions();
                self.mouse = Vector2::new((x as f32 / w as f32) - 0.5,
                                          0.5 - (y as f32 / h as f32));
            }
            MouseWheel(_delta, _) => {

            }
            MouseInput(state, Left) => self.head_spinning = state == Pressed,
            _ => {}
        }
    }
}

fn main() {
    let wb = winit::WindowBuilder::new().with_title("Primus Polygoni");
    gfx_app::launch_gl3::<gfx_app::Wrap<_,_,App<_>>>(wb);
}
<|endoftext|>


<commit_before>// ridgedmulti.rs

use gen::NoiseGen;
use gen::simplex::Simplex;
use utils::{clamp, bound};
use std::num;

pub struct RidgedMulti {
    simp: Simplex,
    octaves: int,
    gain: f64,
    lacunarity: f64,
    offset: f64,
    h: f64,
    frequencies: Vec<f64>,
    max_val: f64
}

impl RidgedMulti {
    pub fn new_rand(octaves: int, gain: f64, lac: f64, offset: f64, h: f64) -> RidgedMulti {
        let freqs = RidgedMulti::calc_freqs(octaves, lac, h);
        RidgedMulti {
            simp: Simplex::new_rand(),
            octaves: octaves,
            gain: gain,
            lacunarity: lac,
            offset: offset,
            h: h,
            frequencies: freqs.clone(),
            max_val: RidgedMulti::calc_max(octaves, gain, offset, freqs)
            }
    }

    pub fn from_seed(seed: u32, octaves: int, gain: f64, lac: f64, offset: f64, h: f64) -> RidgedMulti {
        let freqs = RidgedMulti::calc_freqs(octaves, lac, h);
        RidgedMulti {
            simp: Simplex::from_seed(seed),
            octaves: octaves,
            gain: gain,
            lacunarity: lac,
            offset: offset,
            h: h,
            frequencies: freqs.clone(),
            max_val: RidgedMulti::calc_max(octaves, gain, offset, freqs)
            }
    }

    pub fn get_seed(&mut self) -> u32 {
        self.simp.get_seed()
    }

    fn calc_freqs(octaves: int, lacunarity: f64, h: f64) -> Vec<f64> {
        let mut freqs: Vec<f64> = Vec::new();

        for i in range(0, octaves) {
            let f = lacunarity.powf((-i as f64) * h);
            freqs.push(f);
        }

        freqs
    }

    fn calc_max(octaves: int, gain: f64, offset: f64, freqs: Vec<f64>) -> f64 {
        let mut signal = RidgedMulti::ridge(0.0, offset);
        let mut weight: f64;
        let mut sum = signal;
        for i in range(0, octaves) {
            weight = signal * gain;
            weight = clamp(weight, 0.0, 1.0);
            signal = RidgedMulti::ridge(0.0, offset);
            signal *= weight;
            sum += signal * freqs[i as uint];
        }

        sum
    }

    fn ridge(n: f64, offset: f64) -> f64 {
        let n = offset - num::abs(n);
        n * n
    }
}

impl NoiseGen for RidgedMulti {
    fn get_value2d(&mut self, x: f64, y: f64) -> f64 {
        let mut xx = x;
        let mut yy = y;
        let mut signal = RidgedMulti::ridge(
                            self.simp.get_value2d(x, y),
                            self.offset);
        let mut sum = signal;
        let mut weight: f64;

        for i in range(0, self.octaves) {
            xx = xx * self.lacunarity;
            yy = yy * self.lacunarity;
            weight = signal * self.gain;
            weight = clamp(weight, 0.0, 1.0);
            signal = RidgedMulti::ridge(
                        self.simp.get_value2d(xx, yy),
                        self.offset);
            signal *= weight;
            sum += signal * self.frequencies[i as uint];
        }

        bound(sum, 0.0, 1.0, 0.0, self.max_val)
    }

    fn get_value3d(&mut self, x: f64, y: f64, z: f64) -> f64 {
        let mut xx = x;
        let mut yy = y;
        let mut zz = z;
        let mut signal = RidgedMulti::ridge(
                            self.simp.get_value3d(x, y, z),
                            self.offset);
        let mut sum = signal;
        let mut weight: f64;

        for i in range(0, self.octaves) {
            xx = xx * self.lacunarity;
            yy = yy * self.lacunarity;
            zz = zz * self.lacunarity;
            weight = signal * self.gain;
            weight = clamp(weight, 0.0, 1.0);
            signal = RidgedMulti::ridge(
                        self.simp.get_value3d(xx, yy, zz),
                        self.offset);
            signal *= weight;
            sum += signal * self.frequencies[i as uint];
        }

        bound(sum, 0.0, 1.0, 0.0, self.max_val)
    }
}
<commit_msg>Fixed dead code<commit_after>// ridgedmulti.rs

use gen::NoiseGen;
use gen::simplex::Simplex;
use utils::{clamp, bound};
use std::num;

pub struct RidgedMulti {
    simp: Simplex,
    octaves: int,
    gain: f64,
    lacunarity: f64,
    offset: f64,
    frequencies: Vec<f64>,
    max_val: f64
}

impl RidgedMulti {
    pub fn new_rand(octaves: int, gain: f64, lac: f64, offset: f64, h: f64) -> RidgedMulti {
        let freqs = RidgedMulti::calc_freqs(octaves, lac, h);
        RidgedMulti {
            simp: Simplex::new_rand(),
            octaves: octaves,
            gain: gain,
            lacunarity: lac,
            offset: offset,
            frequencies: freqs.clone(),
            max_val: RidgedMulti::calc_max(octaves, gain, offset, freqs)
            }
    }

    pub fn from_seed(seed: u32, octaves: int, gain: f64, lac: f64, offset: f64, h: f64) -> RidgedMulti {
        let freqs = RidgedMulti::calc_freqs(octaves, lac, h);
        RidgedMulti {
            simp: Simplex::from_seed(seed),
            octaves: octaves,
            gain: gain,
            lacunarity: lac,
            offset: offset,
            frequencies: freqs.clone(),
            max_val: RidgedMulti::calc_max(octaves, gain, offset, freqs)
            }
    }

    pub fn get_seed(&mut self) -> u32 {
        self.simp.get_seed()
    }

    fn calc_freqs(octaves: int, lacunarity: f64, h: f64) -> Vec<f64> {
        let mut freqs: Vec<f64> = Vec::new();

        for i in range(0, octaves) {
            let f = lacunarity.powf((-i as f64) * h);
            freqs.push(f);
        }

        freqs
    }

    fn calc_max(octaves: int, gain: f64, offset: f64, freqs: Vec<f64>) -> f64 {
        let mut signal = RidgedMulti::ridge(0.0, offset);
        let mut weight: f64;
        let mut sum = signal;
        for i in range(0, octaves) {
            weight = signal * gain;
            weight = clamp(weight, 0.0, 1.0);
            signal = RidgedMulti::ridge(0.0, offset);
            signal *= weight;
            sum += signal * freqs[i as uint];
        }

        sum
    }

    fn ridge(n: f64, offset: f64) -> f64 {
        let n = offset - num::abs(n);
        n * n
    }
}

impl NoiseGen for RidgedMulti {
    fn get_value2d(&mut self, x: f64, y: f64) -> f64 {
        let mut xx = x;
        let mut yy = y;
        let mut signal = RidgedMulti::ridge(
                            self.simp.get_value2d(x, y),
                            self.offset);
        let mut sum = signal;
        let mut weight: f64;

        for i in range(0, self.octaves) {
            xx = xx * self.lacunarity;
            yy = yy * self.lacunarity;
            weight = signal * self.gain;
            weight = clamp(weight, 0.0, 1.0);
            signal = RidgedMulti::ridge(
                        self.simp.get_value2d(xx, yy),
                        self.offset);
            signal *= weight;
            sum += signal * self.frequencies[i as uint];
        }

        bound(sum, 0.0, 1.0, 0.0, self.max_val)
    }

    fn get_value3d(&mut self, x: f64, y: f64, z: f64) -> f64 {
        let mut xx = x;
        let mut yy = y;
        let mut zz = z;
        let mut signal = RidgedMulti::ridge(
                            self.simp.get_value3d(x, y, z),
                            self.offset);
        let mut sum = signal;
        let mut weight: f64;

        for i in range(0, self.octaves) {
            xx = xx * self.lacunarity;
            yy = yy * self.lacunarity;
            zz = zz * self.lacunarity;
            weight = signal * self.gain;
            weight = clamp(weight, 0.0, 1.0);
            signal = RidgedMulti::ridge(
                        self.simp.get_value3d(xx, yy, zz),
                        self.offset);
            signal *= weight;
            sum += signal * self.frequencies[i as uint];
        }

        bound(sum, 0.0, 1.0, 0.0, self.max_val)
    }
}
<|endoftext|>


<commit_before>//! I guess these docs will never appear since we re-export the canvas
//! module from graphics...
use std::convert::TryFrom;

use gfx::format::{Format, Swizzle};
use gfx::handle::RawRenderTargetView;
use gfx::memory::{Bind, Usage};
use gfx::texture::{AaMode, Kind};
use gfx::Factory;

use crate::conf;
use crate::context::DebugId;
use crate::error::*;
use crate::graphics::*;
use crate::Context;

/// A generic canvas independent of graphics backend. This type should
/// never need to be used directly; use [`graphics::Canvas`](type.Canvas.html)
/// instead.
#[derive(Debug)]
pub struct CanvasGeneric<Spec>
where
    Spec: BackendSpec,
{
    target: RawRenderTargetView<Spec::Resources>,
    image: Image,
    debug_id: DebugId,
}

/// A canvas that can be rendered to instead of the screen (sometimes referred
/// to as "render target" or "render to texture"). Set the canvas with the
/// [`graphics::set_canvas()`](fn.set_canvas.html) function, and then anything you
/// draw will be drawn to the canvas instead of the screen.
///
/// Resume drawing to the screen by calling `graphics::set_canvas(None)`.
///
/// A `Canvas` allows graphics to be rendered to images off-screen
/// in order to do things like saving to an image file or creating cool effects
/// by using shaders that render to an image.
/// If you just want to draw multiple things efficiently, look at
/// [`SpriteBatch`](spritebatch/struct.Spritebatch.html).
pub type Canvas = CanvasGeneric<GlBackendSpec>;

impl<S> CanvasGeneric<S>
where
    S: BackendSpec,
{
    #[allow(clippy::new_ret_no_self)]
    /// Create a new `Canvas` with the given size and number of samples.
    pub fn new(
        ctx: &mut Context,
        width: u16,
        height: u16,
        samples: conf::NumSamples,
        color_format: Format,
    ) -> GameResult<Canvas> {
        let debug_id = DebugId::get(ctx);
        let aa = match samples {
            conf::NumSamples::One => AaMode::Single,
            s => AaMode::Multi(s.into()),
        };
        let kind = Kind::D2(width, height, aa);
        let levels = 1;
        let factory = &mut ctx.gfx_context.factory;
        let texture_create_info = gfx::texture::Info {
            kind,
            levels,
            format: color_format.0,
            bind: Bind::SHADER_RESOURCE | Bind::RENDER_TARGET | Bind::TRANSFER_SRC,
            usage: Usage::Data,
        };
        let tex = factory.create_texture_raw(texture_create_info, Some(color_format.1), None)?;
        let resource_desc = gfx::texture::ResourceDesc {
            channel: color_format.1,
            layer: None,
            min: 0,
            max: levels - 1,
            swizzle: Swizzle::new(),
        };
        let resource = factory.view_texture_as_shader_resource_raw(&tex, resource_desc)?;
        let render_desc = gfx::texture::RenderDesc {
            channel: color_format.1,
            level: 0,
            layer: None,
        };
        let target = factory.view_texture_as_render_target_raw(&tex, render_desc)?;
        Ok(Canvas {
            target,
            image: Image {
                texture: resource,
                texture_handle: tex,
                sampler_info: ctx.gfx_context.default_sampler_info,
                blend_mode: None,
                width,
                height,
                debug_id,
            },
            debug_id,
        })
    }

    /// Create a new `Canvas` with the current window dimensions.
    pub fn with_window_size(ctx: &mut Context) -> GameResult<Canvas> {
        use crate::graphics;
        let (w, h) = graphics::drawable_size(ctx);
        // Default to no multisampling
        Canvas::new(
            ctx,
            w as u16
            h as u16,
            conf::NumSamples::One,
            get_window_color_format(ctx),
        )
    }

    /// Gets the backend `Image` that is being rendered to.
    pub fn image(&self) -> &Image {
        &self.image
    }

    /// Gets the backend `Target` that is being rendered to.
    pub fn target(&self) -> &RawRenderTargetView<S::Resources> {
        &self.target
    }

    /// Get the filter mode for the image.
    pub fn filter(&self) -> FilterMode {
        self.image.filter()
    }

    /// Set the filter mode for the canvas.
    pub fn set_filter(&mut self, mode: FilterMode) {
        self.image.set_filter(mode)
    }

    /// Destroys the `Canvas` and returns the `Image` it contains.
    pub fn into_inner(self) -> Image {
        // TODO: This texture is created with different settings
        // than the default; does that matter?
        // Test; we really just need to add Bind::TRANSFER_SRC
        // and change the Usage's to match to make them identical.
        // Ask termhn maybe?
        self.image
    }
}

impl Drawable for Canvas {
    fn draw(&self, ctx: &mut Context, param: DrawParam) -> GameResult {
        self.debug_id.assert(ctx);
        // Gotta flip the image on the Y axis here
        // to account for OpenGL's origin being at the bottom-left.
        match param.trans {
            Transform::Values { scale, dest, .. } => {
                let new_scale = mint::Vector2 {
                    x: scale.x,
                    y: -scale.y,
                };
                let new_dest = mint::Point2 {
                    x: dest.x,
                    y: dest.y + f32::from(self.image.height()) * scale.y,
                };
                let new_param = param.dest(new_dest).scale(new_scale);
                self.image.draw(ctx, new_param)
            }
            Transform::Matrix(_) => self.image.draw(ctx, param),
        }
    }
    fn dimensions(&self, _: &mut Context) -> Option<Rect> {
        Some(self.image.dimensions())
    }
    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.image.blend_mode = mode;
    }
    fn blend_mode(&self) -> Option<BlendMode> {
        self.image.blend_mode
    }
}

/// Set the `Canvas` to render to. Specifying `Option::None` will cause all
/// rendering to be done directly to the screen.
pub fn set_canvas(ctx: &mut Context, target: Option<&Canvas>) {
    match target {
        Some(surface) => {
            surface.debug_id.assert(ctx);
            ctx.gfx_context.data.out = surface.target.clone();
        }
        None => {
            ctx.gfx_context.data.out = ctx.gfx_context.screen_render_target.clone();
        }
    };
}
<commit_msg>Inform in Canvas doc about graphics::set_screen_coordinates<commit_after>//! I guess these docs will never appear since we re-export the canvas
//! module from graphics...
use std::convert::TryFrom;

use gfx::format::{Format, Swizzle};
use gfx::handle::RawRenderTargetView;
use gfx::memory::{Bind, Usage};
use gfx::texture::{AaMode, Kind};
use gfx::Factory;

use crate::conf;
use crate::context::DebugId;
use crate::error::*;
use crate::graphics::*;
use crate::Context;

/// A generic canvas independent of graphics backend. This type should
/// never need to be used directly; use [`graphics::Canvas`](type.Canvas.html)
/// instead.
#[derive(Debug)]
pub struct CanvasGeneric<Spec>
where
    Spec: BackendSpec,
{
    target: RawRenderTargetView<Spec::Resources>,
    image: Image,
    debug_id: DebugId,
}

/// A canvas that can be rendered to instead of the screen (sometimes referred
/// to as "render target" or "render to texture"). Set the canvas with the
/// [`graphics::set_canvas()`](fn.set_canvas.html) function, and then anything you
/// draw will be drawn to the canvas instead of the screen.
///
/// Resume drawing to the screen by calling `graphics::set_canvas(None)`.
///
/// A `Canvas` allows graphics to be rendered to images off-screen
/// in order to do things like saving to an image file or creating cool effects
/// by using shaders that render to an image.
/// If you just want to draw multiple things efficiently, look at
/// [`SpriteBatch`](spritebatch/struct.Spritebatch.html).
///
/// Note that if the canvas is not of the same size as the screen, and you want
/// to render using coordinates relative to the canvas' coordinate system, you
/// need to call [`graphics::set_screen_coordinates`](fn.set_screen_coordinates.html)
/// and pass in a rectangle with position (0, 0) and a size equal to that of the
/// canvas.
pub type Canvas = CanvasGeneric<GlBackendSpec>;

impl<S> CanvasGeneric<S>
where
    S: BackendSpec,
{
    #[allow(clippy::new_ret_no_self)]
    /// Create a new `Canvas` with the given size and number of samples.
    pub fn new(
        ctx: &mut Context,
        width: u16,
        height: u16,
        samples: conf::NumSamples,
        color_format: Format,
    ) -> GameResult<Canvas> {
        let debug_id = DebugId::get(ctx);
        let aa = match samples {
            conf::NumSamples::One => AaMode::Single,
            s => AaMode::Multi(s.into()),
        };
        let kind = Kind::D2(width, height, aa);
        let levels = 1;
        let factory = &mut ctx.gfx_context.factory;
        let texture_create_info = gfx::texture::Info {
            kind,
            levels,
            format: color_format.0,
            bind: Bind::SHADER_RESOURCE | Bind::RENDER_TARGET | Bind::TRANSFER_SRC,
            usage: Usage::Data,
        };
        let tex = factory.create_texture_raw(texture_create_info, Some(color_format.1), None)?;
        let resource_desc = gfx::texture::ResourceDesc {
            channel: color_format.1,
            layer: None,
            min: 0,
            max: levels - 1,
            swizzle: Swizzle::new(),
        };
        let resource = factory.view_texture_as_shader_resource_raw(&tex, resource_desc)?;
        let render_desc = gfx::texture::RenderDesc {
            channel: color_format.1,
            level: 0,
            layer: None,
        };
        let target = factory.view_texture_as_render_target_raw(&tex, render_desc)?;
        Ok(Canvas {
            target,
            image: Image {
                texture: resource,
                texture_handle: tex,
                sampler_info: ctx.gfx_context.default_sampler_info,
                blend_mode: None,
                width,
                height,
                debug_id,
            },
            debug_id,
        })
    }

    /// Create a new `Canvas` with the current window dimensions.
    pub fn with_window_size(ctx: &mut Context) -> GameResult<Canvas> {
        use crate::graphics;
        let (w, h) = graphics::drawable_size(ctx);
        // Default to no multisampling
        Canvas::new(
            ctx,
            w as u16
            h as u16,
            conf::NumSamples::One,
            get_window_color_format(ctx),
        )
    }

    /// Gets the backend `Image` that is being rendered to.
    pub fn image(&self) -> &Image {
        &self.image
    }

    /// Gets the backend `Target` that is being rendered to.
    pub fn target(&self) -> &RawRenderTargetView<S::Resources> {
        &self.target
    }

    /// Get the filter mode for the image.
    pub fn filter(&self) -> FilterMode {
        self.image.filter()
    }

    /// Set the filter mode for the canvas.
    pub fn set_filter(&mut self, mode: FilterMode) {
        self.image.set_filter(mode)
    }

    /// Destroys the `Canvas` and returns the `Image` it contains.
    pub fn into_inner(self) -> Image {
        // TODO: This texture is created with different settings
        // than the default; does that matter?
        // Test; we really just need to add Bind::TRANSFER_SRC
        // and change the Usage's to match to make them identical.
        // Ask termhn maybe?
        self.image
    }
}

impl Drawable for Canvas {
    fn draw(&self, ctx: &mut Context, param: DrawParam) -> GameResult {
        self.debug_id.assert(ctx);
        // Gotta flip the image on the Y axis here
        // to account for OpenGL's origin being at the bottom-left.
        match param.trans {
            Transform::Values { scale, dest, .. } => {
                let new_scale = mint::Vector2 {
                    x: scale.x,
                    y: -scale.y,
                };
                let new_dest = mint::Point2 {
                    x: dest.x,
                    y: dest.y + f32::from(self.image.height()) * scale.y,
                };
                let new_param = param.dest(new_dest).scale(new_scale);
                self.image.draw(ctx, new_param)
            }
            Transform::Matrix(_) => self.image.draw(ctx, param),
        }
    }
    fn dimensions(&self, _: &mut Context) -> Option<Rect> {
        Some(self.image.dimensions())
    }
    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.image.blend_mode = mode;
    }
    fn blend_mode(&self) -> Option<BlendMode> {
        self.image.blend_mode
    }
}

/// Set the `Canvas` to render to. Specifying `Option::None` will cause all
/// rendering to be done directly to the screen.
pub fn set_canvas(ctx: &mut Context, target: Option<&Canvas>) {
    match target {
        Some(surface) => {
            surface.debug_id.assert(ctx);
            ctx.gfx_context.data.out = surface.target.clone();
        }
        None => {
            ctx.gfx_context.data.out = ctx.gfx_context.screen_render_target.clone();
        }
    };
}
<|endoftext|>


<commit_before>//! This module defines [`BVH`] and [`BVHNode`] and functions for building and traversing it.
//!
//! [`BVH`]: struct.BVH.html
//! [`BVHNode`]: struct.BVHNode.html
//!

use EPSILON;
use aabb::{AABB, Bounded};
use bounding_hierarchy::{BoundingHierarchy, BHShape};
use ray::Ray;
use std::f32;
use std::iter::repeat;

/// The [`BVHNode`] enum that describes a node in a [`BVH`].
/// It's either a leaf node and references a shape (by holding its index)
/// or a regular node that has two child nodes.
/// The non-leaf node stores the [`AABB`]s of its children.
///
/// [`AABB`]: ../aabb/struct.AABB.html
/// [`BVH`]: struct.BVH.html
/// [`BVH`]: struct.BVHNode.html
///
#[derive(Debug, Copy, Clone)]
pub enum BVHNode {
    /// Leaf node.
    Leaf {
        /// The node's parent.
        parent: usize,

        /// The node's depth.
        depth: u32,

        /// The shape contained in this leaf.
        shape: usize,
    },
    /// Inner node.
    Node {
        /// The node's parent.
        parent: usize,

        /// The node's depth.
        depth: u32,

        /// The convex hull of the shapes' `AABB`s in child_l.
        child_l_aabb: AABB,

        /// Index of the left subtree's root node.
        child_l: usize,

        /// The convex hull of the shapes' `AABB`s in child_r.
        child_r_aabb: AABB,

        /// Index of the right subtree's root node.
        child_r: usize,
    },
}

impl BVHNode {
    /// The build function sometimes needs to add nodes while their data is not available yet.
    /// A dummy cerated by this function serves the purpose of being changed later on.
    fn create_dummy() -> BVHNode {
        BVHNode::Leaf {
            parent: 0,
            depth: 0,
            shape: 0,
        }
    }

    /// Builds a [`BVHNode`] recursively using SAH partitioning.
    /// Returns the index of the node in the nodes vector.
    ///
    /// [`BVHNode`]: enum.BVHNode.html
    ///
    pub fn build<T: BHShape>(shapes: &mut [T],
                             indices: Vec<usize>,
                             nodes: &mut Vec<BVHNode>,
                             parent: usize,
                             depth: u32)
                             -> usize {
        // Helper function to accumulate the AABB joint and the centroids AABB
        fn grow_convex_hull(convex_hull: (AABB, AABB), shape_aabb: &AABB) -> (AABB, AABB) {
            let center = &shape_aabb.center();
            let convex_hull_aabbs = &convex_hull.0;
            let convex_hull_centroids = &convex_hull.1;
            (convex_hull_aabbs.join(shape_aabb), convex_hull_centroids.grow(center))
        }

        let mut convex_hull = Default::default();
        for index in &indices {
            convex_hull = grow_convex_hull(convex_hull, &shapes[*index].aabb());
        }
        let (aabb_bounds, centroid_bounds) = convex_hull;

        // If there is only one element left, don't split anymore
        if indices.len() == 1 {
            let shape_index = indices[0];
            nodes.push(BVHNode::Leaf {
                parent: parent,
                depth: depth,
                shape: shape_index,
            });
            let node_index = nodes.len() - 1;
            // Let the shape know the index of the node that represents it
            shapes[shape_index].set_bh_node_index(node_index);
            return node_index;
        }

        // Find the axis along which the shapes are spread the most
        let split_axis = centroid_bounds.largest_axis();
        let split_axis_size = centroid_bounds.max[split_axis] - centroid_bounds.min[split_axis];

        /// Defines a Bucket utility object.
        #[derive(Copy, Clone)]
        struct Bucket {
            size: usize,
            aabb: AABB,
        }

        impl Bucket {
            /// Returns an empty bucket.
            fn empty() -> Bucket {
                Bucket {
                    size: 0,
                    aabb: AABB::empty(),
                }
            }

            /// Extends this `Bucket` by the given `AABB`.
            fn add_aabb(&mut self, aabb: &AABB) {
                self.size += 1;
                self.aabb = self.aabb.join(aabb);
            }
        }

        /// Joins two `Bucket`s.
        fn join_bucket(a: Bucket, b: &Bucket) -> Bucket {
            Bucket {
                size: a.size + b.size,
                aabb: a.aabb.join(&b.aabb),
            }
        }

        // Create six buckets, and six index assignment vectors
        const NUM_BUCKETS: usize = 6;
        let mut buckets = [Bucket::empty(); NUM_BUCKETS];
        let mut bucket_assignments: [Vec<usize>; NUM_BUCKETS] = Default::default();

        if split_axis_size < EPSILON {
            // Spread the remaining shapes evenly across buckets,
            // instead of using a heuristic
            for (counter, idx) in (&indices).iter().enumerate() {
                let shape = &shapes[*idx];
                let shape_aabb = shape.aabb();

                let bucket_num = counter % NUM_BUCKETS;

                buckets[bucket_num].add_aabb(&shape_aabb);
                bucket_assignments[bucket_num].push(*idx);
            }
        } else {
            // Assign each shape to a bucket
            for idx in &indices {
                let shape = &shapes[*idx];
                let shape_aabb = shape.aabb();
                let shape_center = shape_aabb.center();

                // Get the relative position of the shape centroid [0.0..1.0]
                let bucket_num_relative =
                    (shape_center[split_axis] - centroid_bounds.min[split_axis]) / split_axis_size;

                // Convert that to the actual `Bucket` number
                let bucket_num = (bucket_num_relative * (NUM_BUCKETS as f32 - 0.01)) as usize;

                // Extend the selected `Bucket` and add the index to the actual bucket
                buckets[bucket_num].add_aabb(&shape_aabb);
                bucket_assignments[bucket_num].push(*idx);
            }
        }

        // Compute the costs for each configuration and
        // select the configuration with the minimal costs
        let mut min_bucket = 0;
        let mut min_cost = f32::INFINITY;
        let mut child_l_aabb = AABB::empty();
        let mut child_r_aabb = AABB::empty();
        for i in 0..(NUM_BUCKETS - 1) {
            let child_l = buckets.iter().take(i + 1).fold(Bucket::empty(), join_bucket);
            let child_r = buckets.iter().skip(i + 1).fold(Bucket::empty(), join_bucket);

            let cost = (child_l.size as f32 * child_l.aabb.surface_area() +
                        child_r.size as f32 * child_r.aabb.surface_area()) /
                       aabb_bounds.surface_area();

            if cost < min_cost {
                min_bucket = i;
                min_cost = cost;
                child_l_aabb = child_l.aabb;
                child_r_aabb = child_r.aabb;
            }
        }

        // Join together all index buckets, and proceed recursively
        let mut child_l_indices = Vec::new();
        for mut indices in bucket_assignments.iter_mut().take(min_bucket + 1) {
            child_l_indices.append(&mut indices);
        }
        let mut child_r_indices = Vec::new();
        for mut indices in bucket_assignments.iter_mut().skip(min_bucket + 1) {
            child_r_indices.append(&mut indices);
        }

        let node_index = nodes.len();

        nodes.push(BVHNode::create_dummy());

        let child_l = BVHNode::build(shapes, child_l_indices, nodes, node_index, depth + 1);
        let child_r = BVHNode::build(shapes, child_r_indices, nodes, node_index, depth + 1);

        // Construct the actual data structure
        nodes[node_index] = BVHNode::Node {
            parent: parent,
            depth: depth,
            child_l_aabb: child_l_aabb,
            child_l: child_l,
            child_r_aabb: child_r_aabb,
            child_r: child_r,
        };

        node_index
    }

    /// Traverses the [`BVH`] recursively and returns all shapes whose [`AABB`] is
    /// intersected by the given [`Ray`].
    ///
    /// [`AABB`]: ../aabb/struct.AABB.html
    /// [`BVH`]: struct.BVH.html
    /// [`Ray`]: ../ray/struct.Ray.html
    ///
    pub fn traverse_recursive(nodes: &Vec<BVHNode>, node_index: usize, ray: &Ray, indices: &mut Vec<usize>) {
        let node = &nodes[node_index];
        match *node {
            BVHNode::Node { ref child_l_aabb, child_l, ref child_r_aabb, child_r, .. } => {
                if ray.intersects_aabb(child_l_aabb) {
                    BVHNode::traverse_recursive(nodes, child_l, ray, indices);
                }
                if ray.intersects_aabb(child_r_aabb) {
                    BVHNode::traverse_recursive(nodes, child_r, ray, indices);
                }
            }
            BVHNode::Leaf { shape, .. } => {
                indices.push(shape);
            }
        }
    }
}

/// The [`BVH`] data structure. Contains the list of [`BVHNode`]s.
///
/// [`BVH`]: struct.BVH.html
///
pub struct BVH {
    /// The list of nodes of the [`BVH`].
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub nodes: Vec<BVHNode>,
}

impl BVH {
    /// Creates a new [`BVH`] from the `shapes` slice.
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub fn build<Shape: BHShape>(shapes: &mut [Shape]) -> BVH {
        let indices = (0..shapes.len()).collect::<Vec<usize>>();
        let mut nodes = Vec::new();
        BVHNode::build(shapes, indices, &mut nodes, 0, 0);
        BVH { nodes: nodes }
    }

    /// Traverses the [`BVH`].
    /// Returns a subset of `shapes`, in which the [`AABB`]s of the elements were hit by `ray`.
    ///
    /// [`BVH`]: struct.BVH.html
    /// [`AABB`]: ../aabb/struct.AABB.html
    ///
    pub fn traverse<'a, Shape: Bounded>(&'a self, ray: &Ray, shapes: &'a [Shape]) -> Vec<&Shape> {
        let mut indices = Vec::new();
        BVHNode::traverse_recursive(&self.nodes, 0, ray, &mut indices);
        let mut hit_shapes = Vec::new();
        for index in &indices {
            let shape = &shapes[*index];
            hit_shapes.push(shape);
        }
        hit_shapes
    }

    /// Prints the [`BVH`] in a tree-like visualization.
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub fn pretty_print(&self) {
        let nodes = &self.nodes;
        fn print_node(nodes: &Vec<BVHNode>, node_index: usize) {
            let node = &nodes[node_index];
            match *node {
                BVHNode::Node { child_l, child_r, depth, child_l_aabb, child_r_aabb, .. } => {
                    let padding: String = repeat(" ").take(depth as usize).collect();
                    println!("{}child_l {:?}", padding, child_l_aabb);
                    print_node(nodes, child_l);
                    println!("{}child_r {:?}", padding, child_r_aabb);
                    print_node(nodes, child_r);
                }
                BVHNode::Leaf { shape, depth, .. } => {
                    let padding: String = repeat(" ").take(depth as usize).collect();
                    println!("{}shape\t{:?}", padding, shape);
                }
            }
        }
        print_node(nodes, 0);
    }
}

impl BoundingHierarchy for BVH {
    fn build<Shape: BHShape>(shapes: &mut [Shape]) -> BVH {
        BVH::build(shapes)
    }

    fn traverse<'a, Shape: Bounded>(&'a self, ray: &Ray, shapes: &'a [Shape]) -> Vec<&Shape> {
        self.traverse(ray, shapes)
    }

    fn pretty_print(&self) {
        self.pretty_print();
    }
}

#[cfg(test)]
pub mod tests {
    use bvh::BVH;
    use testbase::{build_some_bh, traverse_some_bh, build_1200_triangles_bh,
                   build_12k_triangles_bh, build_120k_triangles_bh, intersect_1200_triangles_bh,
                   intersect_12k_triangles_bh, intersect_120k_triangles_bh};

    #[test]
    /// Tests whether the building procedure succeeds in not failing.
    fn test_build_bvh() {
        build_some_bh::<BVH>();
    }

    #[test]
    /// Runs some primitive tests for intersections of a ray with a fixed scene given as a BVH.
    fn test_traverse_bvh() {
        traverse_some_bh::<BVH>();
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 1,200 triangles.
    fn bench_build_1200_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_1200_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 12,000 triangles.
    fn bench_build_12k_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_12k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 120,000 triangles.
    fn bench_build_120k_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_120k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 1,200 triangles using the recursive `BVH`.
    fn bench_intersect_1200_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_1200_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 12,000 triangles using the recursive `BVH`.
    fn bench_intersect_12k_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_12k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 120,000 triangles using the recursive `BVH`.
    fn bench_intersect_120k_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_120k_triangles_bh::<BVH>(&mut b);
    }
}
<commit_msg>Simplify code<commit_after>//! This module defines [`BVH`] and [`BVHNode`] and functions for building and traversing it.
//!
//! [`BVH`]: struct.BVH.html
//! [`BVHNode`]: struct.BVHNode.html
//!

use EPSILON;
use aabb::{AABB, Bounded};
use bounding_hierarchy::{BoundingHierarchy, BHShape};
use ray::Ray;
use std::f32;
use std::iter::repeat;

/// The [`BVHNode`] enum that describes a node in a [`BVH`].
/// It's either a leaf node and references a shape (by holding its index)
/// or a regular node that has two child nodes.
/// The non-leaf node stores the [`AABB`]s of its children.
///
/// [`AABB`]: ../aabb/struct.AABB.html
/// [`BVH`]: struct.BVH.html
/// [`BVH`]: struct.BVHNode.html
///
#[derive(Debug, Copy, Clone)]
pub enum BVHNode {
    /// Leaf node.
    Leaf {
        /// The node's parent.
        parent: usize,

        /// The node's depth.
        depth: u32,

        /// The shape contained in this leaf.
        shape: usize,
    },
    /// Inner node.
    Node {
        /// The node's parent.
        parent: usize,

        /// The node's depth.
        depth: u32,

        /// The convex hull of the shapes' `AABB`s in child_l.
        child_l_aabb: AABB,

        /// Index of the left subtree's root node.
        child_l: usize,

        /// The convex hull of the shapes' `AABB`s in child_r.
        child_r_aabb: AABB,

        /// Index of the right subtree's root node.
        child_r: usize,
    },
}

impl BVHNode {
    /// The build function sometimes needs to add nodes while their data is not available yet.
    /// A dummy cerated by this function serves the purpose of being changed later on.
    fn create_dummy() -> BVHNode {
        BVHNode::Leaf {
            parent: 0,
            depth: 0,
            shape: 0,
        }
    }

    /// Builds a [`BVHNode`] recursively using SAH partitioning.
    /// Returns the index of the node in the nodes vector.
    ///
    /// [`BVHNode`]: enum.BVHNode.html
    ///
    pub fn build<T: BHShape>(shapes: &mut [T],
                             indices: Vec<usize>,
                             nodes: &mut Vec<BVHNode>,
                             parent: usize,
                             depth: u32)
                             -> usize {
        // Helper function to accumulate the AABB joint and the centroids AABB
        fn grow_convex_hull(convex_hull: (AABB, AABB), shape_aabb: &AABB) -> (AABB, AABB) {
            let center = &shape_aabb.center();
            let convex_hull_aabbs = &convex_hull.0;
            let convex_hull_centroids = &convex_hull.1;
            (convex_hull_aabbs.join(shape_aabb), convex_hull_centroids.grow(center))
        }

        let mut convex_hull = Default::default();
        for index in &indices {
            convex_hull = grow_convex_hull(convex_hull, &shapes[*index].aabb());
        }
        let (aabb_bounds, centroid_bounds) = convex_hull;

        // If there is only one element left, don't split anymore
        if indices.len() == 1 {
            let shape_index = indices[0];
            let node_index = nodes.len();
            nodes.push(BVHNode::Leaf {
                parent: parent,
                depth: depth,
                shape: shape_index,
            });
            // Let the shape know the index of the node that represents it
            shapes[shape_index].set_bh_node_index(node_index);
            return node_index;
        }

        // Find the axis along which the shapes are spread the most
        let split_axis = centroid_bounds.largest_axis();
        let split_axis_size = centroid_bounds.max[split_axis] - centroid_bounds.min[split_axis];

        /// Defines a Bucket utility object.
        #[derive(Copy, Clone)]
        struct Bucket {
            size: usize,
            aabb: AABB,
        }

        impl Bucket {
            /// Returns an empty bucket.
            fn empty() -> Bucket {
                Bucket {
                    size: 0,
                    aabb: AABB::empty(),
                }
            }

            /// Extends this `Bucket` by the given `AABB`.
            fn add_aabb(&mut self, aabb: &AABB) {
                self.size += 1;
                self.aabb = self.aabb.join(aabb);
            }
        }

        /// Joins two `Bucket`s.
        fn join_bucket(a: Bucket, b: &Bucket) -> Bucket {
            Bucket {
                size: a.size + b.size,
                aabb: a.aabb.join(&b.aabb),
            }
        }

        // Create six buckets, and six index assignment vectors
        const NUM_BUCKETS: usize = 6;
        let mut buckets = [Bucket::empty(); NUM_BUCKETS];
        let mut bucket_assignments: [Vec<usize>; NUM_BUCKETS] = Default::default();

        if split_axis_size < EPSILON {
            // Spread the remaining shapes evenly across buckets,
            // instead of using a heuristic
            for (counter, idx) in (&indices).iter().enumerate() {
                let shape = &shapes[*idx];
                let shape_aabb = shape.aabb();

                let bucket_num = counter % NUM_BUCKETS;

                buckets[bucket_num].add_aabb(&shape_aabb);
                bucket_assignments[bucket_num].push(*idx);
            }
        } else {
            // Assign each shape to a bucket
            for idx in &indices {
                let shape = &shapes[*idx];
                let shape_aabb = shape.aabb();
                let shape_center = shape_aabb.center();

                // Get the relative position of the shape centroid [0.0..1.0]
                let bucket_num_relative =
                    (shape_center[split_axis] - centroid_bounds.min[split_axis]) / split_axis_size;

                // Convert that to the actual `Bucket` number
                let bucket_num = (bucket_num_relative * (NUM_BUCKETS as f32 - 0.01)) as usize;

                // Extend the selected `Bucket` and add the index to the actual bucket
                buckets[bucket_num].add_aabb(&shape_aabb);
                bucket_assignments[bucket_num].push(*idx);
            }
        }

        // Compute the costs for each configuration and
        // select the configuration with the minimal costs
        let mut min_bucket = 0;
        let mut min_cost = f32::INFINITY;
        let mut child_l_aabb = AABB::empty();
        let mut child_r_aabb = AABB::empty();
        for i in 0..(NUM_BUCKETS - 1) {
            let child_l = buckets.iter().take(i + 1).fold(Bucket::empty(), join_bucket);
            let child_r = buckets.iter().skip(i + 1).fold(Bucket::empty(), join_bucket);

            let cost = (child_l.size as f32 * child_l.aabb.surface_area() +
                        child_r.size as f32 * child_r.aabb.surface_area()) /
                       aabb_bounds.surface_area();

            if cost < min_cost {
                min_bucket = i;
                min_cost = cost;
                child_l_aabb = child_l.aabb;
                child_r_aabb = child_r.aabb;
            }
        }

        // Join together all index buckets, and proceed recursively
        let mut child_l_indices = Vec::new();
        for mut indices in bucket_assignments.iter_mut().take(min_bucket + 1) {
            child_l_indices.append(&mut indices);
        }
        let mut child_r_indices = Vec::new();
        for mut indices in bucket_assignments.iter_mut().skip(min_bucket + 1) {
            child_r_indices.append(&mut indices);
        }

        let node_index = nodes.len();

        nodes.push(BVHNode::create_dummy());

        let child_l = BVHNode::build(shapes, child_l_indices, nodes, node_index, depth + 1);
        let child_r = BVHNode::build(shapes, child_r_indices, nodes, node_index, depth + 1);

        // Construct the actual data structure
        nodes[node_index] = BVHNode::Node {
            parent: parent,
            depth: depth,
            child_l_aabb: child_l_aabb,
            child_l: child_l,
            child_r_aabb: child_r_aabb,
            child_r: child_r,
        };

        node_index
    }

    /// Traverses the [`BVH`] recursively and returns all shapes whose [`AABB`] is
    /// intersected by the given [`Ray`].
    ///
    /// [`AABB`]: ../aabb/struct.AABB.html
    /// [`BVH`]: struct.BVH.html
    /// [`Ray`]: ../ray/struct.Ray.html
    ///
    pub fn traverse_recursive(nodes: &Vec<BVHNode>, node_index: usize, ray: &Ray, indices: &mut Vec<usize>) {
        let node = &nodes[node_index];
        match *node {
            BVHNode::Node { ref child_l_aabb, child_l, ref child_r_aabb, child_r, .. } => {
                if ray.intersects_aabb(child_l_aabb) {
                    BVHNode::traverse_recursive(nodes, child_l, ray, indices);
                }
                if ray.intersects_aabb(child_r_aabb) {
                    BVHNode::traverse_recursive(nodes, child_r, ray, indices);
                }
            }
            BVHNode::Leaf { shape, .. } => {
                indices.push(shape);
            }
        }
    }
}

/// The [`BVH`] data structure. Contains the list of [`BVHNode`]s.
///
/// [`BVH`]: struct.BVH.html
///
pub struct BVH {
    /// The list of nodes of the [`BVH`].
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub nodes: Vec<BVHNode>,
}

impl BVH {
    /// Creates a new [`BVH`] from the `shapes` slice.
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub fn build<Shape: BHShape>(shapes: &mut [Shape]) -> BVH {
        let indices = (0..shapes.len()).collect::<Vec<usize>>();
        let mut nodes = Vec::new();
        BVHNode::build(shapes, indices, &mut nodes, 0, 0);
        BVH { nodes: nodes }
    }

    /// Traverses the [`BVH`].
    /// Returns a subset of `shapes`, in which the [`AABB`]s of the elements were hit by `ray`.
    ///
    /// [`BVH`]: struct.BVH.html
    /// [`AABB`]: ../aabb/struct.AABB.html
    ///
    pub fn traverse<'a, Shape: Bounded>(&'a self, ray: &Ray, shapes: &'a [Shape]) -> Vec<&Shape> {
        let mut indices = Vec::new();
        BVHNode::traverse_recursive(&self.nodes, 0, ray, &mut indices);
        let mut hit_shapes = Vec::new();
        for index in &indices {
            let shape = &shapes[*index];
            hit_shapes.push(shape);
        }
        hit_shapes
    }

    /// Prints the [`BVH`] in a tree-like visualization.
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub fn pretty_print(&self) {
        let nodes = &self.nodes;
        fn print_node(nodes: &Vec<BVHNode>, node_index: usize) {
            let node = &nodes[node_index];
            match *node {
                BVHNode::Node { child_l, child_r, depth, child_l_aabb, child_r_aabb, .. } => {
                    let padding: String = repeat(" ").take(depth as usize).collect();
                    println!("{}child_l {:?}", padding, child_l_aabb);
                    print_node(nodes, child_l);
                    println!("{}child_r {:?}", padding, child_r_aabb);
                    print_node(nodes, child_r);
                }
                BVHNode::Leaf { shape, depth, .. } => {
                    let padding: String = repeat(" ").take(depth as usize).collect();
                    println!("{}shape\t{:?}", padding, shape);
                }
            }
        }
        print_node(nodes, 0);
    }
}

impl BoundingHierarchy for BVH {
    fn build<Shape: BHShape>(shapes: &mut [Shape]) -> BVH {
        BVH::build(shapes)
    }

    fn traverse<'a, Shape: Bounded>(&'a self, ray: &Ray, shapes: &'a [Shape]) -> Vec<&Shape> {
        self.traverse(ray, shapes)
    }

    fn pretty_print(&self) {
        self.pretty_print();
    }
}

#[cfg(test)]
pub mod tests {
    use bvh::BVH;
    use testbase::{build_some_bh, traverse_some_bh, build_1200_triangles_bh,
                   build_12k_triangles_bh, build_120k_triangles_bh, intersect_1200_triangles_bh,
                   intersect_12k_triangles_bh, intersect_120k_triangles_bh};

    #[test]
    /// Tests whether the building procedure succeeds in not failing.
    fn test_build_bvh() {
        build_some_bh::<BVH>();
    }

    #[test]
    /// Runs some primitive tests for intersections of a ray with a fixed scene given as a BVH.
    fn test_traverse_bvh() {
        traverse_some_bh::<BVH>();
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 1,200 triangles.
    fn bench_build_1200_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_1200_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 12,000 triangles.
    fn bench_build_12k_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_12k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 120,000 triangles.
    fn bench_build_120k_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_120k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 1,200 triangles using the recursive `BVH`.
    fn bench_intersect_1200_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_1200_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 12,000 triangles using the recursive `BVH`.
    fn bench_intersect_12k_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_12k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 120,000 triangles using the recursive `BVH`.
    fn bench_intersect_120k_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_120k_triangles_bh::<BVH>(&mut b);
    }
}
<|endoftext|>


<commit_before>use core::borrow::{Borrow, BorrowMut};
use core::cmp::{self, Ordering};
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};
use core::ops::{Deref, DerefMut};

#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use alloc::string::String;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;

use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor};
use serde::ser::{Serialize, Serializer};

use crate::Bytes;

/// Wrapper around `Vec<u8>` to serialize and deserialize efficiently.
///
/// ```
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::ByteBuf;
///
/// fn deserialize_bytebufs() -> bincode::Result<()> {
///     let example_data = [
///         2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 116,
///         119, 111, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 111, 110, 101];
///
///     let map: HashMap<u32, ByteBuf> = bincode::deserialize(&example_data[..])?;
///
///     println!("{:?}", map);
///
///     Ok(())
/// }
/// #
/// # fn main() {
/// #     deserialize_bytebufs().unwrap();
/// # }
/// ```
#[derive(Clone, Default, Eq, Ord)]
pub struct ByteBuf {
    bytes: Vec<u8>,
}

impl ByteBuf {
    /// Construct a new, empty `ByteBuf`.
    pub fn new() -> Self {
        ByteBuf::from(Vec::new())
    }

    /// Construct a new, empty `ByteBuf` with the specified capacity.
    pub fn with_capacity(cap: usize) -> Self {
        ByteBuf::from(Vec::with_capacity(cap))
    }

    /// Wrap existing bytes in a `ByteBuf`.
    pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
        ByteBuf {
            bytes: bytes.into(),
        }
    }

    /// Unwrap the vector of byte underlying this `ByteBuf`.
    pub fn into_vec(self) -> Vec<u8> {
        self.bytes
    }

    #[allow(missing_docs)]
    pub fn into_boxed_bytes(self) -> Box<Bytes> {
        self.bytes.into_boxed_slice().into()
    }

    // This would hit "cannot move out of borrowed content" if invoked through
    // the Deref impl; make it just work.
    #[doc(hidden)]
    pub fn into_boxed_slice(self) -> Box<[u8]> {
        self.bytes.into_boxed_slice()
    }

    #[doc(hidden)]
    pub fn into_iter(self) -> <Vec<u8> as IntoIterator>::IntoIter {
        self.bytes.into_iter()
    }
}

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

impl AsRef<[u8]> for ByteBuf {
    fn as_ref(&self) -> &[u8] {
        &self.bytes
    }
}

impl AsMut<[u8]> for ByteBuf {
    fn as_mut(&mut self) -> &mut [u8] {
        &mut self.bytes
    }
}

impl Deref for ByteBuf {
    type Target = Vec<u8>;

    fn deref(&self) -> &Self::Target {
        &self.bytes
    }
}

impl DerefMut for ByteBuf {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.bytes
    }
}

impl Borrow<Bytes> for ByteBuf {
    fn borrow(&self) -> &Bytes {
        Bytes::new(&self.bytes)
    }
}

impl BorrowMut<Bytes> for ByteBuf {
    fn borrow_mut(&mut self) -> &mut Bytes {
        unsafe { &mut *(&mut self.bytes as &mut [u8] as *mut [u8] as *mut Bytes) }
    }
}

impl<Rhs> PartialEq<Rhs> for ByteBuf
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn eq(&self, other: &Rhs) -> bool {
        self.as_ref().eq(other.as_ref())
    }
}

impl<Rhs> PartialOrd<Rhs> for ByteBuf
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> {
        self.as_ref().partial_cmp(other.as_ref())
    }
}

impl Hash for ByteBuf {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.bytes.hash(state);
    }
}

impl IntoIterator for ByteBuf {
    type Item = u8;
    type IntoIter = <Vec<u8> as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.bytes.into_iter()
    }
}

impl<'a> IntoIterator for &'a ByteBuf {
    type Item = &'a u8;
    type IntoIter = <&'a [u8] as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.bytes.iter()
    }
}

impl<'a> IntoIterator for &'a mut ByteBuf {
    type Item = &'a mut u8;
    type IntoIter = <&'a mut [u8] as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.bytes.iter_mut()
    }
}

impl Serialize for ByteBuf {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(&self.bytes)
    }
}

struct ByteBufVisitor;

impl<'de> Visitor<'de> for ByteBufVisitor {
    type Value = ByteBuf;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("byte array")
    }

    fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
    where
        V: SeqAccess<'de>,
    {
        let len = cmp::min(visitor.size_hint().unwrap_or(0), 4096);
        let mut values = Vec::with_capacity(len);

        while let Some(value) = visitor.next_element()? {
            values.push(value);
        }

        Ok(ByteBuf::from(values))
    }

    fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }
}

impl<'de> Deserialize<'de> for ByteBuf {
    fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_byte_buf(ByteBufVisitor)
    }
}
<commit_msg>Improve naming in ByteBufVisitor::visit_seq<commit_after>use core::borrow::{Borrow, BorrowMut};
use core::cmp::{self, Ordering};
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};
use core::ops::{Deref, DerefMut};

#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use alloc::string::String;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;

use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor};
use serde::ser::{Serialize, Serializer};

use crate::Bytes;

/// Wrapper around `Vec<u8>` to serialize and deserialize efficiently.
///
/// ```
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::ByteBuf;
///
/// fn deserialize_bytebufs() -> bincode::Result<()> {
///     let example_data = [
///         2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 116,
///         119, 111, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 111, 110, 101];
///
///     let map: HashMap<u32, ByteBuf> = bincode::deserialize(&example_data[..])?;
///
///     println!("{:?}", map);
///
///     Ok(())
/// }
/// #
/// # fn main() {
/// #     deserialize_bytebufs().unwrap();
/// # }
/// ```
#[derive(Clone, Default, Eq, Ord)]
pub struct ByteBuf {
    bytes: Vec<u8>,
}

impl ByteBuf {
    /// Construct a new, empty `ByteBuf`.
    pub fn new() -> Self {
        ByteBuf::from(Vec::new())
    }

    /// Construct a new, empty `ByteBuf` with the specified capacity.
    pub fn with_capacity(cap: usize) -> Self {
        ByteBuf::from(Vec::with_capacity(cap))
    }

    /// Wrap existing bytes in a `ByteBuf`.
    pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
        ByteBuf {
            bytes: bytes.into(),
        }
    }

    /// Unwrap the vector of byte underlying this `ByteBuf`.
    pub fn into_vec(self) -> Vec<u8> {
        self.bytes
    }

    #[allow(missing_docs)]
    pub fn into_boxed_bytes(self) -> Box<Bytes> {
        self.bytes.into_boxed_slice().into()
    }

    // This would hit "cannot move out of borrowed content" if invoked through
    // the Deref impl; make it just work.
    #[doc(hidden)]
    pub fn into_boxed_slice(self) -> Box<[u8]> {
        self.bytes.into_boxed_slice()
    }

    #[doc(hidden)]
    pub fn into_iter(self) -> <Vec<u8> as IntoIterator>::IntoIter {
        self.bytes.into_iter()
    }
}

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

impl AsRef<[u8]> for ByteBuf {
    fn as_ref(&self) -> &[u8] {
        &self.bytes
    }
}

impl AsMut<[u8]> for ByteBuf {
    fn as_mut(&mut self) -> &mut [u8] {
        &mut self.bytes
    }
}

impl Deref for ByteBuf {
    type Target = Vec<u8>;

    fn deref(&self) -> &Self::Target {
        &self.bytes
    }
}

impl DerefMut for ByteBuf {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.bytes
    }
}

impl Borrow<Bytes> for ByteBuf {
    fn borrow(&self) -> &Bytes {
        Bytes::new(&self.bytes)
    }
}

impl BorrowMut<Bytes> for ByteBuf {
    fn borrow_mut(&mut self) -> &mut Bytes {
        unsafe { &mut *(&mut self.bytes as &mut [u8] as *mut [u8] as *mut Bytes) }
    }
}

impl<Rhs> PartialEq<Rhs> for ByteBuf
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn eq(&self, other: &Rhs) -> bool {
        self.as_ref().eq(other.as_ref())
    }
}

impl<Rhs> PartialOrd<Rhs> for ByteBuf
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> {
        self.as_ref().partial_cmp(other.as_ref())
    }
}

impl Hash for ByteBuf {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.bytes.hash(state);
    }
}

impl IntoIterator for ByteBuf {
    type Item = u8;
    type IntoIter = <Vec<u8> as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.bytes.into_iter()
    }
}

impl<'a> IntoIterator for &'a ByteBuf {
    type Item = &'a u8;
    type IntoIter = <&'a [u8] as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.bytes.iter()
    }
}

impl<'a> IntoIterator for &'a mut ByteBuf {
    type Item = &'a mut u8;
    type IntoIter = <&'a mut [u8] as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.bytes.iter_mut()
    }
}

impl Serialize for ByteBuf {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(&self.bytes)
    }
}

struct ByteBufVisitor;

impl<'de> Visitor<'de> for ByteBufVisitor {
    type Value = ByteBuf;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("byte array")
    }

    fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
    where
        V: SeqAccess<'de>,
    {
        let len = cmp::min(visitor.size_hint().unwrap_or(0), 4096);
        let mut bytes = Vec::with_capacity(len);

        while let Some(b) = visitor.next_element()? {
            bytes.push(b);
        }

        Ok(ByteBuf::from(bytes))
    }

    fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }
}

impl<'de> Deserialize<'de> for ByteBuf {
    fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_byte_buf(ByteBufVisitor)
    }
}
<|endoftext|>


<commit_before>use super::rust_string::RustString;
use std::mem;
use std::ptr;

#[repr(C)]
pub(crate) struct RustVec<T> {
    repr: Vec<T>,
}

macro_rules! attr {
    (#[$name:ident = $value:expr] $($rest:tt)*) => {
        #[$name = $value]
        $($rest)*
    };
}

macro_rules! rust_vec_shims {
    ($segment:expr, $ty:ty) => {
        const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
        const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<$ty>>());

        const _: () = {
            attr! {
                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$new")]
                unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
                    ptr::write(this, RustVec { repr: Vec::new() });
                }
            }
            attr! {
                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$drop")]
                unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
                    ptr::drop_in_place(this);
                }
            }
            attr! {
                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$len")]
                unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
                    (*this).repr.len()
                }
            }
            attr! {
                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$data")]
                unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
                    (*this).repr.as_ptr()
                }
            }
            attr! {
                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$stride")]
                unsafe extern "C" fn __stride() -> usize {
                    mem::size_of::<$ty>()
                }
            }
        };
    };
}

macro_rules! rust_vec_shims_for_primitive {
    ($ty:ident) => {
        rust_vec_shims!(stringify!($ty), $ty);
    };
}

rust_vec_shims_for_primitive!(bool);
rust_vec_shims_for_primitive!(u8);
rust_vec_shims_for_primitive!(u16);
rust_vec_shims_for_primitive!(u32);
rust_vec_shims_for_primitive!(u64);
rust_vec_shims_for_primitive!(i8);
rust_vec_shims_for_primitive!(i16);
rust_vec_shims_for_primitive!(i32);
rust_vec_shims_for_primitive!(i64);
rust_vec_shims_for_primitive!(f32);
rust_vec_shims_for_primitive!(f64);

rust_vec_shims!("string", RustString);
<commit_msg>Remove duplicated attr macro<commit_after>use super::rust_string::RustString;
use std::mem;
use std::ptr;

#[repr(C)]
pub(crate) struct RustVec<T> {
    repr: Vec<T>,
}

macro_rules! rust_vec_shims {
    ($segment:expr, $ty:ty) => {
        const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
        const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<$ty>>());

        const _: () = {
            attr! {
                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$new")]
                unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
                    ptr::write(this, RustVec { repr: Vec::new() });
                }
            }
            attr! {
                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$drop")]
                unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
                    ptr::drop_in_place(this);
                }
            }
            attr! {
                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$len")]
                unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
                    (*this).repr.len()
                }
            }
            attr! {
                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$data")]
                unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
                    (*this).repr.as_ptr()
                }
            }
            attr! {
                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$stride")]
                unsafe extern "C" fn __stride() -> usize {
                    mem::size_of::<$ty>()
                }
            }
        };
    };
}

macro_rules! rust_vec_shims_for_primitive {
    ($ty:ident) => {
        rust_vec_shims!(stringify!($ty), $ty);
    };
}

rust_vec_shims_for_primitive!(bool);
rust_vec_shims_for_primitive!(u8);
rust_vec_shims_for_primitive!(u16);
rust_vec_shims_for_primitive!(u32);
rust_vec_shims_for_primitive!(u64);
rust_vec_shims_for_primitive!(i8);
rust_vec_shims_for_primitive!(i16);
rust_vec_shims_for_primitive!(i32);
rust_vec_shims_for_primitive!(i64);
rust_vec_shims_for_primitive!(f32);
rust_vec_shims_for_primitive!(f64);

rust_vec_shims!("string", RustString);
<|endoftext|>


<commit_before>use std::boxed::Box;
use memory::Memory;

/// Hook for changing the address before a value is read from `Memory`.
type ReadPreHook = Fn(&mut usize);
/// Hook for changing the value that is returned after being read from `Memory`.
type ReadPostHook = Fn(&usize, &mut u32);
/// Hook for changing both the address and the value before it is written
/// to `Memory`.
type WriteHook = Fn(&mut usize, &mut u32);
/// Hook for changing the reported size of `Memory`.
type SizeHook = Fn(&mut usize);

/// Calls callbacks on reads or writes.
///
/// The `HookMemory` allows to hook into the `Memory` interface. These hooks are
/// allowed to modify the parameters of the call.
///
/// # Examples
///
/// ```
/// use osciemu::memory::{Memory, HookMemory, SliceMemory};
///
/// let mut hook_mem =
///     HookMemory::new(
///         SliceMemory::from_slice_u32(16, [0, 1, 2, 3])
///     );
/// hook_mem.read_prehook(Box::new(|addr| *addr += 4));
/// hook_mem.read_posthook(Box::new(|addr, val| *val <<= 1));
///
/// // This will read cell 1 and the result will be shifted left by 1.
/// assert_eq!(hook_mem.get(0), 2);
/// ```
///
pub struct HookMemory<T: Memory> {
    get_prehook: Option<Box<ReadPreHook>>,
    get_posthook: Option<Box<ReadPostHook>>,
    set_hook: Option<Box<WriteHook>>,
    size_hook: Option<Box<SizeHook>>,
    memory: T,
}

impl<T: Memory> HookMemory<T> {
    pub fn new(memory: T) -> HookMemory<T> {
        HookMemory {
            get_prehook: None,
            get_posthook: None,
            set_hook: None,
            size_hook: None,
            memory: memory,
        }
    }

    pub fn read_prehook(&mut self, h: Box<ReadPreHook>) {
        self.get_prehook = Some(h);
    }

    pub fn read_posthook(&mut self, h: Box<ReadPostHook>) {
        self.get_posthook = Some(h);
    }

    pub fn write_hook(&mut self, h: Box<WriteHook>) {
        self.set_hook = Some(h);
    }

    pub fn size_hook(&mut self, h: Box<SizeHook>) {
        self.size_hook = Some(h);
    }
}

impl<T: Memory> Memory for HookMemory<T> {
    fn get(&self, mut addr: usize) -> u32 {
        self.get_prehook.as_ref().map(|ref f| f(&mut addr));
        let mut v = self.memory.get(addr);
        self.get_posthook.as_ref().map(|f| f(&addr, &mut v));
        v
    }

    fn set(&mut self, mut addr: usize, mut value: u32) {
        self.set_hook.as_ref().map(|f| f(&mut addr, &mut value));
        self.memory.set(addr, value);
    }

    fn size(&self) -> usize {
        let mut size = self.memory.size();
        self.size_hook.as_ref().map(|f| f(&mut size));
        size
    }
}

#[cfg(test)]
mod tests {
    use memory::{Memory, SliceMemory};

    #[test]
    fn read_prehook() {
        let mut hook_mem = super::HookMemory::new(SliceMemory::from_slice(Box::new([0, 2, 4])));
        assert_eq!(hook_mem.get(0), 0);
        hook_mem.read_prehook(Box::new(|addr| *addr += 4));
        assert_eq!(hook_mem.get(0), 2);
        assert_eq!(hook_mem.get(4), 4);
    }

    #[test]
    fn read_posthook() {
        let mut hook_mem = super::HookMemory::new(SliceMemory::from_slice(Box::new([0, 2, 4])));
        assert_eq!(hook_mem.get(0), 0);
        hook_mem.read_posthook(Box::new(|_, val| *val += 1));
        assert_eq!(hook_mem.get(0), 1);
        assert_eq!(hook_mem.get(4), 3);
        assert_eq!(hook_mem.get(8), 5);
    }

    #[test]
    fn write_hook() {
        let mut hook_mem = super::HookMemory::new(SliceMemory::from_slice(Box::new([0, 0])));
        assert_eq!(hook_mem.get(0), 0);
        hook_mem.set(0, 1);
        assert_eq!(hook_mem.get(0), 1);
        hook_mem.set(0, 0);
        hook_mem.write_hook(Box::new(|addr, val| {
            *addr += 4;
            *val += 1;
        }));
        hook_mem.set(0, 1);
        assert_eq!(hook_mem.get(0), 0);
        assert_eq!(hook_mem.get(4), 2);
    }

    #[test]
    fn size_hook() {
        let mut hook_mem = super::HookMemory::new(SliceMemory::from_slice(Box::new([0, 0])));
        assert_eq!(hook_mem.size(), 8);
        hook_mem.size_hook(Box::new(|size| { *size += 1; }));
        assert_eq!(hook_mem.size(), 9);
    }
}
<commit_msg>refactor(hookmemory): Update for new memory design<commit_after>use std::boxed::Box;
use memory::Memory;

/// Hook for changing the address before a value is read from `Memory`.
type ReadPreHook = Fn(&mut usize);
/// Hook for changing the value that is returned after being read from `Memory`.
type ReadPostHook = Fn(&usize, &mut u32);
/// Hook for changing both the address and the value before it is written
/// to `Memory`.
type WriteHook = Fn(&mut usize, &mut u32);
/// Hook for changing the reported size of `Memory`.
type SizeHook = Fn(&mut usize);

/// Calls callbacks on reads or writes.
///
/// The `HookMemory` allows to hook into the `Memory` interface. These hooks are
/// allowed to modify the parameters of the call.
///
/// # Examples
///
/// ```
/// use osciemu::memory::{Memory, HookMemory, SliceMemory};
///
/// let mut hook_mem =
///     HookMemory::new(
///         SliceMemory::from_slice(Box::new([0, 9]))
///     );
/// hook_mem.read_prehook(Box::new(|addr| *addr += 1));
/// hook_mem.read_posthook(Box::new(|addr, val| *val <<= 1));
///
/// // This will read cell 1 and the result will be shifted left by 1.
/// assert_eq!(hook_mem.get(0), 18);
/// ```
///
pub struct HookMemory<T: Memory> {
    get_prehook: Option<Box<ReadPreHook>>,
    get_posthook: Option<Box<ReadPostHook>>,
    set_hook: Option<Box<WriteHook>>,
    size_hook: Option<Box<SizeHook>>,
    memory: T,
}

impl<T: Memory> HookMemory<T> {
    pub fn new(memory: T) -> HookMemory<T> {
        HookMemory {
            get_prehook: None,
            get_posthook: None,
            set_hook: None,
            size_hook: None,
            memory: memory,
        }
    }

    pub fn read_prehook(&mut self, h: Box<ReadPreHook>) {
        self.get_prehook = Some(h);
    }

    pub fn read_posthook(&mut self, h: Box<ReadPostHook>) {
        self.get_posthook = Some(h);
    }

    pub fn write_hook(&mut self, h: Box<WriteHook>) {
        self.set_hook = Some(h);
    }

    pub fn size_hook(&mut self, h: Box<SizeHook>) {
        self.size_hook = Some(h);
    }
}

impl<T: Memory> Memory for HookMemory<T> {
    fn get(&self, mut addr: usize) -> u32 {
        self.get_prehook.as_ref().map(|ref f| f(&mut addr));
        let mut v = self.memory.get(addr);
        self.get_posthook.as_ref().map(|f| f(&addr, &mut v));
        v
    }

    fn set(&mut self, mut addr: usize, mut value: u32) {
        self.set_hook.as_ref().map(|f| f(&mut addr, &mut value));
        self.memory.set(addr, value);
    }

    fn size(&self) -> usize {
        let mut size = self.memory.size();
        self.size_hook.as_ref().map(|f| f(&mut size));
        size
    }
}

#[cfg(test)]
mod tests {
    use memory::{Memory, SliceMemory};

    #[test]
    fn read_prehook() {
        let mut hook_mem = super::HookMemory::new(SliceMemory::from_slice(Box::new([0, 2, 4])));
        assert_eq!(hook_mem.get(0), 0);
        hook_mem.read_prehook(Box::new(|addr| *addr += 1));
        assert_eq!(hook_mem.get(0), 2);
        assert_eq!(hook_mem.get(1), 4);
    }

    #[test]
    fn read_posthook() {
        let mut hook_mem = super::HookMemory::new(SliceMemory::from_slice(Box::new([0, 2, 4])));
        assert_eq!(hook_mem.get(0), 0);
        hook_mem.read_posthook(Box::new(|_, val| *val += 1));
        assert_eq!(hook_mem.get(0), 1);
        assert_eq!(hook_mem.get(1), 3);
        assert_eq!(hook_mem.get(2), 5);
    }

    #[test]
    fn write_hook() {
        let mut hook_mem = super::HookMemory::new(SliceMemory::from_slice(Box::new([0, 0])));
        assert_eq!(hook_mem.get(0), 0);
        hook_mem.set(0, 1);
        assert_eq!(hook_mem.get(0), 1);
        hook_mem.set(0, 0);
        hook_mem.write_hook(Box::new(|addr, val| {
            *addr += 1;
            *val += 1;
        }));
        hook_mem.set(0, 1);
        assert_eq!(hook_mem.get(0), 0);
        assert_eq!(hook_mem.get(1), 2);
    }

    #[test]
    fn size_hook() {
        let mut hook_mem = super::HookMemory::new(SliceMemory::from_slice(Box::new([0, 0])));
        assert_eq!(hook_mem.size(), 2);
        hook_mem.size_hook(Box::new(|size| { *size += 1; }));
        assert_eq!(hook_mem.size(), 3);
    }
}
<|endoftext|>