<commit_before>#![deny(missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unstable_features,
        unused_import_braces, unused_qualifications)]

#![cfg_attr(feature = "nightly", allow(unstable_features))]
#![cfg_attr(feature = "lints", feature(plugin))]
#![cfg_attr(feature = "lints", plugin(clippy))]

extern crate librsync_sys as raw;
extern crate libc;
#[cfg(feature = "log")]
#[macro_use]
extern crate log;

mod macros;
mod job;
mod logfwd;
pub mod whole;

use job::{Job, JobDriver};

use std::error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, Read, Seek};
use std::ops::Deref;
use std::mem;
use std::ptr;
use std::slice;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SignatureType {
    MD4,
    Blake2,
}

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Syntax,
    Mem,
    BadMagic,
    Unimplemented,
    Internal,
    Unknown(i32),
}

pub type Result<T> = std::result::Result<T, Error>;

pub struct Signature<R> {
    driver: JobDriver<R>,
}

pub struct Delta<R> {
    driver: JobDriver<R>,
    _sumset: Sumset,
}

pub struct Patch<'a, R> {
    driver: JobDriver<R>,
    _base: Box<StreamHolder<'a>>,
}

struct Sumset(*mut raw::rs_signature_t);

struct StreamHolder<'a>(Box<ReadAndSeek + 'a>);

// workaround for E0225
trait ReadAndSeek: Read + Seek {}
impl<T: Read + Seek> ReadAndSeek for T {}

impl<R: Read> Signature<R> {
    pub fn new(input: R,
               block_len: usize,
               strong_len: usize,
               sig_magic: SignatureType)
               -> Result<Self> {
        logfwd::init();
        let job = unsafe { raw::rs_sig_begin(block_len, strong_len, sig_magic.as_raw()) };
        if job.is_null() {
            return Err(Error::BadMagic);
        }
        Ok(Signature { driver: JobDriver::new(input, Job(job)) })
    }

    pub fn into_inner(self) -> R {
        self.driver.into_inner()
    }
}

impl<R: Read> Read for Signature<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl<R: Read> Delta<R> {
    pub fn new<S: Read>(new: R, base_sig: S) -> Result<Self> {
        logfwd::init();
        // load the signature
        let sumset = unsafe {
            let mut sumset = ptr::null_mut();
            let job = raw::rs_loadsig_begin(&mut sumset);
            assert!(!job.is_null());
            let mut job = JobDriver::new(base_sig, Job(job));
            try!(job.consume_input());
            let sumset = Sumset(sumset);
            let res = raw::rs_build_hash_table(*sumset);
            if res != raw::RS_DONE {
                return Err(Error::from(res));
            }
            sumset
        };
        let job = unsafe { raw::rs_delta_begin(*sumset) };
        if job.is_null() {
            return Err(io_err(io::ErrorKind::InvalidData, "invalid signature given"));
        }
        Ok(Delta {
            driver: JobDriver::new(new, Job(job)),
            _sumset: sumset,
        })
    }

    pub fn into_inner(self) -> R {
        self.driver.into_inner()
    }
}

impl<R: Read> Read for Delta<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl<'a, R: Read> Patch<'a, R> {
    pub fn new<B: Read + Seek + 'a>(base: B, delta: R) -> Result<Self> {
        logfwd::init();

        let mut baseh = Box::new(StreamHolder(Box::new(base)));
        let job = unsafe { raw::rs_patch_begin(patch_copy_cb, baseh.as_raw()) };
        assert!(!job.is_null());
        Ok(Patch {
            driver: JobDriver::new(delta, Job(job)),
            _base: baseh,
        })
    }

    pub fn into_delta(self) -> R {
        self.driver.into_inner()
    }
}

impl<'a, R: Read> Read for Patch<'a, R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::Syntax => "syntax error",
            Error::Mem => "out of memory",
            Error::BadMagic => "bad magic number given",
            Error::Unimplemented => "unimplemented feature",
            Error::Internal => "internal error",
            Error::Unknown(_) => "unknown error from librsync",
        }
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref e) => write!(fmt, "{}", e),
            Error::Unknown(n) => write!(fmt, "unknown error {} from native library", n),
            _ => write!(fmt, "{}", std::error::Error::description(self)),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<raw::rs_result> for Error {
    fn from(err: raw::rs_result) -> Error {
        match err {
            raw::RS_BLOCKED => io_err(io::ErrorKind::WouldBlock, "blocked waiting for more data"),
            raw::RS_IO_ERROR => io_err(io::ErrorKind::Other, "unknown IO error from librsync"),
            raw::RS_SYNTAX_ERROR => Error::Syntax,
            raw::RS_MEM_ERROR => Error::Mem,
            raw::RS_INPUT_ENDED => {
                io_err(io::ErrorKind::UnexpectedEof, "unexpected end of input file")
            }
            raw::RS_BAD_MAGIC => Error::BadMagic,
            raw::RS_UNIMPLEMENTED => Error::Unimplemented,
            raw::RS_CORRUPT => io_err(io::ErrorKind::InvalidData, "unbelievable value in stream"),
            raw::RS_INTERNAL_ERROR => Error::Internal,
            raw::RS_PARAM_ERROR => io_err(io::ErrorKind::InvalidInput, "bad parameter"),
            n => Error::Unknown(n),
        }
    }
}

impl SignatureType {
    fn as_raw(&self) -> raw::rs_magic_number {
        match *self {
            SignatureType::MD4 => raw::RS_MD4_SIG_MAGIC,
            SignatureType::Blake2 => raw::RS_BLAKE2_SIG_MAGIC,
        }
    }
}

impl Drop for Sumset {
    fn drop(&mut self) {
        unsafe {
            if !self.0.is_null() {
                raw::rs_free_sumset(self.0);
            }
        }
    }
}

impl Deref for Sumset {
    type Target = *mut raw::rs_signature_t;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a> StreamHolder<'a> {
    fn as_stream(&mut self) -> &mut ReadAndSeek {
        &mut *self.0
    }

    fn as_raw(&mut self) -> *mut libc::c_void {
        unsafe { mem::transmute(self) }
    }
}

extern "C" fn patch_copy_cb(opaque: *mut libc::c_void,
                            pos: raw::rs_long_t,
                            len: *mut libc::size_t,
                            buf: *mut *mut libc::c_void)
                            -> raw::rs_result {
    let input = unsafe {
        let h: *mut StreamHolder = mem::transmute(opaque);
        (*h).as_stream()
    };
    let output = unsafe {
        let buf: *mut u8 = mem::transmute(*buf);
        slice::from_raw_parts_mut(buf, *len)
    };
    try_or_rs_error!(input.seek(io::SeekFrom::Start(pos as u64)));
    try_or_rs_error!(input.read(output));
    raw::RS_DONE
}

fn io_err<E>(kind: io::ErrorKind, e: E) -> Error
    where E: Into<Box<error::Error + Send + Sync>>
{
    Error::Io(io::Error::new(kind, e))
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Cursor, Read};

    const DATA: &'static str = "this is a string to be tested";
    const DATA2: &'static str = "this is another string to be tested";

    // generated with `rdiff signature -b 10 -S 5 data data.sig`
    fn data_signature() -> Vec<u8> {
        vec![0x72, 0x73, 0x01, 0x36, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x1b, 0x21,
             0x04, 0x8b, 0xad, 0x3c, 0xbd, 0x19, 0x09, 0x1d, 0x1b, 0x04, 0xf0, 0x9d, 0x1f, 0x64,
             0x31, 0xde, 0x15, 0xf4, 0x04, 0x87, 0x60, 0x96, 0x19, 0x50, 0x39]
    }

    // generated with `rdiff delta data.sig data2 data2.delta`
    fn data2_delta() -> Vec<u8> {
        vec![0x72, 0x73, 0x02, 0x36, 0x41, 0x10, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
             0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x45, 0x0a, 0x13, 0x00]
    }

    #[test]
    fn signature() {
        let cursor = Cursor::new(DATA);
        let mut sig = Signature::new(cursor, 10, 5, SignatureType::MD4).unwrap();
        let mut signature = Vec::new();
        let read = sig.read_to_end(&mut signature).unwrap();
        assert_eq!(read, signature.len());
        assert_eq!(signature, data_signature());
    }

    #[test]
    fn delta() {
        let sig = data_signature();
        let sig = Cursor::new(sig);
        let input = Cursor::new(DATA2);
        let mut job = Delta::new(input, sig).unwrap();
        let mut delta = Vec::new();
        let read = job.read_to_end(&mut delta).unwrap();
        assert_eq!(read, delta.len());
        assert_eq!(delta, data2_delta());
    }

    #[test]
    fn patch() {
        let base = Cursor::new(DATA);
        let delta = data2_delta();
        let delta = Cursor::new(delta);
        let mut patch = Patch::new(base, delta).unwrap();
        let mut computed_new = String::new();
        patch.read_to_string(&mut computed_new).unwrap();
        assert_eq!(computed_new, DATA2);
    }

    #[test]
    fn integration() {
        let base = Cursor::new(DATA);
        let new = Cursor::new(DATA2);
        let sig = Signature::new(base, 10, 5, SignatureType::MD4).unwrap();
        let delta = Delta::new(new, sig).unwrap();
        let base = Cursor::new(DATA);
        let mut patch = Patch::new(base, delta).unwrap();
        let mut computed_new = String::new();
        patch.read_to_string(&mut computed_new).unwrap();
        assert_eq!(computed_new, DATA2);
    }
}
<commit_msg>Added intro docs and example for streams<commit_after>//! librsync bindings for Rust.
//!
//! This library contains bindings to librsync[1], to support computation and application of
//! network deltas, used in rsync and duplicity backup applications. This library encapsulates the
//! algorithms of the rsync protocol, which computes differences between files efficiently.
//!
//! The rsync protocol, when computes differences, does not require the presence of both files.
//! It needs instead the new file and a set of checksums of the first file (namely the signature).
//! Computed differences can be stored in a delta file. The rsync protocol is then able to
//! reproduce the new file, by having the old one and the delta.
//!
//! [1]: http://librsync.sourcefrog.net/
//!
//!
//! # Overview of types and modules
//!
//! This crate provides the streaming operations to produce signatures, delta and patches in the
//! top-level module, with `Signature`, `Delta` and `Patch` structs. Those structs take some input
//! stream (`Read` or `Read + Seek` traits) and implement another stream (`Read` trait) from which
//! the output can be read.
//!
//! Higher level operations are provided within the `whole` submodule. If the application does not
//! need fine-grained control over IO operations, `sig`, `delta` and `patch` submodules can be
//! used. Those functions apply the algorithms to an output stream (implementing the `Write` trait)
//! in a single call.
//!
//!
//! # Example: streams
//!
//! This example shows how to go trough the streaming APIs, starting from an input string and a
//! modified string which act as old and new files.
//!
//! ```rust
//! use std::io::prelude::*;
//! use std::io::Cursor;
//! use librsync::{Delta, Patch, Signature, SignatureType};
//!
//! let base = "base file".as_bytes();
//! let new = "base file (modified)".as_bytes();
//!
//! // create signature starting from base file
//! let sig = Signature::new(base, 10, 5, SignatureType::Blake2).unwrap();
//! // create delta from new file and the base signature
//! let delta = Delta::new(new, sig).unwrap();
//! // create and store the new file from the base one and the delta
//! let mut patch = Patch::new(Cursor::new(base), delta).unwrap();
//! let mut computed_new = Vec::new();
//! patch.read_to_end(&mut computed_new).unwrap();
//!
//! // test whether the computed file is exactly the new file, as expected
//! assert_eq!(computed_new, new);
//! ```
//!
//! Note that intermediate results are not stored anywhere. For example the `Signature` type is
//! directly used to feed the delta operation. This is possible because of the streaming fashon of
//! the operations.

#![deny(missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unstable_features,
        unused_import_braces, unused_qualifications)]

#![cfg_attr(feature = "nightly", allow(unstable_features))]
#![cfg_attr(feature = "lints", feature(plugin))]
#![cfg_attr(feature = "lints", plugin(clippy))]

extern crate librsync_sys as raw;
extern crate libc;
#[cfg(feature = "log")]
#[macro_use]
extern crate log;

mod macros;
mod job;
mod logfwd;
pub mod whole;

use job::{Job, JobDriver};

use std::error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, Read, Seek};
use std::ops::Deref;
use std::mem;
use std::ptr;
use std::slice;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SignatureType {
    MD4,
    Blake2,
}

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Syntax,
    Mem,
    BadMagic,
    Unimplemented,
    Internal,
    Unknown(i32),
}

pub type Result<T> = std::result::Result<T, Error>;

pub struct Signature<R> {
    driver: JobDriver<R>,
}

pub struct Delta<R> {
    driver: JobDriver<R>,
    _sumset: Sumset,
}

pub struct Patch<'a, R> {
    driver: JobDriver<R>,
    _base: Box<StreamHolder<'a>>,
}

struct Sumset(*mut raw::rs_signature_t);

struct StreamHolder<'a>(Box<ReadAndSeek + 'a>);

// workaround for E0225
trait ReadAndSeek: Read + Seek {}
impl<T: Read + Seek> ReadAndSeek for T {}

impl<R: Read> Signature<R> {
    pub fn new(input: R,
               block_len: usize,
               strong_len: usize,
               sig_magic: SignatureType)
               -> Result<Self> {
        logfwd::init();
        let job = unsafe { raw::rs_sig_begin(block_len, strong_len, sig_magic.as_raw()) };
        if job.is_null() {
            return Err(Error::BadMagic);
        }
        Ok(Signature { driver: JobDriver::new(input, Job(job)) })
    }

    pub fn into_inner(self) -> R {
        self.driver.into_inner()
    }
}

impl<R: Read> Read for Signature<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl<R: Read> Delta<R> {
    pub fn new<S: Read>(new: R, base_sig: S) -> Result<Self> {
        logfwd::init();
        // load the signature
        let sumset = unsafe {
            let mut sumset = ptr::null_mut();
            let job = raw::rs_loadsig_begin(&mut sumset);
            assert!(!job.is_null());
            let mut job = JobDriver::new(base_sig, Job(job));
            try!(job.consume_input());
            let sumset = Sumset(sumset);
            let res = raw::rs_build_hash_table(*sumset);
            if res != raw::RS_DONE {
                return Err(Error::from(res));
            }
            sumset
        };
        let job = unsafe { raw::rs_delta_begin(*sumset) };
        if job.is_null() {
            return Err(io_err(io::ErrorKind::InvalidData, "invalid signature given"));
        }
        Ok(Delta {
            driver: JobDriver::new(new, Job(job)),
            _sumset: sumset,
        })
    }

    pub fn into_inner(self) -> R {
        self.driver.into_inner()
    }
}

impl<R: Read> Read for Delta<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl<'a, R: Read> Patch<'a, R> {
    pub fn new<B: Read + Seek + 'a>(base: B, delta: R) -> Result<Self> {
        logfwd::init();

        let mut baseh = Box::new(StreamHolder(Box::new(base)));
        let job = unsafe { raw::rs_patch_begin(patch_copy_cb, baseh.as_raw()) };
        assert!(!job.is_null());
        Ok(Patch {
            driver: JobDriver::new(delta, Job(job)),
            _base: baseh,
        })
    }

    pub fn into_delta(self) -> R {
        self.driver.into_inner()
    }
}

impl<'a, R: Read> Read for Patch<'a, R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::Syntax => "syntax error",
            Error::Mem => "out of memory",
            Error::BadMagic => "bad magic number given",
            Error::Unimplemented => "unimplemented feature",
            Error::Internal => "internal error",
            Error::Unknown(_) => "unknown error from librsync",
        }
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref e) => write!(fmt, "{}", e),
            Error::Unknown(n) => write!(fmt, "unknown error {} from native library", n),
            _ => write!(fmt, "{}", std::error::Error::description(self)),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<raw::rs_result> for Error {
    fn from(err: raw::rs_result) -> Error {
        match err {
            raw::RS_BLOCKED => io_err(io::ErrorKind::WouldBlock, "blocked waiting for more data"),
            raw::RS_IO_ERROR => io_err(io::ErrorKind::Other, "unknown IO error from librsync"),
            raw::RS_SYNTAX_ERROR => Error::Syntax,
            raw::RS_MEM_ERROR => Error::Mem,
            raw::RS_INPUT_ENDED => {
                io_err(io::ErrorKind::UnexpectedEof, "unexpected end of input file")
            }
            raw::RS_BAD_MAGIC => Error::BadMagic,
            raw::RS_UNIMPLEMENTED => Error::Unimplemented,
            raw::RS_CORRUPT => io_err(io::ErrorKind::InvalidData, "unbelievable value in stream"),
            raw::RS_INTERNAL_ERROR => Error::Internal,
            raw::RS_PARAM_ERROR => io_err(io::ErrorKind::InvalidInput, "bad parameter"),
            n => Error::Unknown(n),
        }
    }
}

impl SignatureType {
    fn as_raw(&self) -> raw::rs_magic_number {
        match *self {
            SignatureType::MD4 => raw::RS_MD4_SIG_MAGIC,
            SignatureType::Blake2 => raw::RS_BLAKE2_SIG_MAGIC,
        }
    }
}

impl Drop for Sumset {
    fn drop(&mut self) {
        unsafe {
            if !self.0.is_null() {
                raw::rs_free_sumset(self.0);
            }
        }
    }
}

impl Deref for Sumset {
    type Target = *mut raw::rs_signature_t;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a> StreamHolder<'a> {
    fn as_stream(&mut self) -> &mut ReadAndSeek {
        &mut *self.0
    }

    fn as_raw(&mut self) -> *mut libc::c_void {
        unsafe { mem::transmute(self) }
    }
}

extern "C" fn patch_copy_cb(opaque: *mut libc::c_void,
                            pos: raw::rs_long_t,
                            len: *mut libc::size_t,
                            buf: *mut *mut libc::c_void)
                            -> raw::rs_result {
    let input = unsafe {
        let h: *mut StreamHolder = mem::transmute(opaque);
        (*h).as_stream()
    };
    let output = unsafe {
        let buf: *mut u8 = mem::transmute(*buf);
        slice::from_raw_parts_mut(buf, *len)
    };
    try_or_rs_error!(input.seek(io::SeekFrom::Start(pos as u64)));
    try_or_rs_error!(input.read(output));
    raw::RS_DONE
}

fn io_err<E>(kind: io::ErrorKind, e: E) -> Error
    where E: Into<Box<error::Error + Send + Sync>>
{
    Error::Io(io::Error::new(kind, e))
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Cursor, Read};

    const DATA: &'static str = "this is a string to be tested";
    const DATA2: &'static str = "this is another string to be tested";

    // generated with `rdiff signature -b 10 -S 5 data data.sig`
    fn data_signature() -> Vec<u8> {
        vec![0x72, 0x73, 0x01, 0x36, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x1b, 0x21,
             0x04, 0x8b, 0xad, 0x3c, 0xbd, 0x19, 0x09, 0x1d, 0x1b, 0x04, 0xf0, 0x9d, 0x1f, 0x64,
             0x31, 0xde, 0x15, 0xf4, 0x04, 0x87, 0x60, 0x96, 0x19, 0x50, 0x39]
    }

    // generated with `rdiff delta data.sig data2 data2.delta`
    fn data2_delta() -> Vec<u8> {
        vec![0x72, 0x73, 0x02, 0x36, 0x41, 0x10, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
             0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x45, 0x0a, 0x13, 0x00]
    }

    #[test]
    fn signature() {
        let cursor = Cursor::new(DATA);
        let mut sig = Signature::new(cursor, 10, 5, SignatureType::MD4).unwrap();
        let mut signature = Vec::new();
        let read = sig.read_to_end(&mut signature).unwrap();
        assert_eq!(read, signature.len());
        assert_eq!(signature, data_signature());
    }

    #[test]
    fn delta() {
        let sig = data_signature();
        let sig = Cursor::new(sig);
        let input = Cursor::new(DATA2);
        let mut job = Delta::new(input, sig).unwrap();
        let mut delta = Vec::new();
        let read = job.read_to_end(&mut delta).unwrap();
        assert_eq!(read, delta.len());
        assert_eq!(delta, data2_delta());
    }

    #[test]
    fn patch() {
        let base = Cursor::new(DATA);
        let delta = data2_delta();
        let delta = Cursor::new(delta);
        let mut patch = Patch::new(base, delta).unwrap();
        let mut computed_new = String::new();
        patch.read_to_string(&mut computed_new).unwrap();
        assert_eq!(computed_new, DATA2);
    }

    #[test]
    fn integration() {
        let base = Cursor::new(DATA);
        let new = Cursor::new(DATA2);
        let sig = Signature::new(base, 10, 5, SignatureType::MD4).unwrap();
        let delta = Delta::new(new, sig).unwrap();
        let base = Cursor::new(DATA);
        let mut patch = Patch::new(base, delta).unwrap();
        let mut computed_new = String::new();
        patch.read_to_string(&mut computed_new).unwrap();
        assert_eq!(computed_new, DATA2);
    }
}
<|endoftext|>


<commit_before>extern crate gobject_2_0_sys as gobject;
extern crate glib_sys as glib;
extern crate gtypes;

use std::os::raw::c_char;
use gtypes::gboolean;
use gobject::GObject;

use glib::{GList, GError};

enum NotifyNotificationPrivate {}

#[repr(C)]
pub struct NotifyNotification {
    _parent_object: GObject,
    _priv_: NotifyNotificationPrivate,
}

extern "C" {
    pub fn notify_init(app_name: *const c_char) -> gboolean;
    pub fn notify_uninit();
    pub fn notify_is_initted() -> gboolean;

    pub fn notify_get_app_name() -> *const c_char;
    pub fn notify_set_app_name(app_name: *const c_char);

    pub fn notify_get_server_caps() -> *mut GList;

    pub fn notify_get_server_info(ret_name: *mut *mut c_char,
                                  ret_vendor: *mut *mut c_char,
                                  ret_version: *mut *mut c_char,
                                  ret_spec_version: *mut *mut c_char);

    pub fn notify_notification_new(summary: *const c_char,
                                   body: *const c_char,
                                   icon: *const c_char)
                                   -> *mut NotifyNotification;

    pub fn notify_notification_show(notification: *mut NotifyNotification,
                                    error: *mut *mut GError);
}
<commit_msg>Add notify_notification_set_hint()<commit_after>extern crate gobject_2_0_sys as gobject;
extern crate glib_sys as glib;
extern crate gtypes;

use std::os::raw::c_char;
use gtypes::gboolean;
use gobject::GObject;

use glib::{GList, GError, GVariant};

enum NotifyNotificationPrivate {}

#[repr(C)]
pub struct NotifyNotification {
    _parent_object: GObject,
    _priv_: NotifyNotificationPrivate,
}

extern "C" {
    pub fn notify_init(app_name: *const c_char) -> gboolean;
    pub fn notify_uninit();
    pub fn notify_is_initted() -> gboolean;

    pub fn notify_get_app_name() -> *const c_char;
    pub fn notify_set_app_name(app_name: *const c_char);

    pub fn notify_get_server_caps() -> *mut GList;

    pub fn notify_get_server_info(ret_name: *mut *mut c_char,
                                  ret_vendor: *mut *mut c_char,
                                  ret_version: *mut *mut c_char,
                                  ret_spec_version: *mut *mut c_char);

    pub fn notify_notification_new(summary: *const c_char,
                                   body: *const c_char,
                                   icon: *const c_char)
                                   -> *mut NotifyNotification;

    pub fn notify_notification_show(notification: *mut NotifyNotification,
                                    error: *mut *mut GError);

    pub fn notify_notification_set_hint(notification: *mut NotifyNotification,
                                        key: *const c_char,
                                        value: *mut GVariant);
}
<|endoftext|>


<commit_before>use crate::cargo::TestBinary;
use crate::config::*;
use crate::errors::*;
use crate::event_log::*;
use crate::process_handling::*;
use crate::report::report_coverage;
use crate::source_analysis::LineAnalysis;
use crate::statemachine::*;
use crate::test_loader::*;
use crate::traces::*;
use chrono::offset::Local;
use log::{error, info, trace, warn};
use nix::unistd::*;
use std::collections::HashMap;
use std::env;
use std::ffi::CString;
use std::fs::{create_dir_all, File};
use std::path::{Path, PathBuf};

pub mod breakpoint;
mod cargo;
pub mod config;
pub mod errors;
mod event_log;
mod path_utils;
mod process_handling;
pub mod report;
mod source_analysis;
mod statemachine;
pub mod test_loader;
pub mod traces;

mod ptrace_control;

pub fn trace(configs: &[Config]) -> Result<TraceMap, RunError> {
    let mut tracemap = TraceMap::new();
    let mut tarpaulin_result = Ok(());
    let mut ret = 0i32;
    let logger = if configs.iter().any(|c| c.debug) {
        Some(EventLog::new())
    } else {
        None
    };

    for config in configs.iter() {
        if config.name == "report" {
            continue;
        }
        if let Some(log) = logger.as_ref() {
            let name = if config.name.is_empty() {
                "<anonymous>".to_string()
            } else {
                config.name.clone()
            };
            log.push_config(name);
        }
        let tgt = config.target_dir();
        if !tgt.exists() {
            let create_dir_result = create_dir_all(&tgt);
            if let Err(e) = create_dir_result {
                warn!("Failed to create target-dir {}", e);
            }
        }
        match launch_tarpaulin(config, &logger) {
            Ok((t, r)) => {
                ret |= r;
                tracemap.merge(&t);
            }
            Err(e) => {
                error!("{}", e);
                tarpaulin_result = tarpaulin_result.and_then(|_| Err(e));
            }
        }
    }
    tracemap.dedup();
    if let Some(log) = logger.as_ref() {
        let fname = format!("tarpaulin-run-{}.json", Local::now().to_rfc3339());
        let path = Path::new(&fname);
        info!("Serializing tarpaulin debug log to {}", path.display());
        if let Ok(output) = File::create(path) {
            if let Err(e) = serde_json::to_writer(output, log) {
                warn!("Failed to serialise or write result: {}", e);
            }
        } else {
            warn!("Failed to create log file");
        }
    }

    if ret == 0 {
        tarpaulin_result.map(|_| tracemap)
    } else {
        Err(RunError::TestFailed)
    }
}

pub fn run(configs: &[Config]) -> Result<(), RunError> {
    let tracemap = trace(configs)?;
    if configs.len() == 1 {
        report_coverage(&configs[0], &tracemap)?;
    } else if !configs.is_empty() {
        let mut reported = false;
        for c in configs.iter() {
            if c.name == "report" {
                reported = true;
                report_coverage(c, &tracemap)?;
            }
        }
        if !reported {
            report_coverage(&configs[0], &tracemap)?;
        }
    }

    Ok(())
}

/// Launches tarpaulin with the given configuration.
pub fn launch_tarpaulin(
    config: &Config,
    logger: &Option<EventLog>,
) -> Result<(TraceMap, i32), RunError> {
    if !config.name.is_empty() {
        info!("Running config {}", config.name);
    }

    info!("Running Tarpaulin");

    let mut result = TraceMap::new();
    let mut return_code = 0i32;
    info!("Building project");
    let executables = cargo::get_tests(config)?;
    if !config.no_run {
        let project_analysis = source_analysis::get_line_analysis(config);
        for exe in &executables {
            if exe.should_panic() {
                info!("Running a test executable that is expected to panic");
            }
            let coverage = get_test_coverage(&exe, &project_analysis, config, false, logger)?;
            if let Some(res) = coverage {
                result.merge(&res.0);
                return_code |= if exe.should_panic() {
                    (res.1 == 0) as i32
                } else {
                    res.1
                };
            }
            if config.run_ignored {
                let coverage = get_test_coverage(&exe, &project_analysis, config, true, logger)?;
                if let Some(res) = coverage {
                    result.merge(&res.0);
                    return_code |= res.1;
                }
            }
        }
        result.dedup();
    }
    Ok((result, return_code))
}

/// Returns the coverage statistics for a test executable in the given workspace
pub fn get_test_coverage(
    test: &TestBinary,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
    ignored: bool,
    logger: &Option<EventLog>,
) -> Result<Option<(TraceMap, i32)>, RunError> {
    if !test.path().exists() {
        return Ok(None);
    }
    if let Err(e) = limit_affinity() {
        warn!("Failed to set processor affinity {}", e);
    }
    if let Some(log) = logger.as_ref() {
        log.push_binary(test.clone());
    }
    match fork() {
        Ok(ForkResult::Parent { child }) => {
            match collect_coverage(test.path(), child, analysis, config, logger) {
                Ok(t) => Ok(Some(t)),
                Err(e) => Err(RunError::TestCoverage(e.to_string())),
            }
        }
        Ok(ForkResult::Child) => {
            info!("Launching test");
            execute_test(test, ignored, config)?;
            Ok(None)
        }
        Err(err) => Err(RunError::TestCoverage(format!(
            "Failed to run test {}, Error: {}",
            test.path().display(),
            err.to_string()
        ))),
    }
}

/// Collects the coverage data from the launched test
fn collect_coverage(
    test_path: &Path,
    test: Pid,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
    logger: &Option<EventLog>,
) -> Result<(TraceMap, i32), RunError> {
    let mut ret_code = 0;
    let mut traces = generate_tracemap(test_path, analysis, config)?;
    {
        trace!("Test PID is {}", test);
        let (mut state, mut data) = create_state_machine(test, &mut traces, config, logger);
        loop {
            state = state.step(&mut data, config)?;
            if state.is_finished() {
                if let TestState::End(i) = state {
                    ret_code = i;
                }
                break;
            }
        }
    }
    Ok((traces, ret_code))
}

/// Launches the test executable
fn execute_test(test: &TestBinary, ignored: bool, config: &Config) -> Result<(), RunError> {
    let exec_path = CString::new(test.path().to_str().unwrap()).unwrap();
    info!("running {}", test.path().display());
    let _ = match test.manifest_dir() {
        Some(md) => env::set_current_dir(&md),
        None => env::set_current_dir(&config.root()),
    };

    let mut envars: Vec<CString> = Vec::new();

    for (key, value) in env::vars() {
        let mut temp = String::new();
        temp.push_str(key.as_str());
        temp.push('=');
        temp.push_str(value.as_str());
        envars.push(CString::new(temp).unwrap());
    }
    let mut argv = if ignored {
        vec![exec_path.clone(), CString::new("--ignored").unwrap()]
    } else {
        vec![exec_path.clone()]
    };
    if config.verbose {
        envars.push(CString::new("RUST_BACKTRACE=1").unwrap());
    }
    for s in &config.varargs {
        argv.push(CString::new(s.as_bytes()).unwrap_or_default());
    }

    if let Some(s) = test.pkg_name() {
        envars.push(CString::new(format!("CARGO_PKG_NAME={}", s)).unwrap_or_default());
    }
    if let Some(s) = test.pkg_version() {
        envars.push(CString::new(format!("CARGO_PKG_VERSION={}", s)).unwrap_or_default());
    }
    if let Some(s) = test.pkg_authors() {
        envars.push(CString::new(format!("CARGO_PKG_AUTHORS={}", s.join(":"))).unwrap_or_default());
    }
    if let Some(s) = test.manifest_dir() {
        envars
            .push(CString::new(format!("CARGO_MANIFEST_DIR={}", s.display())).unwrap_or_default());
    }

    execute(exec_path, &argv, envars.as_slice())
}
<commit_msg>Make event_log module public<commit_after>use crate::cargo::TestBinary;
use crate::config::*;
use crate::errors::*;
use crate::event_log::*;
use crate::process_handling::*;
use crate::report::report_coverage;
use crate::source_analysis::LineAnalysis;
use crate::statemachine::*;
use crate::test_loader::*;
use crate::traces::*;
use chrono::offset::Local;
use log::{error, info, trace, warn};
use nix::unistd::*;
use std::collections::HashMap;
use std::env;
use std::ffi::CString;
use std::fs::{create_dir_all, File};
use std::path::{Path, PathBuf};

pub mod breakpoint;
mod cargo;
pub mod config;
pub mod errors;
pub mod event_log;
mod path_utils;
mod process_handling;
pub mod report;
mod source_analysis;
mod statemachine;
pub mod test_loader;
pub mod traces;

mod ptrace_control;

pub fn trace(configs: &[Config]) -> Result<TraceMap, RunError> {
    let mut tracemap = TraceMap::new();
    let mut tarpaulin_result = Ok(());
    let mut ret = 0i32;
    let logger = if configs.iter().any(|c| c.debug) {
        Some(EventLog::new())
    } else {
        None
    };

    for config in configs.iter() {
        if config.name == "report" {
            continue;
        }
        if let Some(log) = logger.as_ref() {
            let name = if config.name.is_empty() {
                "<anonymous>".to_string()
            } else {
                config.name.clone()
            };
            log.push_config(name);
        }
        let tgt = config.target_dir();
        if !tgt.exists() {
            let create_dir_result = create_dir_all(&tgt);
            if let Err(e) = create_dir_result {
                warn!("Failed to create target-dir {}", e);
            }
        }
        match launch_tarpaulin(config, &logger) {
            Ok((t, r)) => {
                ret |= r;
                tracemap.merge(&t);
            }
            Err(e) => {
                error!("{}", e);
                tarpaulin_result = tarpaulin_result.and_then(|_| Err(e));
            }
        }
    }
    tracemap.dedup();
    if let Some(log) = logger.as_ref() {
        let fname = format!("tarpaulin-run-{}.json", Local::now().to_rfc3339());
        let path = Path::new(&fname);
        info!("Serializing tarpaulin debug log to {}", path.display());
        if let Ok(output) = File::create(path) {
            if let Err(e) = serde_json::to_writer(output, log) {
                warn!("Failed to serialise or write result: {}", e);
            }
        } else {
            warn!("Failed to create log file");
        }
    }

    if ret == 0 {
        tarpaulin_result.map(|_| tracemap)
    } else {
        Err(RunError::TestFailed)
    }
}

pub fn run(configs: &[Config]) -> Result<(), RunError> {
    let tracemap = trace(configs)?;
    if configs.len() == 1 {
        report_coverage(&configs[0], &tracemap)?;
    } else if !configs.is_empty() {
        let mut reported = false;
        for c in configs.iter() {
            if c.name == "report" {
                reported = true;
                report_coverage(c, &tracemap)?;
            }
        }
        if !reported {
            report_coverage(&configs[0], &tracemap)?;
        }
    }

    Ok(())
}

/// Launches tarpaulin with the given configuration.
pub fn launch_tarpaulin(
    config: &Config,
    logger: &Option<EventLog>,
) -> Result<(TraceMap, i32), RunError> {
    if !config.name.is_empty() {
        info!("Running config {}", config.name);
    }

    info!("Running Tarpaulin");

    let mut result = TraceMap::new();
    let mut return_code = 0i32;
    info!("Building project");
    let executables = cargo::get_tests(config)?;
    if !config.no_run {
        let project_analysis = source_analysis::get_line_analysis(config);
        for exe in &executables {
            if exe.should_panic() {
                info!("Running a test executable that is expected to panic");
            }
            let coverage = get_test_coverage(&exe, &project_analysis, config, false, logger)?;
            if let Some(res) = coverage {
                result.merge(&res.0);
                return_code |= if exe.should_panic() {
                    (res.1 == 0) as i32
                } else {
                    res.1
                };
            }
            if config.run_ignored {
                let coverage = get_test_coverage(&exe, &project_analysis, config, true, logger)?;
                if let Some(res) = coverage {
                    result.merge(&res.0);
                    return_code |= res.1;
                }
            }
        }
        result.dedup();
    }
    Ok((result, return_code))
}

/// Returns the coverage statistics for a test executable in the given workspace
pub fn get_test_coverage(
    test: &TestBinary,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
    ignored: bool,
    logger: &Option<EventLog>,
) -> Result<Option<(TraceMap, i32)>, RunError> {
    if !test.path().exists() {
        return Ok(None);
    }
    if let Err(e) = limit_affinity() {
        warn!("Failed to set processor affinity {}", e);
    }
    if let Some(log) = logger.as_ref() {
        log.push_binary(test.clone());
    }
    match fork() {
        Ok(ForkResult::Parent { child }) => {
            match collect_coverage(test.path(), child, analysis, config, logger) {
                Ok(t) => Ok(Some(t)),
                Err(e) => Err(RunError::TestCoverage(e.to_string())),
            }
        }
        Ok(ForkResult::Child) => {
            info!("Launching test");
            execute_test(test, ignored, config)?;
            Ok(None)
        }
        Err(err) => Err(RunError::TestCoverage(format!(
            "Failed to run test {}, Error: {}",
            test.path().display(),
            err.to_string()
        ))),
    }
}

/// Collects the coverage data from the launched test
fn collect_coverage(
    test_path: &Path,
    test: Pid,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
    logger: &Option<EventLog>,
) -> Result<(TraceMap, i32), RunError> {
    let mut ret_code = 0;
    let mut traces = generate_tracemap(test_path, analysis, config)?;
    {
        trace!("Test PID is {}", test);
        let (mut state, mut data) = create_state_machine(test, &mut traces, config, logger);
        loop {
            state = state.step(&mut data, config)?;
            if state.is_finished() {
                if let TestState::End(i) = state {
                    ret_code = i;
                }
                break;
            }
        }
    }
    Ok((traces, ret_code))
}

/// Launches the test executable
fn execute_test(test: &TestBinary, ignored: bool, config: &Config) -> Result<(), RunError> {
    let exec_path = CString::new(test.path().to_str().unwrap()).unwrap();
    info!("running {}", test.path().display());
    let _ = match test.manifest_dir() {
        Some(md) => env::set_current_dir(&md),
        None => env::set_current_dir(&config.root()),
    };

    let mut envars: Vec<CString> = Vec::new();

    for (key, value) in env::vars() {
        let mut temp = String::new();
        temp.push_str(key.as_str());
        temp.push('=');
        temp.push_str(value.as_str());
        envars.push(CString::new(temp).unwrap());
    }
    let mut argv = if ignored {
        vec![exec_path.clone(), CString::new("--ignored").unwrap()]
    } else {
        vec![exec_path.clone()]
    };
    if config.verbose {
        envars.push(CString::new("RUST_BACKTRACE=1").unwrap());
    }
    for s in &config.varargs {
        argv.push(CString::new(s.as_bytes()).unwrap_or_default());
    }

    if let Some(s) = test.pkg_name() {
        envars.push(CString::new(format!("CARGO_PKG_NAME={}", s)).unwrap_or_default());
    }
    if let Some(s) = test.pkg_version() {
        envars.push(CString::new(format!("CARGO_PKG_VERSION={}", s)).unwrap_or_default());
    }
    if let Some(s) = test.pkg_authors() {
        envars.push(CString::new(format!("CARGO_PKG_AUTHORS={}", s.join(":"))).unwrap_or_default());
    }
    if let Some(s) = test.manifest_dir() {
        envars
            .push(CString::new(format!("CARGO_MANIFEST_DIR={}", s.display())).unwrap_or_default());
    }

    execute(exec_path, &argv, envars.as_slice())
}
<|endoftext|>


<commit_before>#![feature(zero_one)]

extern crate openblas;

use linalg::{Transpose};

use openblas::ffi::*;

use std::num::{Zero};

pub mod linalg;

pub trait ArrayIndex: Copy {
  fn least_stride(&self) -> Self;
  fn flat_len(&self) -> usize;
  fn offset(&self, stride: Self) -> usize;
  fn diff(&self, rhs: Self) -> Self;

  /*fn major_iter(self) -> MajorIter<Self> where Self: Default {
    MajorIter{
      idx:          Default::default(),
      upper_bound:  self,
    }
  }*/
}

impl ArrayIndex for usize {
  fn least_stride(&self) -> Self {
    1
  }

  fn flat_len(&self) -> usize {
    *self
  }

  fn offset(&self, stride: Self) -> usize {
    *self * stride
  }

  fn diff(&self, rhs: Self) -> Self {
    *self - rhs
  }
}

impl ArrayIndex for (usize, usize) {
  fn least_stride(&self) -> Self {
    (1, self.0)
  }

  fn flat_len(&self) -> usize {
    self.0 * self.1
  }

  fn offset(&self, stride: Self) -> usize {
    //stride.0 * (self.0 + stride.1 * self.1)
    stride.0 * self.0 + stride.1 * self.1
  }

  fn diff(&self, rhs: Self) -> Self {
    (self.0 - rhs.0, self.1 - rhs.1)
  }
}

impl ArrayIndex for (usize, usize, usize) {
  fn least_stride(&self) -> Self {
    (1, self.0, self.0 * self.1)
  }

  fn flat_len(&self) -> usize {
    self.0 * self.1 * self.2
  }

  fn offset(&self, stride: Self) -> usize {
    //stride.0 * (self.0 + stride.1 * (self.1 + stride.2 * self.2))
    stride.0 * self.0 + stride.1 * self.1 + stride.2 * self.2
  }

  fn diff(&self, rhs: Self) -> Self {
    (self.0 - rhs.0, self.1 - rhs.1, self.2 - rhs.2)
  }
}

pub trait Reshape<'a, Idx, Target> where Idx: ArrayIndex {
  fn reshape(&'a self, dim: Idx) -> Target;
  fn reshape_stride(&'a self, dim: Idx, stride: Idx) -> Target { unimplemented!(); }
}

pub trait ReshapeMut<'a, Idx, Target> where Idx: ArrayIndex {
  fn reshape_mut(&'a mut self, dim: Idx) -> Target;
  fn reshape_mut_stride(&'a mut self, dim: Idx, stride: Idx) -> Target { unimplemented!(); }
}

pub trait View<'a, Idx, Target> where Idx: ArrayIndex {
  fn view(&'a self, lo: Idx, hi: Idx) -> Target;
}

pub trait ViewMut<'a, Idx, Target> where Idx: ArrayIndex {
  fn view_mut(&'a mut self, lo: Idx, hi: Idx) -> Target;
}

pub trait AsView<'a, Target> {
  fn as_view(&'a self) -> Target;
}

pub trait AsViewMut<'a, Target> {
  fn as_view_mut(&'a mut self) -> Target;
}

impl<'a, T> Reshape<'a, (usize, usize), Array2dView<'a, T>> for [T] where T: Copy {
  fn reshape(&'a self, dim: (usize, usize)) -> Array2dView<'a, T> {
    // Assume unit stride.
    Array2dView{
      data_buf: self,
      dim:      dim,
      stride:   dim.least_stride(),
    }
  }
}

impl<'a, T> ReshapeMut<'a, (usize, usize), Array2dViewMut<'a, T>> for [T] where T: Copy {
  fn reshape_mut(&'a mut self, dim: (usize, usize)) -> Array2dViewMut<'a, T> {
    // Assume unit stride.
    Array2dViewMut{
      data_buf: self,
      dim:      dim,
      stride:   dim.least_stride(),
    }
  }
}

pub struct Array1d<T> where T: Copy {
  data_buf: Vec<T>,
  dim:      usize,
  stride:   usize,
}

/*pub struct Array1d<T, S=Vec<T>> where T: Copy, S: Storage<T> {
  data_buf: S,
  dim:      usize,
  stride:   usize,
}*/

impl<T> Array1d<T> where T: Copy + Zero {
  pub fn zeros(dim: usize) -> Array1d<T> {
    let len = dim.flat_len();
    let mut data = Vec::with_capacity(len);
    unsafe { data.set_len(len) };
    for i in 0 .. len {
      data[i] = T::zero();
    }
    Array1d{
      data_buf: data,
      dim:      dim,
      stride:   dim.least_stride(),
    }
  }
}

impl<T> Array1d<T> where T: Copy {
}

pub struct Array2d<T> where T: Copy {
  data_buf: Vec<T>,
  dim:      (usize, usize),
  stride:   (usize, usize),
}

impl<T> Array2d<T> where T: Copy + Zero {
  pub fn zeros(dim: (usize, usize)) -> Array2d<T> {
    let len = dim.flat_len();
    let mut data = Vec::with_capacity(len);
    unsafe { data.set_len(len) };
    for i in 0 .. len {
      data[i] = T::zero();
    }
    Array2d{
      data_buf: data,
      dim:      dim,
      stride:   dim.least_stride(),
    }
  }
}

impl<T> Array2d<T> where T: Copy {
  pub fn as_mut_slice(&mut self) -> &mut [T] {
    &mut self.data_buf
  }
}

impl<'a, T> AsView<'a, Array2dView<'a, T>> for Array2d<T> where T: Copy {
  fn as_view(&'a self) -> Array2dView<'a, T> {
    Array2dView{
      data_buf: &self.data_buf,
      dim:      self.dim,
      stride:   self.stride,
    }
  }
}

impl<'a, T> AsViewMut<'a, Array2dViewMut<'a, T>> for Array2d<T> where T: Copy {
  fn as_view_mut(&'a mut self) -> Array2dViewMut<'a, T> {
    Array2dViewMut{
      data_buf: &mut self.data_buf,
      dim:      self.dim,
      stride:   self.stride,
    }
  }
}

pub struct Array2dView<'a, T> where T: 'a + Copy {
  data_buf: &'a [T],
  dim:      (usize, usize),
  stride:   (usize, usize),
}

impl<'a> Array2dView<'a, f32> {
  pub fn dim(&self) -> (usize, usize) {
    self.dim
  }

  pub fn stride(&self) -> (usize, usize) {
    self.stride
  }
}

impl<'a, T> View<'a, (usize, usize), Array2dView<'a, T>> for Array2dView<'a, T> where T: 'a + Copy {
  fn view(&'a self, lo: (usize, usize), hi: (usize, usize)) -> Array2dView<'a, T> {
    let lo_offset = lo.offset(self.stride);
    let hi_offset = hi.offset(self.stride);
    let new_dim = hi.diff(lo);
    Array2dView{
      data_buf: &self.data_buf[lo_offset .. hi_offset],
      dim:      new_dim,
      stride:   self.stride,
    }
  }
}

pub struct Array2dViewMut<'a, T> where T: 'a + Copy {
  data_buf: &'a mut [T],
  dim:      (usize, usize),
  stride:   (usize, usize),
}

impl<'a, T> ViewMut<'a, (usize, usize), Array2dViewMut<'a, T>> for Array2dViewMut<'a, T> where T: 'a + Copy {
  fn view_mut(&'a mut self, lo: (usize, usize), hi: (usize, usize)) -> Array2dViewMut<'a, T> {
    let lo_offset = lo.offset(self.stride);
    let hi_offset = hi.offset(self.stride);
    let new_dim = hi.diff(lo);
    Array2dViewMut{
      data_buf: &mut self.data_buf[lo_offset .. hi_offset],
      dim:      new_dim,
      stride:   self.stride,
    }
  }
}

impl<'a> Array2dViewMut<'a, f32> {
  pub fn dim(&self) -> (usize, usize) {
    self.dim
  }

  pub fn stride(&self) -> (usize, usize) {
    self.stride
  }

  pub fn set_constant(&'a mut self, alpha: f32) {
    for i in 0 .. self.dim.flat_len() {
      self.data_buf[i] = alpha;
    }
  }

  pub fn matrix_sum(&'a mut self, alpha: f32, x: Array2dView<'a, f32>) {
    let (x_m, x_n) = x.dim();
    let (y_m, y_n) = self.dim();
    assert_eq!(x_m, y_m);
    assert_eq!(x_n, y_n);
    let (incx, ldx) = x.stride();
    let (incy, ldy) = self.stride();
    if x_n == 1 {
      unsafe { cblas_saxpy(
          x_m as _,
          alpha,
          x.data_buf.as_ptr(),
          incx as _,
          self.data_buf.as_mut_ptr(),
          incy as _,
      ) };
    } else if x_m == 1 {
      unimplemented!();
    } else {
      unimplemented!();
    }
  }

  pub fn matrix_prod(&'a mut self, alpha: f32, a: Array2dView<'a, f32>, a_trans: Transpose, b: Array2dView<'a, f32>, b_trans: Transpose, beta: f32) {
    let (a_m, a_n) = a.dim();
    let (b_m, b_n) = b.dim();
    let (c_m, c_n) = self.dim();
    let k = match (a_trans, b_trans) {
      (Transpose::N, Transpose::N) => {
        assert_eq!(c_m, a_m);
        assert_eq!(c_n, b_n);
        assert_eq!(a_n, b_m);
        a_n
      }
      (Transpose::T, Transpose::N) => {
        assert_eq!(c_m, a_n);
        assert_eq!(c_n, b_n);
        assert_eq!(a_m, b_m);
        a_m
      }
      (Transpose::N, Transpose::T) => {
        assert_eq!(c_m, a_m);
        assert_eq!(c_n, b_m);
        assert_eq!(a_n, b_n);
        a_n
      }
      (Transpose::T, Transpose::T) => {
        assert_eq!(c_m, a_n);
        assert_eq!(c_n, b_m);
        assert_eq!(a_m, b_n);
        a_m
      }
    };
    let (a_s0, lda) = a.stride();
    let (b_s0, ldb) = b.stride();
    let (c_s0, ldc) = self.stride();
    assert_eq!(1, a_s0);
    assert_eq!(1, b_s0);
    assert_eq!(1, c_s0);
    unsafe { cblas_sgemm(
        CblasOrder::ColMajor,
        match a_trans {
          Transpose::N => CblasTranspose::NoTrans,
          Transpose::T => CblasTranspose::Trans,
        },
        match b_trans {
          Transpose::N => CblasTranspose::NoTrans,
          Transpose::T => CblasTranspose::Trans,
        },
        c_m as _, c_n as _, k as _,
        alpha,
        a.data_buf.as_ptr(),
        lda as _,
        b.data_buf.as_ptr(),
        ldb as _,
        beta,
        self.data_buf.as_mut_ptr(),
        ldc as _,
    ) };
  }
}

impl<'a> Array2dViewMut<'a, f64> {
  pub fn matrix_prod(&'a mut self) {
    unimplemented!();
  }
}
<commit_msg>Abstract out the underlying storage for an array.<commit_after>#![feature(zero_one)]

extern crate openblas;

use linalg::{Transpose};

use openblas::ffi::*;

use std::marker::{PhantomData};
use std::num::{Zero};

pub mod linalg;

pub trait ArrayIndex: Copy {
  fn least_stride(&self) -> Self;
  fn flat_len(&self) -> usize;
  fn offset(&self, stride: Self) -> usize;
  fn diff(&self, rhs: Self) -> Self;

  /*fn major_iter(self) -> MajorIter<Self> where Self: Default {
    MajorIter{
      idx:          Default::default(),
      upper_bound:  self,
    }
  }*/
}

impl ArrayIndex for usize {
  fn least_stride(&self) -> Self {
    1
  }

  fn flat_len(&self) -> usize {
    *self
  }

  fn offset(&self, stride: Self) -> usize {
    *self * stride
  }

  fn diff(&self, rhs: Self) -> Self {
    *self - rhs
  }
}

impl ArrayIndex for (usize, usize) {
  fn least_stride(&self) -> Self {
    (1, self.0)
  }

  fn flat_len(&self) -> usize {
    self.0 * self.1
  }

  fn offset(&self, stride: Self) -> usize {
    //stride.0 * (self.0 + stride.1 * self.1)
    stride.0 * self.0 + stride.1 * self.1
  }

  fn diff(&self, rhs: Self) -> Self {
    (self.0 - rhs.0, self.1 - rhs.1)
  }
}

impl ArrayIndex for (usize, usize, usize) {
  fn least_stride(&self) -> Self {
    (1, self.0, self.0 * self.1)
  }

  fn flat_len(&self) -> usize {
    self.0 * self.1 * self.2
  }

  fn offset(&self, stride: Self) -> usize {
    //stride.0 * (self.0 + stride.1 * (self.1 + stride.2 * self.2))
    stride.0 * self.0 + stride.1 * self.1 + stride.2 * self.2
  }

  fn diff(&self, rhs: Self) -> Self {
    (self.0 - rhs.0, self.1 - rhs.1, self.2 - rhs.2)
  }
}

pub trait Reshape<'a, Idx, Target> where Idx: ArrayIndex {
  fn reshape(&'a self, dim: Idx) -> Target;
  fn reshape_stride(&'a self, dim: Idx, stride: Idx) -> Target { unimplemented!(); }
}

pub trait ReshapeMut<'a, Idx, Target> where Idx: ArrayIndex {
  fn reshape_mut(&'a mut self, dim: Idx) -> Target;
  fn reshape_mut_stride(&'a mut self, dim: Idx, stride: Idx) -> Target { unimplemented!(); }
}

pub trait View<'a, Idx, Target> where Idx: ArrayIndex {
  fn view(&'a self, lo: Idx, hi: Idx) -> Target;
}

pub trait ViewMut<'a, Idx, Target> where Idx: ArrayIndex {
  fn view_mut(&'a mut self, lo: Idx, hi: Idx) -> Target;
}

pub trait AsView<'a, Target> {
  fn as_view(&'a self) -> Target;
}

pub trait AsViewMut<'a, Target> {
  fn as_view_mut(&'a mut self) -> Target;
}

impl<'a, T> Reshape<'a, (usize, usize), Array2dView<'a, T>> for [T] where T: Copy {
  fn reshape(&'a self, dim: (usize, usize)) -> Array2dView<'a, T> {
    // Assume unit stride.
    Array2dView{
      data_buf: self,
      dim:      dim,
      stride:   dim.least_stride(),
    }
  }
}

impl<'a, T> ReshapeMut<'a, (usize, usize), Array2dViewMut<'a, T>> for [T] where T: Copy {
  fn reshape_mut(&'a mut self, dim: (usize, usize)) -> Array2dViewMut<'a, T> {
    // Assume unit stride.
    Array2dViewMut{
      data_buf: self,
      dim:      dim,
      stride:   dim.least_stride(),
    }
  }
}

pub trait ArrayStorage<T>: AsRef<[T]> + AsMut<[T]> {}

impl<T> ArrayStorage<T> for Vec<T> {}

pub struct Array1d<T, S=Vec<T>> where T: Copy, S: ArrayStorage<T> {
  data_buf: S,
  dim:      usize,
  stride:   usize,
  _marker:  PhantomData<T>,
}

impl<T> Array1d<T> where T: Copy + Zero {
  pub fn zeros(dim: usize) -> Array1d<T> {
    let len = dim.flat_len();
    let mut data = Vec::with_capacity(len);
    unsafe { data.set_len(len) };
    for i in 0 .. len {
      data[i] = T::zero();
    }
    Array1d{
      data_buf: data,
      dim:      dim,
      stride:   dim.least_stride(),
      _marker:  PhantomData,
    }
  }
}

impl<T, S> Array1d<T, S> where T: Copy, S: ArrayStorage<T> {
}

pub struct Array2d<T, S=Vec<T>> where T: Copy, S: ArrayStorage<T> {
  data_buf: S,
  dim:      (usize, usize),
  stride:   (usize, usize),
  _marker:  PhantomData<T>,
}

impl<T> Array2d<T> where T: Copy + Zero {
  pub fn zeros(dim: (usize, usize)) -> Array2d<T> {
    let len = dim.flat_len();
    let mut data = Vec::with_capacity(len);
    unsafe { data.set_len(len) };
    for i in 0 .. len {
      data[i] = T::zero();
    }
    Array2d{
      data_buf: data,
      dim:      dim,
      stride:   dim.least_stride(),
      _marker:  PhantomData,
    }
  }
}

impl<T, S> Array2d<T, S> where T: Copy, S: ArrayStorage<T> {
  pub fn as_slice(&self) -> &[T] {
    self.data_buf.as_ref()
  }

  pub fn as_mut_slice(&mut self) -> &mut [T] {
    self.data_buf.as_mut()
  }
}

impl<'a, T, S> AsView<'a, Array2dView<'a, T>> for Array2d<T, S> where T: Copy, S: ArrayStorage<T> {
  fn as_view(&'a self) -> Array2dView<'a, T> {
    Array2dView{
      data_buf: self.data_buf.as_ref(),
      dim:      self.dim,
      stride:   self.stride,
    }
  }
}

impl<'a, T, S> AsViewMut<'a, Array2dViewMut<'a, T>> for Array2d<T, S> where T: Copy, S: ArrayStorage<T> {
  fn as_view_mut(&'a mut self) -> Array2dViewMut<'a, T> {
    Array2dViewMut{
      data_buf: self.data_buf.as_mut(),
      dim:      self.dim,
      stride:   self.stride,
    }
  }
}

pub struct Array2dView<'a, T> where T: 'a + Copy {
  data_buf: &'a [T],
  dim:      (usize, usize),
  stride:   (usize, usize),
}

impl<'a> Array2dView<'a, f32> {
  pub fn dim(&self) -> (usize, usize) {
    self.dim
  }

  pub fn stride(&self) -> (usize, usize) {
    self.stride
  }
}

impl<'a, T> View<'a, (usize, usize), Array2dView<'a, T>> for Array2dView<'a, T> where T: 'a + Copy {
  fn view(&'a self, lo: (usize, usize), hi: (usize, usize)) -> Array2dView<'a, T> {
    let lo_offset = lo.offset(self.stride);
    let hi_offset = hi.offset(self.stride);
    let new_dim = hi.diff(lo);
    Array2dView{
      data_buf: &self.data_buf[lo_offset .. hi_offset],
      dim:      new_dim,
      stride:   self.stride,
    }
  }
}

pub struct Array2dViewMut<'a, T> where T: 'a + Copy {
  data_buf: &'a mut [T],
  dim:      (usize, usize),
  stride:   (usize, usize),
}

impl<'a, T> ViewMut<'a, (usize, usize), Array2dViewMut<'a, T>> for Array2dViewMut<'a, T> where T: 'a + Copy {
  fn view_mut(&'a mut self, lo: (usize, usize), hi: (usize, usize)) -> Array2dViewMut<'a, T> {
    let lo_offset = lo.offset(self.stride);
    let hi_offset = hi.offset(self.stride);
    let new_dim = hi.diff(lo);
    Array2dViewMut{
      data_buf: &mut self.data_buf[lo_offset .. hi_offset],
      dim:      new_dim,
      stride:   self.stride,
    }
  }
}

impl<'a> Array2dViewMut<'a, f32> {
  pub fn dim(&self) -> (usize, usize) {
    self.dim
  }

  pub fn stride(&self) -> (usize, usize) {
    self.stride
  }

  pub fn set_constant(&'a mut self, alpha: f32) {
    for i in 0 .. self.dim.flat_len() {
      self.data_buf[i] = alpha;
    }
  }

  pub fn matrix_sum(&'a mut self, alpha: f32, x: Array2dView<'a, f32>) {
    let (x_m, x_n) = x.dim();
    let (y_m, y_n) = self.dim();
    assert_eq!(x_m, y_m);
    assert_eq!(x_n, y_n);
    let (incx, ldx) = x.stride();
    let (incy, ldy) = self.stride();
    if x_n == 1 {
      unsafe { cblas_saxpy(
          x_m as _,
          alpha,
          x.data_buf.as_ptr(),
          incx as _,
          self.data_buf.as_mut_ptr(),
          incy as _,
      ) };
    } else if x_m == 1 {
      unimplemented!();
    } else {
      unimplemented!();
    }
  }

  pub fn matrix_prod(&'a mut self, alpha: f32, a: Array2dView<'a, f32>, a_trans: Transpose, b: Array2dView<'a, f32>, b_trans: Transpose, beta: f32) {
    let (a_m, a_n) = a.dim();
    let (b_m, b_n) = b.dim();
    let (c_m, c_n) = self.dim();
    let k = match (a_trans, b_trans) {
      (Transpose::N, Transpose::N) => {
        assert_eq!(c_m, a_m);
        assert_eq!(c_n, b_n);
        assert_eq!(a_n, b_m);
        a_n
      }
      (Transpose::T, Transpose::N) => {
        assert_eq!(c_m, a_n);
        assert_eq!(c_n, b_n);
        assert_eq!(a_m, b_m);
        a_m
      }
      (Transpose::N, Transpose::T) => {
        assert_eq!(c_m, a_m);
        assert_eq!(c_n, b_m);
        assert_eq!(a_n, b_n);
        a_n
      }
      (Transpose::T, Transpose::T) => {
        assert_eq!(c_m, a_n);
        assert_eq!(c_n, b_m);
        assert_eq!(a_m, b_n);
        a_m
      }
    };
    let (a_s0, lda) = a.stride();
    let (b_s0, ldb) = b.stride();
    let (c_s0, ldc) = self.stride();
    assert_eq!(1, a_s0);
    assert_eq!(1, b_s0);
    assert_eq!(1, c_s0);
    unsafe { cblas_sgemm(
        CblasOrder::ColMajor,
        match a_trans {
          Transpose::N => CblasTranspose::NoTrans,
          Transpose::T => CblasTranspose::Trans,
        },
        match b_trans {
          Transpose::N => CblasTranspose::NoTrans,
          Transpose::T => CblasTranspose::Trans,
        },
        c_m as _, c_n as _, k as _,
        alpha,
        a.data_buf.as_ptr(),
        lda as _,
        b.data_buf.as_ptr(),
        ldb as _,
        beta,
        self.data_buf.as_mut_ptr(),
        ldc as _,
    ) };
  }
}

impl<'a> Array2dViewMut<'a, f64> {
  pub fn matrix_prod(&'a mut self) {
    unimplemented!();
  }
}
<|endoftext|>


<commit_before>#![crate_name = "graphics"]
#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

//! A library for 2D graphics that works with multiple back-ends.

extern crate "vecmath" as vecmath_lib;
extern crate texture;
extern crate read_color;
#[macro_use]
extern crate quack;
extern crate interpolation;
extern crate "draw_state" as draw_state_lib;

pub use texture::ImageSize;
pub use draw_state_lib as draw_state;
pub use draw_state::DrawState;

pub use graphics::Graphics;
pub use graphics::Graphics as BackEnd;
pub use relative::Colored as RelativeColor;
pub use relative::Rectangled as RelativeRectangle;
pub use relative::SourceRectangled as RelativeSourceRectangle;
pub use relative::Transformed as RelativeTransform;
pub use relative::ViewTransformed as RelativeViewTransform;
pub use relative::{
    Colored,
    Rectangled,
    SourceRectangled,
    Transformed,
    ViewTransformed,
};
pub use rectangle::Rectangle;
pub use line::Line;
pub use ellipse::Ellipse;
pub use image::Image;
pub use polygon::Polygon;
pub use vecmath::abs_transform;
pub use default_draw_state::default_draw_state;

pub use context::Context as Context;

/// Any triangulation method called on the back-end
/// never exceeds this number of vertices.
/// This can be used to initialize buffers that fit the chunk size.
pub static BACK_END_MAX_VERTEX_COUNT: usize = 1024;

mod graphics;
mod relative;
mod default_draw_state;

pub mod character;
pub mod context;
pub mod color;
pub mod polygon;
pub mod line;
pub mod ellipse;
pub mod rectangle;
pub mod image;
pub mod internal;
pub mod modular_index;
pub mod text;
pub mod triangulation;
pub mod vecmath;
pub mod deform;
pub mod grid;

pub mod radians {
    //! Reexport radians helper trait from vecmath

    pub use vecmath_lib::consts::Radians;
}

/// A color property
#[derive(Copy)]
pub struct Color(pub internal::Color);

/// A rectangle property
#[derive(Copy)]
pub struct Rect(pub internal::Rectangle);

/// A source rectangle property
#[derive(Copy)]
pub struct SrcRect(pub internal::SourceRectangle);

/// Clears the screen.
pub fn clear<G>(
    color: internal::Color, g: &mut G
)
    where G: Graphics
{
    g.clear(color);
}

/// Draws image.
pub fn image<G>(
    image: &<G as Graphics>::Texture,
    transform: vecmath::Matrix2d,
    g: &mut G
)
    where G: Graphics
{
    Image::new().draw(image, default_draw_state(), transform, g);
}

/// Draws ellipse.
pub fn ellipse<G>(
    color: internal::Color,
    rect: internal::Rectangle,
    transform: vecmath::Matrix2d,
    g: &mut G
)
    where G: Graphics
{
    Ellipse::new(color).draw(rect, default_draw_state(), transform, g);
}

/// Draws rectangle.
pub fn rectangle<G>(
    color: internal::Color,
    rect: internal::Rectangle,
    transform: vecmath::Matrix2d,
    g: &mut G
)
    where G: Graphics
{
    Rectangle::new(color).draw(rect, default_draw_state(), transform, g);
}

/// Draws polygon.
pub fn polygon<G>(
    color: internal::Color,
    polygon: internal::Polygon,
    transform: vecmath::Matrix2d,
    g: &mut G
)
    where G: Graphics
{
    Polygon::new(color).draw(polygon, default_draw_state(), transform, g);
}
<commit_msg>Fix warnings<commit_after>#![crate_name = "graphics"]
#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

//! A library for 2D graphics that works with multiple back-ends.

extern crate vecmath as vecmath_lib;
extern crate texture;
extern crate read_color;
#[macro_use]
extern crate quack;
extern crate interpolation;
extern crate draw_state as draw_state_lib;

pub use texture::ImageSize;
pub use draw_state_lib as draw_state;
pub use draw_state::DrawState;

pub use graphics::Graphics;
pub use graphics::Graphics as BackEnd;
pub use relative::Colored as RelativeColor;
pub use relative::Rectangled as RelativeRectangle;
pub use relative::SourceRectangled as RelativeSourceRectangle;
pub use relative::Transformed as RelativeTransform;
pub use relative::ViewTransformed as RelativeViewTransform;
pub use relative::{
    Colored,
    Rectangled,
    SourceRectangled,
    Transformed,
    ViewTransformed,
};
pub use rectangle::Rectangle;
pub use line::Line;
pub use ellipse::Ellipse;
pub use image::Image;
pub use polygon::Polygon;
pub use vecmath::abs_transform;
pub use default_draw_state::default_draw_state;

pub use context::Context as Context;

/// Any triangulation method called on the back-end
/// never exceeds this number of vertices.
/// This can be used to initialize buffers that fit the chunk size.
pub static BACK_END_MAX_VERTEX_COUNT: usize = 1024;

mod graphics;
mod relative;
mod default_draw_state;

pub mod character;
pub mod context;
pub mod color;
pub mod polygon;
pub mod line;
pub mod ellipse;
pub mod rectangle;
pub mod image;
pub mod internal;
pub mod modular_index;
pub mod text;
pub mod triangulation;
pub mod vecmath;
pub mod deform;
pub mod grid;

pub mod radians {
    //! Reexport radians helper trait from vecmath

    pub use vecmath_lib::consts::Radians;
}

/// A color property
#[derive(Copy)]
pub struct Color(pub internal::Color);

/// A rectangle property
#[derive(Copy)]
pub struct Rect(pub internal::Rectangle);

/// A source rectangle property
#[derive(Copy)]
pub struct SrcRect(pub internal::SourceRectangle);

/// Clears the screen.
pub fn clear<G>(
    color: internal::Color, g: &mut G
)
    where G: Graphics
{
    g.clear(color);
}

/// Draws image.
pub fn image<G>(
    image: &<G as Graphics>::Texture,
    transform: vecmath::Matrix2d,
    g: &mut G
)
    where G: Graphics
{
    Image::new().draw(image, default_draw_state(), transform, g);
}

/// Draws ellipse.
pub fn ellipse<G>(
    color: internal::Color,
    rect: internal::Rectangle,
    transform: vecmath::Matrix2d,
    g: &mut G
)
    where G: Graphics
{
    Ellipse::new(color).draw(rect, default_draw_state(), transform, g);
}

/// Draws rectangle.
pub fn rectangle<G>(
    color: internal::Color,
    rect: internal::Rectangle,
    transform: vecmath::Matrix2d,
    g: &mut G
)
    where G: Graphics
{
    Rectangle::new(color).draw(rect, default_draw_state(), transform, g);
}

/// Draws polygon.
pub fn polygon<G>(
    color: internal::Color,
    polygon: internal::Polygon,
    transform: vecmath::Matrix2d,
    g: &mut G
)
    where G: Graphics
{
    Polygon::new(color).draw(polygon, default_draw_state(), transform, g);
}
<|endoftext|>


<commit_before>//! An undo-redo library with dynamic dispatch and automatic command merging.
//! It uses the [command pattern](https://en.wikipedia.org/wiki/Command_pattern)
//! where the user modifies a receiver by applying commands on it.
//!
//! The library has currently two data structures that can be used to modify the receiver:
//!
//! * A stack that can push and pop commands to modify the receiver.
//! * A record that can roll the state of the receiver forwards and backwards.

#![forbid(unstable_features, bad_style)]
#![deny(missing_debug_implementations, unused_import_braces, unused_qualifications, unsafe_code)]

mod group;
mod record;
mod stack;

use std::error;
use std::fmt::{self, Debug, Display, Formatter};

pub use group::{Group, GroupBuilder};
pub use record::{Commands, Record, RecordBuilder, Signal};
pub use stack::Stack;

/// Base functionality for all commands.
#[cfg(not(feature = "display"))]
pub trait Command<R>: Debug {
    /// Executes the desired command and returns `Ok` if everything went fine, and `Err` if
    /// something went wrong.
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    /// Restores the state as it was before [`exec`] was called and returns `Ok` if everything
    /// went fine, and `Err` if something went wrong.
    ///
    /// [`exec`]: trait.Command.html#tymethod.exec
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    /// Used for automatic merging of commands.
    ///
    /// Two commands are merged together when a command is pushed, and it has
    /// the same id as the top command already on the stack or record. When commands are merged together,
    /// undoing and redoing them are done in one step.
    ///
    /// # Examples
    /// ```
    /// use std::error::Error;
    /// use undo::{Command, Record};
    ///
    /// #[derive(Debug)]
    /// struct Add(char);
    ///
    /// impl Command<String> for Add {
    ///     fn exec(&mut self, s: &mut String) -> Result<(), Box<Error>> {
    ///         s.push(self.0);
    ///         Ok(())
    ///     }
    ///
    ///     fn undo(&mut self, s: &mut String) -> Result<(), Box<Error>> {
    ///         self.0 = s.pop().ok_or("`String` is unexpectedly empty")?;
    ///         Ok(())
    ///     }
    ///
    ///     fn id(&self) -> Option<u32> {
    ///         Some(1)
    ///     }
    /// }
    ///
    /// fn foo() -> Result<(), Box<Error>> {
    ///     let mut record = Record::default();
    ///
    ///     // 'a', 'b', and 'c' are merged.
    ///     record.exec(Add('a'))?;
    ///     record.exec(Add('b'))?;
    ///     record.exec(Add('c'))?;
    ///     assert_eq!(record.len(), 1);
    ///     assert_eq!(record.as_receiver(), "abc");
    ///
    ///     // Calling `undo` once will undo all merged commands.
    ///     record.undo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "");
    ///
    ///     // Calling `redo` once will redo all merged commands.
    ///     record.redo().unwrap()?;
    ///     assert_eq!(record.into_receiver(), "abc");
    ///
    ///     Ok(())
    /// }
    /// # foo().unwrap();
    /// ```
    #[inline]
    fn id(&self) -> Option<u32> {
        None
    }
}

/// Base functionality for all commands.
#[cfg(feature = "display")]
pub trait Command<R>: Debug + Display {
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    #[inline]
    fn id(&self) -> Option<u32> {
        None
    }
}

impl<R, C: Command<R> + ?Sized> Command<R> for Box<C> {
    #[inline]
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        (**self).exec(receiver)
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        (**self).undo(receiver)
    }

    #[inline]
    fn id(&self) -> Option<u32> {
        (**self).id()
    }
}

struct Merger<R> {
    cmd1: Box<Command<R>>,
    cmd2: Box<Command<R>>,
}

impl<R> Command<R> for Merger<R> {
    #[inline]
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        self.cmd1.exec(receiver)?;
        self.cmd2.exec(receiver)
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        self.cmd2.undo(receiver)?;
        self.cmd1.undo(receiver)
    }

    #[inline]
    fn id(&self) -> Option<u32> {
        self.cmd1.id()
    }
}

impl<R> Debug for Merger<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Merger")
            .field("cmd1", &self.cmd1)
            .field("cmd2", &self.cmd2)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<R> Display for Merger<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{} + {}", self.cmd1, self.cmd2)
    }
}

/// An error kind that holds the error and the command that caused the error.
#[derive(Debug)]
pub struct Error<R>(pub Box<Command<R>>, pub Box<error::Error>);

impl<R> Display for Error<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.1)
    }
}

impl<R: Debug> error::Error for Error<R> {
    #[inline]
    fn description(&self) -> &str {
        self.1.description()
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        self.1.cause()
    }
}
<commit_msg>Remove all documentation from display version<commit_after>//! An undo-redo library with dynamic dispatch and automatic command merging.
//! It uses the [command pattern](https://en.wikipedia.org/wiki/Command_pattern)
//! where the user modifies a receiver by applying commands on it.
//!
//! The library has currently two data structures that can be used to modify the receiver:
//!
//! * A stack that can push and pop commands to modify the receiver.
//! * A record that can roll the state of the receiver forwards and backwards.

#![forbid(unstable_features, bad_style)]
#![deny(missing_debug_implementations, unused_import_braces, unused_qualifications, unsafe_code)]

mod group;
mod record;
mod stack;

use std::error;
use std::fmt::{self, Debug, Display, Formatter};

pub use group::{Group, GroupBuilder};
pub use record::{Commands, Record, RecordBuilder, Signal};
pub use stack::Stack;

/// Base functionality for all commands.
#[cfg(not(feature = "display"))]
pub trait Command<R>: Debug {
    /// Executes the desired command and returns `Ok` if everything went fine, and `Err` if
    /// something went wrong.
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    /// Restores the state as it was before [`exec`] was called and returns `Ok` if everything
    /// went fine, and `Err` if something went wrong.
    ///
    /// [`exec`]: trait.Command.html#tymethod.exec
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    /// Used for automatic merging of commands.
    ///
    /// Two commands are merged together when a command is pushed, and it has
    /// the same id as the top command already on the stack or record. When commands are merged together,
    /// undoing and redoing them are done in one step.
    ///
    /// # Examples
    /// ```
    /// use std::error::Error;
    /// use undo::{Command, Record};
    ///
    /// #[derive(Debug)]
    /// struct Add(char);
    ///
    /// impl Command<String> for Add {
    ///     fn exec(&mut self, s: &mut String) -> Result<(), Box<Error>> {
    ///         s.push(self.0);
    ///         Ok(())
    ///     }
    ///
    ///     fn undo(&mut self, s: &mut String) -> Result<(), Box<Error>> {
    ///         self.0 = s.pop().ok_or("`String` is unexpectedly empty")?;
    ///         Ok(())
    ///     }
    ///
    ///     fn id(&self) -> Option<u32> {
    ///         Some(1)
    ///     }
    /// }
    ///
    /// fn foo() -> Result<(), Box<Error>> {
    ///     let mut record = Record::default();
    ///
    ///     // 'a', 'b', and 'c' are merged.
    ///     record.exec(Add('a'))?;
    ///     record.exec(Add('b'))?;
    ///     record.exec(Add('c'))?;
    ///     assert_eq!(record.len(), 1);
    ///     assert_eq!(record.as_receiver(), "abc");
    ///
    ///     // Calling `undo` once will undo all merged commands.
    ///     record.undo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "");
    ///
    ///     // Calling `redo` once will redo all merged commands.
    ///     record.redo().unwrap()?;
    ///     assert_eq!(record.into_receiver(), "abc");
    ///
    ///     Ok(())
    /// }
    /// # foo().unwrap();
    /// ```
    #[inline]
    fn id(&self) -> Option<u32> {
        None
    }
}

#[cfg(feature = "display")]
pub trait Command<R>: Debug + Display {
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    #[inline]
    fn id(&self) -> Option<u32> {
        None
    }
}

impl<R, C: Command<R> + ?Sized> Command<R> for Box<C> {
    #[inline]
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        (**self).exec(receiver)
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        (**self).undo(receiver)
    }

    #[inline]
    fn id(&self) -> Option<u32> {
        (**self).id()
    }
}

struct Merger<R> {
    cmd1: Box<Command<R>>,
    cmd2: Box<Command<R>>,
}

impl<R> Command<R> for Merger<R> {
    #[inline]
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        self.cmd1.exec(receiver)?;
        self.cmd2.exec(receiver)
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        self.cmd2.undo(receiver)?;
        self.cmd1.undo(receiver)
    }

    #[inline]
    fn id(&self) -> Option<u32> {
        self.cmd1.id()
    }
}

impl<R> Debug for Merger<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Merger")
            .field("cmd1", &self.cmd1)
            .field("cmd2", &self.cmd2)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<R> Display for Merger<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{} + {}", self.cmd1, self.cmd2)
    }
}

/// An error kind that holds the error and the command that caused the error.
#[derive(Debug)]
pub struct Error<R>(pub Box<Command<R>>, pub Box<error::Error>);

impl<R> Display for Error<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.1)
    }
}

impl<R: Debug> error::Error for Error<R> {
    #[inline]
    fn description(&self) -> &str {
        self.1.description()
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        self.1.cause()
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate slog;
extern crate slog_term;
extern crate slog_async;

extern crate blas;
extern crate openblas_src;

#[macro_use] extern crate ndarray;

extern crate serde;
extern crate serde_json;
extern crate serde_test;
#[macro_use] extern crate serde_derive;

// extern crate futures;
extern crate rand;

mod utils;
mod consts;
mod macros;

pub mod parameter;
pub use self::parameter::Parameter;

mod experiment;
pub use self::experiment::*;

pub mod agents;
pub mod domains;
pub mod fa;
pub mod geometry;
pub mod logging;
pub mod policies;
<commit_msg>refactor: hide parameter module<commit_after>#[macro_use] extern crate slog;
extern crate slog_term;
extern crate slog_async;

extern crate blas;
extern crate openblas_src;

#[macro_use] extern crate ndarray;

extern crate serde;
extern crate serde_json;
extern crate serde_test;
#[macro_use] extern crate serde_derive;

// extern crate futures;
extern crate rand;

mod utils;
mod consts;
mod macros;

mod experiment;
pub use self::experiment::*;

mod parameter;
pub use self::parameter::Parameter;

pub mod agents;
pub mod domains;
pub mod fa;
pub mod geometry;
pub mod logging;
pub mod policies;
<|endoftext|>


<commit_before>extern crate num;
use num::traits::{Zero, One, Signed, ToPrimitive};
use num::bigint::{BigInt, ToBigInt};
use num::rational::BigRational;

fn factorial(nf: f32) -> BigInt
{
    let n = nf as i64; // hack, let's do the cast here
    let mut acc = One::one();
    for i in 2 .. n + 1
    {
        acc = acc * i.to_bigint().unwrap();
    }
    acc
}

fn minus_one_pow(n: i64) -> i64
{
    1 - n % 2 * 2
}

fn to_bigint(n: f32) -> BigInt
{
    (n as i64).to_bigint().unwrap()
}

// could optimize the type usage better if i knew what i'm doing
pub fn clebschgordansq(j1: f32, m1: f32, j2: f32, m2: f32, j12: f32, m12: f32) -> (i32, BigRational)
{
    if m1 + m2 != m12 || j1 + j2 < j12 || (j1 - j2).abs() > j12 || (2. * (j1 + j2 + j12)) % 2. != 0.
    {
        return (0, Zero::zero())
    }

    let kmin = -(0_f32.min(j12 - j2 + m1).min(j12 - j1 - m2).trunc());
    let kmax = (j1 + j2 - j12).min(j1 - m1).min(j2 + m2).trunc();
    if kmin > kmax
    {
        return (0, Zero::zero())
    }

    let mut c1 = kmin.trunc();
    let mut c2 = (j1 + j2 - j12 - kmin).trunc();
    let mut c3 = (j1 - m1 - kmin).trunc();
    let mut c4 = (j2 + m2 - kmin).trunc();
    let mut c5 = (j12 - j2 + m1 + kmin).trunc();
    let mut c6 = (j12 - j1 - m2 + kmin).trunc();
    let mut c = BigRational::new(
        minus_one_pow(kmin as i64).to_bigint().unwrap(),
        factorial(c1) * factorial(c2) * factorial(c3) * factorial(c4) * factorial(c5) * factorial(c6)
    );
    let mut r = c.clone();

    for _ in kmin as i64 .. kmax as i64  // k unused, removed the +1
    {
        c1 += 1.;
        c5 += 1.;
        c6 += 1.;
        c = c * BigRational::new(
            to_bigint(-c2 * c3 * c4),  // could overflow, don't know the size of values
            to_bigint(c1 * c5 * c6)
        );
        c2 -= 1.;
        c3 -= 1.;
        c4 -= 1.;
        r = r + c.clone();  // ops::AddAssign is still on RFC
    }

    let sign = r.signum().to_integer().to_i32().unwrap(); // this sucks
    let rsq = r.clone() * r; // ugly, pow() not implemented for BigInt

    let val = BigRational::new(
        to_bigint(2. * j12 + 1.) *
        factorial(j12 + j1 - j2) *
        factorial(j12 - j1 + j2) *
        factorial(j1 + j2 - j12) *
        factorial(j12 + m12) * // reordered things here because BigRational * BigInt isn't implemented
        factorial(j12 - m12) *
        factorial(j1 - m1) *
        factorial(j1 + m1) *
        factorial(j2 - m2) *
        factorial(j2 + m2),
        factorial(j1 + j2 + j12 + 1.)
    ) * rsq;

    (sign, val)
}

/*
// can't sqrt() a BigNum, so this doesn't work. maybe should turn it back into float?
pub fn clebschgordan(j1: f32, m1: f32, j2: f32, m2: f32, j12: f32, m12: f32) -> BigRational
{
    let (s, r) = clebschgordansq(j1, m1, j2, m2, j12, m12);
    s * r.sqrt()
}
*/
<commit_msg>use more ints<commit_after>extern crate num;
use num::traits::{Zero, One, Signed, ToPrimitive};
use num::bigint::{BigInt, ToBigInt};
use num::rational::BigRational;

fn factorial(n: i64) -> BigInt
{
    let mut acc = One::one();
    for i in 2 .. n + 1
    {
        acc = acc * i.to_bigint().unwrap();
    }
    acc
}

fn factorial_f(n: f32) -> BigInt
{
    factorial(n as i64)
}

fn minus_one_pow(n: i64) -> i64
{
    1 - n % 2 * 2
}

// could optimize the type usage better if i knew what i'm doing
pub fn clebschgordansq(j1: f32, m1: f32, j2: f32, m2: f32, j12: f32, m12: f32) -> (i32, BigRational)
{
    if m1 + m2 != m12 || j1 + j2 < j12 || (j1 - j2).abs() > j12 || (2. * (j1 + j2 + j12)) % 2. != 0.
    {
        return (0, Zero::zero())
    }

    let kmin = -(0_f32.min(j12 - j2 + m1).min(j12 - j1 - m2).trunc());
    let kmax = (j1 + j2 - j12).min(j1 - m1).min(j2 + m2).trunc();
    if kmin > kmax
    {
        return (0, Zero::zero())
    }

    let mut c1 = kmin as i64;
    let mut c2 = (j1 + j2 - j12 - kmin) as i64;
    let mut c3 = (j1 - m1 - kmin) as i64;
    let mut c4 = (j2 + m2 - kmin) as i64;
    let mut c5 = (j12 - j2 + m1 + kmin) as i64;
    let mut c6 = (j12 - j1 - m2 + kmin) as i64;
    let mut c = BigRational::new(
        minus_one_pow(kmin as i64).to_bigint().unwrap(),
        factorial(c1) * factorial(c2) * factorial(c3) * factorial(c4) * factorial(c5) * factorial(c6)
    );
    let mut r = c.clone();

    for _ in kmin as i64 .. kmax as i64  // k unused, removed the +1
    {
        c1 += 1;
        c5 += 1;
        c6 += 1;
        c = c * BigRational::new(
            (-c2 * c3 * c4).to_bigint().unwrap(),  // could overflow, don't know the size of values
            (c1 * c5 * c6).to_bigint().unwrap()
        );
        c2 -= 1;
        c3 -= 1;
        c4 -= 1;
        r = r + c.clone();  // ops::AddAssign is still on RFC
    }

    let sign = r.signum().to_integer().to_i32().unwrap(); // this sucks
    let rsq = r.clone() * r; // ugly, pow() not implemented for BigInt

    let val = BigRational::new(
        ((2. * j12 + 1.) as i64).to_bigint().unwrap() *
        factorial_f(j12 + j1 - j2) *
        factorial_f(j12 - j1 + j2) *
        factorial_f(j1 + j2 - j12) *
        factorial_f(j12 + m12) * // reordered things here because BigRational * BigInt isn't implemented
        factorial_f(j12 - m12) *
        factorial_f(j1 - m1) *
        factorial_f(j1 + m1) *
        factorial_f(j2 - m2) *
        factorial_f(j2 + m2),
        factorial_f(j1 + j2 + j12 + 1.)
    ) * rsq;

    (sign, val)
}

/*
// can't sqrt() a BigNum, so this doesn't work. maybe should turn it back into float?
pub fn clebschgordan(j1: f32, m1: f32, j2: f32, m2: f32, j12: f32, m12: f32) -> BigRational
{
    let (s, r) = clebschgordansq(j1, m1, j2, m2, j12, m12);
    s * r.sqrt()
}
*/
<|endoftext|>