<commit_before>//! Targets the Nintendo Game Boy Advance (GBA).
//!
//! The GBA is a handheld game device from 2001. Inside, the CPU is an ARM7TDMI.
//! That's in the ARMv4T architecture family.
//!
//! Technically the device has no OS, however we're going to copy the
//! `mipsel_sony_psp` target setup and set the OS string to be "GBA". Other than
//! the setting of the `target_os` and `target_vendor` values, this target is a
//! fairly standard configuration for `thumbv4t`

use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        llvm_target: "thumbv4t-none-eabi".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "gba".to_string(),
        target_env: String::new(),
        target_vendor: "nintendo".to_string(),
        arch: "arm".to_string(),
        data_layout: "TODO".to_string(),
        linker_flavor: LinkerFlavor::Ld,
        options: TargetOptions {
            // TODO
            ..TargetOptions::default()
        },
    })
}
<commit_msg>fill in all those options.<commit_after>//! Targets the Nintendo Game Boy Advance (GBA), a handheld game device from 2001.
//!
//! Please ping @Lokathor if changes are needed.
//!
//! Important: This target **does not** specify a linker script or the ROM
//! header. You'll still need to provide these yourself to construct a final
//! binary. Generally you'd do this with something like
//! `-Clink-arg=-Tmy_script.ld` and `-Clink-arg=my_crt.o`.

use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        llvm_target: "thumbv4t-none-eabi".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "none".to_string(),
        target_env: "gba".to_string(),
        target_vendor: "nintendo".to_string(),
        arch: "arm".to_string(),
        /* Data layout args are '-' separated:
         * little endian
         * stack is 64-bit aligned (EABI)
         * pointers are 32-bit
         * i64 must be 64-bit aligned (EABI)
         * mangle names with ELF style
         * native integers are 32-bit
         * All other elements are default
         */
        data_layout: "e-S64-p:32:32-i64:64-m:e-n32".to_string(),
        linker_flavor: LinkerFlavor::Ld,
        options: TargetOptions {
            linker: Some("arm-none-eabi-ld".to_string()),
            linker_is_gnu: true,

            // extra args passed to the external assembler
            asm_args: vec!["-mcpu=arm7tdmi".to_string(), "-mthumb-interwork".to_string()],

            cpu: "arm7tdmi".to_string(),

            // minimum extra features, these cannot be disabled via -C
            features: "+soft-float,+strict-align".to_string(),

            executables: true,

            relocation_model: RelocModel::Static,

            //function_sections: bool,
            //exe_suffix: String,
            main_needs_argc_argv: false,

            // if we have thread-local storage
            has_elf_tls: false,

            // don't have atomic compare-and-swap
            atomic_cas: false,

            // always just abort
            panic_strategy: PanicStrategy::Abort,

            // ABIs to not use
            unsupported_abis: super::arm_base::unsupported_abis(),

            // The minimum alignment for global symbols.
            min_global_align: Some(4),

            // no threads here
            singlethread: true,

            // GBA has no builtins
            no_builtins: true,

            // this is off just like in the `thumb_base`
            emit_debug_gdb_scripts: false,

            ..TargetOptions::default()
        },
    })
}
<|endoftext|>


<commit_before>//! pseudo authenticator for use with plain access tokens
use crate::error::Error;
use crate::types::TokenInfo;
use hyper::client::connect::Connection;
// use hyper::header;
use http::Uri;
// use serde::{Deserialize, Serialize};
use std::error::Error as StdError;
use tokio::io::{AsyncRead, AsyncWrite};
use tower_service::Service;
// use url::form_urlencoded;

/// the flow for the access token authenticator
pub struct AccessTokenFlow {
    pub(crate) access_token: String,
}

impl AccessTokenFlow {
    /// just return the access token
    pub(crate) async fn token<S, T>(
        &self,
        _hyper_client: &hyper::Client<S>,
        _scopes: &[T],
    ) -> Result<TokenInfo, Error>
    where
        T: AsRef<str>,
        S: Service<Uri> + Clone + Send + Sync + 'static,
        S::Response: Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
        S::Future: Send + Unpin + 'static,
        S::Error: Into<Box<dyn StdError + Send + Sync>>,
    {
        Ok(TokenInfo {
            access_token: self.access_token.clone(),
            refresh_token: None,
            expires_at: None,
            id_token: None,
        })
    }
}
<commit_msg>removed commented imports and added a better description<commit_after>//! pseudo authenticator for use with plain access tokens.
//! If you use a specialized service to manage your
//! OAuth2-tokens you may get just the fresh generated
//! access token from your service.
//! The intention behind this is that if two services using the
//! same refresh token then each service will invalitate the
//! access token of the other service by generating a new token.
use crate::error::Error;
use crate::types::TokenInfo;
use hyper::client::connect::Connection;
use http::Uri;
use std::error::Error as StdError;
use tokio::io::{AsyncRead, AsyncWrite};
use tower_service::Service;

/// the flow for the access token authenticator
pub struct AccessTokenFlow {
    pub(crate) access_token: String,
}

impl AccessTokenFlow {
    /// just return the access token
    pub(crate) async fn token<S, T>(
        &self,
        _hyper_client: &hyper::Client<S>,
        _scopes: &[T],
    ) -> Result<TokenInfo, Error>
    where
        T: AsRef<str>,
        S: Service<Uri> + Clone + Send + Sync + 'static,
        S::Response: Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
        S::Future: Send + Unpin + 'static,
        S::Error: Into<Box<dyn StdError + Send + Sync>>,
    {
        Ok(TokenInfo {
            access_token: self.access_token.clone(),
            refresh_token: None,
            expires_at: None,
            id_token: None,
        })
    }
}
<|endoftext|>


<commit_before>use std::ffi::c_void;
use std::pin::Pin;
use std::task::{Context, Poll};

use libc::size_t;
use tokio::io::{AsyncRead, AsyncWrite};

use super::task::hyper_context;

/// Sentinal value to return from a read or write callback that the operation
/// is pending.
pub const HYPER_IO_PENDING: size_t = 0xFFFFFFFF;
/// Sentinal value to return from a read or write callback that the operation
/// has errored.
pub const HYPER_IO_ERROR: size_t = 0xFFFFFFFE;

type hyper_io_read_callback =
    extern "C" fn(*mut c_void, *mut hyper_context<'_>, *mut u8, size_t) -> size_t;
type hyper_io_write_callback =
    extern "C" fn(*mut c_void, *mut hyper_context<'_>, *const u8, size_t) -> size_t;

/// An IO object used to represent a socket or similar concept.
pub struct hyper_io {
    read: hyper_io_read_callback,
    write: hyper_io_write_callback,
    userdata: *mut c_void,
}

ffi_fn! {
    /// Create a new IO type used to represent a transport.
    ///
    /// The read and write functions of this transport should be set with
    /// `hyper_io_set_read` and `hyper_io_set_write`.
    fn hyper_io_new() -> *mut hyper_io {
        Box::into_raw(Box::new(hyper_io {
            read: read_noop,
            write: write_noop,
            userdata: std::ptr::null_mut(),
        }))
    } ?= std::ptr::null_mut()
}

ffi_fn! {
    /// Free an unused `hyper_io *`.
    ///
    /// This is typically only useful if you aren't going to pass ownership
    /// of the IO handle to hyper, such as with `hyper_clientconn_handshake()`.
    fn hyper_io_free(io: *mut hyper_io) {
        drop(unsafe { Box::from_raw(io) });
    }
}

ffi_fn! {
    /// Set the user data pointer for this IO to some value.
    ///
    /// This value is passed as an argument to the read and write callbacks.
    fn hyper_io_set_userdata(io: *mut hyper_io, data: *mut c_void) {
        unsafe { &mut *io }.userdata = data;
    }
}

ffi_fn! {
    /// Set the read function for this IO transport.
    ///
    /// Data that is read from the transport should be put in the `buf` pointer,
    /// up to `buf_len` bytes. The number of bytes read should be the return value.
    ///
    /// It is undefined behavior to try to access the bytes in the `buf` pointer,
    /// unless you have already written them yourself. It is also undefined behavior
    /// to return that more bytes have been written than actually set on the `buf`.
    ///
    /// If there is no data currently available, a waker should be claimed from
    /// the `ctx` and registered with whatever polling mechanism is used to signal
    /// when data is available later on. The return value should be
    /// `HYPER_IO_PENDING`.
    ///
    /// If there is an irrecoverable error reading data, then `HYPER_IO_ERROR`
    /// should be the return value.
    fn hyper_io_set_read(io: *mut hyper_io, func: hyper_io_read_callback) {
        unsafe { &mut *io }.read = func;
    }
}

ffi_fn! {
    /// Set the write function for this IO transport.
    ///
    /// Data from the `buf` pointer should be written to the transport, up to
    /// `buf_len` bytes. The number of bytes written should be the return value.
    ///
    /// If no data can currently be written, the `waker` should be cloned and
    /// registered with whatever polling mechanism is used to signal when data
    /// is available later on. The return value should be `HYPER_IO_PENDING`.
    ///
    /// Yeet.
    ///
    /// If there is an irrecoverable error reading data, then `HYPER_IO_ERROR`
    /// should be the return value.
    fn hyper_io_set_write(io: *mut hyper_io, func: hyper_io_write_callback) {
        unsafe { &mut *io }.write = func;
    }
}

/// cbindgen:ignore
extern "C" fn read_noop(
    _userdata: *mut c_void,
    _: *mut hyper_context<'_>,
    _buf: *mut u8,
    _buf_len: size_t,
) -> size_t {
    0
}

/// cbindgen:ignore
extern "C" fn write_noop(
    _userdata: *mut c_void,
    _: *mut hyper_context<'_>,
    _buf: *const u8,
    _buf_len: size_t,
) -> size_t {
    0
}

impl AsyncRead for hyper_io {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut tokio::io::ReadBuf<'_>,
    ) -> Poll<std::io::Result<()>> {
        let buf_ptr = unsafe { buf.unfilled_mut() }.as_mut_ptr() as *mut u8;
        let buf_len = buf.remaining();

        match (self.read)(self.userdata, hyper_context::wrap(cx), buf_ptr, buf_len) {
            HYPER_IO_PENDING => Poll::Pending,
            HYPER_IO_ERROR => Poll::Ready(Err(std::io::Error::new(
                std::io::ErrorKind::Other,
                "io error",
            ))),
            ok => {
                // We have to trust that the user's read callback actually
                // filled in that many bytes... :(
                unsafe { buf.assume_init(ok) };
                buf.advance(ok);
                Poll::Ready(Ok(()))
            }
        }
    }
}

impl AsyncWrite for hyper_io {
    fn poll_write(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<std::io::Result<usize>> {
        let buf_ptr = buf.as_ptr();
        let buf_len = buf.len();

        match (self.write)(self.userdata, hyper_context::wrap(cx), buf_ptr, buf_len) {
            HYPER_IO_PENDING => Poll::Pending,
            HYPER_IO_ERROR => Poll::Ready(Err(std::io::Error::new(
                std::io::ErrorKind::Other,
                "io error",
            ))),
            ok => Poll::Ready(Ok(ok)),
        }
    }

    fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<std::io::Result<()>> {
        Poll::Ready(Ok(()))
    }

    fn poll_shutdown(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<std::io::Result<()>> {
        Poll::Ready(Ok(()))
    }
}

unsafe impl Send for hyper_io {}
unsafe impl Sync for hyper_io {}
<commit_msg>docs(ffi): spelling error (#2489)<commit_after>use std::ffi::c_void;
use std::pin::Pin;
use std::task::{Context, Poll};

use libc::size_t;
use tokio::io::{AsyncRead, AsyncWrite};

use super::task::hyper_context;

/// Sentinel value to return from a read or write callback that the operation
/// is pending.
pub const HYPER_IO_PENDING: size_t = 0xFFFFFFFF;
/// Sentinel value to return from a read or write callback that the operation
/// has errored.
pub const HYPER_IO_ERROR: size_t = 0xFFFFFFFE;

type hyper_io_read_callback =
    extern "C" fn(*mut c_void, *mut hyper_context<'_>, *mut u8, size_t) -> size_t;
type hyper_io_write_callback =
    extern "C" fn(*mut c_void, *mut hyper_context<'_>, *const u8, size_t) -> size_t;

/// An IO object used to represent a socket or similar concept.
pub struct hyper_io {
    read: hyper_io_read_callback,
    write: hyper_io_write_callback,
    userdata: *mut c_void,
}

ffi_fn! {
    /// Create a new IO type used to represent a transport.
    ///
    /// The read and write functions of this transport should be set with
    /// `hyper_io_set_read` and `hyper_io_set_write`.
    fn hyper_io_new() -> *mut hyper_io {
        Box::into_raw(Box::new(hyper_io {
            read: read_noop,
            write: write_noop,
            userdata: std::ptr::null_mut(),
        }))
    } ?= std::ptr::null_mut()
}

ffi_fn! {
    /// Free an unused `hyper_io *`.
    ///
    /// This is typically only useful if you aren't going to pass ownership
    /// of the IO handle to hyper, such as with `hyper_clientconn_handshake()`.
    fn hyper_io_free(io: *mut hyper_io) {
        drop(unsafe { Box::from_raw(io) });
    }
}

ffi_fn! {
    /// Set the user data pointer for this IO to some value.
    ///
    /// This value is passed as an argument to the read and write callbacks.
    fn hyper_io_set_userdata(io: *mut hyper_io, data: *mut c_void) {
        unsafe { &mut *io }.userdata = data;
    }
}

ffi_fn! {
    /// Set the read function for this IO transport.
    ///
    /// Data that is read from the transport should be put in the `buf` pointer,
    /// up to `buf_len` bytes. The number of bytes read should be the return value.
    ///
    /// It is undefined behavior to try to access the bytes in the `buf` pointer,
    /// unless you have already written them yourself. It is also undefined behavior
    /// to return that more bytes have been written than actually set on the `buf`.
    ///
    /// If there is no data currently available, a waker should be claimed from
    /// the `ctx` and registered with whatever polling mechanism is used to signal
    /// when data is available later on. The return value should be
    /// `HYPER_IO_PENDING`.
    ///
    /// If there is an irrecoverable error reading data, then `HYPER_IO_ERROR`
    /// should be the return value.
    fn hyper_io_set_read(io: *mut hyper_io, func: hyper_io_read_callback) {
        unsafe { &mut *io }.read = func;
    }
}

ffi_fn! {
    /// Set the write function for this IO transport.
    ///
    /// Data from the `buf` pointer should be written to the transport, up to
    /// `buf_len` bytes. The number of bytes written should be the return value.
    ///
    /// If no data can currently be written, the `waker` should be cloned and
    /// registered with whatever polling mechanism is used to signal when data
    /// is available later on. The return value should be `HYPER_IO_PENDING`.
    ///
    /// Yeet.
    ///
    /// If there is an irrecoverable error reading data, then `HYPER_IO_ERROR`
    /// should be the return value.
    fn hyper_io_set_write(io: *mut hyper_io, func: hyper_io_write_callback) {
        unsafe { &mut *io }.write = func;
    }
}

/// cbindgen:ignore
extern "C" fn read_noop(
    _userdata: *mut c_void,
    _: *mut hyper_context<'_>,
    _buf: *mut u8,
    _buf_len: size_t,
) -> size_t {
    0
}

/// cbindgen:ignore
extern "C" fn write_noop(
    _userdata: *mut c_void,
    _: *mut hyper_context<'_>,
    _buf: *const u8,
    _buf_len: size_t,
) -> size_t {
    0
}

impl AsyncRead for hyper_io {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut tokio::io::ReadBuf<'_>,
    ) -> Poll<std::io::Result<()>> {
        let buf_ptr = unsafe { buf.unfilled_mut() }.as_mut_ptr() as *mut u8;
        let buf_len = buf.remaining();

        match (self.read)(self.userdata, hyper_context::wrap(cx), buf_ptr, buf_len) {
            HYPER_IO_PENDING => Poll::Pending,
            HYPER_IO_ERROR => Poll::Ready(Err(std::io::Error::new(
                std::io::ErrorKind::Other,
                "io error",
            ))),
            ok => {
                // We have to trust that the user's read callback actually
                // filled in that many bytes... :(
                unsafe { buf.assume_init(ok) };
                buf.advance(ok);
                Poll::Ready(Ok(()))
            }
        }
    }
}

impl AsyncWrite for hyper_io {
    fn poll_write(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<std::io::Result<usize>> {
        let buf_ptr = buf.as_ptr();
        let buf_len = buf.len();

        match (self.write)(self.userdata, hyper_context::wrap(cx), buf_ptr, buf_len) {
            HYPER_IO_PENDING => Poll::Pending,
            HYPER_IO_ERROR => Poll::Ready(Err(std::io::Error::new(
                std::io::ErrorKind::Other,
                "io error",
            ))),
            ok => Poll::Ready(Ok(ok)),
        }
    }

    fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<std::io::Result<()>> {
        Poll::Ready(Ok(()))
    }

    fn poll_shutdown(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<std::io::Result<()>> {
        Poll::Ready(Ok(()))
    }
}

unsafe impl Send for hyper_io {}
unsafe impl Sync for hyper_io {}
<|endoftext|>


<commit_before>#![doc="Sorting algorithms
"]

pub mod quick_sort;
pub mod insertion_sort;

/// Returns whether the slice is sorted in ascending order or not.
pub fn is_ascending_slice<T : PartialOrd>(data : & [T]) -> bool {
    let n = data.len();
    if n == 0 {
        return true;
    }
    for i in range(0, n-1){
        if data[i] > data[i + 1]{
            return false;
        }
    }
    true
}

/// Returns whether the slice is sorted in descending order or not.
pub fn is_descending_slice<T : PartialOrd>(data : & [T]) -> bool {
    let n = data.len();
    if n == 0 {
        return true;
    }
    for i in range(0, n-1){
        if data[i] < data[i + 1]{
            return false;
        }
    }
    true
}

/// Returns whether the data in buffer is sorted in ascending order or not.
pub fn is_ascending_buffer<T : PartialOrd>(data : *const T, n : uint) -> bool {
    if n == 0 {
        return true;
    }
    let mut ptr = data;
    for _ in range(0, n-1){
        unsafe {
            if *ptr > *ptr.offset(1i){
                return false;
            }
            ptr = ptr.offset(1i);
        }
    }
    true
}

/// Returns whether the data in buffer is sorted in descending order or not.
pub fn is_descending_buffer<T : PartialOrd>(data : *const T, n : uint) -> bool {
    if n == 0 {
        return true;
    }
    let mut ptr = data;
    for _ in range(0, n-1){
        unsafe {
            if *ptr < *ptr.offset(1i){
                return false;
            }
            ptr = ptr.offset(1i);
        }
    }
    true
}

/******************************************************
 *
 *   Unit tests
 *
 *******************************************************/

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

    #[test]
    fn test_is_ascending_slice(){
        let v = vec!(1i, 2, 3, 4);
        assert!(is_ascending_slice(v.as_slice()));
        let v = vec!(1i);
        assert!(is_ascending_slice(v.as_slice()));
        let v : Vec<int> = vec!();
        assert!(is_ascending_slice(v.as_slice()));
        let v = vec!(2i, 1);
        assert!(!is_ascending_slice(v.as_slice()));
        let v = vec!(3i, 2, 1);
        assert!(!is_ascending_slice(v.as_slice()));
        let v = vec!(1i, 3, 2);
        assert!(!is_ascending_slice(v.as_slice()));
        let v = vec!(2i, 1, 3);
        assert!(!is_ascending_slice(v.as_slice()));
    }

    #[test]
    fn test_is_ascending_buffer(){
        let v = vec!(1i, 2, 3, 4);
        assert!(is_ascending_buffer(v.as_ptr(), v.len()));
        let v = vec!(1i);
        assert!(is_ascending_buffer(v.as_ptr(), v.len()));
        let v : Vec<int> = vec!();
        assert!(is_ascending_buffer(v.as_ptr(), v.len()));
        let v = vec!(2i, 1);
        assert!(!is_ascending_buffer(v.as_ptr(), v.len()));
        let v = vec!(3i, 2, 1);
        assert!(!is_ascending_buffer(v.as_ptr(), v.len()));
        let v = vec!(1i, 3, 2);
        assert!(!is_ascending_buffer(v.as_ptr(), v.len()));
        let v = vec!(2i, 1, 3);
        assert!(!is_ascending_buffer(v.as_ptr(), v.len()));
    }

    #[test]
    fn test_is_descending_slice(){
        let v = vec!(4i, 3, 2, 1);
        assert!(is_descending_slice(v.as_slice()));
        let v = vec!(1i);
        assert!(is_descending_slice(v.as_slice()));
        let v : Vec<int> = vec!();
        assert!(is_descending_slice(v.as_slice()));
        let v = vec!(1i, 2);
        assert!(!is_descending_slice(v.as_slice()));
        let v = vec!(1i, 2, 3);
        assert!(!is_descending_slice(v.as_slice()));
        let v = vec!(2i, 3, 1);
        assert!(!is_descending_slice(v.as_slice()));
        let v = vec!(3i, 1, 2);
        assert!(!is_descending_slice(v.as_slice()));
    }

    #[test]
    fn test_is_descending_buffer(){
        let v = vec!(4i, 3, 2, 1);
        assert!(is_descending_buffer(v.as_ptr(), v.len()));
        let v = vec!(1i);
        assert!(is_descending_buffer(v.as_ptr(), v.len()));
        let v : Vec<int> = vec!();
        assert!(is_descending_buffer(v.as_ptr(), v.len()));
        let v = vec!(1i, 2);
        assert!(!is_descending_buffer(v.as_ptr(), v.len()));
        let v = vec!(1i, 2, 3);
        assert!(!is_descending_buffer(v.as_ptr(), v.len()));
        let v = vec!(2i, 3, 1);
        assert!(!is_descending_buffer(v.as_ptr(), v.len()));
        let v = vec!(3i, 1, 2);
        assert!(!is_descending_buffer(v.as_ptr(), v.len()));
    }

}

/******************************************************
 *
 *   Bench marks
 *
 *******************************************************/

#[cfg(test)]
mod bench{
    extern crate test;
    use self::test::Bencher;
    use super::*;
    #[bench]
    fn bench_is_ascending_slice(b: &mut Bencher){
        let v = Vec::from_fn(10000, |idx| idx * 2);
        b.iter(|| {
            assert!(is_ascending_slice(v.as_slice()));
                });
    }
    #[bench]
    fn bench_is_ascending_buffer(b: &mut Bencher){
        let v = Vec::from_fn(10000, |idx| idx * 2);
        b.iter(|| {
            assert!(is_ascending_buffer(v.as_ptr(), v.len()));
                });
    }
    #[bench]
    fn bench_is_descending_slice(b: &mut Bencher){
        let v = Vec::from_fn(10000, |idx| -(idx as int) * 2i);
        b.iter(|| {
            assert!(is_descending_slice(v.as_slice()));
                });
    }
    #[bench]
    fn bench_is_descending_buffer(b: &mut Bencher){
        let v = Vec::from_fn(10000, |idx| -(idx as int) * 2i);
        b.iter(|| {
            assert!(is_descending_buffer(v.as_ptr(), v.len()));
                });
    }
}

<commit_msg>introduced asc / desc checks on strided buffers.<commit_after>#![doc="Sorting algorithms
"]

pub mod quick_sort;
pub mod insertion_sort;

/// Returns whether the slice is sorted in ascending order or not.
pub fn is_ascending_slice<T : PartialOrd>(data : & [T]) -> bool {
    let n = data.len();
    if n == 0 {
        return true;
    }
    for i in range(0, n-1){
        if data[i] > data[i + 1]{
            return false;
        }
    }
    true
}

/// Returns whether the slice is sorted in descending order or not.
pub fn is_descending_slice<T : PartialOrd>(data : & [T]) -> bool {
    let n = data.len();
    if n == 0 {
        return true;
    }
    for i in range(0, n-1){
        if data[i] < data[i + 1]{
            return false;
        }
    }
    true
}

/// Returns whether the data in buffer is sorted in ascending order or not.
pub unsafe fn is_ascending_buffer<T : PartialOrd>(data : *const T, n : uint) -> bool {
    if n == 0 {
        return true;
    }
    let mut ptr = data;
    for _ in range(0, n-1){
        if *ptr > *ptr.offset(1i){
            return false;
        }
        ptr = ptr.offset(1i);
    }
    true
}

/// Returns whether the data in buffer is sorted in descending order or not.
pub unsafe fn is_descending_buffer<T : PartialOrd>(data : *const T, n : uint) -> bool {
    if n == 0 {
        return true;
    }
    let mut ptr = data;
    for _ in range(0, n-1){
        if *ptr < *ptr.offset(1i){
            return false;
        }
        ptr = ptr.offset(1i);
    }
    true
}

/// Returns whether the data in strided buffer is sorted in ascending order or not
/// every stride-th entry is considered in the buffer
/// assumes that the buffer as at least n* stride entries
pub unsafe fn is_ascending_buffer_strided<T : PartialOrd>(data : *const T,
    n : uint,
    stride : uint) -> bool {
    if n == 0 {
        return true;
    }
    let mut ptr = data;
    let stride = stride as int;
    for _ in range(0, n-1){
        if *ptr > *ptr.offset(stride){
            return false;
        }
        ptr = ptr.offset(stride);
    }
    true
}

/// Returns whether the data in strided buffer is sorted in ascending order or not
/// every stride-th entry is considered in the buffer
/// assumes that the buffer as at least n* stride entries
pub unsafe fn is_descending_buffer_strided<T : PartialOrd>(data : *const T,
    n : uint,
    stride : uint) -> bool {
    if n == 0 {
        return true;
    }
    let mut ptr = data;
    let stride = stride as int;
    for _ in range(0, n-1){
        if *ptr < *ptr.offset(stride){
            return false;
        }
        ptr = ptr.offset(stride);
    }
    true
}

/******************************************************
 *
 *   Unit tests
 *
 *******************************************************/

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

    #[test]
    fn test_is_ascending_slice(){
        let v = vec!(1i, 2, 3, 4);
        assert!(is_ascending_slice(v.as_slice()));
        let v = vec!(1i);
        assert!(is_ascending_slice(v.as_slice()));
        let v : Vec<int> = vec!();
        assert!(is_ascending_slice(v.as_slice()));
        let v = vec!(2i, 1);
        assert!(!is_ascending_slice(v.as_slice()));
        let v = vec!(3i, 2, 1);
        assert!(!is_ascending_slice(v.as_slice()));
        let v = vec!(1i, 3, 2);
        assert!(!is_ascending_slice(v.as_slice()));
        let v = vec!(2i, 1, 3);
        assert!(!is_ascending_slice(v.as_slice()));
    }

    #[test]
    fn test_is_ascending_buffer(){
        unsafe {
            let v = vec!(1i, 2, 3, 4);
            assert!(is_ascending_buffer(v.as_ptr(), v.len()));
            let v = vec!(1i);
            assert!(is_ascending_buffer(v.as_ptr(), v.len()));
            let v : Vec<int> = vec!();
            assert!(is_ascending_buffer(v.as_ptr(), v.len()));
            let v = vec!(2i, 1);
            assert!(!is_ascending_buffer(v.as_ptr(), v.len()));
            let v = vec!(3i, 2, 1);
            assert!(!is_ascending_buffer(v.as_ptr(), v.len()));
            let v = vec!(1i, 3, 2);
            assert!(!is_ascending_buffer(v.as_ptr(), v.len()));
            let v = vec!(2i, 1, 3);
            assert!(!is_ascending_buffer(v.as_ptr(), v.len()));
        }
    }

    #[test]
    fn test_is_descending_slice(){
        let v = vec!(4i, 3, 2, 1);
        assert!(is_descending_slice(v.as_slice()));
        let v = vec!(1i);
        assert!(is_descending_slice(v.as_slice()));
        let v : Vec<int> = vec!();
        assert!(is_descending_slice(v.as_slice()));
        let v = vec!(1i, 2);
        assert!(!is_descending_slice(v.as_slice()));
        let v = vec!(1i, 2, 3);
        assert!(!is_descending_slice(v.as_slice()));
        let v = vec!(2i, 3, 1);
        assert!(!is_descending_slice(v.as_slice()));
        let v = vec!(3i, 1, 2);
        assert!(!is_descending_slice(v.as_slice()));
    }

    #[test]
    fn test_is_descending_buffer(){
        unsafe {
            let v = vec!(4i, 3, 2, 1);
            assert!(is_descending_buffer(v.as_ptr(), v.len()));
            let v = vec!(1i);
            assert!(is_descending_buffer(v.as_ptr(), v.len()));
            let v : Vec<int> = vec!();
            assert!(is_descending_buffer(v.as_ptr(), v.len()));
            let v = vec!(1i, 2);
            assert!(!is_descending_buffer(v.as_ptr(), v.len()));
            let v = vec!(1i, 2, 3);
            assert!(!is_descending_buffer(v.as_ptr(), v.len()));
            let v = vec!(2i, 3, 1);
            assert!(!is_descending_buffer(v.as_ptr(), v.len()));
            let v = vec!(3i, 1, 2);
            assert!(!is_descending_buffer(v.as_ptr(), v.len()));
        }
    }

    #[test]
    fn test_is_ascending_buffer_strided(){
        unsafe {
            let v = vec!(4i, 3, 2, 1);
            assert!(!is_ascending_buffer_strided(v.as_ptr(), v.len() / 2, 2));
            let v = vec!(4i, 3, 5, 1);
            assert!(is_ascending_buffer_strided(v.as_ptr(), v.len() / 2, 2));
            let v = vec!(4i, 1, 5, 2, 3, 7);
            assert!(!is_ascending_buffer_strided(v.as_ptr(), v.len() / 2, 2));
            let v = vec!(4i, 3, 5, 2, 7, 1);
            assert!(is_ascending_buffer_strided(v.as_ptr(), v.len() / 2, 2));
        }
    }

}

/******************************************************
 *
 *   Bench marks
 *
 *******************************************************/

#[cfg(test)]
mod bench{
    extern crate test;
    use self::test::Bencher;
    use super::*;
    #[bench]
    fn bench_is_ascending_slice(b: &mut Bencher){
        let v = Vec::from_fn(10000, |idx| idx * 2);
        b.iter(|| {
            assert!(is_ascending_slice(v.as_slice()));
                });
    }
    #[bench]
    fn bench_is_ascending_buffer(b: &mut Bencher){
        let v = Vec::from_fn(10000, |idx| idx * 2);
        b.iter(|| unsafe {
            assert!(is_ascending_buffer(v.as_ptr(), v.len()));
                });
    }
    #[bench]
    fn bench_is_descending_slice(b: &mut Bencher){
        let v = Vec::from_fn(10000, |idx| -(idx as int) * 2i);
        b.iter(|| {
            assert!(is_descending_slice(v.as_slice()));
                });
    }
    #[bench]
    fn bench_is_descending_buffer(b: &mut Bencher){
        let v = Vec::from_fn(10000, |idx| -(idx as int) * 2i);
        b.iter(|| unsafe {
            assert!(is_descending_buffer(v.as_ptr(), v.len()));
                });
    }
}

<|endoftext|>


<commit_before>use iron::{Request, Response};
use term::{attr, color};
use http::status::NotFound;

use std::default::Default;
use std::from_str::FromStr;

/// A formatting style for the `Logger`, consisting of multiple
/// `FormatUnit`s concatenated into one line.
#[deriving(Clone)]
pub struct Format(pub Vec<FormatUnit>);

impl Default for Format {
    /// Return the default formatting style for the `Logger`:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response_time})
    /// ```
    ///
    /// The method is in bold, and the response status is colored blue for 100s,
    /// green for 200s, yellow for 300s, and red for 400s and 500s. For now,
    /// this needs to take `req`/`res` as arguments in order to color the status
    /// appropriately.
    fn default() -> Format {
        fn status_color(_req: &Request, res: &Response) -> Option<color::Color> {
            match res.status.as_ref().unwrap_or(&NotFound).code() / 100 {
                1 => Some(color::BLUE), // Information
                2 => Some(color::GREEN), // Success
                3 => Some(color::YELLOW), // Redirection
                4 | 5 => Some(color::RED), // Error
                _ => None
            }
        }

        Format::new("@[bold]{method}@@ {uri} @[bold]->@@ @[C]{status}@@ ({response_time})",
           vec![FunctionColor(status_color)], vec![]).unwrap()
    }
}

impl Format {
    /// Create a `Format` from a format string, which can contain the fields
    /// `{method}`, `{uri}`, `{status}`, and `{response_time}`.
    /// Returns `None` if the format string syntax is incorrect.
    pub fn new(s: &str, mut colors: Vec<FormatColor>,
               mut attrses: Vec<FormatAttrs>) -> Option<Format> {

        // We use these as stacks, but in the wrong direction.
        attrses.reverse();
        colors.reverse();

        // The buffer we will be filling with formatting options.
        let mut result = vec![];

        // String buffers will we use throughout to build relevant Strings.
        let mut string = "".into_string();
        let mut name = "".into_string();

        // Attributes we will set and push into result.
        let mut color = ConstantColor(None);
        let mut attrs = ConstantAttrs(vec![]);

        // The characters of the input string, which we are parsing.
        let mut chars = s.chars();

        loop {
            match chars.next() {
                None => {
                    // No more chars, push our final format unit.
                    result.push(FormatUnit { text: Str(string), color: color, attrs: attrs.clone() });

                    // Done.
                    return Some(Format(result));
                },

                // Parse a thing to print, e.g. {method}, {uri}.
                Some('{') => {
                    result.push(FormatUnit { text: Str(string), color: color, attrs: attrs.clone() });
                    string = "".into_string();

                    loop {
                        match chars.next() {
                            None => return None,

                            Some('}') => {
                                let text = match name.as_slice() {
                                    "method" => Method,
                                    "uri" => URI,
                                    "status" => Status,
                                    "response_time" => ResponseTime,
                                    _ => return None
                                };

                                result.push(FormatUnit { text: text, color: color, attrs: attrs.clone() });
                                name.clear();
                                break;
                            },

                            Some(c) => name.push(c)
                        }
                    }
                },

                // Begin the application of an attribute. The grammar is as follows:
                //
                // `@[attribute]applies to@@`
                //
                // @ begins the attribute, which is then followed by `[attribute]`, which declares
                // what attribute is being applied, then follows the text or {object} that the
                // attribute will be applied to. `@@` then ends the application of the attribute.
                Some('@') => {
                    result.push(FormatUnit { text: Str(string), color: color, attrs: attrs.clone() });
                    string = "".into_string();

                    match chars.next() {
                        // This is actually the end of an attribute application.
                        Some('@') => {
                            color = ConstantColor(None);
                            attrs = ConstantAttrs(vec![]);
                        },

                        // Parse the attribute or style being applied.
                        Some('[') => {
                            loop {
                                match chars.next() {
                                    // Unexpected end of input.
                                    None => { return None; },

                                    // Parse the attribute.
                                    Some(']') => {
                                        for word in name.as_slice().words() {
                                            match word {
                                                "A" => {
                                                    attrs = attrses.pop().unwrap_or(ConstantAttrs(vec![]));
                                                },

                                                "C" => {
                                                    color = colors.pop().unwrap_or(ConstantColor(None));
                                                },

                                                style => match from_str(style) {
                                                    Some(Color(c)) => match color {
                                                        ConstantColor(_) => { color = ConstantColor(Some(c)); },
                                                        _ => {}
                                                    },

                                                    Some(Attr(a)) => match attrs {
                                                        ConstantAttrs(ref mut v) => { v.push(a); },
                                                        _ => {}
                                                    },

                                                    _ => {}
                                                }
                                            }
                                        }

                                        name.clear();
                                        break;
                                    },

                                    Some(c) => { name.push(c); }
                                }
                            }
                        }
                        // Unexpected non `@` or `[` after `@`
                        _ => return None,
                    }
                },

                Some(c) => { string.push(c); }
            }
        }
    }
}

impl FromStr for ColorOrAttr {
    fn from_str(name: &str) -> Option<ColorOrAttr> {
        match name {
            "black" => Some(Color(color::BLACK)),
            "blue" => Some(Color(color::BLUE)),
            "brightblack" => Some(Color(color::BRIGHT_BLACK)),
            "brightblue" => Some(Color(color::BRIGHT_BLUE)),
            "brightcyan" => Some(Color(color::BRIGHT_CYAN)),
            "brightgreen" => Some(Color(color::BRIGHT_GREEN)),
            "brightmagenta" => Some(Color(color::BRIGHT_MAGENTA)),
            "brightred" => Some(Color(color::BRIGHT_RED)),
            "brightwhite" => Some(Color(color::BRIGHT_WHITE)),
            "brightyellow" => Some(Color(color::BRIGHT_YELLOW)),
            "cyan" => Some(Color(color::CYAN)),
            "green" => Some(Color(color::GREEN)),
            "magenta" => Some(Color(color::MAGENTA)),
            "red" => Some(Color(color::RED)),
            "white" => Some(Color(color::WHITE)),
            "yellow" => Some(Color(color::YELLOW)),

            "bold" => Some(Attr(attr::Bold)),
            "dim" => Some(Attr(attr::Dim)),
            "italic" => Some(Attr(attr::Italic(true))),
            "underline" => Some(Attr(attr::Underline(true))),
            "blink" => Some(Attr(attr::Blink)),
            "standout" => Some(Attr(attr::Standout(true))),
            "reverse" => Some(Attr(attr::Reverse)),
            "secure" => Some(Attr(attr::Secure)),

            _ => None
        }
    }
}

enum ColorOrAttr {
    Color(color::Color),
    Attr(attr::Attr)
}

/// A representation of color in a `FormatUnit`.
pub enum FormatColor {
    ConstantColor(Option<color::Color>),
    FunctionColor(fn(&Request, &Response) -> Option<color::Color>)
}

/// A representation of attributes in a `FormatUnit`.
pub enum FormatAttrs {
    ConstantAttrs(Vec<attr::Attr>),
    FunctionAttrs(fn(&Request, &Response) -> Vec<attr::Attr>)
}

impl Clone for FormatColor {
    fn clone(&self) -> FormatColor { *self }
}

impl Clone for FormatAttrs {
    fn clone(&self) -> FormatAttrs {
        match *self {
            ConstantAttrs(ref attrs) => ConstantAttrs(attrs.iter().map(|&attr| attr).collect()),
            FunctionAttrs(f) => FunctionAttrs(f)
        }
    }
}

/// A string of text to be logged. This is either one of the data
/// fields supported by the `Logger`, or a custom `&str`.
#[deriving(Clone)]
pub enum FormatText {
    Str(String),
    Method,
    URI,
    Status,
    ResponseTime
}

/// A `FormatText` with associated style information.
#[deriving(Clone)]
pub struct FormatUnit {
    pub text: FormatText,
    pub color: FormatColor,
    pub attrs: FormatAttrs
}

<commit_msg>(refactor) Change the grammar for custom format strings and simplify the parser.<commit_after>use iron::{Request, Response};
use term::{attr, color};
use http::status::NotFound;

use std::default::Default;
use std::from_str::FromStr;
use std::str::Chars;
use std::vec::MoveItems;
use std::iter::Peekable;

/// A formatting style for the `Logger`, consisting of multiple
/// `FormatUnit`s concatenated into one line.
#[deriving(Clone)]
pub struct Format(pub Vec<FormatUnit>);

impl Default for Format {
    /// Return the default formatting style for the `Logger`:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response_time})
    /// ```
    ///
    /// The method is in bold, and the response status is colored blue for 100s,
    /// green for 200s, yellow for 300s, and red for 400s and 500s. For now,
    /// this needs to take `req`/`res` as arguments in order to color the status
    /// appropriately.
    fn default() -> Format {
        fn status_color(_req: &Request, res: &Response) -> Option<color::Color> {
            match res.status.as_ref().unwrap_or(&NotFound).code() / 100 {
                1 => Some(color::BLUE), // Information
                2 => Some(color::GREEN), // Success
                3 => Some(color::YELLOW), // Redirection
                4 | 5 => Some(color::RED), // Error
                _ => None
            }
        }

        Format::new("@[bold]{method}@ {uri} @[bold]->@ @[C]{status}@ ({response-time})",
           vec![FunctionColor(status_color)], vec![]).unwrap()
    }
}

impl Format {
    /// Create a `Format` from a format string, which can contain the fields
    /// `{method}`, `{uri}`, `{status}`, and `{response_time}`.
    /// Returns `None` if the format string syntax is incorrect.
    pub fn new(s: &str, mut colors: Vec<FormatColor>,
               mut attrses: Vec<FormatAttrs>) -> Option<Format> {

        // We use these as stacks, but in the wrong direction.
        attrses.reverse();
        colors.reverse();

        let mut parser = FormatParser::new(s.chars().peekable(), colors.into_iter(), attrses.into_iter());

        let mut results = Vec::new();

        for unit in parser {
            match unit {
                Some(unit) => results.push(unit),
                None => return None
            }
        }

        Some(Format(results))
    }
}

struct FormatParser<'a> {
    // The characters of the format string.
    chars: Peekable<char, Chars<'a>>,

    // Passed-in FormatColors
    colors: MoveItems<FormatColor>,

    // Passed-in FormatAttrs
    attrs: MoveItems<FormatAttrs>,

    // A reusable buffer for parsing style attributes.
    object_buffer: String,

    // Are we done?
    finished: bool,

    // A queue of waiting format units to avoid full-on
    // state-machine parsing.
    waitqueue: Vec<FormatUnit>
}

impl<'a> FormatParser<'a> {
    fn new(chars: Peekable<char, Chars>, colors: MoveItems<FormatColor>, attrs: MoveItems<FormatAttrs>) -> FormatParser {
        FormatParser {
            chars: chars,
            colors: colors,
            attrs: attrs,

            // No attributes are longer than 14 characters, so we can
            // avoid reallocating.
            object_buffer: String::with_capacity(14),

            finished: false,
            waitqueue: vec![]
        }
    }
}

// Some(None) means there was a parse error and this FormatParser
// should be abandoned.
impl<'a> Iterator<Option<FormatUnit>> for FormatParser<'a> {
    fn next(&mut self) -> Option<Option<FormatUnit>> {
        // If the parser has been cancelled or errored for some reason.
        if self.finished { return None }

        if self.waitqueue.len() != 0 {
            return Some(self.waitqueue.remove(0));
        }

        // Try to parse a new FormatUnit.
        match self.chars.next() {
            // Parse a recognized object.
            //
            // The allowed forms are:
            //   - {method}
            //   - {uri}
            //   - {status}
            //   - {response-time}
            Some('{') => {
                self.object_buffer.clear();

                loop {
                    match self.chars.next() {
                        // Finished parsing, parse buffer.
                        Some('}') => break,

                        Some(c) => self.object_buffer.push(c),

                        None => break
                    }
                }

                let text = match self.object_buffer.as_slice() {
                    "method" => Method,
                    "uri" => URI,
                    "status" => Status,
                    "response-time" => ResponseTime,
                    _ => {
                        // Error, so mark as finished.
                        self.finished = true;
                        return Some(None);
                    }
                };

                Some(Some(FormatUnit {
                    text: text,
                    color: ConstantColor(None),
                    attrs: ConstantAttrs(vec![])
                }))
            },

            // Parse an attribute and the thing it applies to.
            //
            // The form is:
            //   - @[attributes]target@
            Some('@') => {
                match self.chars.next() {
                    // Parse attributes
                    Some('[') => {
                        let mut buffer = String::new();

                        loop {
                            match self.chars.next() {
                                // Finished parsing into buffer.
                                Some(']') => break,

                                // Push into buffer.
                                Some(c) => buffer.push(c),

                                None => {
                                    // Error, so mark as finished.
                                    self.finished = true;
                                    return Some(None);
                                }
                            }
                        }

                        let mut attrs = ConstantAttrs(vec![]);
                        let mut color = ConstantColor(None);

                        // Collect the attributes into attrs and color, for use as properties
                        // of a FormatUnit.
                        for word in buffer.as_slice().words() {
                            match word {
                                "A" => attrs = self.attrs.next().unwrap_or(ConstantAttrs(vec![])),

                                "C" => color = self.colors.next().unwrap_or(ConstantColor(None)),

                                style => match from_str(style) {
                                    Some(Color(c)) => match color {
                                        ConstantColor(_) => { color = ConstantColor(Some(c)); },
                                        _ => {}
                                    },

                                    Some(Attr(a)) => match attrs {
                                        ConstantAttrs(ref mut v) => { v.push(a); },
                                        _ => {}
                                    },

                                    _ => {}
                                }
                            }
                        }

                        // Nested attributes are not supported.
                        if self.chars.peek() == Some(&'@') {
                            self.finished = true;
                            return Some(None);
                        }

                        // Now we have the parsed attributes, so we can parse what they apply to.
                        let mut apply_to = vec![];

                        loop {
                            match self.next() {
                                Some(Some(unit)) => apply_to.push(unit),
                                _ => {
                                    self.finished = true;
                                    return Some(None);
                                }
                            };

                            if self.chars.peek() == Some(&'@') {
                                // Jump over the closing '@'
                                self.chars.next();
                                break;
                            }
                        }

                        self.waitqueue.extend(apply_to.into_iter().map(|unit| {
                            FormatUnit {
                                text: unit.text,
                                color: color.clone(),
                                attrs: attrs.clone()
                            }
                        }));

                        self.next()
                    },

                    _ => {
                        // Error, so mark as finished.
                        self.finished = true;
                        return Some(None);
                    }
                }
            },

            // Parse a regular string part of the format string.
            Some(c) => {
                let mut buffer = String::new();
                buffer.push(c);

                loop {
                    match self.chars.peek() {
                        // Done parsing.
                        Some(&'@') | Some(&'{') | None => {
                            return Some(Some(FormatUnit {
                                text: Str(buffer),
                                color: ConstantColor(None),
                                attrs: ConstantAttrs(vec![])
                            }))
                        },

                        Some(_) => {
                            buffer.push(self.chars.next().unwrap())
                        }
                    }
                }
            },

            // Reached end of the format string.
            None => None
        }
    }
}

impl FromStr for ColorOrAttr {
    fn from_str(name: &str) -> Option<ColorOrAttr> {
        match name {
            "black" => Some(Color(color::BLACK)),
            "blue" => Some(Color(color::BLUE)),
            "brightblack" => Some(Color(color::BRIGHT_BLACK)),
            "brightblue" => Some(Color(color::BRIGHT_BLUE)),
            "brightcyan" => Some(Color(color::BRIGHT_CYAN)),
            "brightgreen" => Some(Color(color::BRIGHT_GREEN)),
            "brightmagenta" => Some(Color(color::BRIGHT_MAGENTA)),
            "brightred" => Some(Color(color::BRIGHT_RED)),
            "brightwhite" => Some(Color(color::BRIGHT_WHITE)),
            "brightyellow" => Some(Color(color::BRIGHT_YELLOW)),
            "cyan" => Some(Color(color::CYAN)),
            "green" => Some(Color(color::GREEN)),
            "magenta" => Some(Color(color::MAGENTA)),
            "red" => Some(Color(color::RED)),
            "white" => Some(Color(color::WHITE)),
            "yellow" => Some(Color(color::YELLOW)),

            "bold" => Some(Attr(attr::Bold)),
            "dim" => Some(Attr(attr::Dim)),
            "italic" => Some(Attr(attr::Italic(true))),
            "underline" => Some(Attr(attr::Underline(true))),
            "blink" => Some(Attr(attr::Blink)),
            "standout" => Some(Attr(attr::Standout(true))),
            "reverse" => Some(Attr(attr::Reverse)),
            "secure" => Some(Attr(attr::Secure)),

            _ => None
        }
    }
}

enum ColorOrAttr {
    Color(color::Color),
    Attr(attr::Attr)
}

/// A representation of color in a `FormatUnit`.
pub enum FormatColor {
    ConstantColor(Option<color::Color>),
    FunctionColor(fn(&Request, &Response) -> Option<color::Color>)
}

/// A representation of attributes in a `FormatUnit`.
pub enum FormatAttrs {
    ConstantAttrs(Vec<attr::Attr>),
    FunctionAttrs(fn(&Request, &Response) -> Vec<attr::Attr>)
}

impl Clone for FormatColor {
    fn clone(&self) -> FormatColor { *self }
}

impl Clone for FormatAttrs {
    fn clone(&self) -> FormatAttrs {
        match *self {
            ConstantAttrs(ref attrs) => ConstantAttrs(attrs.iter().map(|&attr| attr).collect()),
            FunctionAttrs(f) => FunctionAttrs(f)
        }
    }
}

/// A string of text to be logged. This is either one of the data
/// fields supported by the `Logger`, or a custom `&str`.
#[deriving(Clone)]
pub enum FormatText {
    Str(String),
    Method,
    URI,
    Status,
    ResponseTime
}

/// A `FormatText` with associated style information.
#[deriving(Clone)]
pub struct FormatUnit {
    pub text: FormatText,
    pub color: FormatColor,
    pub attrs: FormatAttrs
}

<|endoftext|>


<commit_before>// Copyright 2013 The rust-gobject authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[link(name = "gi", vers = "0.1")];
#[crate_type = "lib"];

extern mod glib;
extern mod gobject;

use std::ptr;

mod detail;

pub struct Repository {
    priv ptr: *detail::GIRepository,
    priv owns: bool
}

impl Repository {
    fn default() -> Repository {
        Repository {
            ptr: detail::g_irepository_get_default() as *detail::GIRepository,
            owns: false
        }
    }
}

impl Drop for Repository {
    fn drop(&mut self) {
        if self.owns {
            gobject::detail::g_object_unref(self.ptr as *mut detail::GIRepository as glib::gpointer);
        }
        self.ptr = ptr::null();
    }
}
<commit_msg>Make Repository::default() public<commit_after>// Copyright 2013 The rust-gobject authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[link(name = "gi", vers = "0.1")];
#[crate_type = "lib"];

extern mod glib;
extern mod gobject;

use std::ptr;

mod detail;

pub struct Repository {
    priv ptr: *detail::GIRepository,
    priv owns: bool
}

impl Repository {
    pub fn default() -> Repository {
        Repository {
            ptr: detail::g_irepository_get_default() as *detail::GIRepository,
            owns: false
        }
    }
}

impl Drop for Repository {
    fn drop(&mut self) {
        if self.owns {
            gobject::detail::g_object_unref(self.ptr as *mut detail::GIRepository as glib::gpointer);
        }
        self.ptr = ptr::null();
    }
}
<|endoftext|>


<commit_before>/// Asserts that the trait is a child of all of the other traits.
///
/// Related:
/// - [`assert_trait_super_all!`]
///
/// # Examples
///
/// All types that implement [`Copy`] must implement [`Clone`]:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_trait_sub_all!(Copy: Clone);
/// ```
///
/// All types that implement [`Ord`] must implement [`PartialEq`], [`Eq`], and
/// [`PartialOrd`]:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_trait_sub_all!(Ord: PartialEq, Eq, PartialOrd);
/// ```
///
/// The following example fails to compile because [`Eq`] is not required for
/// [`PartialOrd`]:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_trait_sub_all!(PartialOrd: Eq);
/// ```
///
/// [`assert_trait_super_all!`]: macro.assert_trait_super_all.html
///
/// [`Copy`]:       https://doc.rust-lang.org/std/marker/trait.Copy.html
/// [`Clone`]:      https://doc.rust-lang.org/std/clone/trait.Clone.html
/// [`Ord`]:        https://doc.rust-lang.org/std/cmp/trait.Ord.html
/// [`PartialOrd`]: https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html
/// [`Eq`]:         https://doc.rust-lang.org/std/cmp/trait.Eq.html
/// [`PartialEq`]:  https://doc.rust-lang.org/std/cmp/trait.PartialEq.html
#[macro_export]
macro_rules! assert_trait_sub_all {
    ($sub:path: $($super:path),+ $(,)?) => {
        const _: () = {
            $({
                #[allow(non_camel_case_types)]
                trait __Impl_Implication: $super {}

                impl<T: $sub> __Impl_Implication for T {}
            })+
        };
    };
}

/// Asserts that the trait is a parent of all of the other traits.
///
/// Related:
/// - [`assert_trait_sub_all!`]
///
/// # Examples
///
/// With this, traits `A` and `B` can both be tested to require [`Copy`] on a
/// single line:
///
/// ```
/// # use static_assertions::assert_trait_super_all;
/// trait A: Copy {}
/// trait B: Copy {}
///
/// assert_trait_super_all!(Copy: A, B);
/// ```
///
/// Otherwise, each sub-trait would require its own call to
/// [`assert_trait_sub_all!`]:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// # trait A: Copy {}
/// # trait B: Copy {}
/// assert_trait_sub_all!(A: Copy);
/// assert_trait_sub_all!(B: Copy);
/// ```
///
/// The following example fails to compile because trait `C` does not require
/// [`Copy`]:
///
/// ```compile_fail
/// # use static_assertions::assert_trait_super_all;
/// # trait A: Copy {}
/// # trait B: Copy {}
/// trait C {}
///
/// assert_trait_super_all!(Copy: A, B, C);
/// ```
///
/// [`assert_trait_sub_all!`]: macro.assert_trait_sub_all.html
///
/// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html
#[macro_export(local_inner_macros)]
macro_rules! assert_trait_super_all {
    ($super:path: $($sub:path),+ $(,)?) => {
        $(assert_trait_sub_all!($sub: $super);)+
    };
}
<commit_msg>Add comments to `assert_trait_sub_all!`<commit_after>/// Asserts that the trait is a child of all of the other traits.
///
/// Related:
/// - [`assert_trait_super_all!`]
///
/// # Examples
///
/// All types that implement [`Copy`] must implement [`Clone`]:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_trait_sub_all!(Copy: Clone);
/// ```
///
/// All types that implement [`Ord`] must implement [`PartialEq`], [`Eq`], and
/// [`PartialOrd`]:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_trait_sub_all!(Ord: PartialEq, Eq, PartialOrd);
/// ```
///
/// The following example fails to compile because [`Eq`] is not required for
/// [`PartialOrd`]:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_trait_sub_all!(PartialOrd: Eq);
/// ```
///
/// [`assert_trait_super_all!`]: macro.assert_trait_super_all.html
///
/// [`Copy`]:       https://doc.rust-lang.org/std/marker/trait.Copy.html
/// [`Clone`]:      https://doc.rust-lang.org/std/clone/trait.Clone.html
/// [`Ord`]:        https://doc.rust-lang.org/std/cmp/trait.Ord.html
/// [`PartialOrd`]: https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html
/// [`Eq`]:         https://doc.rust-lang.org/std/cmp/trait.Eq.html
/// [`PartialEq`]:  https://doc.rust-lang.org/std/cmp/trait.PartialEq.html
#[macro_export]
macro_rules! assert_trait_sub_all {
    ($sub:path: $($super:path),+ $(,)?) => {
        const _: () = {
            // One scope per super-trait.
            $({
                #[allow(non_camel_case_types)]
                trait __Impl_Implication: $super {}

                // Can only be implemented for `$sub` types if `$super` is
                // also implemented.
                impl<T: $sub> __Impl_Implication for T {}
            })+
        };
    };
}

/// Asserts that the trait is a parent of all of the other traits.
///
/// Related:
/// - [`assert_trait_sub_all!`]
///
/// # Examples
///
/// With this, traits `A` and `B` can both be tested to require [`Copy`] on a
/// single line:
///
/// ```
/// # use static_assertions::assert_trait_super_all;
/// trait A: Copy {}
/// trait B: Copy {}
///
/// assert_trait_super_all!(Copy: A, B);
/// ```
///
/// Otherwise, each sub-trait would require its own call to
/// [`assert_trait_sub_all!`]:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// # trait A: Copy {}
/// # trait B: Copy {}
/// assert_trait_sub_all!(A: Copy);
/// assert_trait_sub_all!(B: Copy);
/// ```
///
/// The following example fails to compile because trait `C` does not require
/// [`Copy`]:
///
/// ```compile_fail
/// # use static_assertions::assert_trait_super_all;
/// # trait A: Copy {}
/// # trait B: Copy {}
/// trait C {}
///
/// assert_trait_super_all!(Copy: A, B, C);
/// ```
///
/// [`assert_trait_sub_all!`]: macro.assert_trait_sub_all.html
///
/// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html
#[macro_export(local_inner_macros)]
macro_rules! assert_trait_super_all {
    ($super:path: $($sub:path),+ $(,)?) => {
        $(assert_trait_sub_all!($sub: $super);)+
    };
}
<|endoftext|>


<commit_before>extern crate find_folder;

use bot::Bot;
use player::Player;
use io::tileset::Tileset;
use io::read_tileset;
use io::read_level;
use level::Level;
use io::all_sprites::SpriteMap;
use std::str::FromStr;
use std::fs::File;
use std::io::BufReader;
use xml::reader::{EventReader, XmlEvent};
use item::Item;
use gfx_device_gl::Factory;

pub fn load_xml<'a>
    (path: &str,
     map: &'a SpriteMap,
     factory: &mut Factory)
     -> (Level, Tileset, Vec<Option<Bot<'a>>>, Vec<Option<Player<'a>>>, Vec<Item<'a>>) {
    // Initialize objects
    let mut bots: Vec<Option<Bot>> = Vec::new();
    let mut items: Vec<Item> = Vec::new();
    let mut tileset = Tileset::new(1, 1, 1, 1);
    let mut level = Level::with_size(0, 0);
    let mut players: Vec<Option<Player>> = Vec::new();
    let mut last = String::new();
    let mut i = 0;

    // Open xml-file
    let file = File::open(path).unwrap();
    let file = BufReader::new(file);

    let parser = EventReader::new(file);

    // Iterate over xml-file
    for e in parser {
        match e {
            Ok(XmlEvent::StartElement { name, attributes, .. }) => {
                last = name.local_name.clone();
                // Iterate over tags
                match &last[..] {
                    "tileset" => {
                        // Iterate over attributes
                        let mut it = attributes.iter();

                        // read tileset-attributes
                        let path = match it.next() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!"),
                        };
                        let tileset_path = path.value.clone();

                        let tile_height = match it.next() {
                            Some(s) => {
                                match u32::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let tile_width = match it.next() {
                            Some(s) => {
                                match u32::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let tileset_height = match it.next() {
                            Some(s) => {
                                match u32::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let tileset_width = match it.next() {
                            Some(s) => {
                                match u32::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let tiles = match find_folder::Search::Kids(1).for_folder("tiles") {
                            Ok(res) => res.join(tileset_path),
                            Err(_) => panic!("Folder 'tiles' not found!"),
                        };

                        let file_path = match tiles.to_str() {
                            Some(res) => res,
                            None => panic!("Tileset not found!"),
                        };

                        // generate tileset with given attributes
                        tileset = read_tileset(file_path,
                                               factory,
                                               tile_height,
                                               tile_width,
                                               tileset_height,
                                               tileset_width);
                    }
                    "file" => {
                        let path = match attributes.first() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!aaa"),
                        };
                        let lvl_path = path.value.clone();

                        let folder_level = match find_folder::Search::Kids(0).for_folder("src") {
                            Ok(res) => res.join(lvl_path),
                            Err(_) => panic!("Folder 'src' not found!"),
                        };

                        let level_path = match folder_level.to_str() {
                            Some(res) => res,
                            None => panic!("Level not found!"),
                        };

                        // generate level by path
                        level = read_level(level_path);
                    }
                    "player1" => {
                        let mut it = attributes.iter();

                        let x = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };
                        let y = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let mut p1 = Player::new(x, y, 1, map);
                        let p = match it.next() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!"),
                        };

                        // generate player1 with sprite-path and coordinates
                        let sprite = p.value.clone();
                        p1.set_sprite(map.get_sprite(sprite));
                        players.push(Some(p1));
                    }
                    "player2" => {
                        let mut it = attributes.iter();

                        let x = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };
                        let y = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let mut p2 = Player::new(x, y, 2, map);
                        let p = match it.next() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!"),
                        };

                        // generate player2 with sprite-path and coordinates
                        let sprite = p.value.clone();
                        p2.set_sprite(map.get_sprite(sprite));
                        players.push(Some(p2));
                    }
                    "bot" => {
                        let mut it = attributes.iter();

                        let x = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };
                        let y = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let life = match it.next() {
                            Some(s) => {
                                match i32::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let passive = match it.next() {
                            Some(s) => {
                                match bool::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let p = match it.next() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!"),
                        };

                        // generate bot with sprite-path and coordinates
                        let sprite = p.value.clone();
                        let mut b = Bot::new(x, y, life, passive, i, &map);
                        b.set_sprite(map.get_sprite(sprite));

                        bots.push(Some(b));
                        i += 1;
                    }
                    "item" => {
                        let mut it = attributes.iter();

                        let x = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };
                        let y = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };
                        let p = match it.next() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!"),
                        };
                        // generate item with sprite-path and coordinates
                        let sprite = p.value.clone();

                        let mut item = Item::new(x, y);
                        item.load_sprite(map, sprite);

                        items.push(item);

                    }
                    _ => (),
                }
            }
            Err(_) => {
                panic!("Wrong xml format!");
            }
            _ => {}
        }
    }

    // return created elements
    (level, tileset, bots, players, items)
}
<commit_msg>delete unused variable<commit_after>extern crate find_folder;

use bot::Bot;
use player::Player;
use io::tileset::Tileset;
use io::read_tileset;
use io::read_level;
use level::Level;
use io::all_sprites::SpriteMap;
use std::str::FromStr;
use std::fs::File;
use std::io::BufReader;
use xml::reader::{EventReader, XmlEvent};
use item::Item;
use gfx_device_gl::Factory;

pub fn load_xml<'a>
    (path: &str,
     map: &'a SpriteMap,
     factory: &mut Factory)
     -> (Level, Tileset, Vec<Option<Bot<'a>>>, Vec<Option<Player<'a>>>, Vec<Item<'a>>) {
    // Initialize objects
    let mut bots: Vec<Option<Bot>> = Vec::new();
    let mut items: Vec<Item> = Vec::new();
    let mut tileset = Tileset::new(1, 1, 1, 1);
    let mut level = Level::with_size(0, 0);
    let mut players: Vec<Option<Player>> = Vec::new();
    let mut i = 0;

    // Open xml-file
    let file = File::open(path).unwrap();
    let file = BufReader::new(file);

    let parser = EventReader::new(file);

    // Iterate over xml-file
    for e in parser {
        match e {
            Ok(XmlEvent::StartElement { name, attributes, .. }) => {
                let last = name.local_name.clone();
                // Iterate over tags
                match &last[..] {
                    "tileset" => {
                        // Iterate over attributes
                        let mut it = attributes.iter();

                        // read tileset-attributes
                        let path = match it.next() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!"),
                        };
                        let tileset_path = path.value.clone();

                        let tile_height = match it.next() {
                            Some(s) => {
                                match u32::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let tile_width = match it.next() {
                            Some(s) => {
                                match u32::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let tileset_height = match it.next() {
                            Some(s) => {
                                match u32::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let tileset_width = match it.next() {
                            Some(s) => {
                                match u32::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let tiles = match find_folder::Search::Kids(1).for_folder("tiles") {
                            Ok(res) => res.join(tileset_path),
                            Err(_) => panic!("Folder 'tiles' not found!"),
                        };

                        let file_path = match tiles.to_str() {
                            Some(res) => res,
                            None => panic!("Tileset not found!"),
                        };

                        // generate tileset with given attributes
                        tileset = read_tileset(file_path,
                                               factory,
                                               tile_height,
                                               tile_width,
                                               tileset_height,
                                               tileset_width);
                    }
                    "file" => {
                        let path = match attributes.first() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!aaa"),
                        };
                        let lvl_path = path.value.clone();

                        let folder_level = match find_folder::Search::Kids(0).for_folder("src") {
                            Ok(res) => res.join(lvl_path),
                            Err(_) => panic!("Folder 'src' not found!"),
                        };

                        let level_path = match folder_level.to_str() {
                            Some(res) => res,
                            None => panic!("Level not found!"),
                        };

                        // generate level by path
                        level = read_level(level_path);
                    }
                    "player1" => {
                        let mut it = attributes.iter();

                        let x = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };
                        let y = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let mut p1 = Player::new(x, y, 1, map);
                        let p = match it.next() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!"),
                        };

                        // generate player1 with sprite-path and coordinates
                        let sprite = p.value.clone();
                        p1.set_sprite(map.get_sprite(sprite));
                        players.push(Some(p1));
                    }
                    "player2" => {
                        let mut it = attributes.iter();

                        let x = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };
                        let y = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let mut p2 = Player::new(x, y, 2, map);
                        let p = match it.next() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!"),
                        };

                        // generate player2 with sprite-path and coordinates
                        let sprite = p.value.clone();
                        p2.set_sprite(map.get_sprite(sprite));
                        players.push(Some(p2));
                    }
                    "bot" => {
                        let mut it = attributes.iter();

                        let x = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };
                        let y = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let life = match it.next() {
                            Some(s) => {
                                match i32::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let passive = match it.next() {
                            Some(s) => {
                                match bool::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };

                        let p = match it.next() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!"),
                        };

                        // generate bot with sprite-path and coordinates
                        let sprite = p.value.clone();
                        let mut b = Bot::new(x, y, life, passive, i, &map);
                        b.set_sprite(map.get_sprite(sprite));

                        bots.push(Some(b));
                        i += 1;
                    }
                    "item" => {
                        let mut it = attributes.iter();

                        let x = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };
                        let y = match it.next() {
                            Some(s) => {
                                match u64::from_str(&s.value) {
                                    Ok(n) => n,
                                    Err(_) => panic!("{:?} is not a number!", s.value),
                                }
                            }
                            None => panic!("Wrong xml format!"),
                        };
                        let p = match it.next() {
                            Some(s) => s,
                            None => panic!("Wrong xml format!"),
                        };
                        // generate item with sprite-path and coordinates
                        let sprite = p.value.clone();

                        let mut item = Item::new(x, y);
                        item.load_sprite(map, sprite);

                        items.push(item);

                    }
                    _ => (),
                }
            }
            Err(_) => {
                panic!("Wrong xml format!");
            }
            _ => {}
        }
    }

    // return created elements
    (level, tileset, bots, players, items)
}
<|endoftext|>


<commit_before>
// We want a function which takes an existing graph, its distance labeling for each node, and a sequence of edge
// modifications, and which outputs the corresponding sequence of changes to the distance labelings for each node.

// For each depth, for each node, we can determine for which time intervals that depth is the correct answer. By
// accumulating this information over depths, we get larger and larger regions of time for which the node's depth
// is sorted out, and fewer interesting future moments.

type Node = usize;

// The input parameters are:
//
//    edges: the graph structure in the form of an adjacency list.
//    dists: the proposed distances for each node, as (round, count).
//    changes: the edits we plan to make to the edge collection.

struct PerNode {
	// "join" state
	edges: Vec<Node>,					// edges
	diffs: Vec<(Node, usize, isize)>,	// changes to edges (time, diff).
	// "group" state
	dists: Vec<(usize, usize)>,			// distance proposals (and counts)
	edits: Vec<(usize, usize, isize)>,	// changes to distance proposals.
}

impl PerNode {
	// re-evaluate at all times with this depth
	fn update(&mut self, depth: usize, changes: &mut Vec<(usize, usize, isize)>) {

		let mut history = Vec::new();

		// self.edits is fixed for this round; we want to swing through each time
		self.edits.sort_by(|x,y| x.1.cmp(&y.1));
		let mut count_prev = 0;
		let mut count_this = 0;

		// initialize counts properly

		let mut new_edits = Vec::new();

		for (d, c) in &self.dists[..] {
			// need to determine if the output changes, and what to remember about this input change.
			if d < depth {
				// change to a prior depth; could conceal/reveal this depth, or a later depth.
				if count_prev > 0 && count_prev + c == 0 {
					if
				}

				count_prev += c;
			}
			if d == depth {

				count_this += c;
			}
			if d > depth {

			}
		}

	}
}

fn bfs(state: Vec<PerNode>) {

	let mut group_todo = Vec::new();

	for source in 0 .. edges.len() {
		for &(target, time, diff) in &state[source].diffs {
			if state[source].dists.len() > 0 {
				let distance = state[source].dists[0].0 + 1;
				state[target].edits.push((distance, time, diff));
				// add (target, time) to our todo list.
				while group_todo.len() <= distance { group_todo.push(Vec::new()); }
				group_todo[distance].push((target, time));
			}
		}
	}

	// We've now populated initial proposal changes for each node and initial todo lists for each distance.
	let mut depth = 0;
	while depth < todo.len() {

		// perform all work in `todo[depth]`.
		let todo = ::std::mem::replace(&mut group_todo[depth], Vec::new());
		todo.sort();
		todo.dedup();

		let mut cursor = 0;
		while cursor < todo.len() {

			let node = todo[cursor];

			// prepare times at which to do work.
			while todo[cursor].0 == node {
				times.push(todo_depth[cursor].1);
				cursor += 1;
			}

			// perform work at indicated times.
			state[node].update(&times[..], &mut new_times);
		}

		depth + 1;
	}
}

// NOTE: Cleverness in bfs: we don't really need a value, just the set of reachable nodes, as long as we can extract the
// round at which each became reachable. This means that the "state maintenance" becomes very easy if we use compacted
// times in dd, because we are just tracking "reachable yet or not", which should almost just be a counter.

// NOTE: For monotonic operators, it seems like we can put the monotonic quantity in the timestamp, like distances for
// bfs. What happens is that we learn when a quantity first becomes set, as in what "time" it starts to exist. This seems
// to have some positive implications for how state are compacted, and future interesting times. <commit_msg>moved to in_progress/ so things can build<commit_after><|endoftext|>


<commit_before>extern crate bytes;

use self::bytes::{BufMut, BytesMut};
use super::bls::PublicKey;
use super::VALIDATOR_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError};
use std::sync::Arc;

#[derive(Debug, PartialEq)]
pub enum ValidatorStoreError {
    DBError(String),
    DecodeError,
}

impl From<DBError> for ValidatorStoreError {
    fn from(error: DBError) -> Self {
        ValidatorStoreError::DBError(error.message)
    }
}

#[derive(Debug, PartialEq)]
enum KeyPrefixes {
    PublicKey,
}

pub struct ValidatorStore<T>
where
    T: ClientDB,
{
    db: Arc<T>,
}

impl<T: ClientDB> ValidatorStore<T> {
    pub fn new(db: Arc<T>) -> Self {
        Self { db }
    }

    fn prefix_bytes(&self, key_prefix: &KeyPrefixes) -> Vec<u8> {
        match key_prefix {
            KeyPrefixes::PublicKey => b"pubkey".to_vec(),
        }
    }

    fn get_db_key_for_index(&self, key_prefix: &KeyPrefixes, index: usize) -> Vec<u8> {
        let mut buf = BytesMut::with_capacity(6 + 8);
        buf.put(self.prefix_bytes(key_prefix));
        buf.put_u64_be(index as u64);
        buf.take().to_vec()
    }

    pub fn put_public_key_by_index(
        &self,
        index: usize,
        public_key: &PublicKey,
    ) -> Result<(), ValidatorStoreError> {
        let key = self.get_db_key_for_index(&KeyPrefixes::PublicKey, index);
        let val = public_key.as_bytes();
        self.db
            .put(DB_COLUMN, &key[..], &val[..])
            .map_err(ValidatorStoreError::from)
    }

    pub fn get_public_key_by_index(
        &self,
        index: usize,
    ) -> Result<Option<PublicKey>, ValidatorStoreError> {
        let key = self.get_db_key_for_index(&KeyPrefixes::PublicKey, index);
        let val = self.db.get(DB_COLUMN, &key[..])?;
        match val {
            None => Ok(None),
            Some(val) => match PublicKey::from_bytes(&val) {
                Ok(key) => Ok(Some(key)),
                Err(_) => Err(ValidatorStoreError::DecodeError),
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::super::MemoryDB;
    use super::super::bls::Keypair;
    use super::*;

    #[test]
    fn test_validator_store_put_get() {
        let db = Arc::new(MemoryDB::open());
        let store = ValidatorStore::new(db);

        let keys = vec![
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
        ];

        for i in 0..keys.len() {
            store.put_public_key_by_index(i, &keys[i].pk).unwrap();
        }

        /*
         * Check all keys are retrieved correctly.
         */
        for i in 0..keys.len() {
            let retrieved = store.get_public_key_by_index(i).unwrap().unwrap();
            assert_eq!(retrieved, keys[i].pk);
        }

        /*
         * Check that an index that wasn't stored returns None.
         */
        assert!(
            store
                .get_public_key_by_index(keys.len() + 1)
                .unwrap()
                .is_none()
        );
    }

    #[test]
    fn test_validator_store_bad_key() {
        let db = Arc::new(MemoryDB::open());
        let store = ValidatorStore::new(db.clone());

        let key = store.get_db_key_for_index(&KeyPrefixes::PublicKey, 42);
        db.put(DB_COLUMN, &key[..], "cats".as_bytes()).unwrap();

        assert_eq!(
            store.get_public_key_by_index(42),
            Err(ValidatorStoreError::DecodeError)
        );
    }
}
<commit_msg>validator store cleanup<commit_after>extern crate bytes;

use self::bytes::{BufMut, BytesMut};
use super::bls::PublicKey;
use super::VALIDATOR_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError};
use std::sync::Arc;

#[derive(Debug, PartialEq)]
pub enum ValidatorStoreError {
    DBError(String),
    DecodeError,
}

impl From<DBError> for ValidatorStoreError {
    fn from(error: DBError) -> Self {
        ValidatorStoreError::DBError(error.message)
    }
}

#[derive(Debug, PartialEq)]
enum KeyPrefixes {
    PublicKey,
}

pub struct ValidatorStore<T>
where
    T: ClientDB,
{
    db: Arc<T>,
}

impl<T: ClientDB> ValidatorStore<T> {
    pub fn new(db: Arc<T>) -> Self {
        Self { db }
    }

    fn prefix_bytes(&self, key_prefix: &KeyPrefixes) -> Vec<u8> {
        match key_prefix {
            KeyPrefixes::PublicKey => b"pubkey".to_vec(),
        }
    }

    fn get_db_key_for_index(&self, key_prefix: &KeyPrefixes, index: usize) -> Vec<u8> {
        let mut buf = BytesMut::with_capacity(6 + 8);
        buf.put(self.prefix_bytes(key_prefix));
        buf.put_u64_be(index as u64);
        buf.take().to_vec()
    }

    pub fn put_public_key_by_index(
        &self,
        index: usize,
        public_key: &PublicKey,
    ) -> Result<(), ValidatorStoreError> {
        let key = self.get_db_key_for_index(&KeyPrefixes::PublicKey, index);
        let val = public_key.as_bytes();
        self.db
            .put(DB_COLUMN, &key[..], &val[..])
            .map_err(ValidatorStoreError::from)
    }

    pub fn get_public_key_by_index(
        &self,
        index: usize,
    ) -> Result<Option<PublicKey>, ValidatorStoreError> {
        let key = self.get_db_key_for_index(&KeyPrefixes::PublicKey, index);
        let val = self.db.get(DB_COLUMN, &key[..])?;
        match val {
            None => Ok(None),
            Some(val) => match PublicKey::from_bytes(&val) {
                Ok(key) => Ok(Some(key)),
                Err(_) => Err(ValidatorStoreError::DecodeError),
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::super::MemoryDB;
    use super::super::bls::Keypair;
    use super::*;

    #[test]
    fn test_put_public_key_by_index() {
        let db = Arc::new(MemoryDB::open());
        let store = ValidatorStore::new(db.clone());

        let index = 3;
        let public_key = Keypair::random().pk;

        store.put_public_key_by_index(index, &public_key).unwrap();
        let public_key_at_index = db.get(
            DB_COLUMN,
            &store.get_db_key_for_index(&KeyPrefixes::PublicKey, index)[..]
        ).unwrap().unwrap();

        assert_eq!(public_key_at_index, public_key.as_bytes());
    }

    #[test]
    fn test_get_public_key_by_index() {
        let db = Arc::new(MemoryDB::open());
        let store = ValidatorStore::new(db.clone());

        let index = 4;
        let public_key = Keypair::random().pk;

        db.put(
            DB_COLUMN,
            &store.get_db_key_for_index(&KeyPrefixes::PublicKey, index)[..],
            &public_key.as_bytes()[..]
        ).unwrap();

        let public_key_at_index = store.get_public_key_by_index(index).unwrap().unwrap();
        assert_eq!(public_key_at_index, public_key);
    }

    #[test]
    fn test_get_public_key_by_invalid_index() {
        let db = Arc::new(MemoryDB::open());
        let store = ValidatorStore::new(db.clone());

        let public_key = Keypair::random().pk;

        db.put(
            DB_COLUMN,
            &store.get_db_key_for_index(&KeyPrefixes::PublicKey, 3)[..],
            &public_key.as_bytes()[..]
        ).unwrap();

        let public_key_at_index = store.get_public_key_by_index(4).unwrap();
        assert_eq!(public_key_at_index, None);
    }

    #[test]
    fn test_validator_store_put_get() {
        let db = Arc::new(MemoryDB::open());
        let store = ValidatorStore::new(db);

        let keys = vec![
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
        ];

        for i in 0..keys.len() {
            store.put_public_key_by_index(i, &keys[i].pk).unwrap();
        }

        /*
         * Check all keys are retrieved correctly.
         */
        for i in 0..keys.len() {
            let retrieved = store.get_public_key_by_index(i).unwrap().unwrap();
            assert_eq!(retrieved, keys[i].pk);
        }

        /*
         * Check that an index that wasn't stored returns None.
         */
        assert!(
            store
                .get_public_key_by_index(keys.len() + 1)
                .unwrap()
                .is_none()
        );
    }

    #[test]
    fn test_validator_store_bad_key() {
        let db = Arc::new(MemoryDB::open());
        let store = ValidatorStore::new(db.clone());

        let key = store.get_db_key_for_index(&KeyPrefixes::PublicKey, 42);
        db.put(DB_COLUMN, &key[..], "cats".as_bytes()).unwrap();

        assert_eq!(
            store.get_public_key_by_index(42),
            Err(ValidatorStoreError::DecodeError)
        );
    }
}
<|endoftext|>