<commit_before>use std::fs::File;
use std::io::{Read, Error};
use std::path::Path;
use std::num::Wrapping;

pub fn wrapping_add(r1: u16, r2: u16) -> u16 {
	(Wrapping(r1) + Wrapping(r2)).0
}

pub fn wrapping_sub(r1: u16, r2: u16) -> u16 {
	(Wrapping(r1) - Wrapping(r2)).0
}

pub fn read_file<P: AsRef<Path>>(path: P) -> Result<Box<[u8]>, Error> {
	let mut file = try!(File::open(path));
	let mut buffer = Vec::new();
	try!(file.read_to_end(&mut buffer));
	Ok(buffer.into_boxed_slice())
}
<commit_msg>Reading a file should return a Result.<commit_after>use std::fs::File;
use std::io::{Read, Error};
use std::path::Path;
use std::num::Wrapping;

pub fn wrapping_add(r1: u16, r2: u16) -> u16 {
	(Wrapping(r1) + Wrapping(r2)).0
}

pub fn wrapping_sub(r1: u16, r2: u16) -> u16 {
	(Wrapping(r1) - Wrapping(r2)).0
}

pub fn read_file<P: AsRef<Path>>(path: P) -> Result<Box<[u8]>, Error> {
	let mut file = try!(File::open(path));
	let mut buffer = Vec::new();
	let result = file.read_to_end(&mut buffer);
	//try!(file.read_to_end(&mut buffer));
	//Ok(buffer.into_boxed_slice())
	match result {
		Ok(_) => Ok(buffer.into_boxed_slice()),
		Err(err) => Err(err),
	}
}
<|endoftext|>


<commit_before>use super::{ Message, Element, Pressed, Released, MouseMoved };
use entities::{ EntitiesState, EntitiesHelper, EntityID, ComponentID, NativeComponentType };
use nalgebra::na;
use nalgebra::na::Inv;
use script;

pub struct InputSystem {
    logger: Box<::log::Logger>,
    current_hover: Option<EntityID>,
    last_known_mouse_position: na::Vec2<f64>
}

impl InputSystem {
    pub fn new<L: ::log::Logger + 'static>(_: &EntitiesState, logger: L)
        -> InputSystem
    {
        InputSystem {
            logger: box logger,
            current_hover: None,
            last_known_mouse_position: na::Vec2::new(0.0, 0.0)
        }
    }

    pub fn process(&mut self, state: &mut EntitiesState, elapsed: &f64, messages: &[Message])
    {
        self.process_hover(state, elapsed, messages);
        self.process_input_handlers(state, elapsed, messages);
    }

    /// Processes all "inputHandler" components.
    pub fn process_input_handlers(&mut self, state: &mut EntitiesState,
                                  elapsed: &f64, messages: &[Message])
    {
        // creating an iterator to have only the "pressed" and "release" messages
        let mut filteredMessagesIter = messages
            .iter()
            .filter_map(|msg| match msg {
                &Pressed(ref e) => Some((e, true)),
                &Released(ref e) => Some((e, false)),
                _ => None
            });

        for (element, pressed) in filteredMessagesIter {
            let element = format!("{}", element);

            // getting all "inputHandler" components that match the element
            for component in state
                .get_visible_native_components("inputHandler")
                .move_iter()
                .filter(|c|
                    match state.get_as_string(c, "element") {
                        Some(s) => s == element,
                        _ => false
                    }
                )
                .collect::<Vec<ComponentID>>().move_iter()
            {
                // this component **may** need an update
                // we delegate this to a subfunction
                self.update_input_handler(state, &component, pressed)
            }
        }
    }

    /// Processes all "hoverHandler" components.
    fn process_hover(&mut self, state: &mut EntitiesState, _: &f64, messages: &[Message])
    {
        // getting the mouse position between (-1, -1) and (1, 1)
        let mouse_position = messages
            .iter().rev()
            .filter_map(|msg| match msg {
                &MouseMoved(x, y) => Some(na::Vec2::new(x, y)),
                _ => None
            })
            .next().unwrap_or(self.last_known_mouse_position);
        self.last_known_mouse_position = mouse_position;

        // getting the mouse position in camera units
        let mouse_position = {
            let mousePosVector = na::Vec4::new(mouse_position.x as f32, mouse_position.y as f32, 0.0, 1.0);
            let matrix = { let mut m = ::display::DisplaySystem::get_camera(state).unwrap(); m.inv(); m };
            let result = mousePosVector * matrix;
            na::Vec2::new(result.x / result.w, result.y / result.w)
        };

        // getting which entity is being hovered
        let hovered_entity: Option<EntityID> = state
            .get_visible_native_components("clickBox")
            .move_iter()
            .filter_map(|component| {
                let entity = match state.get_owner(&component) { Ok(t) => t, _ => return None };
                let entity_position = ::physics::PhysicsSystem::get_entity_position(state, &entity);

                let coord1 = match (state.get_as_number(&component, "leftX"), state.get_as_number(&component, "bottomY"))
                {
                    (Some(x), Some(y)) => na::Vec2::new(x as f32 + entity_position.x, y as f32 + entity_position.y),
                    _ => return None
                };

                let coord2 = match (state.get_as_number(&component, "rightX"), state.get_as_number(&component, "topY"))
                {
                    (Some(x), Some(y)) => na::Vec2::new(x as f32 + entity_position.x, y as f32 + entity_position.y),
                    _ => return None
                };

                if (coord1.x < coord2.x) && coord2.x < mouse_position.x { return None }
                if (coord2.x < coord1.x) && coord1.x < mouse_position.x { return None }
                if (coord1.x > coord2.x) && coord2.x > mouse_position.x { return None }
                if (coord2.x > coord1.x) && coord1.x > mouse_position.x { return None }
                if (coord1.y < coord2.y) && coord2.y < mouse_position.y { return None }
                if (coord2.y < coord1.y) && coord1.y < mouse_position.y { return None }
                if (coord1.y > coord2.y) && coord2.y > mouse_position.y { return None }
                if (coord2.y > coord1.y) && coord1.y > mouse_position.y { return None }

                Some(entity)
            })
            .next();

        // if the hovered entity has not changed, we have finished
        if hovered_entity == self.current_hover {
            return
        }

        // we have left the current hovered entity, executing script and removing prototype
        if self.current_hover.is_some() {
            // looping through each "hoverHandler" of the current_hover entity
            for cmp in state
                .get_components_iter()
                .filter(|c| state.is_component_visible(*c).unwrap())
                .filter(|c| match state.get_type(*c) { Ok(NativeComponentType(t)) => t.as_slice() == "hoverHandler", _ => false })
                .filter(|c| state.get_owner(*c).ok() == self.current_hover)
                .map(|c| c.clone())
                .collect::<Vec<ComponentID>>().move_iter()
            {
                // removing all its children (ie. the prototype)
                for c in state.get_component_children(&cmp).unwrap().move_iter() {
                    state.destroy_component(&c).ok();
                }

                // executing onLeave script
                match state.get_as_string(&cmp, "scriptOnLeave") {
                    None => (),
                    Some(script) => { script::execute_mut(state, &cmp, &script.as_slice()).unwrap(); }
                };
            }
        }

        // updating self
        self.current_hover = hovered_entity;

        // processing the new entity
        match hovered_entity {
            None => (),
            Some(hovered_entity) => {
                // looping through each "hoverHandler" of the new entity
                for cmp in state
                    .get_visible_native_components("hoverHandler")
                    .move_iter()
                    .filter(|c| state.get_owner(c).ok() == Some(hovered_entity))
                    .collect::<Vec<ComponentID>>().move_iter()
                {
                    // adding prototype
                    match state.get_as_entity(&cmp, "prototype") {
                        Some(prototype) => {
                            let newCmp = state.create_component_from_entity(&hovered_entity, &prototype, ::std::collections::HashMap::new()).unwrap();
                            state.set_component_parent(&newCmp, &cmp);
                        },
                        None => ()
                    };

                    // executing onLeave script
                    match state.get_as_string(&cmp, "scriptOnEnter") {
                        None => (),
                        Some(script) => { script::execute_mut(state, &cmp, &script.as_slice()).unwrap(); }
                    };
                }
            }
        }
    }

    /// Updates a single "inputHandler" component.
    /// This function checks whether the component has its state matching
    /// the pressed/release state of the input.
    fn update_input_handler(&mut self, state: &mut EntitiesState,
                            component: &ComponentID, pressed: bool)
    {
        // executing the script if the component has one
        match state.get_as_string(component, "script") {
            Some(script) => {
                script::execute_mut(state, component, &script.as_slice()).unwrap();
            },
            None => ()
        };

        // handling prototype
        match state.get_as_entity(component, "prototypeWhilePressed") {
            None => (),
            Some(prototype) => {
                let children = state.get_component_children(component).unwrap();

                match (children.len() != 0, pressed) {
                    (false, true) =>
                        {
                            let owner = match state.get_owner(component) { Ok(o) => o, _ => return };
                            let newCmp = state.create_component_from_entity(&owner, &prototype, ::std::collections::HashMap::new()).unwrap();
                            state.set_component_parent(&newCmp, component);
                        },

                    (true, false) =>
                        {
                            for c in children.iter() {
                                state.destroy_component(c);
                            }
                        },

                    _ => ()
                }
            }
        }
    }
}
<commit_msg>Minor style improvements in input<commit_after>use super::{ Message, Element, Pressed, Released, MouseMoved };
use entities::{ EntitiesState, EntitiesHelper, EntityID, ComponentID, NativeComponentType };
use nalgebra::na;
use nalgebra::na::Inv;
use script;

pub struct InputSystem {
    logger: Box<::log::Logger>,
    current_hover: Option<EntityID>,
    last_known_mouse_position: na::Vec2<f64>
}

impl InputSystem {
    pub fn new<L: ::log::Logger + 'static>(_: &EntitiesState, logger: L)
        -> InputSystem
    {
        InputSystem {
            logger: box logger,
            current_hover: None,
            last_known_mouse_position: na::Vec2::new(0.0, 0.0)
        }
    }

    pub fn process(&mut self, state: &mut EntitiesState, elapsed: &f64, messages: &[Message])
    {
        self.process_hover(state, elapsed, messages);
        self.process_input_handlers(state, elapsed, messages);
    }

    /// Processes all "inputHandler" components.
    fn process_input_handlers(&mut self, state: &mut EntitiesState,
                                  elapsed: &f64, messages: &[Message])
    {
        // creating an iterator to have only the "pressed" and "release" messages
        let mut filteredMessagesIter = messages
            .iter()
            .filter_map(|msg| match msg {
                &Pressed(ref e) => Some((e, true)),
                &Released(ref e) => Some((e, false)),
                _ => None
            });

        for (element, pressed) in filteredMessagesIter {
            let element = format!("{}", element);

            // getting all "inputHandler" components that match the element
            for component in state
                .get_visible_native_components("inputHandler")
                .move_iter()
                .filter(|c|
                    match state.get_as_string(c, "element") {
                        Some(s) => s == element,
                        _ => false
                    }
                )
                .collect::<Vec<ComponentID>>().move_iter()
            {
                // this component **may** need an update
                // we delegate this to a subfunction
                self.update_input_handler(state, &component, pressed)
            }
        }
    }

    /// Processes all "hoverHandler" components.
    fn process_hover(&mut self, state: &mut EntitiesState, _: &f64, messages: &[Message])
    {
        // getting the mouse position between (-1, -1) and (1, 1)
        let mouse_position = messages
            .iter().rev()
            .filter_map(|msg| match msg {
                &MouseMoved(x, y) => Some(na::Vec2::new(x, y)),
                _ => None
            })
            .next().unwrap_or(self.last_known_mouse_position);

        self.last_known_mouse_position = mouse_position;

        // getting the mouse position in camera units
        let mouse_position = {
            let mousePosVector =
                na::Vec4::new(mouse_position.x as f32, mouse_position.y as f32, 0.0, 1.0);
            let matrix =
                { let mut m = ::display::DisplaySystem::get_camera(state).unwrap(); m.inv(); m };
            let result = mousePosVector * matrix;
            na::Vec2::new(result.x / result.w, result.y / result.w)
        };

        // getting which entity is being hovered
        let hovered_entity: Option<EntityID> = state
            .get_visible_native_components("clickBox")
            .move_iter()
            .filter_map(|component| {
                let entity = match state.get_owner(&component) { Ok(t) => t, _ => return None };
                let entity_position =
                    ::physics::PhysicsSystem::get_entity_position(state, &entity);

                let coord1 = match (state.get_as_number(&component, "leftX"),
                                    state.get_as_number(&component, "bottomY"))
                {
                    (Some(x), Some(y)) =>
                        na::Vec2::new(x as f32 + entity_position.x, y as f32 + entity_position.y),
                    _ => return None
                };

                let coord2 = match (state.get_as_number(&component, "rightX"),
                                    state.get_as_number(&component, "topY"))
                {
                    (Some(x), Some(y)) =>
                        na::Vec2::new(x as f32 + entity_position.x, y as f32 + entity_position.y),
                    _ => return None
                };

                if (coord1.x < coord2.x) && coord2.x < mouse_position.x { return None }
                if (coord2.x < coord1.x) && coord1.x < mouse_position.x { return None }
                if (coord1.x > coord2.x) && coord2.x > mouse_position.x { return None }
                if (coord2.x > coord1.x) && coord1.x > mouse_position.x { return None }
                if (coord1.y < coord2.y) && coord2.y < mouse_position.y { return None }
                if (coord2.y < coord1.y) && coord1.y < mouse_position.y { return None }
                if (coord1.y > coord2.y) && coord2.y > mouse_position.y { return None }
                if (coord2.y > coord1.y) && coord1.y > mouse_position.y { return None }

                Some(entity)
            })
            .next();

        // if the hovered entity has not changed, we have finished
        if hovered_entity == self.current_hover {
            return
        }

        // we have left the current hovered entity, executing script and removing prototype
        if self.current_hover.is_some() {
            // looping through each "hoverHandler" of the current_hover entity
            for cmp in state
                .get_visible_native_components("hoverHandler").move_iter()
                .filter(|c| state.get_owner(c).ok() == self.current_hover)
                .collect::<Vec<ComponentID>>().move_iter()
            {
                // removing all its children (ie. the prototype)
                for c in state.get_component_children(&cmp).unwrap().move_iter() {
                    state.destroy_component(&c).ok();
                }

                // executing onLeave script
                match state.get_as_string(&cmp, "scriptOnLeave") {
                    None => (),
                    Some(script) => {
                        script::execute_mut(state, &cmp, &script.as_slice()).unwrap();
                    }
                };
            }
        }

        // updating self
        self.current_hover = hovered_entity;

        // processing the new entity
        match hovered_entity {
            None => (),
            Some(hovered_entity) => {
                // looping through each "hoverHandler" of the new entity
                for cmp in state
                    .get_visible_native_components("hoverHandler")
                    .move_iter()
                    .filter(|c| state.get_owner(c).ok() == Some(hovered_entity))
                    .collect::<Vec<ComponentID>>().move_iter()
                {
                    // adding prototype
                    match state.get_as_entity(&cmp, "prototype") {
                        Some(prototype) => {
                            let newCmp =
                                state.create_component_from_entity(
                                    &hovered_entity,
                                    &prototype,
                                    ::std::collections::HashMap::new()
                                ).unwrap();
                            state.set_component_parent(&newCmp, &cmp);
                        },
                        None => ()
                    };

                    // executing onLeave script
                    match state.get_as_string(&cmp, "scriptOnEnter") {
                        None => (),
                        Some(script) =>
                            { script::execute_mut(state, &cmp, &script.as_slice()).unwrap(); }
                    };
                }
            }
        }
    }

    /// Updates a single "inputHandler" component.
    /// This function checks whether the component has its state matching
    /// the pressed/release state of the input.
    fn update_input_handler(&mut self, state: &mut EntitiesState,
                            component: &ComponentID, pressed: bool)
    {
        // executing the script if the component has one
        match state.get_as_string(component, "script") {
            Some(script) => {
                script::execute_mut(state, component, &script.as_slice()).unwrap();
            },
            None => ()
        };

        // handling prototype
        match state.get_as_entity(component, "prototypeWhilePressed") {
            None => (),
            Some(prototype) => {
                let children = state.get_component_children(component).unwrap();

                match (children.len() != 0, pressed) {
                    (false, true) =>
                        {
                            let owner = match state.get_owner(component) {
                                Ok(o) => o,
                                _ => return
                            };

                            let newCmp =
                                state.create_component_from_entity(
                                    &owner,
                                    &prototype,
                                    ::std::collections::HashMap::new()
                                ).unwrap();
                            state.set_component_parent(&newCmp, component);
                        },

                    (true, false) =>
                        {
                            for c in children.iter() {
                                state.destroy_component(c);
                            }
                        },

                    _ => ()
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>#![stable(feature = "core_hint", since = "1.27.0")]

//! Hints to compiler that affects how code should be emitted or optimized.

use intrinsics;

/// Informs the compiler that this point in the code is not reachable, enabling
/// further optimizations.
///
/// # Safety
///
/// Reaching this function is completely *undefined behavior* (UB). In
/// particular, the compiler assumes that all UB must never happen, and
/// therefore will eliminate all branches that reach to a call to
/// `unreachable_unchecked()`.
///
/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
/// `unreachable_unchecked()` call is actually reachable among all possible
/// control flow, the compiler will apply the wrong optimization strategy, and
/// may sometimes even corrupt seemingly unrelated code, causing
/// difficult-to-debug problems.
///
/// Use this function only when you can prove that the code will never call it.
///
/// The [`unreachable!()`] macro is the safe counterpart of this function, which
/// will panic instead when executed.
///
/// [`unreachable!()`]: ../macro.unreachable.html
///
/// # Example
///
/// ```
/// fn div_1(a: u32, b: u32) -> u32 {
///     use std::hint::unreachable_unchecked;
///
///     // `b.saturating_add(1)` is always positive (not zero),
///     // hence `checked_div` will never return `None`.
///     // Therefore, the else branch is unreachable.
///     a.checked_div(b.saturating_add(1))
///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
/// }
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
/// assert_eq!(div_1(11, std::u32::MAX), 0);
/// ```
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
pub unsafe fn unreachable_unchecked() -> ! {
    intrinsics::unreachable()
}

/// Save power or switch hyperthreads in a busy-wait spin-loop.
///
/// This function is deliberately more primitive than
/// [`std::thread::yield_now`](../../std/thread/fn.yield_now.html) and
/// does not directly yield to the system's scheduler.
/// In some cases it might be useful to use a combination of both functions.
/// Careful benchmarking is advised.
///
/// On some platforms this function may not do anything at all.
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    unsafe {
        asm!("pause" ::: "memory" : "volatile");
    }

    #[cfg(target_arch = "aarch64")]
    unsafe {
        asm!("yield" ::: "memory" : "volatile");
    }
}
<commit_msg>Rollup merge of #59239 - gnzlbg:fix_spin_loop, r=nagisa<commit_after>#![stable(feature = "core_hint", since = "1.27.0")]

//! Hints to compiler that affects how code should be emitted or optimized.

use intrinsics;

/// Informs the compiler that this point in the code is not reachable, enabling
/// further optimizations.
///
/// # Safety
///
/// Reaching this function is completely *undefined behavior* (UB). In
/// particular, the compiler assumes that all UB must never happen, and
/// therefore will eliminate all branches that reach to a call to
/// `unreachable_unchecked()`.
///
/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
/// `unreachable_unchecked()` call is actually reachable among all possible
/// control flow, the compiler will apply the wrong optimization strategy, and
/// may sometimes even corrupt seemingly unrelated code, causing
/// difficult-to-debug problems.
///
/// Use this function only when you can prove that the code will never call it.
///
/// The [`unreachable!()`] macro is the safe counterpart of this function, which
/// will panic instead when executed.
///
/// [`unreachable!()`]: ../macro.unreachable.html
///
/// # Example
///
/// ```
/// fn div_1(a: u32, b: u32) -> u32 {
///     use std::hint::unreachable_unchecked;
///
///     // `b.saturating_add(1)` is always positive (not zero),
///     // hence `checked_div` will never return `None`.
///     // Therefore, the else branch is unreachable.
///     a.checked_div(b.saturating_add(1))
///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
/// }
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
/// assert_eq!(div_1(11, std::u32::MAX), 0);
/// ```
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
pub unsafe fn unreachable_unchecked() -> ! {
    intrinsics::unreachable()
}

/// Save power or switch hyperthreads in a busy-wait spin-loop.
///
/// This function is deliberately more primitive than
/// [`std::thread::yield_now`](../../std/thread/fn.yield_now.html) and
/// does not directly yield to the system's scheduler.
/// In some cases it might be useful to use a combination of both functions.
/// Careful benchmarking is advised.
///
/// On some platforms this function may not do anything at all.
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
    #[cfg(
        all(
            any(target_arch = "x86", target_arch = "x86_64"),
            target_feature = "sse2"
        )
    )] {
        #[cfg(target_arch = "x86")] {
            unsafe { crate::arch::x86::_mm_pause() };
        }

        #[cfg(target_arch = "x86_64")] {
            unsafe { crate::arch::x86_64::_mm_pause() };
        }
    }

    #[cfg(
        any(
            target_arch = "aarch64",
            all(target_arch = "arm", target_feature = "v6")
        )
    )] {
        #[cfg(target_arch = "aarch64")] {
            unsafe { crate::arch::aarch64::__yield() };
        }
        #[cfg(target_arch = "arm")] {
            unsafe { crate::arch::arm::__yield() };
        }
    }
}
<|endoftext|>


<commit_before>
extern crate ndarray;

use ndarray::{
    Array,
    ArrayBase,
    DataMut,
    Dimension,
    ArrayView,
};

use std::cmp;

#[derive(Copy, Clone, Debug)]
pub enum ZipError {
    NotSameLayout,
    NotSameShape,
}

/// Defines a function similar to zip_mut_with, that takes multiple read-only
/// arguments. All arrays must be of default layout and same shape.
macro_rules! define_zip {
    ($name:ident, $($arg:ident),+) => {
#[allow(non_snake_case)]
fn $name<A, $($arg,)+ Data, Dim, Func>(a: &mut ArrayBase<Data, Dim>,
    $($arg: ArrayView<$arg, Dim>,)+ mut f: Func)
    -> Result<(), ZipError>
    where Data: DataMut<Elem=A>,
          Dim: Dimension,
          Func: FnMut(&mut A, $(&$arg),+)
{
    if $(a.shape() != $arg.shape() ||)+ false {
        return Err(ZipError::NotSameShape);
    }
    if let Some(a_s) = a.as_slice_mut() {
        let len = a_s.len();
        $(
            // extract the slice
            let $arg = if let Some(s) = $arg.as_slice() {
                s
            } else {
                return Err(ZipError::NotSameLayout);
            };
            let len = cmp::min(len, $arg.len());
        )+
        let a_s = &mut a_s[..len];
        $(
            let $arg = &$arg[..len];
        )+
        for i in 0..len {
            f(&mut a_s[i], $(&$arg[i]),+)
        }
        return Ok(());
    }
    // otherwise
    Err(ZipError::NotSameLayout)
}
    }
}

//define_zip!(zip_2, B);
define_zip!(zip_3, B, C);
//define_zip!(zip_4, B, C, D);
//define_zip!(zip_5, B, C, D, E);

fn main() {
    let n = 16;
    let mut a = Array::<f32, _>::zeros((n, n));
    let mut b = Array::<f32, _>::from_elem((n, n), 1.);
    for ((i, j), elt) in b.indexed_iter_mut() {
        *elt /= 1. + (i + j) as f32;
    }
    let c = Array::<f32, _>::from_elem((n, n), 1.7);

    for _ in 0..1000 {
        zip_3(&mut a, b.view(), c.view(), |x, &y, &z| *x += y * z).unwrap();
    }
    println!("{:4.2?}", a);
}
<commit_msg>zip_many: Extend the zip macro to handle read-only / read-write array views<commit_after>
extern crate ndarray;

use ndarray::{
    Array,
    ArrayBase,
    Data,
    DataMut,
    Dimension,
    ArrayView,
    ArrayViewMut,
    Ix,
};

use std::cmp;

#[derive(Copy, Clone, Debug)]
pub enum ZipError {
    NotSameLayout,
    NotSameShape,
}

pub trait Slice {
    type Ref ;
    fn len(&self) -> usize;
    unsafe fn get_unchecked(&mut self, i: usize) -> Self::Ref ;
}

impl<'a, T> Slice for &'a [T]
{
    type Ref  = &'a T;
    fn len(&self) -> usize { (**self).len() }
    unsafe fn get_unchecked(&mut self, i: usize) -> Self::Ref  {
        (*self).get_unchecked(i)
    }
}

impl<'a, T> Slice for &'a mut [T]
{
    type Ref  = &'a mut T;
    fn len(&self) -> usize { (**self).len() }
    unsafe fn get_unchecked(&mut self, i: usize) -> Self::Ref  {
        (*(*self as *mut [T])).get_unchecked_mut(i)
    }
}

pub trait LockStep {
    type Item;
    type Ref;
    type Slice: Slice<Ref=Self::Ref>;
    type Dim;
    fn shape(&self) -> &[Ix];
    fn borrow_slice(self) -> Option<Self::Slice>;
}

impl<'b, A: 'b, S,  D> LockStep for &'b ArrayBase<S, D>
    where D: Dimension,
          S: Data<Elem=A>,
{
    type Item = A;
    type Ref = &'b A;
    type Slice = &'b [A];
    type Dim = D;
    fn shape(&self) -> &[Ix] { (*self).shape() }
    fn borrow_slice(self) -> Option<Self::Slice> {
        self.as_slice()
    }
}

impl<'b, A: 'b, S,  D> LockStep for &'b mut ArrayBase<S, D>
    where D: Dimension,
          S: DataMut<Elem=A>,
{
    type Item = A;
    type Ref = &'b mut A;
    type Slice = &'b mut [A];
    type Dim = D;
    fn shape(&self) -> &[Ix] { (**self).shape() }
    fn borrow_slice(self) -> Option<Self::Slice> {
        self.as_slice_mut()
    }
}

impl<'a, A, D> LockStep for ArrayView<'a, A, D>
    where D: Dimension,
{
    type Item = A;
    type Ref = &'a A;
    type Slice = &'a [A];
    type Dim = D;
    fn shape(&self) -> &[Ix] { self.shape() }
    fn borrow_slice(self) -> Option<Self::Slice> {
        self.into_slice()
    }
}

impl<'a, A, D> LockStep for ArrayViewMut<'a, A, D>
    where D: Dimension,
{
    type Item = A;
    type Ref = &'a mut A;
    type Slice = &'a mut [A];
    type Dim = D;
    fn shape(&self) -> &[Ix] { self.shape() }
    fn borrow_slice(self) -> Option<Self::Slice> {
        self.into_slice()
    }
}

/// Defines a function similar to zip_mut_with, that takes multiple read-only
/// arguments. All arrays must be of default layout and same shape.
macro_rules! define_zip {
    ($name:ident, $($arg:ident),+) => {
#[allow(non_snake_case)]
fn $name<A, $($arg),+, Dim, Func>(a: A, $($arg : $arg,)+ mut f: Func)
    -> Result<(), ZipError>
    where Dim: Dimension,
          A: LockStep<Dim=Dim>,
          $(
              $arg : LockStep<Dim=Dim>,
          )+
          Func: FnMut(A::Ref, $($arg ::Ref),+)
{
    if $(a.shape() != $arg.shape() ||)+ false {
        return Err(ZipError::NotSameShape);
    }
    if let Some(mut a_s) = a.borrow_slice() {
        let len = a_s.len();
        $(
            // extract the slice
            let mut $arg = if let Some(s) = $arg.borrow_slice() {
                s
            } else {
                return Err(ZipError::NotSameLayout);
            };
            let len = cmp::min(len, $arg.len());
        )+
        for i in 0..len {
            unsafe {
                f(a_s.get_unchecked(i), $($arg.get_unchecked(i)),+)
            }
        }
        return Ok(());
    }
    // otherwise
    Err(ZipError::NotSameLayout)
}
    }
}

//define_zip!(zip_2, B);
define_zip!(zip_3, B, C);
//define_zip!(zip_4, B, C, D);
//define_zip!(zip_5, B, C, D, E);

fn main() {
    let n = 16;
    let mut a = Array::<f32, _>::zeros((n, n));
    let mut b = Array::<f32, _>::from_elem((n, n), 1.);
    for ((i, j), elt) in b.indexed_iter_mut() {
        *elt /= 1. + (i + j) as f32;
    }
    let c = Array::<f32, _>::from_elem((n, n), 1.7);

    for _ in 0..1000 {
        zip_3(&mut a, &b, &c, |x, &y, &z| *x += y * z).unwrap();
    }
    println!("{:4.2?}", a);
}
<|endoftext|>


<commit_before><commit_msg>improve `filesearch::get_or_default_sysroot` r=ozkanonur<commit_after><|endoftext|>


<commit_before>use piston::window::WindowSettings;
use piston_window;
use piston_window::{PistonWindow, UpdateArgs, Event, OpenGL, TextureSettings, Flip, Input};
use gfx_device_gl::Resources;
use glutin;
use input::Button;
use input::Axis;
use game_object::GameObject;
use game_object;
use texture::Texture;
use texture;
use transform::Transform;
use transform;
use camera::Camera;
use physics::nphysics2d::world::World;
use serde_hjson;
use rodio;
use rodio::Decoder;
use rodio::source::Buffered;
use rodio::Source;
use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
use std::collections::LinkedList;
use std::path::PathBuf;
use std::f32;
use std::mem;

pub struct App {
    window: PistonWindow,
    // When searching for a GameObject you will need to search both of
    // these vectors. At any given time either one of them could contain the GameObject you are
    // searching for. As GameObjects are updated they are migrated from
    // game_objects to updated_game_objects and once the update is complete
    // the two vectors are swapped.
    game_objects: LinkedList<GameObject>,
    updated_game_objects: LinkedList<GameObject>,
    buttons_pressed: Vec<Button>,
    previous_buttons_pressed: Vec<Button>, // buttons_pressed from last frame.
    axes: HashMap<i32, Axis>,
    actions: HashMap<i32, Button>,
    sound_cache: HashMap<String, Box<Buffered<Decoder<BufReader<File>>>>>,
    pub camera: Camera,
    pub world: World<f32>,
}

impl App {
    pub fn new(name: &str) -> App {
        let opengl = OpenGL::V3_2;
        let (width, height) = glutin::get_primary_monitor().get_dimensions();
        App {
            game_objects: LinkedList::new(),
            updated_game_objects: LinkedList::new(),
            buttons_pressed: vec![],
            previous_buttons_pressed: vec![],
            axes: HashMap::new(),
            actions: HashMap::new(),
            sound_cache: HashMap::new(),
            window: WindowSettings::new(name, [width, height])
                .opengl(opengl)
                .exit_on_esc(true)
                .fullscreen(true)
                .build()
                .unwrap(),
            camera: Camera { transform: Transform::new() },
            world: World::new(),
        }
    }

    fn render(&mut self, e: &Event) {
        // This should never be false.
        // The only reason I didn't request the render_args in the signature is the Piston API
        // requires the event object.
        if let Event::Render(render_args) = *e {
            use graphics::*;
            const GREY: [f32; 4] = [0.9, 0.9, 0.9, 1.0];
            let game_objs = &self.game_objects;
            let camera_transform = self.camera.transform;
            self.window.draw_2d(e, |c, gl| {
                // Clear the screen.
                clear(GREY, gl);
                for game_obj in game_objs {
                    let mut render_transform = game_obj.transform;
                    *render_transform.mut_x() -= *camera_transform.x() -
                                                 (render_args.draw_width / 2) as f32;
                    *render_transform.mut_y() -= *camera_transform.y() -
                                                 (render_args.draw_height / 2) as f32;
                    *render_transform.mut_rotation() -= *camera_transform.rotation();
                    let (tex_width, tex_height) = texture::get_raw(&game_obj.texture).get_size();
                    image(texture::get_raw(&game_obj.texture),
                          c.transform
                              .append_transform(transform::get_raw(&render_transform))
                              .trans(-(tex_width as f64) / 2.0, -(tex_height as f64) / 2.0),
                          gl);
                }
            });
        } else {
            panic!("Render should never be called with an event that isn't Event::Render.");
        }
    }

    fn update(&mut self, args: &UpdateArgs) {
        for mut game_object in &mut self.game_objects {
            game_object::copy_to_physics(&mut game_object);
        }
        self.world.step(args.dt as f32);
        for mut game_object in &mut self.game_objects {
            game_object::copy_from_physics(&mut game_object);
        }
        let mut pop_result = self.game_objects.pop_front();
        while let Some(mut game_object) = pop_result {
            game_object.update(self, args.dt as f32);
            *game_object.transform.mut_rotation() %= 2.0 * f32::consts::PI;
            self.updated_game_objects.push_back(game_object);
            pop_result = self.game_objects.pop_front();
        }
        assert_eq!(self.game_objects.len(), 0);
        mem::swap(&mut self.game_objects, &mut self.updated_game_objects);
        self.previous_buttons_pressed = self.buttons_pressed.clone();
    }

    pub fn run(&mut self) {
        while let Some(e) = self.window.next() {
            match e {
                Event::Render(..) => {
                    self.render(&e);
                }
                Event::AfterRender(..) => {}
                Event::Update(update_args) => self.update(&update_args),
                Event::Idle(..) => {}
                Event::Input(input_event) => {
                    match input_event {
                        Input::Press(button) => {
                            // The button may already be here as this event does repeat.
                            if !self.buttons_pressed.iter().any(|&item| item == button) {
                                self.buttons_pressed.push(button);
                            }
                        }
                        Input::Release(button) => {
                            while let Some(i) = self.buttons_pressed
                                .iter()
                                .position(|&item| item == button) {
                                self.buttons_pressed.swap_remove(i);
                            }
                        }
                        _ => {}
                    }
                }
            }
        }
    }

    pub fn play_sound(&mut self, path: &str) {
        let source = self.fetch_sound(path);
        let endpoint = rodio::get_default_endpoint().unwrap();
        let sink = rodio::Sink::new(&endpoint);
        sink.append(source.buffered());
    }

    pub fn loop_sound_forever(&mut self, path: &str) {
        let source = self.fetch_sound(path).repeat_infinite();
        let endpoint = rodio::get_default_endpoint().unwrap();
        let sink = rodio::Sink::new(&endpoint);
        sink.append(source.buffered());
    }

    // Fetches sound from cache if present, otherwise loads it from the filesystem.
    fn fetch_sound(&mut self, path: &str) -> Box<Buffered<Decoder<BufReader<File>>>> {
        let source;
        if self.sound_cache.contains_key(path) {
            let cached = self.sound_cache.get(path).unwrap();
            source = cached.clone();
        } else {
            let mut sound_path = PathBuf::from("assets");
            sound_path.push("sounds");
            sound_path.push(path);
            let file = File::open(sound_path).unwrap();
            let new_source =
                Box::new(rodio::Decoder::new(BufReader::new(file)).unwrap().buffered());
            source = new_source.clone();
            self.sound_cache.insert(path.to_owned(), new_source);
        }
        return source;
    }

    pub fn load_sound(&mut self, path: &str) {
        if !self.sound_cache.contains_key(path) {
            let mut sound_path = PathBuf::from("assets");
            sound_path.push("sounds");
            sound_path.push(path);
            let file = File::open(sound_path).unwrap();
            let new_source =
                Box::new(rodio::Decoder::new(BufReader::new(file)).unwrap().buffered());
            self.sound_cache.insert(path.to_owned(), new_source);
        }
    }

    pub fn unload_sound(&mut self, path: &str) {
        self.sound_cache.remove(path);
    }

    pub fn save_bindings(&mut self, path: &str) -> Result<(), String> {
        for axis in &self.axes {
            match serde_hjson::ser::to_string(&axis) {
                Ok(result) => {
                    println!("{}", result);
                }
                Err(err) => {
                    return Err(format!("{:?}", err));
                }
            }
        }
        Ok(())
    }

    pub fn add_axis(&mut self, axis: Axis, id: i32) {
        if self.axes.contains_key(&id) {
            panic!("Axis id values must be unique!");
        }
        self.axes.insert(id, axis);
    }

    pub fn get_axis_value(&self, id: i32) -> Option<f32> {
        if let Some(axis) = self.axes.get(&id) {
            return Some(axis.get_value(self));
        }
        None
    }

    pub fn add_action(&mut self, button: Button, id: i32) {
        if self.actions.contains_key(&id) {
            panic!("Action id values must be unique!");
        }
        self.actions.insert(id, button);
    }

    // Named for consistency with get_axis_value
    pub fn action_pressed(&self, id: i32) -> Option<bool> {
        if let Some(button) = self.actions.get(&id) {
            return Some(self.is_button_pressed(*button));
        }
        None
    }

    pub fn action_down(&self, id: i32) -> Option<bool> {
        if let Some(button) = self.actions.get(&id) {
            return Some(self.is_button_down(*button));
        }
        None
    }

    pub fn action_released(&self, id: i32) -> Option<bool> {
        if let Some(button) = self.actions.get(&id) {
            return Some(self.is_button_released(*button));
        }
        None
    }

    pub fn is_button_pressed(&self, button: Button) -> bool {
        (&self.buttons_pressed).into_iter().any(|&b| b == button) &&
        !(&self.previous_buttons_pressed).into_iter().any(|&b| b == button)
    }

    pub fn is_button_down(&self, button: Button) -> bool {
        (&self.buttons_pressed).into_iter().any(|&b| b == button)
    }

    pub fn is_button_released(&self, button: Button) -> bool {
        !(&self.buttons_pressed).into_iter().any(|&b| b == button) &&
        (&self.previous_buttons_pressed).into_iter().any(|&b| b == button)
    }

    pub fn add_gameobject(&mut self, game_object: GameObject) {
        self.game_objects.push_front(game_object);
    }

    pub fn empty_raw_texture(&mut self) -> piston_window::Texture<Resources> {
        piston_window::Texture::empty(&mut self.window.factory)
            .expect("Getting empty texture failed. 0_o")
    }

    pub fn fetch_texture(&mut self, texture_name: &str) -> Texture {
        let mut texture_path = PathBuf::from("assets");
        texture_path.push("textures");
        texture_path.push(texture_name);
        let result = piston_window::Texture::from_path(&mut self.window.factory,
                                                       texture_path,
                                                       Flip::None,
                                                       &TextureSettings::new());
        let mut return_value = Texture::empty(self);
        match result {
            Ok(texture) => {
                texture::set_raw_texture(&mut return_value, texture);
            }
            Err(err) => {
                println!("Unable to load texture, {} Error: {:?}", texture_name, err);
            }
        }
        return_value
    }
}
<commit_msg>Further updates to audio API<commit_after>use piston::window::WindowSettings;
use piston_window;
use piston_window::{PistonWindow, UpdateArgs, Event, OpenGL, TextureSettings, Flip, Input};
use gfx_device_gl::Resources;
use glutin;
use input::Button;
use input::Axis;
use game_object::GameObject;
use game_object;
use texture::Texture;
use texture;
use transform::Transform;
use transform;
use camera::Camera;
use physics::nphysics2d::world::World;
use serde_hjson;
use rodio;
use rodio::Decoder;
use rodio::source::Buffered;
use rodio::Source;
use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
use std::collections::LinkedList;
use std::path::PathBuf;
use std::f32;
use std::mem;

pub struct App {
    window: PistonWindow,
    // When searching for a GameObject you will need to search both of
    // these vectors. At any given time either one of them could contain the GameObject you are
    // searching for. As GameObjects are updated they are migrated from
    // game_objects to updated_game_objects and once the update is complete
    // the two vectors are swapped.
    game_objects: LinkedList<GameObject>,
    updated_game_objects: LinkedList<GameObject>,
    buttons_pressed: Vec<Button>,
    previous_buttons_pressed: Vec<Button>, // buttons_pressed from last frame.
    axes: HashMap<i32, Axis>,
    actions: HashMap<i32, Button>,
    sound_cache: HashMap<String, Box<Buffered<Decoder<BufReader<File>>>>>,
    pub camera: Camera,
    pub world: World<f32>,
}

impl App {
    pub fn new(name: &str) -> App {
        let opengl = OpenGL::V3_2;
        let (width, height) = glutin::get_primary_monitor().get_dimensions();
        App {
            game_objects: LinkedList::new(),
            updated_game_objects: LinkedList::new(),
            buttons_pressed: vec![],
            previous_buttons_pressed: vec![],
            axes: HashMap::new(),
            actions: HashMap::new(),
            sound_cache: HashMap::new(),
            window: WindowSettings::new(name, [width, height])
                .opengl(opengl)
                .exit_on_esc(true)
                .fullscreen(true)
                .build()
                .unwrap(),
            camera: Camera { transform: Transform::new() },
            world: World::new(),
        }
    }

    fn render(&mut self, e: &Event) {
        // This should never be false.
        // The only reason I didn't request the render_args in the signature is the Piston API
        // requires the event object.
        if let Event::Render(render_args) = *e {
            use graphics::*;
            const GREY: [f32; 4] = [0.9, 0.9, 0.9, 1.0];
            let game_objs = &self.game_objects;
            let camera_transform = self.camera.transform;
            self.window.draw_2d(e, |c, gl| {
                // Clear the screen.
                clear(GREY, gl);
                for game_obj in game_objs {
                    let mut render_transform = game_obj.transform;
                    *render_transform.mut_x() -= *camera_transform.x() -
                                                 (render_args.draw_width / 2) as f32;
                    *render_transform.mut_y() -= *camera_transform.y() -
                                                 (render_args.draw_height / 2) as f32;
                    *render_transform.mut_rotation() -= *camera_transform.rotation();
                    let (tex_width, tex_height) = texture::get_raw(&game_obj.texture).get_size();
                    image(texture::get_raw(&game_obj.texture),
                          c.transform
                              .append_transform(transform::get_raw(&render_transform))
                              .trans(-(tex_width as f64) / 2.0, -(tex_height as f64) / 2.0),
                          gl);
                }
            });
        } else {
            panic!("Render should never be called with an event that isn't Event::Render.");
        }
    }

    fn update(&mut self, args: &UpdateArgs) {
        for mut game_object in &mut self.game_objects {
            game_object::copy_to_physics(&mut game_object);
        }
        self.world.step(args.dt as f32);
        for mut game_object in &mut self.game_objects {
            game_object::copy_from_physics(&mut game_object);
        }
        let mut pop_result = self.game_objects.pop_front();
        while let Some(mut game_object) = pop_result {
            game_object.update(self, args.dt as f32);
            *game_object.transform.mut_rotation() %= 2.0 * f32::consts::PI;
            self.updated_game_objects.push_back(game_object);
            pop_result = self.game_objects.pop_front();
        }
        assert_eq!(self.game_objects.len(), 0);
        mem::swap(&mut self.game_objects, &mut self.updated_game_objects);
        self.previous_buttons_pressed = self.buttons_pressed.clone();
    }

    pub fn run(&mut self) {
        while let Some(e) = self.window.next() {
            match e {
                Event::Render(..) => {
                    self.render(&e);
                }
                Event::AfterRender(..) => {}
                Event::Update(update_args) => self.update(&update_args),
                Event::Idle(..) => {}
                Event::Input(input_event) => {
                    match input_event {
                        Input::Press(button) => {
                            // The button may already be here as this event does repeat.
                            if !self.buttons_pressed.iter().any(|&item| item == button) {
                                self.buttons_pressed.push(button);
                            }
                        }
                        Input::Release(button) => {
                            while let Some(i) = self.buttons_pressed
                                .iter()
                                .position(|&item| item == button) {
                                self.buttons_pressed.swap_remove(i);
                            }
                        }
                        _ => {}
                    }
                }
            }
        }
    }

    pub fn play_sound(&mut self, path: &str) {
        let source = self.fetch_sound(path);
        let endpoint = rodio::get_default_endpoint().unwrap();
        let sink = rodio::Sink::new(&endpoint);
        sink.append(source);
    }

    pub fn loop_sound_forever(&mut self, path: &str) {
        let source = self.fetch_sound(path).repeat_infinite();
        let endpoint = rodio::get_default_endpoint().unwrap();
        let sink = rodio::Sink::new(&endpoint);
        sink.append(source);
    }

    // Fetches sound from cache if present, otherwise loads it from the filesystem.
    fn fetch_sound(&mut self, path: &str) -> Buffered<Decoder<BufReader<File>>> {
        self.load_sound(path);
        (**self.sound_cache.get(path).unwrap()).clone()
    }

    // Load a sound into the cache if it's not already there.
    pub fn load_sound(&mut self, path: &str) {
        if !self.sound_cache.contains_key(path) {
            let mut sound_path = PathBuf::from("assets");
            sound_path.push("sounds");
            sound_path.push(path);
            let file = File::open(sound_path).unwrap();
            let new_source =
                Box::new(rodio::Decoder::new(BufReader::new(file)).unwrap().buffered());
            self.sound_cache.insert(path.to_owned(), new_source);
        }
    }

    pub fn unload_sound(&mut self, path: &str) {
        self.sound_cache.remove(path);
    }

    pub fn save_bindings(&mut self, path: &str) -> Result<(), String> {
        for axis in &self.axes {
            match serde_hjson::ser::to_string(&axis) {
                Ok(result) => {
                    println!("{}", result);
                }
                Err(err) => {
                    return Err(format!("{:?}", err));
                }
            }
        }
        Ok(())
    }

    pub fn add_axis(&mut self, axis: Axis, id: i32) {
        if self.axes.contains_key(&id) {
            panic!("Axis id values must be unique!");
        }
        self.axes.insert(id, axis);
    }

    pub fn get_axis_value(&self, id: i32) -> Option<f32> {
        if let Some(axis) = self.axes.get(&id) {
            return Some(axis.get_value(self));
        }
        None
    }

    pub fn add_action(&mut self, button: Button, id: i32) {
        if self.actions.contains_key(&id) {
            panic!("Action id values must be unique!");
        }
        self.actions.insert(id, button);
    }

    // Named for consistency with get_axis_value
    pub fn action_pressed(&self, id: i32) -> Option<bool> {
        if let Some(button) = self.actions.get(&id) {
            return Some(self.is_button_pressed(*button));
        }
        None
    }

    pub fn action_down(&self, id: i32) -> Option<bool> {
        if let Some(button) = self.actions.get(&id) {
            return Some(self.is_button_down(*button));
        }
        None
    }

    pub fn action_released(&self, id: i32) -> Option<bool> {
        if let Some(button) = self.actions.get(&id) {
            return Some(self.is_button_released(*button));
        }
        None
    }

    pub fn is_button_pressed(&self, button: Button) -> bool {
        (&self.buttons_pressed).into_iter().any(|&b| b == button) &&
        !(&self.previous_buttons_pressed).into_iter().any(|&b| b == button)
    }

    pub fn is_button_down(&self, button: Button) -> bool {
        (&self.buttons_pressed).into_iter().any(|&b| b == button)
    }

    pub fn is_button_released(&self, button: Button) -> bool {
        !(&self.buttons_pressed).into_iter().any(|&b| b == button) &&
        (&self.previous_buttons_pressed).into_iter().any(|&b| b == button)
    }

    pub fn add_gameobject(&mut self, game_object: GameObject) {
        self.game_objects.push_front(game_object);
    }

    pub fn empty_raw_texture(&mut self) -> piston_window::Texture<Resources> {
        piston_window::Texture::empty(&mut self.window.factory)
            .expect("Getting empty texture failed. 0_o")
    }

    pub fn fetch_texture(&mut self, texture_name: &str) -> Texture {
        let mut texture_path = PathBuf::from("assets");
        texture_path.push("textures");
        texture_path.push(texture_name);
        let result = piston_window::Texture::from_path(&mut self.window.factory,
                                                       texture_path,
                                                       Flip::None,
                                                       &TextureSettings::new());
        let mut return_value = Texture::empty(self);
        match result {
            Ok(texture) => {
                texture::set_raw_texture(&mut return_value, texture);
            }
            Err(err) => {
                println!("Unable to load texture, {} Error: {:?}", texture_name, err);
            }
        }
        return_value
    }
}
<|endoftext|>


<commit_before>import cast = unsafe::reinterpret_cast;
import comm;
import option::{some, none};
import option = option::t;
import ptr;

export task;
export joinable_task;
export sleep;
export yield;
export task_notification;
export join;
export unsupervise;
export pin;
export unpin;
export set_min_stack;
export task_result;
export tr_success;
export tr_failure;
export get_task_id;
export spawn;
export spawn_notify;
export spawn_joinable;

native "rust" mod rustrt {                           // C Stack?
    fn task_sleep(time_in_us: uint);                 // No
    fn task_yield();                                 // No
    fn start_task(id: task_id, closure: *u8);        // No
    fn task_join(t: task_id) -> int;                 // Refactor
}

native "c-stack-cdecl" mod rustrt2 = "rustrt" {
    fn pin_task();                                   // Yes
    fn unpin_task();                                 // Yes
    fn get_task_id() -> task_id;                     // Yes

    fn set_min_stack(stack_size: uint);              // Yes

    fn new_task() -> task_id;
    fn drop_task(task: *rust_task);
    fn get_task_pointer(id: task_id) -> *rust_task;

    fn migrate_alloc(alloc: *u8, target: task_id);   // Yes
}

type rust_task =
    {id: task,
     mutable notify_enabled: u32,
     mutable notify_chan: comm::chan<task_notification>,
     mutable stack_ptr: *u8};

resource rust_task_ptr(task: *rust_task) { rustrt2::drop_task(task); }

type task = int;
type task_id = task;
type joinable_task = (task_id, comm::port<task_notification>);

fn get_task_id() -> task_id { rustrt2::get_task_id() }

/**
 * Hints the scheduler to yield this task for a specified ammount of time.
 *
 * arg: time_in_us maximum number of microseconds to yield control for
 */
fn sleep(time_in_us: uint) { ret rustrt::task_sleep(time_in_us); }

fn yield() { ret rustrt::task_yield(); }

tag task_result { tr_success; tr_failure; }

tag task_notification { exit(task, task_result); }

fn join(task_port: (task_id, comm::port<task_notification>)) -> task_result {
    let (id, port) = task_port;
    alt comm::recv::<task_notification>(port) {
      exit(_id, res) {
        if _id == id {
            ret res
        } else { fail #fmt["join received id %d, expected %d", _id, id] }
      }
    }
}

fn join_id(t: task_id) -> task_result {
    alt rustrt::task_join(t) { 0 { tr_success } _ { tr_failure } }
}

fn unsupervise() { ret sys::unsupervise(); }

fn pin() { rustrt2::pin_task(); }

fn unpin() { rustrt2::unpin_task(); }

fn set_min_stack(stack_size: uint) { rustrt2::set_min_stack(stack_size); }

fn spawn<~T>(-data: T, f: fn(T)) -> task {
    spawn_inner2(data, f, none)
}

fn spawn_notify<~T>(-data: T, f: fn(T),
                         notify: comm::chan<task_notification>) -> task {
    spawn_inner2(data, f, some(notify))
}

fn spawn_joinable<~T>(-data: T, f: fn(T)) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify(data, f, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: To transition from the unsafe spawn that spawns a shared closure to
// the safe spawn that spawns a bare function we're going to write
// barefunc-spawn on top of unsafe-spawn.  Sadly, bind does not work reliably
// enough to suite our needs (#1034, probably others yet to be discovered), so
// we're going to copy the bootstrap data into a unique pointer, cast it to an
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
// shared closure to spawn.
//
// After the transition this should all be rewritten.

fn spawn_inner2<~T>(-data: T, f: fn(T),
                    notify: option<comm::chan<task_notification>>)
    -> task_id {

    fn wrapper<~T>(-data: *u8, f: fn(T)) {
        let data: ~T = unsafe::reinterpret_cast(data);
        f(*data);
    }

    let data = ~data;
    let dataptr: *u8 = unsafe::reinterpret_cast(data);
    unsafe::leak(data);
    let wrapped = bind wrapper(dataptr, f);
    ret unsafe_spawn_inner(wrapped, notify);
}

// FIXME: This is the old spawn function that spawns a shared closure.
// It is a hack and needs to be rewritten.
fn unsafe_spawn_inner(-thunk: fn@(),
                      notify: option<comm::chan<task_notification>>) ->
   task_id unsafe {
    let id = rustrt2::new_task();

    let raw_thunk: {code: u32, env: u32} = cast(thunk);

    // set up the task pointer
    let task_ptr <- rust_task_ptr(rustrt2::get_task_pointer(id));

    assert (ptr::null() != (**task_ptr).stack_ptr);

    // copy the thunk from our stack to the new stack
    let sp: uint = cast((**task_ptr).stack_ptr);
    let ptrsize = sys::size_of::<*u8>();
    let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
    let thunkenv: *mutable uint = cast(sp - ptrsize);
    *thunkfn = cast(raw_thunk.code);;
    *thunkenv = cast(raw_thunk.env);;
    // align the stack to 16 bytes
    (**task_ptr).stack_ptr = cast(sp - ptrsize * 4u);

    // set up notifications if they are enabled.
    alt notify {
      some(c) {
        (**task_ptr).notify_enabled = 1u32;;
        (**task_ptr).notify_chan = c;
      }
      none { }
    }

    // give the thunk environment's allocation to the new task
    rustrt2::migrate_alloc(cast(raw_thunk.env), id);
    rustrt::start_task(id, cast(thunkfn));
    // don't cleanup the thunk in this task
    unsafe::leak(thunk);
    ret id;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>move remaining task natives to cdecl ABI (run on rust stack)<commit_after>import cast = unsafe::reinterpret_cast;
import comm;
import option::{some, none};
import option = option::t;
import ptr;

export task;
export joinable_task;
export sleep;
export yield;
export task_notification;
export join;
export unsupervise;
export pin;
export unpin;
export set_min_stack;
export task_result;
export tr_success;
export tr_failure;
export get_task_id;
export spawn;
export spawn_notify;
export spawn_joinable;

native "cdecl" mod rustrt {
    // these must run on the Rust stack so that they can swap stacks etc:
    fn task_sleep(time_in_us: uint);
    fn task_yield();
    fn start_task(id: task_id, closure: *u8);
    fn task_join(t: task_id) -> int;
}

native "c-stack-cdecl" mod rustrt2 = "rustrt" {
    // these can run on the C stack:
    fn pin_task();
    fn unpin_task();
    fn get_task_id() -> task_id;

    fn set_min_stack(stack_size: uint);

    fn new_task() -> task_id;
    fn drop_task(task: *rust_task);
    fn get_task_pointer(id: task_id) -> *rust_task;

    fn migrate_alloc(alloc: *u8, target: task_id);
}

type rust_task =
    {id: task,
     mutable notify_enabled: u32,
     mutable notify_chan: comm::chan<task_notification>,
     mutable stack_ptr: *u8};

resource rust_task_ptr(task: *rust_task) { rustrt2::drop_task(task); }

type task = int;
type task_id = task;
type joinable_task = (task_id, comm::port<task_notification>);

fn get_task_id() -> task_id { rustrt2::get_task_id() }

/**
 * Hints the scheduler to yield this task for a specified ammount of time.
 *
 * arg: time_in_us maximum number of microseconds to yield control for
 */
fn sleep(time_in_us: uint) { ret rustrt::task_sleep(time_in_us); }

fn yield() { ret rustrt::task_yield(); }

tag task_result { tr_success; tr_failure; }

tag task_notification { exit(task, task_result); }

fn join(task_port: (task_id, comm::port<task_notification>)) -> task_result {
    let (id, port) = task_port;
    alt comm::recv::<task_notification>(port) {
      exit(_id, res) {
        if _id == id {
            ret res
        } else { fail #fmt["join received id %d, expected %d", _id, id] }
      }
    }
}

fn join_id(t: task_id) -> task_result {
    alt rustrt::task_join(t) { 0 { tr_success } _ { tr_failure } }
}

fn unsupervise() { ret sys::unsupervise(); }

fn pin() { rustrt2::pin_task(); }

fn unpin() { rustrt2::unpin_task(); }

fn set_min_stack(stack_size: uint) { rustrt2::set_min_stack(stack_size); }

fn spawn<~T>(-data: T, f: fn(T)) -> task {
    spawn_inner2(data, f, none)
}

fn spawn_notify<~T>(-data: T, f: fn(T),
                         notify: comm::chan<task_notification>) -> task {
    spawn_inner2(data, f, some(notify))
}

fn spawn_joinable<~T>(-data: T, f: fn(T)) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify(data, f, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: To transition from the unsafe spawn that spawns a shared closure to
// the safe spawn that spawns a bare function we're going to write
// barefunc-spawn on top of unsafe-spawn.  Sadly, bind does not work reliably
// enough to suite our needs (#1034, probably others yet to be discovered), so
// we're going to copy the bootstrap data into a unique pointer, cast it to an
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
// shared closure to spawn.
//
// After the transition this should all be rewritten.

fn spawn_inner2<~T>(-data: T, f: fn(T),
                    notify: option<comm::chan<task_notification>>)
    -> task_id {

    fn wrapper<~T>(-data: *u8, f: fn(T)) {
        let data: ~T = unsafe::reinterpret_cast(data);
        f(*data);
    }

    let data = ~data;
    let dataptr: *u8 = unsafe::reinterpret_cast(data);
    unsafe::leak(data);
    let wrapped = bind wrapper(dataptr, f);
    ret unsafe_spawn_inner(wrapped, notify);
}

// FIXME: This is the old spawn function that spawns a shared closure.
// It is a hack and needs to be rewritten.
fn unsafe_spawn_inner(-thunk: fn@(),
                      notify: option<comm::chan<task_notification>>) ->
   task_id unsafe {
    let id = rustrt2::new_task();

    let raw_thunk: {code: u32, env: u32} = cast(thunk);

    // set up the task pointer
    let task_ptr <- rust_task_ptr(rustrt2::get_task_pointer(id));

    assert (ptr::null() != (**task_ptr).stack_ptr);

    // copy the thunk from our stack to the new stack
    let sp: uint = cast((**task_ptr).stack_ptr);
    let ptrsize = sys::size_of::<*u8>();
    let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
    let thunkenv: *mutable uint = cast(sp - ptrsize);
    *thunkfn = cast(raw_thunk.code);;
    *thunkenv = cast(raw_thunk.env);;
    // align the stack to 16 bytes
    (**task_ptr).stack_ptr = cast(sp - ptrsize * 4u);

    // set up notifications if they are enabled.
    alt notify {
      some(c) {
        (**task_ptr).notify_enabled = 1u32;;
        (**task_ptr).notify_chan = c;
      }
      none { }
    }

    // give the thunk environment's allocation to the new task
    rustrt2::migrate_alloc(cast(raw_thunk.env), id);
    rustrt::start_task(id, cast(thunkfn));
    // don't cleanup the thunk in this task
    unsafe::leak(thunk);
    ret id;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>use ape;
use id3;
use lewton::inside_ogg::OggStreamReader;
use metaflac;
use regex::Regex;
use std::fs;
use std::path::Path;

use errors::*;
use utils;
use utils::AudioFormat;

#[derive(Debug, PartialEq)]
pub struct SongTags {
	pub disc_number: Option<u32>,
	pub track_number: Option<u32>,
	pub title: Option<String>,
	pub duration: Option<u32>,
	pub artist: Option<String>,
	pub album_artist: Option<String>,
	pub album: Option<String>,
	pub year: Option<i32>,
}

pub fn read(path: &Path) -> Result<SongTags> {
	match utils::get_audio_format(path) {
		Some(AudioFormat::FLAC) => read_flac(path),
		Some(AudioFormat::MP3) => read_id3(path),
		Some(AudioFormat::MPC) => read_ape(path),
		Some(AudioFormat::OGG) => read_vorbis(path),
		_ => bail!("Unsupported file format for reading metadata"),
	}
}

fn read_id3(path: &Path) -> Result<SongTags> {
	let tag = id3::Tag::read_from_path(path)?;

	let artist = tag.artist().map(|s| s.to_string());
	let album_artist = tag.album_artist().map(|s| s.to_string());
	let album = tag.album().map(|s| s.to_string());
	let title = tag.title().map(|s| s.to_string());
	let disc_number = tag.disc();
	let track_number = tag.track();
	let year = tag.year()
		.map(|y| y as i32)
		.or(tag.date_released().and_then(|d| Some(d.year)))
		.or(tag.date_recorded().and_then(|d| Some(d.year)));

	Ok(SongTags {
	       artist: artist,
	       album_artist: album_artist,
	       album: album,
	       title: title,
		   duration: None,
	       disc_number: disc_number,
	       track_number: track_number,
	       year: year,
	   })
}

fn read_ape_string(item: &ape::Item) -> Option<String> {
	match item.value {
		ape::ItemValue::Text(ref s) => Some(s.clone()),
		_ => None,
	}
}

fn read_ape_i32(item: &ape::Item) -> Option<i32> {
	match item.value {
		ape::ItemValue::Text(ref s) => s.parse::<i32>().ok(),
		_ => None,
	}
}

fn read_ape_x_of_y(item: &ape::Item) -> Option<u32> {
	match item.value {
		ape::ItemValue::Text(ref s) => {
			let format = Regex::new(r#"^\d+"#).unwrap();
			if let Some(m) = format.find(s) {
				s[m.start()..m.end()].parse().ok()
			} else {
				None
			}
		}
		_ => None,
	}
}

fn read_ape(path: &Path) -> Result<SongTags> {
	let tag = ape::read(path)?;
	let artist = tag.item("Artist").and_then(read_ape_string);
	let album = tag.item("Album").and_then(read_ape_string);
	let album_artist = tag.item("Album artist").and_then(read_ape_string);
	let title = tag.item("Title").and_then(read_ape_string);
	let year = tag.item("Year").and_then(read_ape_i32);
	let disc_number = tag.item("Disc").and_then(read_ape_x_of_y);
	let track_number = tag.item("Track").and_then(read_ape_x_of_y);
	Ok(SongTags {
	       artist: artist,
	       album_artist: album_artist,
	       album: album,
	       title: title,
		   duration: None,
	       disc_number: disc_number,
	       track_number: track_number,
	       year: year,
	   })
}

fn read_vorbis(path: &Path) -> Result<SongTags> {

	let file = fs::File::open(path)?;
	let source = OggStreamReader::new(file)?;

	let mut tags = SongTags {
		artist: None,
		album_artist: None,
		album: None,
		title: None,
		duration:None,
		disc_number: None,
		track_number: None,
		year: None,
	};

	for (key, value) in source.comment_hdr.comment_list {
		match key.as_str() {
			"TITLE" => tags.title = Some(value),
			"ALBUM" => tags.album = Some(value),
			"ARTIST" => tags.artist = Some(value),
			"ALBUMARTIST" => tags.album_artist = Some(value),
			"TRACKNUMBER" => tags.track_number = value.parse::<u32>().ok(),
			"DISCNUMBER" => tags.disc_number = value.parse::<u32>().ok(),
			"DATE" => tags.year = value.parse::<i32>().ok(),
			_ => (),
		}
	}

	Ok(tags)
}

fn read_flac(path: &Path) -> Result<SongTags> {
	let tag = metaflac::Tag::read_from_path(path)?;
	let vorbis = tag.vorbis_comments().ok_or("Missing Vorbis comments")?;
	let disc_number = vorbis
		.get("DISCNUMBER")
		.and_then(|d| d[0].parse::<u32>().ok());
	let year = vorbis.get("DATE").and_then(|d| d[0].parse::<i32>().ok());
	Ok(SongTags {
	       artist: vorbis.artist().map(|v| v[0].clone()),
	       album_artist: vorbis.album_artist().map(|v| v[0].clone()),
	       album: vorbis.album().map(|v| v[0].clone()),
	       title: vorbis.title().map(|v| v[0].clone()),
	       duration: None,
	       disc_number: disc_number,
	       track_number: vorbis.track(),
	       year: year,
	   })
}

#[test]
fn test_read_metadata() {
	let sample_tags = SongTags {
		disc_number: Some(3),
		track_number: Some(1),
		title: Some("TEST TITLE".into()),
		artist: Some("TEST ARTIST".into()),
		album_artist: Some("TEST ALBUM ARTIST".into()),
		album: Some("TEST ALBUM".into()),
		year: Some(2016),
	};
	assert_eq!(read(Path::new("test/sample.mp3")).unwrap(), sample_tags);
	assert_eq!(read(Path::new("test/sample.ogg")).unwrap(), sample_tags);
	assert_eq!(read(Path::new("test/sample.flac")).unwrap(), sample_tags);
}
<commit_msg>add song duration for flac files<commit_after>use ape;
use id3;
use lewton::inside_ogg::OggStreamReader;
use metaflac;
use regex::Regex;
use std::fs;
use std::path::Path;

use errors::*;
use utils;
use utils::AudioFormat;

#[derive(Debug, Clone, PartialEq)]
pub struct SongTags {
	pub disc_number: Option<u32>,
	pub track_number: Option<u32>,
	pub title: Option<String>,
	pub duration: Option<u32>,
	pub artist: Option<String>,
	pub album_artist: Option<String>,
	pub album: Option<String>,
	pub year: Option<i32>,
}

pub fn read(path: &Path) -> Result<SongTags> {
	match utils::get_audio_format(path) {
		Some(AudioFormat::FLAC) => read_flac(path),
		Some(AudioFormat::MP3) => read_id3(path),
		Some(AudioFormat::MPC) => read_ape(path),
		Some(AudioFormat::OGG) => read_vorbis(path),
		_ => bail!("Unsupported file format for reading metadata"),
	}
}

fn read_id3(path: &Path) -> Result<SongTags> {
	let tag = id3::Tag::read_from_path(path)?;

	let artist = tag.artist().map(|s| s.to_string());
	let album_artist = tag.album_artist().map(|s| s.to_string());
	let album = tag.album().map(|s| s.to_string());
	let title = tag.title().map(|s| s.to_string());
	let disc_number = tag.disc();
	let track_number = tag.track();
	let year = tag.year()
		.map(|y| y as i32)
		.or(tag.date_released().and_then(|d| Some(d.year)))
		.or(tag.date_recorded().and_then(|d| Some(d.year)));

	Ok(SongTags {
	       artist: artist,
	       album_artist: album_artist,
	       album: album,
	       title: title,
		   duration: None,
	       disc_number: disc_number,
	       track_number: track_number,
	       year: year,
	   })
}

fn read_ape_string(item: &ape::Item) -> Option<String> {
	match item.value {
		ape::ItemValue::Text(ref s) => Some(s.clone()),
		_ => None,
	}
}

fn read_ape_i32(item: &ape::Item) -> Option<i32> {
	match item.value {
		ape::ItemValue::Text(ref s) => s.parse::<i32>().ok(),
		_ => None,
	}
}

fn read_ape_x_of_y(item: &ape::Item) -> Option<u32> {
	match item.value {
		ape::ItemValue::Text(ref s) => {
			let format = Regex::new(r#"^\d+"#).unwrap();
			if let Some(m) = format.find(s) {
				s[m.start()..m.end()].parse().ok()
			} else {
				None
			}
		}
		_ => None,
	}
}

fn read_ape(path: &Path) -> Result<SongTags> {
	let tag = ape::read(path)?;
	let artist = tag.item("Artist").and_then(read_ape_string);
	let album = tag.item("Album").and_then(read_ape_string);
	let album_artist = tag.item("Album artist").and_then(read_ape_string);
	let title = tag.item("Title").and_then(read_ape_string);
	let year = tag.item("Year").and_then(read_ape_i32);
	let disc_number = tag.item("Disc").and_then(read_ape_x_of_y);
	let track_number = tag.item("Track").and_then(read_ape_x_of_y);
	Ok(SongTags {
	       artist: artist,
	       album_artist: album_artist,
	       album: album,
	       title: title,
		   duration: None,
	       disc_number: disc_number,
	       track_number: track_number,
	       year: year,
	   })
}

fn read_vorbis(path: &Path) -> Result<SongTags> {

	let file = fs::File::open(path)?;
	let source = OggStreamReader::new(file)?;

	let mut tags = SongTags {
		artist: None,
		album_artist: None,
		album: None,
		title: None,
		duration:None,
		disc_number: None,
		track_number: None,
		year: None,
	};

	for (key, value) in source.comment_hdr.comment_list {
		match key.as_str() {
			"TITLE" => tags.title = Some(value),
			"ALBUM" => tags.album = Some(value),
			"ARTIST" => tags.artist = Some(value),
			"ALBUMARTIST" => tags.album_artist = Some(value),
			"TRACKNUMBER" => tags.track_number = value.parse::<u32>().ok(),
			"DISCNUMBER" => tags.disc_number = value.parse::<u32>().ok(),
			"DATE" => tags.year = value.parse::<i32>().ok(),
			_ => (),
		}
	}

	Ok(tags)
}

fn read_flac(path: &Path) -> Result<SongTags> {
	let tag = metaflac::Tag::read_from_path(path)?;
	let vorbis = tag.vorbis_comments().ok_or("Missing Vorbis comments")?;
	let disc_number = vorbis
		.get("DISCNUMBER")
		.and_then(|d| d[0].parse::<u32>().ok());
	let year = vorbis.get("DATE").and_then(|d| d[0].parse::<i32>().ok());
	let streaminfo = tag.get_blocks(metaflac::BlockType::StreamInfo);
	let duration = match streaminfo.first() {
        Some(&&metaflac::Block::StreamInfo(ref s)) => (s.total_samples as u32 / s.sample_rate) as u32,
        _ => 0
	};

	Ok(SongTags {
	       artist: vorbis.artist().map(|v| v[0].clone()),
	       album_artist: vorbis.album_artist().map(|v| v[0].clone()),
	       album: vorbis.album().map(|v| v[0].clone()),
	       title: vorbis.title().map(|v| v[0].clone()),
	       duration: Some(duration),
	       disc_number: disc_number,
	       track_number: vorbis.track(),
	       year: year,
	   })
}

#[test]
fn test_read_metadata() {
	let sample_tags = SongTags {
		disc_number: Some(3),
		track_number: Some(1),
		title: Some("TEST TITLE".into()),
		artist: Some("TEST ARTIST".into()),
		album_artist: Some("TEST ALBUM ARTIST".into()),
		album: Some("TEST ALBUM".into()),
        duration: None,
		year: Some(2016),
	};
	let flac_sample_tag = SongTags {duration: Some(0), ..sample_tags.clone()};
	assert_eq!(read(Path::new("test/sample.mp3")).unwrap(), sample_tags);
	assert_eq!(read(Path::new("test/sample.ogg")).unwrap(), sample_tags);
	assert_eq!(read(Path::new("test/sample.flac")).unwrap(), flac_sample_tag);
}
<|endoftext|>


<commit_before><commit_msg>Implement the correct SSE2 trait for bool8ix16.<commit_after><|endoftext|>


<commit_before>extern crate flate2;
extern crate nifti;
#[macro_use]
extern crate pretty_assertions;

#[cfg(feature = "ndarray_volumes")]
#[macro_use]
extern crate approx;
#[cfg(feature = "ndarray_volumes")]
extern crate ndarray;
#[cfg(feature = "ndarray_volumes")]
extern crate num_traits;
#[cfg(feature = "ndarray_volumes")]
extern crate safe_transmute;

use nifti::{Endianness, InMemNiftiVolume, NiftiHeader, NiftiVolume, RandomAccessNiftiVolume};

#[test]
fn minimal_img_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.img.gz";
    let volume = InMemNiftiVolume::from_file(FILE_NAME, &minimal_hdr).unwrap();

    assert_eq!(volume.dim(), [64, 64, 10].as_ref());

    for i in 0..64 {
        for j in 0..64 {
            let expected_value = j as f32;
            for k in 0..10 {
                let coords = [i, j, k];
                let got_value = volume.get_f32(&coords).unwrap();
                assert_eq!(
                    expected_value,
                    got_value,
                    "bad value at coords {:?}",
                    &coords
                );
            }
        }
    }
}

#[cfg(feature = "ndarray_volumes")]
mod ndarray_volumes {
    use std::fmt;
    use std::ops::{Add, Mul};
    use nifti::{DataElement, Endianness, InMemNiftiObject, InMemNiftiVolume,
                NiftiHeader, NiftiObject, NiftiVolume, NiftiType, IntoNdArray};
    use ndarray::{Array, Axis, IxDyn, ShapeBuilder};
    use num_traits::AsPrimitive;

    #[test]
    fn minimal_img_gz_ndarray_f32() {
        let minimal_hdr = NiftiHeader {
            sizeof_hdr: 348,
            dim: [3, 64, 64, 10, 0, 0, 0, 0],
            datatype: 2,
            bitpix: 8,
            pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
            vox_offset: 0.,
            scl_slope: 0.,
            scl_inter: 0.,
            magic: *b"ni1\0",
            endianness: Endianness::Big,
            ..Default::default()
        };

        const FILE_NAME: &str = "resources/minimal.img.gz";
        let volume = InMemNiftiVolume::from_file(FILE_NAME, &minimal_hdr).unwrap();

        assert_eq!(volume.dim(), [64, 64, 10].as_ref());

        let volume = volume.into_ndarray::<f32>().unwrap();

        assert_eq!(volume.shape(), [64, 64, 10].as_ref());

        let slices = volume.axis_iter(Axis(1));
        let mut e = Array::zeros(IxDyn(&[64, 10]).f());
        for (j, slice) in slices.enumerate() {
            e.fill(j as f32);
            assert!(
                slice == e,
                "slice was:\n{:?}\n, expected:\n{:?}",
                &slice,
                &e
            );
        }
    }

    #[test]
    fn minimal_img_gz_ndarray_u8() {
        let minimal_hdr = NiftiHeader {
            sizeof_hdr: 348,
            dim: [3, 64, 64, 10, 0, 0, 0, 0],
            datatype: 2,
            bitpix: 8,
            pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
            vox_offset: 0.,
            scl_slope: 0.,
            scl_inter: 0.,
            magic: *b"ni1\0",
            endianness: Endianness::Big,
            ..Default::default()
        };

        const FILE_NAME: &str = "resources/minimal.img.gz";
        let volume = InMemNiftiVolume::from_file(FILE_NAME, &minimal_hdr).unwrap();
        assert_eq!(volume.data_type(), NiftiType::Uint8);
        assert_eq!(volume.dim(), [64, 64, 10].as_ref());

        let volume = volume.into_ndarray::<u8>().unwrap();

        assert_eq!(volume.shape(), [64, 64, 10].as_ref());

        let slices = volume.axis_iter(Axis(1));
        let mut e = Array::zeros(IxDyn(&[64, 10]).f());
        for (j, slice) in slices.enumerate() {
            e.fill(j as u8);
            assert!(
                slice == e,
                "slice was:\n{:?}\n, expected:\n{:?}",
                &slice,
                &e
            );
        }
    }

    #[test]
    fn f32_nii_gz_ndarray() {
        const FILE_NAME: &str = "resources/f32.nii.gz";
        let volume = InMemNiftiObject::from_file(FILE_NAME)
            .unwrap()
            .into_volume();
        assert_eq!(volume.data_type(), NiftiType::Float32);

        let volume = volume.into_ndarray::<f32>().unwrap();

        assert_eq!(volume.shape(), [11, 11, 11].as_ref());

        assert!(volume.iter().any(|v| *v != 0.));

        assert_ulps_eq!(volume[[5, 0, 0]], 0.0);
        assert_ulps_eq!(volume[[0, 5, 0]], 0.0);
        assert_ulps_eq!(volume[[0, 0, 5]], 0.0);
        assert_ulps_eq!(volume[[5, 0, 4]], 0.4);
        assert_ulps_eq!(volume[[0, 8, 5]], 0.8);
        assert_ulps_eq!(volume[[5, 5, 5]], 1.0);
    }

    #[test]
    fn f32_nii_gz_ndarray_f64() {
        const FILE_NAME: &str = "resources/f32.nii.gz";
        let volume = InMemNiftiObject::from_file(FILE_NAME)
            .unwrap()
            .into_volume();
        assert_eq!(volume.data_type(), NiftiType::Float32);

        let volume = volume.into_ndarray::<f64>().unwrap();

        assert_eq!(volume.shape(), [11, 11, 11].as_ref());

        assert!(volume.iter().any(|v| *v != 0.));

        assert_ulps_eq!(volume[[5, 0, 0]], 0.0);
        assert_ulps_eq!(volume[[0, 5, 0]], 0.0);
        assert_ulps_eq!(volume[[0, 0, 5]], 0.0);
        assert_ulps_eq!(volume[[5, 0, 4]], 0.4_f32 as f64);
        assert_ulps_eq!(volume[[0, 8, 5]], 0.8_f32 as f64);
        assert_ulps_eq!(volume[[5, 5, 5]], 1.0_f32 as f64);
    }

    #[test]
    fn test_i8() {
        const FILE_NAME: &str = "resources/27/int8.nii";
        test_all(FILE_NAME, NiftiType::Int8);
    }

    #[test]
    fn test_u8() {
        const FILE_NAME: &str = "resources/27/uint8.nii";
        test_all(FILE_NAME, NiftiType::Uint8);
    }

    #[test]
    fn test_i16() {
        const FILE_NAME: &str = "resources/27/int16.nii";
        test_all(FILE_NAME, NiftiType::Int16);
    }

    #[test]
    fn test_u16() {
        const FILE_NAME: &str = "resources/27/uint16.nii";
        test_all(FILE_NAME, NiftiType::Uint16);
    }

    #[test]
    fn test_i32() {
        const FILE_NAME: &str = "resources/27/int32.nii";
        test_all(FILE_NAME, NiftiType::Int32);
    }

    #[test]
    fn test_u32() {
        const FILE_NAME: &str = "resources/27/uint32.nii";
        test_all(FILE_NAME, NiftiType::Uint32);
    }

    #[test]
    fn test_i64() {
        const FILE_NAME: &str = "resources/27/int64.nii";
        test_all(FILE_NAME, NiftiType::Int64);
    }

    #[test]
    fn test_u64() {
        const FILE_NAME: &str = "resources/27/uint64.nii";
        test_all(FILE_NAME, NiftiType::Uint64);
    }

    #[test]
    fn test_f32() {
        const FILE_NAME: &str = "resources/27/float32.nii";
        test_all(FILE_NAME, NiftiType::Float32);
    }

    #[test]
    fn test_f64() {
        const FILE_NAME: &str = "resources/27/float64.nii";
        test_all(FILE_NAME, NiftiType::Float64);
    }

    fn test_all(path: &str, dtype: NiftiType)
    {
        test_types::<i8>(path, dtype);
        test_types::<u8>(path, dtype);
        test_types::<i16>(path, dtype);
        test_types::<u16>(path, dtype);
        test_types::<i32>(path, dtype);
        test_types::<u32>(path, dtype);
        test_types::<i64>(path, dtype);
        test_types::<u64>(path, dtype);
        test_types::<f32>(path, dtype);
        test_types::<f64>(path, dtype);
    }

    fn test_types<T>(path: &str, dtype: NiftiType)
        where
            T: fmt::Debug,
            T: Add<Output = T>,
            T: Mul<Output = T>,
            T: DataElement,
            T: PartialEq<T>,
            u8: AsPrimitive<T>,
            i8: AsPrimitive<T>,
            u16: AsPrimitive<T>,
            i16: AsPrimitive<T>,
            u32: AsPrimitive<T>,
            i32: AsPrimitive<T>,
            u64: AsPrimitive<T>,
            i64: AsPrimitive<T>,
            f32: AsPrimitive<T>,
            f64: AsPrimitive<T>,
            usize: AsPrimitive<T>,
    {
        let volume = InMemNiftiObject::from_file(path)
            .expect("Can't read input file.")
            .into_volume();
        assert_eq!(volume.data_type(), dtype);

        let data = volume.into_ndarray::<T>().unwrap();
        for (idx, val) in data.iter().enumerate() {
            assert_eq!(idx.as_(), *val);
        }
    }
}
<commit_msg>Add another streamed volume test<commit_after>extern crate flate2;
extern crate nifti;
#[macro_use]
extern crate pretty_assertions;

#[cfg(feature = "ndarray_volumes")]
#[macro_use]
extern crate approx;
#[cfg(feature = "ndarray_volumes")]
extern crate ndarray;
#[cfg(feature = "ndarray_volumes")]
extern crate num_traits;
#[cfg(feature = "ndarray_volumes")]
extern crate safe_transmute;

use nifti::{Endianness, InMemNiftiVolume, NiftiHeader, NiftiVolume, RandomAccessNiftiVolume};

#[test]
fn minimal_img_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.img.gz";
    let volume = InMemNiftiVolume::from_file(FILE_NAME, &minimal_hdr).unwrap();

    assert_eq!(volume.dim(), [64, 64, 10].as_ref());

    for i in 0..64 {
        for j in 0..64 {
            let expected_value = j as f32;
            for k in 0..10 {
                let coords = [i, j, k];
                let got_value = volume.get_f32(&coords).unwrap();
                assert_eq!(
                    expected_value,
                    got_value,
                    "bad value at coords {:?}",
                    &coords
                );
            }
        }
    }
}

#[cfg(feature = "ndarray_volumes")]
mod ndarray_volumes {
    use std::fmt;
    use std::ops::{Add, Mul};
    use nifti::{DataElement, Endianness, InMemNiftiObject, InMemNiftiVolume,
                NiftiHeader, NiftiObject, NiftiVolume, NiftiType, IntoNdArray,
                StreamedNiftiObject};
    use ndarray::{Array, Axis, IxDyn, ShapeBuilder};
    use num_traits::AsPrimitive;

    #[test]
    fn minimal_img_gz_ndarray_f32() {
        let minimal_hdr = NiftiHeader {
            sizeof_hdr: 348,
            dim: [3, 64, 64, 10, 0, 0, 0, 0],
            datatype: 2,
            bitpix: 8,
            pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
            vox_offset: 0.,
            scl_slope: 0.,
            scl_inter: 0.,
            magic: *b"ni1\0",
            endianness: Endianness::Big,
            ..Default::default()
        };

        const FILE_NAME: &str = "resources/minimal.img.gz";
        let volume = InMemNiftiVolume::from_file(FILE_NAME, &minimal_hdr).unwrap();

        assert_eq!(volume.dim(), [64, 64, 10].as_ref());

        let volume = volume.into_ndarray::<f32>().unwrap();

        assert_eq!(volume.shape(), [64, 64, 10].as_ref());

        let slices = volume.axis_iter(Axis(1));
        let mut e = Array::zeros(IxDyn(&[64, 10]).f());
        for (j, slice) in slices.enumerate() {
            e.fill(j as f32);
            assert!(
                slice == e,
                "slice was:\n{:?}\n, expected:\n{:?}",
                &slice,
                &e
            );
        }
    }

    #[test]
    fn minimal_img_gz_ndarray_u8() {
        let minimal_hdr = NiftiHeader {
            sizeof_hdr: 348,
            dim: [3, 64, 64, 10, 0, 0, 0, 0],
            datatype: 2,
            bitpix: 8,
            pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
            vox_offset: 0.,
            scl_slope: 0.,
            scl_inter: 0.,
            magic: *b"ni1\0",
            endianness: Endianness::Big,
            ..Default::default()
        };

        const FILE_NAME: &str = "resources/minimal.img.gz";
        let volume = InMemNiftiVolume::from_file(FILE_NAME, &minimal_hdr).unwrap();
        assert_eq!(volume.data_type(), NiftiType::Uint8);
        assert_eq!(volume.dim(), [64, 64, 10].as_ref());

        let volume = volume.into_ndarray::<u8>().unwrap();

        assert_eq!(volume.shape(), [64, 64, 10].as_ref());

        let slices = volume.axis_iter(Axis(1));
        let mut e = Array::zeros(IxDyn(&[64, 10]).f());
        for (j, slice) in slices.enumerate() {
            e.fill(j as u8);
            assert!(
                slice == e,
                "slice was:\n{:?}\n, expected:\n{:?}",
                &slice,
                &e
            );
        }
    }

    #[test]
    fn f32_nii_gz_ndarray() {
        const FILE_NAME: &str = "resources/f32.nii.gz";
        let volume = InMemNiftiObject::from_file(FILE_NAME)
            .unwrap()
            .into_volume();
        assert_eq!(volume.data_type(), NiftiType::Float32);

        let volume = volume.into_ndarray::<f32>().unwrap();

        assert_eq!(volume.shape(), [11, 11, 11].as_ref());

        assert!(volume.iter().any(|v| *v != 0.));

        assert_ulps_eq!(volume[[5, 0, 0]], 0.0);
        assert_ulps_eq!(volume[[0, 5, 0]], 0.0);
        assert_ulps_eq!(volume[[0, 0, 5]], 0.0);
        assert_ulps_eq!(volume[[5, 0, 4]], 0.4);
        assert_ulps_eq!(volume[[0, 8, 5]], 0.8);
        assert_ulps_eq!(volume[[5, 5, 5]], 1.0);
    }

    #[test]
    fn f32_nii_gz_ndarray_f64() {
        const FILE_NAME: &str = "resources/f32.nii.gz";
        let volume = InMemNiftiObject::from_file(FILE_NAME)
            .unwrap()
            .into_volume();
        assert_eq!(volume.data_type(), NiftiType::Float32);

        let volume = volume.into_ndarray::<f64>().unwrap();

        assert_eq!(volume.shape(), [11, 11, 11].as_ref());

        assert!(volume.iter().any(|v| *v != 0.));

        assert_ulps_eq!(volume[[5, 0, 0]], 0.0);
        assert_ulps_eq!(volume[[0, 5, 0]], 0.0);
        assert_ulps_eq!(volume[[0, 0, 5]], 0.0);
        assert_ulps_eq!(volume[[5, 0, 4]], 0.4_f32 as f64);
        assert_ulps_eq!(volume[[0, 8, 5]], 0.8_f32 as f64);
        assert_ulps_eq!(volume[[5, 5, 5]], 1.0_f32 as f64);
    }

    #[test]
    fn streamed_f32_nii_gz_ndarray_f64() {
        const FILE_NAME: &str = "resources/f32.nii.gz";
        let volume = StreamedNiftiObject::from_file(FILE_NAME)
            .unwrap()
            .into_volume();
        assert_eq!(volume.data_type(), NiftiType::Float32);

        let slices: Vec<_> = volume
            .map(|r| r.expect("slice construction should not fail"))
            .map(|slice| slice.into_ndarray::<f64>().unwrap())
            .collect();

        for slice in &slices {
            assert_eq!(slice.shape(), &[11, 11]);
        }
        assert!(slices[4].iter().any(|v| *v != 0.));
        assert!(slices[5].iter().any(|v| *v != 0.));

        assert_ulps_eq!(slices[0][[5, 0]], 0.0);
        assert_ulps_eq!(slices[0][[0, 5]], 0.0);
        assert_ulps_eq!(slices[5][[0, 0]], 0.0);
        assert_ulps_eq!(slices[4][[5, 0]], 0.4_f32 as f64);
        assert_ulps_eq!(slices[5][[0, 8]], 0.8_f32 as f64);
        assert_ulps_eq!(slices[5][[5, 5]], 1.0_f32 as f64);
    }

    #[test]
    fn test_i8() {
        const FILE_NAME: &str = "resources/27/int8.nii";
        test_all(FILE_NAME, NiftiType::Int8);
    }

    #[test]
    fn test_u8() {
        const FILE_NAME: &str = "resources/27/uint8.nii";
        test_all(FILE_NAME, NiftiType::Uint8);
    }

    #[test]
    fn test_i16() {
        const FILE_NAME: &str = "resources/27/int16.nii";
        test_all(FILE_NAME, NiftiType::Int16);
    }

    #[test]
    fn test_u16() {
        const FILE_NAME: &str = "resources/27/uint16.nii";
        test_all(FILE_NAME, NiftiType::Uint16);
    }

    #[test]
    fn test_i32() {
        const FILE_NAME: &str = "resources/27/int32.nii";
        test_all(FILE_NAME, NiftiType::Int32);
    }

    #[test]
    fn test_u32() {
        const FILE_NAME: &str = "resources/27/uint32.nii";
        test_all(FILE_NAME, NiftiType::Uint32);
    }

    #[test]
    fn test_i64() {
        const FILE_NAME: &str = "resources/27/int64.nii";
        test_all(FILE_NAME, NiftiType::Int64);
    }

    #[test]
    fn test_u64() {
        const FILE_NAME: &str = "resources/27/uint64.nii";
        test_all(FILE_NAME, NiftiType::Uint64);
    }

    #[test]
    fn test_f32() {
        const FILE_NAME: &str = "resources/27/float32.nii";
        test_all(FILE_NAME, NiftiType::Float32);
    }

    #[test]
    fn test_f64() {
        const FILE_NAME: &str = "resources/27/float64.nii";
        test_all(FILE_NAME, NiftiType::Float64);
    }

    fn test_all(path: &str, dtype: NiftiType)
    {
        test_types::<i8>(path, dtype);
        test_types::<u8>(path, dtype);
        test_types::<i16>(path, dtype);
        test_types::<u16>(path, dtype);
        test_types::<i32>(path, dtype);
        test_types::<u32>(path, dtype);
        test_types::<i64>(path, dtype);
        test_types::<u64>(path, dtype);
        test_types::<f32>(path, dtype);
        test_types::<f64>(path, dtype);
    }

    fn test_types<T>(path: &str, dtype: NiftiType)
        where
            T: fmt::Debug,
            T: Add<Output = T>,
            T: Mul<Output = T>,
            T: DataElement,
            T: PartialEq<T>,
            u8: AsPrimitive<T>,
            i8: AsPrimitive<T>,
            u16: AsPrimitive<T>,
            i16: AsPrimitive<T>,
            u32: AsPrimitive<T>,
            i32: AsPrimitive<T>,
            u64: AsPrimitive<T>,
            i64: AsPrimitive<T>,
            f32: AsPrimitive<T>,
            f64: AsPrimitive<T>,
            usize: AsPrimitive<T>,
    {
        let volume = InMemNiftiObject::from_file(path)
            .expect("Can't read input file.")
            .into_volume();
        assert_eq!(volume.data_type(), dtype);

        let data = volume.into_ndarray::<T>().unwrap();
        for (idx, val) in data.iter().enumerate() {
            assert_eq!(idx.as_(), *val);
        }
    }
}
<|endoftext|>