<commit_before>// Copyright (c) 2010-2013, Susumu Yata
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
// - Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#ifndef MARISA_GRIMOIRE_INTRIN_H_
#define MARISA_GRIMOIRE_INTRIN_H_

#include "marisa/base.h"

#if defined(__x86_64__) || defined(_M_X64)
 #define MARISA_X64
#elif defined(__i386__) || defined(_M_IX86)
 #define MARISA_X86
#else  // defined(__i386__) || defined(_M_IX86)
 #ifdef MARISA_USE_POPCNT
  #undef MARISA_USE_POPCNT
 #endif  // MARISA_USE_POPCNT
 #ifdef MARISA_USE_SSE4A
  #undef MARISA_USE_SSE4A
 #endif  // MARISA_USE_SSE4A
 #ifdef MARISA_USE_SSE4
  #undef MARISA_USE_SSE4
 #endif  // MARISA_USE_SSE4
 #ifdef MARISA_USE_SSE4_2
  #undef MARISA_USE_SSE4_2
 #endif  // MARISA_USE_SSE4_2
 #ifdef MARISA_USE_SSE4_1
  #undef MARISA_USE_SSE4_1
 #endif  // MARISA_USE_SSE4_1
 #ifdef MARISA_USE_SSSE3
  #undef MARISA_USE_SSSE3
 #endif  // MARISA_USE_SSSE3
 #ifdef MARISA_USE_SSE3
  #undef MARISA_USE_SSE3
 #endif  // MARISA_USE_SSE3
 #ifdef MARISA_USE_SSE2
  #undef MARISA_USE_SSE2
 #endif  // MARISA_USE_SSE2
#endif  // defined(__i386__) || defined(_M_IX86)

#ifdef MARISA_USE_POPCNT
 #ifndef MARISA_USE_SSE3
  #define MARISA_USE_SSE3
 #endif  // MARISA_USE_SSE3
 #ifdef _MSC_VER
  #include <intrin.h>
 #else  // _MSC_VER
  #include <popcntintrin.h>
 #endif  // _MSC_VER
#endif  // MARISA_USE_POPCNT

#ifdef MARISA_USE_SSE4A
 #ifndef MARISA_USE_SSE3
  #define MARISA_USE_SSE3
 #endif  // MARISA_USE_SSE3
 #ifndef MARISA_USE_POPCNT
  #define MARISA_USE_POPCNT
 #endif  // MARISA_USE_POPCNT
#endif  // MARISA_USE_SSE4A

#ifdef MARISA_USE_SSE4
 #ifndef MARISA_USE_SSE4_2
  #define MARISA_USE_SSE4_2
 #endif  // MARISA_USE_SSE4_2
#endif  // MARISA_USE_SSE4

#ifdef MARISA_USE_SSE4_2
 #ifndef MARISA_USE_SSE4_1
  #define MARISA_USE_SSE4_1
 #endif  // MARISA_USE_SSE4_1
 #ifndef MARISA_USE_POPCNT
  #define MARISA_USE_POPCNT
 #endif  // MARISA_USE_POPCNT
#endif  // MARISA_USE_SSE4_2

#ifdef MARISA_USE_SSE4_1
 #ifndef MARISA_USE_SSSE3
  #define MARISA_USE_SSSE3
 #endif  // MARISA_USE_SSSE3
#endif  // MARISA_USE_SSE4_1

#ifdef MARISA_USE_SSSE3
 #ifndef MARISA_USE_SSE3
  #define MARISA_USE_SSE3
 #endif  // MARISA_USE_SSE3
 #ifdef MARISA_X64
  #define MARISA_X64_SSSE3
 #else  // MARISA_X64
  #define MARISA_X86_SSSE3
 #endif  // MAIRSA_X64
 #include <tmmintrin.h>
#endif  // MARISA_USE_SSSE3

#ifdef MARISA_USE_SSE3
 #ifndef MARISA_USE_SSE2
  #define MARISA_USE_SSE2
 #endif  // MARISA_USE_SSE2
#endif  // MARISA_USE_SSE3

#ifdef MARISA_USE_SSE2
 #ifdef MARISA_X64
  #define MARISA_X64_SSE2
 #else  // MARISA_X64
  #define MARISA_X86_SSE2
 #endif  // MAIRSA_X64
 #include <emmintrin.h>
#endif  // MARISA_USE_SSE2

#ifdef _MSC_VER
 #if MARISA_WORD_SIZE == 64
  #include <intrin.h>
  #pragma intrinsic(_BitScanForward64)
 #else  // MARISA_WORD_SIZE == 64
  #include <intrin.h>
  #pragma intrinsic(_BitScanForward)
 #endif  // MARISA_WORD_SIZE == 64
#endif  // _MSC_VER

#endif  // MARISA_GRIMOIRE_INTRIN_H_
<commit_msg>Remove intrin.rs for now<commit_after><|endoftext|>


<commit_before>//! I/O conveniences when working with primitives in `tokio-core`
//!
//! Contains various combinators to work with I/O objects and type definitions
//! as well.
//!
//! A description of the high-level I/O combinators can be [found online] in
//! addition to a description of the [low level details].
//!
//! [found online]: https://tokio.rs/docs/getting-started/core/
//! [low level details]: https://tokio.rs/docs/going-deeper-tokio/core-low-level/

#![deprecated(note = "moved to the `tokio-io` crate")]

use std::io;

use futures::{Async, Poll};
use futures::future::BoxFuture;
use futures::stream::BoxStream;
use iovec::IoVec;

/// A convenience typedef around a `Future` whose error component is `io::Error`
pub type IoFuture<T> = BoxFuture<T, io::Error>;

/// A convenience typedef around a `Stream` whose error component is `io::Error`
pub type IoStream<T> = BoxStream<T, io::Error>;

/// A convenience macro for working with `io::Result<T>` from the `Read` and
/// `Write` traits.
///
/// This macro takes `io::Result<T>` as input, and returns `T` as the output. If
/// the input type is of the `Err` variant, then `Poll::NotReady` is returned if
/// it indicates `WouldBlock` or otherwise `Err` is returned.
#[macro_export]
macro_rules! try_nb {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {
            return Ok(::futures::Async::NotReady)
        }
        Err(e) => return Err(e.into()),
    })
}

mod copy;
mod frame;
mod flush;
mod read_exact;
mod read_to_end;
mod read;
mod read_until;
mod split;
mod window;
mod write_all;
pub use self::copy::{copy, Copy};
pub use self::frame::{EasyBuf, EasyBufMut, Framed, Codec};
pub use self::flush::{flush, Flush};
pub use self::read_exact::{read_exact, ReadExact};
pub use self::read_to_end::{read_to_end, ReadToEnd};
pub use self::read::{read, Read};
pub use self::read_until::{read_until, ReadUntil};
pub use self::split::{ReadHalf, WriteHalf};
pub use self::window::Window;
pub use self::write_all::{write_all, WriteAll};

/// A trait for read/write I/O objects
///
/// This trait represents I/O object which are readable and writable.
/// Additionally, they're associated with the ability to test whether they're
/// readable or writable.
///
/// Importantly, the methods of this trait are intended to be used in conjunction
/// with the current task of a future. Namely whenever any of them return a
/// value that indicates "would block" the current future's task is arranged to
/// receive a notification when the method would otherwise not indicate that it
/// would block.
pub trait Io: io::Read + io::Write {
    /// Tests to see if this I/O object may be readable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be readable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `read` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is readable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_read(&mut self) -> Async<()> {
        Async::Ready(())
    }

    /// Tests to see if this I/O object may be writable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be writable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `write` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is writable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_write(&mut self) -> Async<()> {
        Async::Ready(())
    }

    /// Read in a list of buffers all at once.
    ///
    /// This operation will attempt to read bytes from this socket and place
    /// them into the list of buffers provided. Note that each buffer is an
    /// `IoVec` which can be created from a byte slice.
    ///
    /// The buffers provided will be filled in sequentially. A buffer will be
    /// entirely filled up before the next is written to.
    ///
    /// The number of bytes read is returned, if successful, or an error is
    /// returned otherwise. If no bytes are available to be read yet then
    /// a "would block" error is returned. This operation should not block.
    ///
    /// There is a default implementation for this function which treats this
    /// as a single read using the first buffer in the list, but objects which
    /// can implement this as an atomic read using all the buffers are
    /// recommended to do so. For example, `TcpStream` can implement this
    /// using the `readv` syscall.
    fn read_vec(&mut self, bufs: &mut [&mut IoVec]) -> io::Result<usize> {
        if bufs.is_empty() {
            Ok(0)
        } else {
            self.read(&mut bufs[0])
        }
    }

    /// Write a list of buffers all at once.
    ///
    /// This operation will attempt to write a list of byte buffers to this
    /// socket. Note that each buffer is an `IoVec` which can be created from a
    /// byte slice.
    ///
    /// The buffers provided will be written sequentially. A buffer will be
    /// entirely written before the next is written.
    ///
    /// The number of bytes written is returned, if successful, or an error is
    /// returned otherwise. If the socket is not currently writable then a
    /// "would block" error is returned. This operation should not block.
    ///
    /// There is a default implementation for this function which writes the
    /// first buffer only, but objects which can implement this as an atomic
    /// write using all the buffers are  recommended to do so. For example,
    /// `TcpStream` can implement this  using the `writev` syscall.
    fn write_vec(&mut self, bufs: &[&IoVec]) -> io::Result<usize> {
        if bufs.is_empty() {
            Ok(0)
        } else {
            self.write(&bufs[0])
        }
    }

    /// Provides a `Stream` and `Sink` interface for reading and writing to this
    /// `Io` object, using `Decode` and `Encode` to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both `Stream` and
    /// `Sink`; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling `split` on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    fn framed<C: Codec>(self, codec: C) -> Framed<Self, C>
        where Self: Sized,
    {
        frame::framed(self, codec)
    }

    /// Helper method for splitting this read/write object into two halves.
    ///
    /// The two halves returned implement the `Read` and `Write` traits,
    /// respectively.
    fn split(self) -> (ReadHalf<Self>, WriteHalf<Self>)
        where Self: Sized
    {
        split::split(self)
    }
}

/// A trait for framed reading and writing.
///
/// Most implementations of `FramedIo` are for doing protocol level
/// serialization and deserialization.
///
/// Importantly, the methods of this trait are intended to be used in conjunction
/// with the current task of a future. Namely whenever any of them return a
/// value that indicates "would block" the current future's task is arranged to
/// receive a notification when the method would otherwise not indicate that it
/// would block.
//
/// For a sample implementation of `FramedIo` you can take a look at the
/// `Framed` type in the `frame` module of this crate.
#[doc(hidden)]
#[deprecated(since = "0.1.1", note = "replaced by Sink + Stream")]
pub trait FramedIo {
    /// Messages written
    type In;

    /// Messages read
    type Out;

    /// Tests to see if this `FramedIo` may be readable.
    fn poll_read(&mut self) -> Async<()>;

    /// Read a message frame from the `FramedIo`
    fn read(&mut self) -> Poll<Self::Out, io::Error>;

    /// Tests to see if this `FramedIo` may be writable.
    ///
    /// Unlike most other calls to poll readiness, it is important that when
    /// `FramedIo::poll_write` returns `Async::Ready` that a write will
    /// succeed.
    fn poll_write(&mut self) -> Async<()>;

    /// Write a message frame to the `FramedIo`
    fn write(&mut self, req: Self::In) -> Poll<(), io::Error>;

    /// Flush pending writes or do any other work not driven by reading /
    /// writing.
    ///
    /// Since the backing source is non-blocking, there is no guarantee that a
    /// call to `FramedIo::write` is able to write the full message to the
    /// backing source immediately. In this case, the `FramedIo` will need to
    /// buffer the remaining data to write. Calls to `FramedIo:flush` attempt
    /// to write any remaining data in the write buffer to the underlying
    /// source.
    fn flush(&mut self) -> Poll<(), io::Error>;
}
<commit_msg>small typo fixed for io module<commit_after>//! I/O conveniences when working with primitives in `tokio-core`
//!
//! Contains various combinators to work with I/O objects and type definitions
//! as well.
//!
//! A description of the high-level I/O combinators can be [found online] in
//! addition to a description of the [low level details].
//!
//! [found online]: https://tokio.rs/docs/getting-started/core/
//! [low level details]: https://tokio.rs/docs/going-deeper-tokio/core-low-level/

#![deprecated(note = "moved to the `tokio-io` crate")]

use std::io;

use futures::{Async, Poll};
use futures::future::BoxFuture;
use futures::stream::BoxStream;
use iovec::IoVec;

/// A convenience typedef around a `Future` whose error component is `io::Error`
pub type IoFuture<T> = BoxFuture<T, io::Error>;

/// A convenience typedef around a `Stream` whose error component is `io::Error`
pub type IoStream<T> = BoxStream<T, io::Error>;

/// A convenience macro for working with `io::Result<T>` from the `Read` and
/// `Write` traits.
///
/// This macro takes `io::Result<T>` as input, and returns `T` as the output. If
/// the input type is of the `Err` variant, then `Poll::NotReady` is returned if
/// it indicates `WouldBlock` or otherwise `Err` is returned.
#[macro_export]
macro_rules! try_nb {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {
            return Ok(::futures::Async::NotReady)
        }
        Err(e) => return Err(e.into()),
    })
}

mod copy;
mod frame;
mod flush;
mod read_exact;
mod read_to_end;
mod read;
mod read_until;
mod split;
mod window;
mod write_all;
pub use self::copy::{copy, Copy};
pub use self::frame::{EasyBuf, EasyBufMut, Framed, Codec};
pub use self::flush::{flush, Flush};
pub use self::read_exact::{read_exact, ReadExact};
pub use self::read_to_end::{read_to_end, ReadToEnd};
pub use self::read::{read, Read};
pub use self::read_until::{read_until, ReadUntil};
pub use self::split::{ReadHalf, WriteHalf};
pub use self::window::Window;
pub use self::write_all::{write_all, WriteAll};

/// A trait for read/write I/O objects
///
/// This trait represents I/O objects which are readable and writable.
/// Additionally, they're associated with the ability to test whether they're
/// readable or writable.
///
/// Importantly, the methods of this trait are intended to be used in conjunction
/// with the current task of a future. Namely whenever any of them return a
/// value that indicates "would block" the current future's task is arranged to
/// receive a notification when the method would otherwise not indicate that it
/// would block.
pub trait Io: io::Read + io::Write {
    /// Tests to see if this I/O object may be readable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be readable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `read` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is readable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_read(&mut self) -> Async<()> {
        Async::Ready(())
    }

    /// Tests to see if this I/O object may be writable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be writable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `write` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is writable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_write(&mut self) -> Async<()> {
        Async::Ready(())
    }

    /// Read in a list of buffers all at once.
    ///
    /// This operation will attempt to read bytes from this socket and place
    /// them into the list of buffers provided. Note that each buffer is an
    /// `IoVec` which can be created from a byte slice.
    ///
    /// The buffers provided will be filled in sequentially. A buffer will be
    /// entirely filled up before the next is written to.
    ///
    /// The number of bytes read is returned, if successful, or an error is
    /// returned otherwise. If no bytes are available to be read yet then
    /// a "would block" error is returned. This operation should not block.
    ///
    /// There is a default implementation for this function which treats this
    /// as a single read using the first buffer in the list, but objects which
    /// can implement this as an atomic read using all the buffers are
    /// recommended to do so. For example, `TcpStream` can implement this
    /// using the `readv` syscall.
    fn read_vec(&mut self, bufs: &mut [&mut IoVec]) -> io::Result<usize> {
        if bufs.is_empty() {
            Ok(0)
        } else {
            self.read(&mut bufs[0])
        }
    }

    /// Write a list of buffers all at once.
    ///
    /// This operation will attempt to write a list of byte buffers to this
    /// socket. Note that each buffer is an `IoVec` which can be created from a
    /// byte slice.
    ///
    /// The buffers provided will be written sequentially. A buffer will be
    /// entirely written before the next is written.
    ///
    /// The number of bytes written is returned, if successful, or an error is
    /// returned otherwise. If the socket is not currently writable then a
    /// "would block" error is returned. This operation should not block.
    ///
    /// There is a default implementation for this function which writes the
    /// first buffer only, but objects which can implement this as an atomic
    /// write using all the buffers are  recommended to do so. For example,
    /// `TcpStream` can implement this  using the `writev` syscall.
    fn write_vec(&mut self, bufs: &[&IoVec]) -> io::Result<usize> {
        if bufs.is_empty() {
            Ok(0)
        } else {
            self.write(&bufs[0])
        }
    }

    /// Provides a `Stream` and `Sink` interface for reading and writing to this
    /// `Io` object, using `Decode` and `Encode` to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both `Stream` and
    /// `Sink`; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling `split` on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    fn framed<C: Codec>(self, codec: C) -> Framed<Self, C>
        where Self: Sized,
    {
        frame::framed(self, codec)
    }

    /// Helper method for splitting this read/write object into two halves.
    ///
    /// The two halves returned implement the `Read` and `Write` traits,
    /// respectively.
    fn split(self) -> (ReadHalf<Self>, WriteHalf<Self>)
        where Self: Sized
    {
        split::split(self)
    }
}

/// A trait for framed reading and writing.
///
/// Most implementations of `FramedIo` are for doing protocol level
/// serialization and deserialization.
///
/// Importantly, the methods of this trait are intended to be used in conjunction
/// with the current task of a future. Namely whenever any of them return a
/// value that indicates "would block" the current future's task is arranged to
/// receive a notification when the method would otherwise not indicate that it
/// would block.
//
/// For a sample implementation of `FramedIo` you can take a look at the
/// `Framed` type in the `frame` module of this crate.
#[doc(hidden)]
#[deprecated(since = "0.1.1", note = "replaced by Sink + Stream")]
pub trait FramedIo {
    /// Messages written
    type In;

    /// Messages read
    type Out;

    /// Tests to see if this `FramedIo` may be readable.
    fn poll_read(&mut self) -> Async<()>;

    /// Read a message frame from the `FramedIo`
    fn read(&mut self) -> Poll<Self::Out, io::Error>;

    /// Tests to see if this `FramedIo` may be writable.
    ///
    /// Unlike most other calls to poll readiness, it is important that when
    /// `FramedIo::poll_write` returns `Async::Ready` that a write will
    /// succeed.
    fn poll_write(&mut self) -> Async<()>;

    /// Write a message frame to the `FramedIo`
    fn write(&mut self, req: Self::In) -> Poll<(), io::Error>;

    /// Flush pending writes or do any other work not driven by reading /
    /// writing.
    ///
    /// Since the backing source is non-blocking, there is no guarantee that a
    /// call to `FramedIo::write` is able to write the full message to the
    /// backing source immediately. In this case, the `FramedIo` will need to
    /// buffer the remaining data to write. Calls to `FramedIo:flush` attempt
    /// to write any remaining data in the write buffer to the underlying
    /// source.
    fn flush(&mut self) -> Poll<(), io::Error>;
}
<|endoftext|>


<commit_before>pub struct Keypad {
    row0: u8,
    row1: u8,
    data: u8,
    pub interrupt: u8,
}

#[derive(Copy, Clone)]
pub enum KeypadKey {
    Right,
    Left,
    Up,
    Down,
    A,
    B,
    Select,
    Start,
}

impl Keypad {
    pub fn new() -> Keypad {
        let mut res = Keypad {
            row0: 0x0F,
            row1: 0x0F,
            data: 0xFF,
            interrupt: 0,
        };
        res.update();
        return res
    }

    pub fn rb(&mut self) -> u8 {
        self.data
    }

    pub fn wb(&mut self, value: u8) {
        self.data = 0xC0 | (value & 0x30) | (self.data & 0x0F);
        self.update();
    }

    fn update(&mut self) {
        let old_values = self.data & 0xF;
        let mut new_values = 0xF;

        if self.data & 0x10 == 0x00 {
            new_values &= self.row0;
        }
        if self.data & 0x20 == 0x00 {
            new_values &= self.row1;
        }

        if old_values == 0xF && new_values != 0xF {
            self.interrupt |= 0x10;
        }

        self.data = (self.data & 0xF0) | new_values;
    }

    pub fn keydown(&mut self, key: KeypadKey) {
        match key {
            KeypadKey::Right =>  self.row0 &= !(1 << 0),
            KeypadKey::Left =>   self.row0 &= !(1 << 1),
            KeypadKey::Up =>     self.row0 &= !(1 << 2),
            KeypadKey::Down =>   self.row0 &= !(1 << 3),
            KeypadKey::A =>      self.row1 &= !(1 << 0),
            KeypadKey::B =>      self.row1 &= !(1 << 1),
            KeypadKey::Select => self.row1 &= !(1 << 2),
            KeypadKey::Start =>  self.row1 &= !(1 << 3),
        }

        self.update();
    }

    pub fn keyup(&mut self, key: KeypadKey) {
        match key {
            KeypadKey::Right =>  self.row0 |= 1 << 0,
            KeypadKey::Left =>   self.row0 |= 1 << 1,
            KeypadKey::Up =>     self.row0 |= 1 << 2,
            KeypadKey::Down =>   self.row0 |= 1 << 3,
            KeypadKey::A =>      self.row1 |= 1 << 0,
            KeypadKey::B =>      self.row1 |= 1 << 1,
            KeypadKey::Select => self.row1 |= 1 << 2,
            KeypadKey::Start =>  self.row1 |= 1 << 3,
        }
        self.update();
    }
}

#[cfg(test)]
mod test {
    use super::KeypadKey;

    #[test]
    fn keys_buttons() {
        let mut keypad = super::Keypad::new();
        let keys0 : [KeypadKey; 4] = [KeypadKey::A, KeypadKey::B, KeypadKey::Select, KeypadKey::Start];

        for i in 0 .. keys0.len() {
            keypad.keydown(keys0[i]);

            keypad.wb(0x00);
            assert_eq!(keypad.rb(), 0xCF & !(1 << i));

            keypad.wb(0x10);
            assert_eq!(keypad.rb(), 0xDF & !(1 << i));

            keypad.wb(0x20);
            assert_eq!(keypad.rb(), 0xEF);

            keypad.wb(0x30);
            assert_eq!(keypad.rb(), 0xFF);

            keypad.keyup(keys0[i]);
        }
    }

    #[test]
    fn keys_direction() {
        let mut keypad = super::Keypad::new();
        let keys1 : [KeypadKey; 4] = [KeypadKey::Right, KeypadKey::Left, KeypadKey::Up, KeypadKey::Down];

        for i in 0 .. keys1.len() {
            keypad.keydown(keys1[i]);

            keypad.wb(0x00);
            assert_eq!(keypad.rb(), 0xCF & !(1 << i));

            keypad.wb(0x10);
            assert_eq!(keypad.rb(), 0xDF);

            keypad.wb(0x20);
            assert_eq!(keypad.rb(), 0xEF & !(1 << i));

            keypad.wb(0x30);
            assert_eq!(keypad.rb(), 0xFF);

            keypad.keyup(keys1[i]);
        }
    }
}
<commit_msg>Small improvements to keypad<commit_after>pub struct Keypad {
    row0: u8,
    row1: u8,
    data: u8,
    pub interrupt: u8,
}

#[derive(Copy, Clone)]
pub enum KeypadKey {
    Right,
    Left,
    Up,
    Down,
    A,
    B,
    Select,
    Start,
}

impl Keypad {
    pub fn new() -> Keypad {
        Keypad {
            row0: 0x0F,
            row1: 0x0F,
            data: 0xFF,
            interrupt: 0,
        }
    }

    pub fn rb(&self) -> u8 {
        self.data
    }

    pub fn wb(&mut self, value: u8) {
        self.data = (self.data & 0xCF) | (value & 0x30);
        self.update();
    }

    fn update(&mut self) {
        let old_values = self.data & 0xF;
        let mut new_values = 0xF;

        if self.data & 0x10 == 0x00 {
            new_values &= self.row0;
        }
        if self.data & 0x20 == 0x00 {
            new_values &= self.row1;
        }

        if old_values == 0xF && new_values != 0xF {
            self.interrupt |= 0x10;
        }

        self.data = (self.data & 0xF0) | new_values;
    }

    pub fn keydown(&mut self, key: KeypadKey) {
        match key {
            KeypadKey::Right =>  self.row0 &= !(1 << 0),
            KeypadKey::Left =>   self.row0 &= !(1 << 1),
            KeypadKey::Up =>     self.row0 &= !(1 << 2),
            KeypadKey::Down =>   self.row0 &= !(1 << 3),
            KeypadKey::A =>      self.row1 &= !(1 << 0),
            KeypadKey::B =>      self.row1 &= !(1 << 1),
            KeypadKey::Select => self.row1 &= !(1 << 2),
            KeypadKey::Start =>  self.row1 &= !(1 << 3),
        }
        self.update();
    }

    pub fn keyup(&mut self, key: KeypadKey) {
        match key {
            KeypadKey::Right =>  self.row0 |= 1 << 0,
            KeypadKey::Left =>   self.row0 |= 1 << 1,
            KeypadKey::Up =>     self.row0 |= 1 << 2,
            KeypadKey::Down =>   self.row0 |= 1 << 3,
            KeypadKey::A =>      self.row1 |= 1 << 0,
            KeypadKey::B =>      self.row1 |= 1 << 1,
            KeypadKey::Select => self.row1 |= 1 << 2,
            KeypadKey::Start =>  self.row1 |= 1 << 3,
        }
        self.update();
    }
}

#[cfg(test)]
mod test {
    use super::KeypadKey;

    #[test]
    fn keys_buttons() {
        let mut keypad = super::Keypad::new();
        let keys0 : [KeypadKey; 4] = [KeypadKey::A, KeypadKey::B, KeypadKey::Select, KeypadKey::Start];

        for i in 0 .. keys0.len() {
            keypad.keydown(keys0[i]);

            keypad.wb(0x00);
            assert_eq!(keypad.rb(), 0xCF & !(1 << i));

            keypad.wb(0x10);
            assert_eq!(keypad.rb(), 0xDF & !(1 << i));

            keypad.wb(0x20);
            assert_eq!(keypad.rb(), 0xEF);

            keypad.wb(0x30);
            assert_eq!(keypad.rb(), 0xFF);

            keypad.keyup(keys0[i]);
        }
    }

    #[test]
    fn keys_direction() {
        let mut keypad = super::Keypad::new();
        let keys1 : [KeypadKey; 4] = [KeypadKey::Right, KeypadKey::Left, KeypadKey::Up, KeypadKey::Down];

        for i in 0 .. keys1.len() {
            keypad.keydown(keys1[i]);

            keypad.wb(0x00);
            assert_eq!(keypad.rb(), 0xCF & !(1 << i));

            keypad.wb(0x10);
            assert_eq!(keypad.rb(), 0xDF);

            keypad.wb(0x20);
            assert_eq!(keypad.rb(), 0xEF & !(1 << i));

            keypad.wb(0x30);
            assert_eq!(keypad.rb(), 0xFF);

            keypad.keyup(keys1[i]);
        }
    }
}
<|endoftext|>


<commit_before>
use ndarray::*;
use lapack::c;

use super::error::*;

pub type LDA = i32;
pub type LEN = i32;
pub type Col = i32;
pub type Row = i32;

#[derive(Debug, Clone, Copy)]
pub enum Layout {
    C((Row, LDA)),
    F((Col, LDA)),
}

impl Layout {
    pub fn size(&self) -> (Row, Col) {
        match *self {
            Layout::C((row, lda)) => (row, lda),
            Layout::F((col, lda)) => (lda, col),
        }
    }

    pub fn resized(&self, row: Row, col: Col) -> Layout {
        match *self {
            Layout::C(_) => Layout::C((row, col)),
            Layout::F(_) => Layout::F((col, row)),
        }
    }

    pub fn lda(&self) -> LDA {
        match *self {
            Layout::C((_, lda)) => lda,
            Layout::F((_, lda)) => lda,
        }
    }

    pub fn len(&self) -> LEN {
        match *self {
            Layout::C((row, _)) => row,
            Layout::F((col, _)) => col,
        }
    }

    pub fn lapacke_layout(&self) -> c::Layout {
        match *self {
            Layout::C(_) => c::Layout::RowMajor,
            Layout::F(_) => c::Layout::ColumnMajor,
        }
    }
}

pub trait AllocatedArray {
    type Elem;
    fn layout(&self) -> Result<Layout>;
    fn square_layout(&self) -> Result<Layout>;
    fn as_allocated(&self) -> Result<&[Self::Elem]>;
}

pub trait AllocatedArrayMut: AllocatedArray {
    fn as_allocated_mut(&mut self) -> Result<&mut [Self::Elem]>;
}

impl<A, S> AllocatedArray for ArrayBase<S, Ix2>
    where S: Data<Elem = A>
{
    type Elem = A;

    fn layout(&self) -> Result<Layout> {
        let strides = self.strides();
        if ::std::cmp::min(strides[0], strides[1]) != 1 {
            return Err(StrideError::new(strides[0], strides[1]).into());
        }
        if strides[0] > strides[1] {
            Ok(Layout::C((self.rows() as i32, self.cols() as i32)))
        } else {
            Ok(Layout::F((self.cols() as i32, self.rows() as i32)))
        }
    }

    fn square_layout(&self) -> Result<Layout> {
        let l = self.layout()?;
        let (n, m) = l.size();
        if n == m {
            Ok(l)
        } else {
            Err(NotSquareError::new(n, m).into())
        }
    }

    fn as_allocated(&self) -> Result<&[A]> {
        Ok(self.as_slice_memory_order().ok_or(MemoryContError::new())?)
    }
}

impl<A, S> AllocatedArrayMut for ArrayBase<S, Ix2>
    where S: DataMut<Elem = A>
{
    fn as_allocated_mut(&mut self) -> Result<&mut [A]> {
        Ok(self.as_slice_memory_order_mut().ok_or(MemoryContError::new())?)
    }
}

impl<A, S> AllocatedArray for ArrayBase<S, Ix1>
    where S: Data<Elem = A>
{
    type Elem = A;

    fn layout(&self) -> Result<Layout> {
        Ok(Layout::F((1, self.len() as i32)))
    }

    fn square_layout(&self) -> Result<Layout> {
        Err(NotSquareError::new(1, self.len() as i32).into())
    }

    fn as_allocated(&self) -> Result<&[A]> {
        Ok(self.as_slice_memory_order().ok_or(MemoryContError::new())?)
    }
}

impl<A, S> AllocatedArrayMut for ArrayBase<S, Ix1>
    where S: DataMut<Elem = A>
{
    fn as_allocated_mut(&mut self) -> Result<&mut [A]> {
        Ok(self.as_slice_memory_order_mut().ok_or(MemoryContError::new())?)
    }
}

pub fn reconstruct<A, S>(l: Layout, a: Vec<A>) -> Result<ArrayBase<S, Ix2>>
    where S: DataOwned<Elem = A>
{
    Ok(match l {
        Layout::C((row, col)) => ArrayBase::from_shape_vec((row as usize, col as usize), a)?,
        Layout::F((col, row)) => ArrayBase::from_shape_vec((row as usize, col as usize).f(), a)?,
    })
}

pub fn replicate<A, Sv, So, D>(a: &ArrayBase<Sv, D>) -> ArrayBase<So, D>
    where A: Copy,
          Sv: Data<Elem = A>,
          So: DataOwned<Elem = A> + DataMut,
          D: Dimension
{
    let mut b = unsafe { ArrayBase::uninitialized(a.dim()) };
    b.assign(a);
    b
}
<commit_msg>Add utlities for Layout<commit_after>
use ndarray::*;
use lapack::c;

use super::error::*;

pub type LDA = i32;
pub type LEN = i32;
pub type Col = i32;
pub type Row = i32;

#[derive(Debug, Clone, Copy)]
pub enum Layout {
    C((Row, LDA)),
    F((Col, LDA)),
}

impl Layout {
    pub fn size(&self) -> (Row, Col) {
        match *self {
            Layout::C((row, lda)) => (row, lda),
            Layout::F((col, lda)) => (lda, col),
        }
    }

    pub fn resized(&self, row: Row, col: Col) -> Layout {
        match *self {
            Layout::C(_) => Layout::C((row, col)),
            Layout::F(_) => Layout::F((col, row)),
        }
    }

    pub fn lda(&self) -> LDA {
        match *self {
            Layout::C((_, lda)) => lda,
            Layout::F((_, lda)) => lda,
        }
    }

    pub fn len(&self) -> LEN {
        match *self {
            Layout::C((row, _)) => row,
            Layout::F((col, _)) => col,
        }
    }

    pub fn lapacke_layout(&self) -> c::Layout {
        match *self {
            Layout::C(_) => c::Layout::RowMajor,
            Layout::F(_) => c::Layout::ColumnMajor,
        }
    }

    pub fn same_order(&self, other: &Layout) -> bool {
        match *self {
            Layout::C(_) => {
                match *other {
                    Layout::C(_) => true,
                    Layout::F(_) => false,
                }
            }
            Layout::F(_) => {
                match *other {
                    Layout::C(_) => false,
                    Layout::F(_) => true,
                }
            }
        }
    }

    pub fn as_shape(&self) -> Shape<Ix2> {
        match *self {
            Layout::C((row, col)) => (row as usize, col as usize).into_shape(),
            Layout::F((col, row)) => (row as usize, col as usize).f().into_shape(),
        }
    }

    pub fn t(&self) -> Self {
        match *self {
            Layout::C((row, col)) => Layout::F((col, row)),
            Layout::F((col, row)) => Layout::C((row, col)),
        }
    }
}

pub trait AllocatedArray {
    type Elem;
    fn layout(&self) -> Result<Layout>;
    fn square_layout(&self) -> Result<Layout>;
    fn as_allocated(&self) -> Result<&[Self::Elem]>;
}

pub trait AllocatedArrayMut: AllocatedArray {
    fn as_allocated_mut(&mut self) -> Result<&mut [Self::Elem]>;
}

impl<A, S> AllocatedArray for ArrayBase<S, Ix2>
    where S: Data<Elem = A>
{
    type Elem = A;

    fn layout(&self) -> Result<Layout> {
        let strides = self.strides();
        if ::std::cmp::min(strides[0], strides[1]) != 1 {
            return Err(StrideError::new(strides[0], strides[1]).into());
        }
        if strides[0] > strides[1] {
            Ok(Layout::C((self.rows() as i32, self.cols() as i32)))
        } else {
            Ok(Layout::F((self.cols() as i32, self.rows() as i32)))
        }
    }

    fn square_layout(&self) -> Result<Layout> {
        let l = self.layout()?;
        let (n, m) = l.size();
        if n == m {
            Ok(l)
        } else {
            Err(NotSquareError::new(n, m).into())
        }
    }

    fn as_allocated(&self) -> Result<&[A]> {
        Ok(self.as_slice_memory_order().ok_or(MemoryContError::new())?)
    }
}

impl<A, S> AllocatedArrayMut for ArrayBase<S, Ix2>
    where S: DataMut<Elem = A>
{
    fn as_allocated_mut(&mut self) -> Result<&mut [A]> {
        Ok(self.as_slice_memory_order_mut().ok_or(MemoryContError::new())?)
    }
}

impl<A, S> AllocatedArray for ArrayBase<S, Ix1>
    where S: Data<Elem = A>
{
    type Elem = A;

    fn layout(&self) -> Result<Layout> {
        Ok(Layout::F((1, self.len() as i32)))
    }

    fn square_layout(&self) -> Result<Layout> {
        Err(NotSquareError::new(1, self.len() as i32).into())
    }

    fn as_allocated(&self) -> Result<&[A]> {
        Ok(self.as_slice_memory_order().ok_or(MemoryContError::new())?)
    }
}

impl<A, S> AllocatedArrayMut for ArrayBase<S, Ix1>
    where S: DataMut<Elem = A>
{
    fn as_allocated_mut(&mut self) -> Result<&mut [A]> {
        Ok(self.as_slice_memory_order_mut().ok_or(MemoryContError::new())?)
    }
}

pub fn reconstruct<A, S>(l: Layout, a: Vec<A>) -> Result<ArrayBase<S, Ix2>>
    where S: DataOwned<Elem = A>
{
    Ok(ArrayBase::from_shape_vec(l.as_shape(), a)?)
}

pub fn uninitialized<A, S>(l: Layout) -> ArrayBase<S, Ix2>
    where A: Copy,
          S: DataOwned<Elem = A>
{
    unsafe { ArrayBase::uninitialized(l.as_shape()) }
}

pub fn replicate<A, Sv, So, D>(a: &ArrayBase<Sv, D>) -> ArrayBase<So, D>
    where A: Copy,
          Sv: Data<Elem = A>,
          So: DataOwned<Elem = A> + DataMut,
          D: Dimension
{
    let mut b = unsafe { ArrayBase::uninitialized(a.dim()) };
    b.assign(a);
    b
}

pub fn clone_with_layout<A, Si, So>(l: Layout, a: &ArrayBase<Si, Ix2>) -> ArrayBase<So, Ix2>
    where A: Copy,
          Si: Data<Elem = A>,
          So: DataOwned<Elem = A> + DataMut
{
    let mut b = uninitialized(l);
    b.assign(a);
    b
}
<|endoftext|>


<commit_before>//! A macro for defining #[cfg] if-else statements.
//!
//! The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C
//! preprocessor macro by allowing definition of a cascade of `#[cfg]` cases,
//! emitting the implementation which matches first.
//!
//! This allows you to conveniently provide a long list #[cfg]'d blocks of code
//! without having to rewrite each clause multiple times.

macro_rules! cfg_if {
    ($(
        if #[cfg($($meta:meta),*)] { $($it:item)* }
    ) else * else {
        $($it2:item)*
    }) => {
        __cfg_if_items! {
            () ;
            $( ( ($($meta),*) ($($it)*) ), )*
            ( () ($($it2)*) ),
        }
    }
}

#[doc(hidden)]
macro_rules! __cfg_if_items {
    (($($not:meta,)*) ; ) => {};
    (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
        __cfg_if_apply! { cfg(all($($m,)* not(any($($not),*)))), $($it)* }
        __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* }
    }
}

#[doc(hidden)]
macro_rules! __cfg_if_apply {
    ($m:meta, $($it:item)*) => {
        $(#[$m] $it)*
    }
}

#[cfg(test)]
mod tests {
    cfg_if! {
        if #[cfg(test)] {
            use std::option::Option as Option2;
            fn works1() -> Option2<u32> { Some(1) }
        } else {
            fn works1() -> Option<u32> { None }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works2() -> bool { false }
        } else if #[cfg(test)] {
            fn works2() -> bool { true }
        } else {
            fn works2() -> bool { false }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works3() -> bool { false }
        } else {
            fn works3() -> bool { true }
        }
    }

    #[test]
    fn it_works() {
        assert!(works1().is_some());
        assert!(works2());
        assert!(works3());
    }
}
<commit_msg>Tweak macros module<commit_after>//! A macro for defining #[cfg] if-else statements.
//!
//! This is similar to the `if/elif` C preprocessor macro by allowing definition
//! of a cascade of `#[cfg]` cases, emitting the implementation which matches
//! first.
//!
//! This allows you to conveniently provide a long list #[cfg]'d blocks of code
//! without having to rewrite each clause multiple times.

macro_rules! cfg_if {
    ($(
        if #[cfg($($meta:meta),*)] { $($it:item)* }
    ) else * else {
        $($it2:item)*
    }) => {
        __cfg_if_items! {
            () ;
            $( ( ($($meta),*) ($($it)*) ), )*
            ( () ($($it2)*) ),
        }
    }
}

macro_rules! __cfg_if_items {
    (($($not:meta,)*) ; ) => {};
    (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
        __cfg_if_apply! { cfg(all($($m,)* not(any($($not),*)))), $($it)* }
        __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* }
    }
}

macro_rules! __cfg_if_apply {
    ($m:meta, $($it:item)*) => {
        $(#[$m] $it)*
    }
}

#[cfg(test)]
mod tests {
    cfg_if! {
        if #[cfg(test)] {
            use std::option::Option as Option2;
            fn works1() -> Option2<u32> { Some(1) }
        } else {
            fn works1() -> Option<u32> { None }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works2() -> bool { false }
        } else if #[cfg(test)] {
            fn works2() -> bool { true }
        } else {
            fn works2() -> bool { false }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works3() -> bool { false }
        } else {
            fn works3() -> bool { true }
        }
    }

    #[test]
    fn it_works() {
        assert!(works1().is_some());
        assert!(works2());
        assert!(works3());
    }
}
<|endoftext|>


<commit_before>/// Macro to print the current stats of ArrayFire's memory manager.
///
/// `mem_info!` print 4 values:
///
///  Name                    | Description
/// -------------------------|-------------------------
///  Allocated Bytes         | Total number of bytes allocated by the memory manager
///  Allocated Buffers       | Total number of buffers allocated
///  Locked (In Use) Bytes   | Number of bytes that are in use by active arrays
///  Locked (In Use) Buffers | Number of buffers that are in use by active arrays
///
///  The `Allocated Bytes` is always a multiple of the memory step size. The
///  default step size is 1024 bytes. This means when a buffer is to be
///  allocated, the size is always rounded up to a multiple of the step size.
///  You can use [get_mem_step_size](./fn.get_mem_step_size.html) to check the
///  current step size and [set_mem_step_size](./fn.set_mem_step_size.html) to
///  set a custom resolution size.
///
///  The `Allocated Buffers` is the number of buffers that use up the allocated
///  bytes. This includes buffers currently in scope, as well as buffers marked
///  as free, ie, from arrays gone out of scope. The free buffers are available
///  for use by new arrays that might be created.
///
///  The `Locked Bytes` is the number of bytes in use that cannot be
///  reallocated at the moment. The difference of Allocated Bytes and Locked
///  Bytes is the total bytes available for reallocation.
///
///  The `Locked Buffers` is the number of buffer in use that cannot be
///  reallocated at the moment. The difference of Allocated Buffers and Locked
///  Buffers is the number of buffers available for reallocation.
///
/// # Parameters
///
/// - `msg` is the message that is printed to screen before printing stats
///
/// # Examples
///
/// ```
/// mem_info!("Here");
/// ```
///
/// Sample Output:
///
/// ```
/// AF Memory: Here
/// Allocated [ Bytes | Buffers ] = [ 4096 | 4 ]
/// In Use    [ Bytes | Buffers ] = [ 2048 | 2 ]
/// ```
#[macro_export]
macro_rules! mem_info {
    [$msg: expr] => {
        {
            let (abytes, abuffs, lbytes, lbuffs) = device_mem_info().unwrap();
            println!("AF Memory: {:?}", $msg);
            println!("Allocated [Bytes | Buffers] = [ {} | {} ]", abytes, abuffs);
            println!("In Use    [Bytes | Buffers] = [ {} | {} ]", lbytes, lbuffs);
        }
    };
}

/// Join multiple Arrays along a given dimension
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate arrayfire;
/// # fn main() {
/// let a = randu::<f32>(Dim4::new(&[5, 3, 1, 1])).unwrap();
/// let b = randu::<f32>(Dim4::new(&[5, 3, 1, 1])).unwrap();
/// let c = randu::<f32>(Dim4::new(&[5, 3, 1, 1])).unwrap();
/// let d = join_many![2, a, b, c];
/// # }
/// ```
///
/// # Panics
///
/// This macro just calls [join_many](./fn.join_many.html) function after collecting all
/// the input arrays into a vector.
// Using macro to implement join many wrapper
#[macro_export]
macro_rules! join_many {
    [$dim: expr; $($x:ident),+] => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
             )*
            join_many($dim, temp_vec)
        }
    };
}
<commit_msg>Fixed example code in join_many macro documentation<commit_after>/// Macro to print the current stats of ArrayFire's memory manager.
///
/// `mem_info!` print 4 values:
///
///  Name                    | Description
/// -------------------------|-------------------------
///  Allocated Bytes         | Total number of bytes allocated by the memory manager
///  Allocated Buffers       | Total number of buffers allocated
///  Locked (In Use) Bytes   | Number of bytes that are in use by active arrays
///  Locked (In Use) Buffers | Number of buffers that are in use by active arrays
///
///  The `Allocated Bytes` is always a multiple of the memory step size. The
///  default step size is 1024 bytes. This means when a buffer is to be
///  allocated, the size is always rounded up to a multiple of the step size.
///  You can use [get_mem_step_size](./fn.get_mem_step_size.html) to check the
///  current step size and [set_mem_step_size](./fn.set_mem_step_size.html) to
///  set a custom resolution size.
///
///  The `Allocated Buffers` is the number of buffers that use up the allocated
///  bytes. This includes buffers currently in scope, as well as buffers marked
///  as free, ie, from arrays gone out of scope. The free buffers are available
///  for use by new arrays that might be created.
///
///  The `Locked Bytes` is the number of bytes in use that cannot be
///  reallocated at the moment. The difference of Allocated Bytes and Locked
///  Bytes is the total bytes available for reallocation.
///
///  The `Locked Buffers` is the number of buffer in use that cannot be
///  reallocated at the moment. The difference of Allocated Buffers and Locked
///  Buffers is the number of buffers available for reallocation.
///
/// # Parameters
///
/// - `msg` is the message that is printed to screen before printing stats
///
/// # Examples
///
/// ```
/// mem_info!("Here");
/// ```
///
/// Sample Output:
///
/// ```
/// AF Memory: Here
/// Allocated [ Bytes | Buffers ] = [ 4096 | 4 ]
/// In Use    [ Bytes | Buffers ] = [ 2048 | 2 ]
/// ```
#[macro_export]
macro_rules! mem_info {
    [$msg: expr] => {
        {
            let (abytes, abuffs, lbytes, lbuffs) = device_mem_info().unwrap();
            println!("AF Memory: {:?}", $msg);
            println!("Allocated [Bytes | Buffers] = [ {} | {} ]", abytes, abuffs);
            println!("In Use    [Bytes | Buffers] = [ {} | {} ]", lbytes, lbuffs);
        }
    };
}

/// Join multiple Arrays along a given dimension
///
/// All the Arrays provided to this macro should be of type `&Array`
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate arrayfire;
/// # fn main() {
/// let a = &randu::<f32>(Dim4::new(&[5, 3, 1, 1])).unwrap();
/// let b = &randu::<f32>(Dim4::new(&[5, 3, 1, 1])).unwrap();
/// let c = &randu::<f32>(Dim4::new(&[5, 3, 1, 1])).unwrap();
/// let d = join_many![2; a, b, c];
/// # }
/// ```
///
/// # Panics
///
/// This macro just calls [join_many](./fn.join_many.html) function after collecting all
/// the input arrays into a vector.
// Using macro to implement join many wrapper
#[macro_export]
macro_rules! join_many {
    [$dim: expr; $($x:ident),+] => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
             )*
            join_many($dim, temp_vec)
        }
    };
}
<|endoftext|>


<commit_before>//! # Glulx memory mapping
//!
//! The Glulx machine memory consists of a ROM and RAM, which themselves
//! are separated into several different groups.
//!
//!
//! ## Program Provided Values
//!
//! The following values are defined by the given program:
//!
//! * RAMSTART -- Specifies the starting point of the RAM
//! * EXTSTART -- Specifies start of zeroed section of RAM
//! * ENDMEM -- Specifies the ending point of the RAM
//!
//!
//! ## ROM
//!
//! The ROM is defined by the following:
//!
//! * The ROM ranges from 0x00000000 to RAMSTART.
//! * The Header ranges from 0x00000000 to 0x00000024.
//! * The ROM is read-only.
//! * The ROM must be at least 0x100 bytes long.
//! * The ROM usually (but not always) contains all the executable code
//! and constants for the loaded program.
//!
//!
//! ## RAM
//!
//! The RAM is defined by the following:
//!
//! * The RAM ranges from RAMSTART to ENDMEM
//! * The RAM from EXTSTART to ENDMEM is initialized to all zeros.
//! * The RAM can be 0x0 bytes long.
//!
//! ## Misc
//!
//! * RAMSTART, EXTSTART, and ENDMEM must be aligned on 0x100 byte
//! boundries
//! * A Glulx gamefile only stores data from 0x0 to EXTSTART.

use byteorder::{BigEndian, ByteOrder};

/// Glulx magic number
const MAGIC_NUMBER: u32 = 0x476C756C;

/// Minimum supported glulx target
const MIN_VERSION: u32 = 0x0020000;

/// Maximum supported glulx target
const MAX_VERSION: u32 = 0x00301FF;

/// Struct representing a glulx memory object.
pub struct GlulxMemory {
    heap_mode: bool,
    memory: Vec<u8>,
}

impl GlulxMemory {

    /// This takes a rom, validates it to verify that it is a valid
    /// Glulx rom, and retuns either an error string or a `GlulxMemory`
    /// TODO: Replace error string with custom glulx error type.
    pub fn from_rom(rom: Vec<u8>) -> Result<GlulxMemory, String> {
        // Validate magic number.
        let magic_number = BigEndian::read_u32(&rom[0x0..0x4]);
        if magic_number != MAGIC_NUMBER {
            return Err("executable code starts with invalid magic number"
                .to_string());
        }

        // Validate glulx version.
        let glulx_version = BigEndian::read_u32(&rom[0x4..0x8]);
        if glulx_version < MIN_VERSION {
            return Err("executable code glulx version is less than 2.0.0"
                .to_string());
        } else if glulx_version > MAX_VERSION {
            return Err("executable code glulx version is greater than 3.1.x"
                .to_string());
        }

        // Validate ramstart value.
        let ramstart = BigEndian::read_u32(&rom[0x8..0xC]);
        if ramstart < 0x100 {
            return Err("ramstart is less than 0x100 bytes".to_string());
        } else if ramstart % 0x100 != 0 {
            return Err("ramstart is misaligned".to_string());
        }

        // Validate extstart value.
        let extstart = BigEndian::read_u32(&rom[0xC..0x10]);
        if extstart < ramstart {
            return Err("extstart is less than ramstart".to_string());
        } else if extstart % 0x100 != 0 {
            return Err("extstart is misaligned".to_string());
        }

        // Validate endmem value.
        let endmem = BigEndian::read_u32(&rom[0x10..0x14]);
        if endmem < extstart {
            return Err("endmem is less than extstart".to_string());
        } else if endmem % 0x100 != 0 {
            return Err("endmem is misaligned".to_string());
        }

        // Validate stack size.
        let stack_size = BigEndian::read_u32(&rom[0x14..0x18]);
        if stack_size % 0x100 != 0 {
            return Err("stack size is misaligned".to_string());
        }

        if (endmem as usize) < rom.len() {
            return Err("rom size is not correct".to_string());
        }

        let checksum = BigEndian::read_u32(&rom[0x20..0x24]);
        let sum = {
            let mut sum = 0u32;
            for i in 0..rom.len()/4 {
                sum = sum.wrapping_add(BigEndian::read_u32(&rom[i*4..]));
            }
            sum.wrapping_sub(checksum)
        };
        if checksum != sum {
            return Err("rom checksum is not correct".to_string());
        }

        let mut rom = rom;
        let ext_size = (endmem - extstart) as usize;
        rom.reserve_exact(ext_size);
        rom.resize(endmem as usize, 0x0);

        Ok(GlulxMemory { heap_mode: false, memory: rom })
    }

    pub fn zero_range(&mut self, size: u32, ptr: u32){
        for i in ptr as usize..(ptr + size) as usize {
            self.memory[i] = 0;
        }
    }

    pub fn copy_range(&mut self, size: u32, from_ptr: u32, to_ptr: u32){
        let to_ptr = to_ptr as usize;
        let from_ptr = from_ptr as usize;

        for i in 0x0..size as usize {
            self.memory[to_ptr + i] = self.memory[from_ptr + i];
        }
    }

    // Header value functions.

    /// The glulx magic number, stored from `0x0..0x4` in the header.
    /// This number is unique to all glulx games. This value should be
    /// `0x476C756C`, which is equivalent to `b"Glul"`.
    fn magic_number(&self) -> u32 {
        BigEndian::read_u32(&self.memory[..0x4])
    }

    /// The glulx version number, stored from `0x4..0x8` in the header.
    /// First two bytes store the major version number. The next byte
    /// stores the minor version number. The final byte stores the patch
    /// version number.
    pub fn glulx_version(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x4..0x8])
    }

    /// The address indicating the start of the RAM, stored from
    /// `0x4..0x8` in the header. TODO: MOAR DATA
    fn ramstart(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x8..0xC])
    }

    fn extstart(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0xC..0x10])
    }

    fn endmem(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x10..0x14])
    }

    pub fn stack_size(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x14..0x18])
    }

    pub fn start_func(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x18..0x1C])
    }

    fn decoding_tbl(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x1C..0x20])
    }

    /// The sum of the intial contents of memory, considered as an array
    /// of `u32`s. When calculated, the checksum value is considered to
    /// be `0`.
    fn checksum(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x20..0x24])
    }

    pub fn get_mem_size(&self) -> u32 {
        self.memory.len() as u32
    }

    /// Sets the memory size to the given value. This call only works if
    /// there is no active heap, the given value is a multiple of 0x100,
    /// and the value is greater than the ENDMEM value identified in the
    /// header.
    pub fn set_mem_size(&mut self, value: u32) -> u32 {
        if self.heap_mode
                && value % 0x100 == 0
                && value >= self.endmem() {
            self.memory.resize(value as usize, 0x0);
            0
        } else {
            1
        }
    }
}

pub trait Memory<T> {
    fn read(&self, ptr: u32) -> T;
    fn write(&mut self, ptr: u32, value: T);
    fn ram_read(&self, ptr: u32) -> T;
    fn ram_write(&mut self, ptr: u32, value: T);
}

impl Memory<u8> for GlulxMemory {
    fn read(&self, ptr: u32) -> u8 {
        self.memory[ptr as usize]
    }

    fn write(&mut self, ptr: u32, value: u8) {
        self.memory[ptr as usize] = value
    }

    fn ram_read(&self, ptr: u32) -> u8 {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr]
    }

    fn ram_write(&mut self, ptr: u32, value: u8) {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr] = value
    }
}

impl Memory<i8> for GlulxMemory {
    fn read(&self, ptr: u32) -> i8 {
        self.memory[ptr as usize] as i8
    }

    fn write(&mut self, ptr: u32, value: i8) {
        self.memory[ptr as usize] = value as u8
    }

    fn ram_read(&self, ptr: u32) -> i8 {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr] as i8
    }

    fn ram_write(&mut self, ptr: u32, value: i8) {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr] = value as u8
    }
}

impl Memory<u16> for GlulxMemory {
    fn read(&self, ptr: u32) -> u16 {
        BigEndian::read_u16(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: u16) {
        BigEndian::write_u16(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> u16 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_u16(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: u16) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_u16(&mut self.memory[ptr..], value)
    }
}

impl Memory<i16> for GlulxMemory {
    fn read(&self, ptr: u32) -> i16 {
        BigEndian::read_i16(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: i16) {
        BigEndian::write_i16(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> i16 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_i16(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: i16) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_i16(&mut self.memory[ptr..], value)
    }
}

impl Memory<u32> for GlulxMemory {
    fn read(&self, ptr: u32) -> u32 {
        BigEndian::read_u32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: u32) {
        BigEndian::write_u32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> u32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_u32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: u32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_u32(&mut self.memory[ptr..], value)
    }
}

impl Memory<i32> for GlulxMemory {
    fn read(&self, ptr: u32) -> i32 {
        BigEndian::read_i32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: i32) {
        BigEndian::write_i32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> i32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_i32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: i32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_i32(&mut self.memory[ptr..], value)
    }
}

impl Memory<f32> for GlulxMemory {
    fn read(&self, ptr: u32) -> f32 {
        BigEndian::read_f32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: f32) {
        BigEndian::write_f32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> f32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_f32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: f32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_f32(&mut self.memory[ptr..], value)
    }
}
<commit_msg>added spaces to memory.rs to match formatting of rest of code<commit_after>//! # Glulx memory mapping
//!
//! The Glulx machine memory consists of a ROM and RAM, which themselves
//! are separated into several different groups.
//!
//!
//! ## Program Provided Values
//!
//! The following values are defined by the given program:
//!
//! * RAMSTART -- Specifies the starting point of the RAM
//! * EXTSTART -- Specifies start of zeroed section of RAM
//! * ENDMEM -- Specifies the ending point of the RAM
//!
//!
//! ## ROM
//!
//! The ROM is defined by the following:
//!
//! * The ROM ranges from 0x00000000 to RAMSTART.
//! * The Header ranges from 0x00000000 to 0x00000024.
//! * The ROM is read-only.
//! * The ROM must be at least 0x100 bytes long.
//! * The ROM usually (but not always) contains all the executable code
//! and constants for the loaded program.
//!
//!
//! ## RAM
//!
//! The RAM is defined by the following:
//!
//! * The RAM ranges from RAMSTART to ENDMEM
//! * The RAM from EXTSTART to ENDMEM is initialized to all zeros.
//! * The RAM can be 0x0 bytes long.
//!
//! ## Misc
//!
//! * RAMSTART, EXTSTART, and ENDMEM must be aligned on 0x100 byte
//! boundries
//! * A Glulx gamefile only stores data from 0x0 to EXTSTART.

use byteorder::{BigEndian, ByteOrder};

/// Glulx magic number
const MAGIC_NUMBER: u32 = 0x476C756C;

/// Minimum supported glulx target
const MIN_VERSION: u32 = 0x0020000;

/// Maximum supported glulx target
const MAX_VERSION: u32 = 0x00301FF;

/// Struct representing a glulx memory object.
pub struct GlulxMemory {
    heap_mode: bool,
    memory: Vec<u8>,
}

impl GlulxMemory {

    /// This takes a rom, validates it to verify that it is a valid
    /// Glulx rom, and retuns either an error string or a `GlulxMemory`
    /// TODO: Replace error string with custom glulx error type.
    pub fn from_rom(rom: Vec<u8>) -> Result<GlulxMemory, String> {
        // Validate magic number.
        let magic_number = BigEndian::read_u32(&rom[0x0..0x4]);
        if magic_number != MAGIC_NUMBER {
            return Err("executable code starts with invalid magic number"
                .to_string());
        }

        // Validate glulx version.
        let glulx_version = BigEndian::read_u32(&rom[0x4..0x8]);
        if glulx_version < MIN_VERSION {
            return Err("executable code glulx version is less than 2.0.0"
                .to_string());
        } else if glulx_version > MAX_VERSION {
            return Err("executable code glulx version is greater than 3.1.x"
                .to_string());
        }

        // Validate ramstart value.
        let ramstart = BigEndian::read_u32(&rom[0x8..0xC]);
        if ramstart < 0x100 {
            return Err("ramstart is less than 0x100 bytes".to_string());
        } else if ramstart % 0x100 != 0 {
            return Err("ramstart is misaligned".to_string());
        }

        // Validate extstart value.
        let extstart = BigEndian::read_u32(&rom[0xC..0x10]);
        if extstart < ramstart {
            return Err("extstart is less than ramstart".to_string());
        } else if extstart % 0x100 != 0 {
            return Err("extstart is misaligned".to_string());
        }

        // Validate endmem value.
        let endmem = BigEndian::read_u32(&rom[0x10..0x14]);
        if endmem < extstart {
            return Err("endmem is less than extstart".to_string());
        } else if endmem % 0x100 != 0 {
            return Err("endmem is misaligned".to_string());
        }

        // Validate stack size.
        let stack_size = BigEndian::read_u32(&rom[0x14..0x18]);
        if stack_size % 0x100 != 0 {
            return Err("stack size is misaligned".to_string());
        }

        if (endmem as usize) < rom.len() {
            return Err("rom size is not correct".to_string());
        }

        let checksum = BigEndian::read_u32(&rom[0x20..0x24]);
        let sum = {
            let mut sum = 0u32;
            for i in 0..rom.len()/4 {
                sum = sum.wrapping_add(BigEndian::read_u32(&rom[i*4..]));
            }
            sum.wrapping_sub(checksum)
        };
        if checksum != sum {
            return Err("rom checksum is not correct".to_string());
        }

        let mut rom = rom;
        let ext_size = (endmem - extstart) as usize;
        rom.reserve_exact(ext_size);
        rom.resize(endmem as usize, 0x0);

        Ok(GlulxMemory { heap_mode: false, memory: rom })
    }

    pub fn zero_range(&mut self, size: u32, ptr: u32){
        for i in ptr as usize..(ptr + size) as usize {
            self.memory[i] = 0;
        }
    }

    pub fn copy_range(&mut self, size: u32, from_ptr: u32, to_ptr: u32){
        let to_ptr = to_ptr as usize;
        let from_ptr = from_ptr as usize;

        for i in 0x0..size as usize {
            self.memory[to_ptr + i] = self.memory[from_ptr + i];
        }
    }

    // Header value functions.

    /// The glulx magic number, stored from `0x0..0x4` in the header.
    /// This number is unique to all glulx games. This value should be
    /// `0x476C756C`, which is equivalent to `b"Glul"`.
    fn magic_number(&self) -> u32 {
        BigEndian::read_u32(&self.memory[..0x4])
    }

    /// The glulx version number, stored from `0x4..0x8` in the header.
    /// First two bytes store the major version number. The next byte
    /// stores the minor version number. The final byte stores the patch
    /// version number.
    pub fn glulx_version(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x4..0x8])
    }

    /// The address indicating the start of the RAM, stored from
    /// `0x4..0x8` in the header. TODO: MOAR DATA
    fn ramstart(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x8..0xC])
    }

    fn extstart(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0xC..0x10])
    }

    fn endmem(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x10..0x14])
    }

    pub fn stack_size(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x14..0x18])
    }

    pub fn start_func(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x18..0x1C])
    }

    fn decoding_tbl(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x1C..0x20])
    }

    /// The sum of the intial contents of memory, considered as an array
    /// of `u32`s. When calculated, the checksum value is considered to
    /// be `0`.
    fn checksum(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x20..0x24])
    }

    pub fn get_mem_size(&self) -> u32 {
        self.memory.len() as u32
    }

    /// Sets the memory size to the given value. This call only works if
    /// there is no active heap, the given value is a multiple of 0x100,
    /// and the value is greater than the ENDMEM value identified in the
    /// header.
    pub fn set_mem_size(&mut self, value: u32) -> u32 {
        if self.heap_mode
                && value % 0x100 == 0
                && value >= self.endmem() {
            self.memory.resize(value as usize, 0x0);
            0
        } else {
            1
        }
    }
}

pub trait Memory<T> {
    fn read(&self, ptr: u32) -> T;
    fn write(&mut self, ptr: u32, value: T);
    fn ram_read(&self, ptr: u32) -> T;
    fn ram_write(&mut self, ptr: u32, value: T);
}

impl Memory<u8> for GlulxMemory {
    fn read(&self, ptr: u32) -> u8 {
        self.memory[ptr as usize]
    }

    fn write(&mut self, ptr: u32, value: u8) {
        self.memory[ptr as usize] = value
    }

    fn ram_read(&self, ptr: u32) -> u8 {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr]
    }

    fn ram_write(&mut self, ptr: u32, value: u8) {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr] = value
    }
}

impl Memory<i8> for GlulxMemory {
    fn read(&self, ptr: u32) -> i8 {
        self.memory[ptr as usize] as i8
    }

    fn write(&mut self, ptr: u32, value: i8) {
        self.memory[ptr as usize] = value as u8
    }

    fn ram_read(&self, ptr: u32) -> i8 {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr] as i8
    }

    fn ram_write(&mut self, ptr: u32, value: i8) {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr] = value as u8
    }
}

impl Memory<u16> for GlulxMemory {
    fn read(&self, ptr: u32) -> u16 {
        BigEndian::read_u16(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: u16) {
        BigEndian::write_u16(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> u16 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_u16(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: u16) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_u16(&mut self.memory[ptr..], value)
    }
}

impl Memory<i16> for GlulxMemory {
    fn read(&self, ptr: u32) -> i16 {
        BigEndian::read_i16(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: i16) {
        BigEndian::write_i16(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> i16 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_i16(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: i16) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_i16(&mut self.memory[ptr..], value)
    }
}

impl Memory<u32> for GlulxMemory {
    fn read(&self, ptr: u32) -> u32 {
        BigEndian::read_u32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: u32) {
        BigEndian::write_u32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> u32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_u32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: u32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_u32(&mut self.memory[ptr..], value)
    }
}

impl Memory<i32> for GlulxMemory {
    fn read(&self, ptr: u32) -> i32 {
        BigEndian::read_i32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: i32) {
        BigEndian::write_i32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> i32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_i32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: i32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_i32(&mut self.memory[ptr..], value)
    }
}

impl Memory<f32> for GlulxMemory {
    fn read(&self, ptr: u32) -> f32 {
        BigEndian::read_f32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: f32) {
        BigEndian::write_f32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> f32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_f32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: f32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_f32(&mut self.memory[ptr..], value)
    }
}
<|endoftext|>