<commit_before>// TODO: whilst developing, suppress unused warnings
#![allow(dead_code)]

extern crate dialoguer;
#[macro_use]
extern crate quote;

use dialoguer::Input;
use std::path::PathBuf;
use std::{
    fs::{self, File},
    io::Write,
    path::Path,
};

mod api_generator;
mod error;
mod rest_spec;

fn main() {
    // This must be run from the src root directory, with cargo run -p api_generator
    let download_dir = fs::canonicalize(PathBuf::from("./api_generator/rest_specs")).unwrap();
    let generated_dir = fs::canonicalize(PathBuf::from("./elasticsearch/src")).unwrap();
    let last_downloaded_version = "./api_generator/last_downloaded_version";

    let mut download_specs = false;
    let mut answer = String::new();
    let mut branch = String::new();
    let default_branch = if Path::new(last_downloaded_version).exists() {
        fs::read_to_string(last_downloaded_version).expect("Could not read branch into string")
    } else {
        String::from("master")
    };

    while answer != "y" && answer != "n" {
        answer = Input::new()
            .default(String::from("n"))
            .show_default(false)
            .with_prompt("Download rest specifications [y/N]")
            .interact()
            .unwrap()
            .to_lowercase();
        download_specs = answer == "y";
    }

    if download_specs {
        branch = Input::new()
            .default(default_branch.clone())
            .show_default(false)
            .with_prompt(
                format!(
                    "Branch to download specification from [default {}]",
                    default_branch
                )
                .as_str(),
            )
            .interact()
            .unwrap();

        fs::remove_dir_all(&download_dir).unwrap();
        rest_spec::download_specs(&branch, &download_dir);

        File::create(last_downloaded_version)
            .expect("failed to create last_downloaded_version file")
            .write_all(branch.as_bytes())
            .expect("unable to write branch to last_downloaded_version file");
    }

    // only offer to generate if there are downloaded specs
    if download_dir
        .read_dir()
        .map(|mut r| r.next().is_some())
        .unwrap_or(false)
    {
        let mut generate_code = true;
        answer = String::new();
        while answer != "y" && answer != "n" {
            answer = Input::new()
                .default(String::from("y"))
                .show_default(false)
                .with_prompt(
                    format!(
                        "Generate code from rest specifications {} [Y/n]",
                        default_branch
                    )
                    .as_str(),
                )
                .interact()
                .unwrap()
                .to_lowercase();
            generate_code = answer == "y";
        }

        if generate_code {
            api_generator::generate(&branch, &download_dir, &generated_dir).unwrap();
        }
    }
}
<commit_msg>Fix generate_code prompt<commit_after>// TODO: whilst developing, suppress unused warnings
#![allow(dead_code)]

extern crate dialoguer;
#[macro_use]
extern crate quote;

use dialoguer::Input;
use std::path::PathBuf;
use std::{
    fs::{self, File},
    io::Write,
    path::Path,
};

mod api_generator;
mod error;
mod rest_spec;

fn main() {
    // This must be run from the src root directory, with cargo run -p api_generator
    let download_dir = fs::canonicalize(PathBuf::from("./api_generator/rest_specs")).unwrap();
    let generated_dir = fs::canonicalize(PathBuf::from("./elasticsearch/src")).unwrap();
    let last_downloaded_version = "./api_generator/last_downloaded_version";

    let mut download_specs = false;
    let mut answer = String::new();
    let default_branch = if Path::new(last_downloaded_version).exists() {
        fs::read_to_string(last_downloaded_version).expect("Could not read branch into string")
    } else {
        String::from("master")
    };
    let mut branch = default_branch.clone();

    while answer != "y" && answer != "n" {
        answer = Input::new()
            .default(String::from("n"))
            .show_default(false)
            .with_prompt("Download rest specifications [y/N]")
            .interact()
            .unwrap()
            .to_lowercase();
        download_specs = answer == "y";
    }

    if download_specs {
        branch = Input::new()
            .default(default_branch.clone())
            .show_default(false)
            .with_prompt(
                format!(
                    "Branch to download specification from [default {}]",
                    default_branch
                )
                .as_str(),
            )
            .interact()
            .unwrap();

        fs::remove_dir_all(&download_dir).unwrap();
        rest_spec::download_specs(&branch, &download_dir);

        File::create(last_downloaded_version)
            .expect("failed to create last_downloaded_version file")
            .write_all(branch.as_bytes())
            .expect("unable to write branch to last_downloaded_version file");
    }

    // only offer to generate if there are downloaded specs
    if download_dir
        .read_dir()
        .map(|mut r| r.next().is_some())
        .unwrap_or(false)
    {
        let mut generate_code = true;
        answer = String::new();
        while answer != "y" && answer != "n" {
            answer = Input::new()
                .default(String::from("y"))
                .show_default(false)
                .with_prompt(
                    format!(
                        "Generate code from rest specifications {} [Y/n]",
                        branch
                    )
                    .as_str(),
                )
                .interact()
                .unwrap()
                .to_lowercase();
            generate_code = answer == "y";
        }

        if generate_code {
            api_generator::generate(&branch, &download_dir, &generated_dir).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Read};
use std::marker::PhantomData;
use std::ops::Deref;
use std::ptr;

use {Error, raw};

pub struct JobDriver<R: Read> {
    input: R,
    job: Job,
    buf: Vec<u8>,
    pos: usize,
    cap: usize,
    input_ended: bool,
}

pub struct Job(pub *mut raw::rs_job_t);

// Wrapper around rs_buffers_t.
struct Buffers<'a> {
    inner: raw::rs_buffers_t,
    _phantom: PhantomData<&'a u8>,
}

impl<R: Read> JobDriver<R> {
    pub fn new(input: R, job: Job) -> Self {
        JobDriver {
            input: input,
            job: job,
            buf: vec![0; raw::RS_DEFAULT_BLOCK_LEN],
            pos: 0,
            cap: 0,
            input_ended: false,
        }
    }

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

    /// Complete the job by working without an output buffer.
    ///
    /// If the job needs to write some data, an `ErrorKind::WouldBlock` error is returned.
    pub fn consume_input(&mut self) -> io::Result<()> {
        loop {
            if self.cap == 0 && !self.input_ended {
                // need to read some data from input
                let read = try!(self.input.read(&mut self.buf));
                if read == 0 {
                    self.input_ended = true;
                }
                self.pos = 0;
                self.cap = read;
            }

            // work
            let mut buffers = Buffers::with_no_out(&self.buf[self.pos..self.pos + self.cap],
                                                   self.input_ended);
            let res = unsafe { raw::rs_job_iter(*self.job, buffers.as_raw()) };
            if res != raw::RS_DONE && res != raw::RS_BLOCKED {
                let err = Error::from(res);
                return Err(io::Error::new(io::ErrorKind::Other, err));
            }

            // update buffer cap and pos
            let read = self.cap - buffers.available_input();
            self.pos += read;
            self.cap -= read;
            if self.input_ended {
                return Ok(());
            }
        }
    }
}

impl<R: Read> Read for JobDriver<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut out_pos = 0;
        let mut out_cap = buf.len();

        loop {
            if self.cap == 0 && !self.input_ended {
                // need to read some data from input
                let read = try!(self.input.read(&mut self.buf));
                if read == 0 {
                    self.input_ended = true;
                }
                self.pos = 0;
                self.cap = read;
            }

            // work
            let mut buffers = Buffers::new(&self.buf[self.pos..self.pos + self.cap],
                                           &mut buf[out_pos..],
                                           self.input_ended);
            let res = unsafe { raw::rs_job_iter(*self.job, buffers.as_raw()) };
            if res != raw::RS_DONE && res != raw::RS_BLOCKED {
                let err = Error::from(res);
                return Err(io::Error::new(io::ErrorKind::Other, err));
            }

            // update buffer cap and pos
            let read = self.cap - buffers.available_input();
            self.pos += read;
            self.cap -= read;
            // determine written
            let written = out_cap - buffers.available_output();
            out_pos += written;
            out_cap -= written;
            if out_cap == 0 || written == 0 {
                return Ok(out_pos);
            }
        }
    }
}

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

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

impl<'a> Buffers<'a> {
    pub fn new(in_buf: &'a [u8], out_buf: &'a mut [u8], eof_in: bool) -> Self {
        Buffers {
            inner: raw::rs_buffers_t {
                next_in: in_buf.as_ptr() as *const i8,
                avail_in: in_buf.len(),
                eof_in: if eof_in { 1 } else { 0 },
                next_out: out_buf.as_mut_ptr() as *mut i8,
                avail_out: out_buf.len(),
            },
            _phantom: PhantomData,
        }
    }

    pub fn with_no_out(in_buf: &'a [u8], eof_in: bool) -> Self {
        Buffers {
            inner: raw::rs_buffers_t {
                next_in: in_buf.as_ptr() as *const i8,
                avail_in: in_buf.len(),
                eof_in: if eof_in { 1 } else { 0 },
                next_out: ptr::null_mut(),
                avail_out: 0,
            },
            _phantom: PhantomData,
        }
    }

    pub fn as_raw(&mut self) -> *mut raw::rs_buffers_t {
        &mut self.inner
    }

    pub fn available_input(&self) -> usize {
        self.inner.avail_in as usize
    }

    pub fn available_output(&self) -> usize {
        self.inner.avail_out as usize
    }
}
<commit_msg>JobDriver now handles missing output buffer<commit_after>use std::io::{self, Read};
use std::marker::PhantomData;
use std::ops::Deref;
use std::ptr;

use {Error, raw};

pub struct JobDriver<R: Read> {
    input: R,
    job: Job,
    buf: Vec<u8>,
    pos: usize,
    cap: usize,
    input_ended: bool,
}

pub struct Job(pub *mut raw::rs_job_t);

// Wrapper around rs_buffers_t.
struct Buffers<'a> {
    inner: raw::rs_buffers_t,
    _phantom: PhantomData<&'a u8>,
}

impl<R: Read> JobDriver<R> {
    pub fn new(input: R, job: Job) -> Self {
        JobDriver {
            input: input,
            job: job,
            buf: vec![0; raw::RS_DEFAULT_BLOCK_LEN],
            pos: 0,
            cap: 0,
            input_ended: false,
        }
    }

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

    /// Complete the job by working without an output buffer.
    ///
    /// If the job needs to write some data, an `ErrorKind::WouldBlock` error is returned.
    pub fn consume_input(&mut self) -> io::Result<()> {
        loop {
            if self.cap == 0 && !self.input_ended {
                // need to read some data from input
                let read = try!(self.input.read(&mut self.buf));
                if read == 0 {
                    self.input_ended = true;
                }
                self.pos = 0;
                self.cap = read;
            }

            // work
            let mut buffers = Buffers::with_no_out(&self.buf[self.pos..self.pos + self.cap],
                                                   self.input_ended);
            let res = unsafe { raw::rs_job_iter(*self.job, buffers.as_raw()) };
            // update buffer cap and pos
            let read = self.cap - buffers.available_input();
            self.pos += read;
            self.cap -= read;

            // determine result
            // NOTE: this should be done here, after the input buffer update, because we need to
            // know if the possible RS_BLOCKED result is due to a full input, or to an empty output
            // buffer
            match res {
                raw::RS_DONE => (),
                raw::RS_BLOCKED => {
                    if self.cap > 0 {
                        // the block is due to a missing output buffer
                        return Err(io::Error::new(io::ErrorKind::WouldBlock,
                                                  "cannot consume input without an output buffer"));
                    }
                }
                _ => {
                    let err = Error::from(res);
                    return Err(io::Error::new(io::ErrorKind::Other, err));
                }
            };

            if self.input_ended {
                return Ok(());
            }
        }
    }
}

impl<R: Read> Read for JobDriver<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut out_pos = 0;
        let mut out_cap = buf.len();

        loop {
            if self.cap == 0 && !self.input_ended {
                // need to read some data from input
                let read = try!(self.input.read(&mut self.buf));
                if read == 0 {
                    self.input_ended = true;
                }
                self.pos = 0;
                self.cap = read;
            }

            // work
            let mut buffers = Buffers::new(&self.buf[self.pos..self.pos + self.cap],
                                           &mut buf[out_pos..],
                                           self.input_ended);
            let res = unsafe { raw::rs_job_iter(*self.job, buffers.as_raw()) };
            if res != raw::RS_DONE && res != raw::RS_BLOCKED {
                let err = Error::from(res);
                return Err(io::Error::new(io::ErrorKind::Other, err));
            }

            // update buffer cap and pos
            let read = self.cap - buffers.available_input();
            self.pos += read;
            self.cap -= read;
            // determine written
            let written = out_cap - buffers.available_output();
            out_pos += written;
            out_cap -= written;
            if out_cap == 0 || written == 0 {
                return Ok(out_pos);
            }
        }
    }
}

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

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

impl<'a> Buffers<'a> {
    pub fn new(in_buf: &'a [u8], out_buf: &'a mut [u8], eof_in: bool) -> Self {
        Buffers {
            inner: raw::rs_buffers_t {
                next_in: in_buf.as_ptr() as *const i8,
                avail_in: in_buf.len(),
                eof_in: if eof_in { 1 } else { 0 },
                next_out: out_buf.as_mut_ptr() as *mut i8,
                avail_out: out_buf.len(),
            },
            _phantom: PhantomData,
        }
    }

    pub fn with_no_out(in_buf: &'a [u8], eof_in: bool) -> Self {
        Buffers {
            inner: raw::rs_buffers_t {
                next_in: in_buf.as_ptr() as *const i8,
                avail_in: in_buf.len(),
                eof_in: if eof_in { 1 } else { 0 },
                next_out: ptr::null_mut(),
                avail_out: 0,
            },
            _phantom: PhantomData,
        }
    }

    pub fn as_raw(&mut self) -> *mut raw::rs_buffers_t {
        &mut self.inner
    }

    pub fn available_input(&self) -> usize {
        self.inner.avail_in as usize
    }

    pub fn available_output(&self) -> usize {
        self.inner.avail_out as usize
    }
}
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![feature(ip_addr)]
#[allow(dead_code)]

use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

// A network
#[derive(Debug)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

pub struct Ipv4Network {
    addr: Ipv4Addr,
    prefix: u8,
}

pub struct Ipv6Network {
    addr: Ipv6Addr,
    prefix: u8,
}

impl Ipv4Network {
    pub fn new(addr: Ipv4Addr, prefix: u8) -> Ipv4Network {
        Ipv4Network { addr: addr, prefix: prefix }
    }

    pub fn ip(&self) -> &Ipv4Addr {
        &(self.addr)
    }

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

    pub fn mask_int(&self) -> u32 {
        let prefix = self.prefix;
        !(0xffffffff >> prefix)
    }

    pub fn mask(&self) -> Ipv4Addr {
        let mask = self.mask_int();
        Ipv4Addr::from(mask)
    }

    pub fn network_int(&self) -> u32 {
        Ipv4Network::ip_to_int(*(self.ip())) & self.mask_int()
    }

    pub fn network(&self) -> Ipv4Addr {
        Ipv4Addr::from(self.network_int())
    }

    fn ip_to_int(addr: Ipv4Addr) -> u32 {
        let ip = addr.octets();
        ((ip[0] as u32) << 24) + ((ip[1] as u32) << 16) + ((ip[2] as u32) << 8) + (ip[3] as u32)
    }
}

impl Ipv6Network {
    pub fn new(addr: Ipv6Addr, prefix: u8) -> Ipv6Network {
        Ipv6Network { addr: addr, prefix: prefix }
    }

    pub fn ip(&self) -> &Ipv6Addr {
        &(self.addr)
    }

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

impl IpNetwork {
    pub fn new(ip: IpAddr, prefix: u8) -> IpNetwork {
        match ip {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::new(a, prefix)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::new(a, prefix)),
        }
    }

    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(*a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(*a.ip()),
        }
    }

    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }
}

impl fmt::Debug for Ipv4Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

impl fmt::Debug for Ipv6Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

#[cfg(test)]
mod test {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use super::*;

    #[test]
    fn create_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(77, 88, 21, 11), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn create_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn mask_int_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask_int(), 4294967288);
    }

    #[test]
    fn mask_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask(), Ipv4Addr::new(255, 255, 255, 248));
    }

    #[test]
    fn network_int_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 25);
        assert_eq!(cidr.network_int(), 1249764096);
    }

    #[test]
    fn network_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 25);
        assert_eq!(cidr.network(), Ipv4Addr::new(74, 125, 227, 0));
    }
}
<commit_msg>Also get rid of more unnecessary method<commit_after>#![crate_type = "lib"]
#![feature(ip_addr)]
#[allow(dead_code)]

use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

// A network
#[derive(Debug)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

pub struct Ipv4Network {
    addr: Ipv4Addr,
    prefix: u8,
}

pub struct Ipv6Network {
    addr: Ipv6Addr,
    prefix: u8,
}

impl Ipv4Network {
    pub fn new(addr: Ipv4Addr, prefix: u8) -> Ipv4Network {
        Ipv4Network { addr: addr, prefix: prefix }
    }

    pub fn ip(&self) -> &Ipv4Addr {
        &(self.addr)
    }

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

    pub fn mask_int(&self) -> u32 {
        let prefix = self.prefix;
        !(0xffffffff >> prefix)
    }

    pub fn mask(&self) -> Ipv4Addr {
        let mask = self.mask_int();
        Ipv4Addr::from(mask)
    }

    pub fn network_int(&self) -> u32 {
        u32::from(*(self.ip())) & self.mask_int()
    }

    pub fn network(&self) -> Ipv4Addr {
        Ipv4Addr::from(self.network_int())
    }
}

impl Ipv6Network {
    pub fn new(addr: Ipv6Addr, prefix: u8) -> Ipv6Network {
        Ipv6Network { addr: addr, prefix: prefix }
    }

    pub fn ip(&self) -> &Ipv6Addr {
        &(self.addr)
    }

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

impl IpNetwork {
    pub fn new(ip: IpAddr, prefix: u8) -> IpNetwork {
        match ip {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::new(a, prefix)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::new(a, prefix)),
        }
    }

    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(*a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(*a.ip()),
        }
    }

    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }
}

impl fmt::Debug for Ipv4Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

impl fmt::Debug for Ipv6Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

#[cfg(test)]
mod test {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use super::*;

    #[test]
    fn create_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(77, 88, 21, 11), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn create_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn mask_int_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask_int(), 4294967288);
    }

    #[test]
    fn mask_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask(), Ipv4Addr::new(255, 255, 255, 248));
    }

    #[test]
    fn network_int_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 25);
        assert_eq!(cidr.network_int(), 1249764096);
    }

    #[test]
    fn network_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 25);
        assert_eq!(cidr.network(), Ipv4Addr::new(74, 125, 227, 0));
    }
}
<|endoftext|>


<commit_before>#![allow(unstable)]

//! **petgraph** is a graph data structure library.
//!
//! The most interesting type is [**Graph**](./graph/struct.Graph.html) which is
//! a directed or undirected graph with owned mutably accessible arbitrary node and edge weights.
//! It is based on rustc's graph implementation.

use std::cmp::Ordering;
use std::hash::{self, Hash};
use std::collections::hash_map::Hasher;
use std::fmt;
use std::ops::{Deref};

pub use scored::MinScored;
pub use graphmap::GraphMap;
pub use graph::Graph;

pub use self::EdgeDirection::{Outgoing, Incoming};
pub use visit::{
    Bfs,
    BfsIter,
    Dfs,
    DfsIter,
};

mod scored;
pub mod graphmap;
pub mod graph;
pub mod visit;

pub mod unionfind;
mod isomorphism;
mod traits_graph;

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum EdgeDirection {
    /// A **Outgoing** edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An **Incoming** edge is an inbound edge *to* the current node.
    Incoming = 1
}

/// Marker type for a directed graph.
#[derive(Copy, Clone, Debug)]
pub struct Directed;

/// Marker type for an undirected graph.
#[derive(Copy, Clone, Debug)]
pub struct Undirected;

/// A graph's edge type determines whether is has directed edges or not.
pub trait EdgeType {
    fn is_directed() -> bool;
}

impl EdgeType for Directed {
    #[inline]
    fn is_directed() -> bool { true }
}

impl EdgeType for Undirected {
    #[inline]
    fn is_directed() -> bool { false }
}

/// A reference that is hashed and compared by its pointer value.
pub struct Ptr<'b, T: 'b>(pub &'b T);

impl<'b, T> Copy for Ptr<'b, T> {}
impl<'b, T> Clone for Ptr<'b, T>
{
    fn clone(&self) -> Self { *self }
}

fn ptreq<T>(a: &T, b: &T) -> bool {
    a as *const _ == b as *const _
}

impl<'b, T> PartialEq for Ptr<'b, T>
{
    /// Ptr compares by pointer equality, i.e if they point to the same value
    fn eq(&self, other: &Ptr<'b, T>) -> bool {
        ptreq(self.0, other.0)
    }
}

impl<'b, T> PartialOrd for Ptr<'b, T>
{
    fn partial_cmp(&self, other: &Ptr<'b, T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'b, T> Ord for Ptr<'b, T>
{
    /// Ptr is ordered by pointer value, i.e. an arbitrary but stable and total order.
    fn cmp(&self, other: &Ptr<'b, T>) -> Ordering {
        let a = self.0 as *const _;
        let b = other.0 as *const _;
        a.cmp(&b)
    }
}

impl<'b, T> Deref for Ptr<'b, T> {
    type Target = T;
    fn deref<'a>(&'a self) -> &'a T {
        self.0
    }
}

impl<'b, T> Eq for Ptr<'b, T> {}

impl<'b, T, H: hash::Writer + hash::Hasher> Hash<H> for Ptr<'b, T>
{
    fn hash(&self, st: &mut H)
    {
        let ptr = (self.0) as *const _;
        ptr.hash(st)
    }
}

impl<'b, T: fmt::Debug> fmt::Debug for Ptr<'b, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}
<commit_msg>Update with feature flags<commit_after>#![feature(core, hash, std_misc)]

//! **petgraph** is a graph data structure library.
//!
//! The most interesting type is [**Graph**](./graph/struct.Graph.html) which is
//! a directed or undirected graph with owned mutably accessible arbitrary node and edge weights.
//! It is based on rustc's graph implementation.

use std::cmp::Ordering;
use std::hash::{self, Hash};
use std::collections::hash_map::Hasher;
use std::fmt;
use std::ops::{Deref};

pub use scored::MinScored;
pub use graphmap::GraphMap;
pub use graph::Graph;

pub use self::EdgeDirection::{Outgoing, Incoming};
pub use visit::{
    Bfs,
    BfsIter,
    Dfs,
    DfsIter,
};

mod scored;
pub mod graphmap;
pub mod graph;
pub mod visit;

pub mod unionfind;
mod isomorphism;
mod traits_graph;

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum EdgeDirection {
    /// A **Outgoing** edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An **Incoming** edge is an inbound edge *to* the current node.
    Incoming = 1
}

/// Marker type for a directed graph.
#[derive(Copy, Clone, Debug)]
pub struct Directed;

/// Marker type for an undirected graph.
#[derive(Copy, Clone, Debug)]
pub struct Undirected;

/// A graph's edge type determines whether is has directed edges or not.
pub trait EdgeType {
    fn is_directed() -> bool;
}

impl EdgeType for Directed {
    #[inline]
    fn is_directed() -> bool { true }
}

impl EdgeType for Undirected {
    #[inline]
    fn is_directed() -> bool { false }
}

/// A reference that is hashed and compared by its pointer value.
pub struct Ptr<'b, T: 'b>(pub &'b T);

impl<'b, T> Copy for Ptr<'b, T> {}
impl<'b, T> Clone for Ptr<'b, T>
{
    fn clone(&self) -> Self { *self }
}

fn ptreq<T>(a: &T, b: &T) -> bool {
    a as *const _ == b as *const _
}

impl<'b, T> PartialEq for Ptr<'b, T>
{
    /// Ptr compares by pointer equality, i.e if they point to the same value
    fn eq(&self, other: &Ptr<'b, T>) -> bool {
        ptreq(self.0, other.0)
    }
}

impl<'b, T> PartialOrd for Ptr<'b, T>
{
    fn partial_cmp(&self, other: &Ptr<'b, T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'b, T> Ord for Ptr<'b, T>
{
    /// Ptr is ordered by pointer value, i.e. an arbitrary but stable and total order.
    fn cmp(&self, other: &Ptr<'b, T>) -> Ordering {
        let a = self.0 as *const _;
        let b = other.0 as *const _;
        a.cmp(&b)
    }
}

impl<'b, T> Deref for Ptr<'b, T> {
    type Target = T;
    fn deref<'a>(&'a self) -> &'a T {
        self.0
    }
}

impl<'b, T> Eq for Ptr<'b, T> {}

impl<'b, T, H: hash::Writer + hash::Hasher> Hash<H> for Ptr<'b, T>
{
    fn hash(&self, st: &mut H)
    {
        let ptr = (self.0) as *const _;
        ptr.hash(st)
    }
}

impl<'b, T: fmt::Debug> fmt::Debug for Ptr<'b, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}
<|endoftext|>


<commit_before>//! Temporarily redirect stdout/stderr.
//!
//! For example, one can temporarily throw away stdout output:
//!
//! ```
//! use gag::Gag;
//! println!("Hello world!");
//! {
//!     let print_gag = Gag::stdout().unwrap();
//!     println!("No one will see this!");
//!     println!("Or this!");
//! }
//! println!("But they will see this!");
//! ```
//!
//! You can also temporarily un-gag by dropping the gag:
//!
//! ```
//! use gag::Gag;
//! let mut print_gag = Gag::stdout().unwrap();
//! println!("No one will see this!");
//! if true {
//!     drop(print_gag);
//!     println!("They will see this...");
//!     print_gag = Gag::stdout().unwrap();
//!     println!("Not this...");
//! }
//! println!("Nor this.");
//! ```
//!
//! However, you can't open multiple Gags/Redirects/Holds for the same output at once:
//! ```
//! use gag::Gag;
//! // Multiple stdout gags
//! let gag_a = Gag::stdout().unwrap();
//! let gag_b_result = Gag::stdout();
//! assert!(gag_b_result.is_err());
//! assert!(gag_b_result.unwrap_err().kind() == std::io::ErrorKind::AlreadyExists);
//!
//! // However, you can still gag stderr:
//! let gag_c = Gag::stderr().unwrap()
//! ```
//!
//! If you don't want to throw away stdout, you can write it to a file:
//!
//! ```
//! use std::fs::OpenOptions;
//! use std::io::{Read, Write, Seek, SeekFrom};
//! use gag::Redirect;
//!
//! println!("Displayed");
//!
//! // Open a log
//! let log = OpenOptions::new()
//!     .truncate(true)
//!     .read(true)
//!     .create(true)
//!     .write(true)
//!     .open("/tmp/my_log.log")
//!     .unwrap();
//!
//! let print_redirect = Redirect::stdout(log).unwrap();
//! println!("Hidden");
//!
//! // Extract redirect
//! let mut log = print_redirect.into_inner();
//! println!("Displayed");
//!
//! let mut buf = String::new();
//! log.seek(SeekFrom::Start(0)).unwrap();
//! log.read_to_string(&mut buf).unwrap();
//! assert_eq!(&buf[..], "Hidden\n");
//!
//! ```
//!
//! Alternatively, you can buffer stdout to a temporary file. On linux 3.11+, this file is
//! guarenteed to be stored in-memory.
//!
//! ```
//! use std::io::Read;
//! use gag::BufferRedirect;
//!
//! let mut buf = BufferRedirect::stdout().unwrap();
//! println!("Hello world!");
//!
//! let mut output = String::new();
//! buf.read_to_string(&mut output).unwrap();
//!
//! assert_eq!(&output[..], "Hello world!\n");
//! ```
//!
//! Finally, if you just want to temporarily hold std output, you can use `Hold` to hold the output
//! until dropped:
//!
//! ```
//! use gag::Hold;
//!
//! let hold = Hold::stdout().unwrap();
//! println!("first");
//! println!("second");
//! drop(hold); // printing happens here!
//! ```
#![feature(from_raw_os)]
extern crate libc;
extern crate tempdir;

mod redirect;
mod gag;
mod buffer;
mod tempfile;
mod hold;

pub use gag::Gag;
pub use redirect::{Redirect, RedirectError};
pub use buffer::{BufferRedirect, Buffer};
pub use hold::Hold;
<commit_msg>Fix docs.<commit_after>//! Temporarily redirect stdout/stderr.
//!
//! For example, one can temporarily throw away stdout output:
//!
//! ```
//! use gag::Gag;
//! println!("Hello world!");
//! {
//!     let print_gag = Gag::stdout().unwrap();
//!     println!("No one will see this!");
//!     println!("Or this!");
//! }
//! println!("But they will see this!");
//! ```
//!
//! You can also temporarily un-gag by dropping the gag:
//!
//! ```
//! use gag::Gag;
//! let mut print_gag = Gag::stdout().unwrap();
//! println!("No one will see this!");
//! if true {
//!     drop(print_gag);
//!     println!("They will see this...");
//!     print_gag = Gag::stdout().unwrap();
//!     println!("Not this...");
//! }
//! println!("Nor this.");
//! ```
//!
//! However, you can't open multiple Gags/Redirects/Holds for the same output at once:
//!
//! ```
//! use gag::Gag;
//! // Multiple stdout gags
//! let gag_a = Gag::stdout().unwrap();
//! let gag_b_result = Gag::stdout();
//! assert!(gag_b_result.is_err());
//! assert!(gag_b_result.unwrap_err().kind() == std::io::ErrorKind::AlreadyExists);
//!
//! // However, you can still gag stderr:
//! let gag_c = Gag::stderr().unwrap()
//! ```
//!
//! If you don't want to throw away stdout, you can write it to a file:
//!
//! ```
//! use std::fs::OpenOptions;
//! use std::io::{Read, Write, Seek, SeekFrom};
//! use gag::Redirect;
//!
//! println!("Displayed");
//!
//! // Open a log
//! let log = OpenOptions::new()
//!     .truncate(true)
//!     .read(true)
//!     .create(true)
//!     .write(true)
//!     .open("/tmp/my_log.log")
//!     .unwrap();
//!
//! let print_redirect = Redirect::stdout(log).unwrap();
//! println!("Hidden");
//!
//! // Extract redirect
//! let mut log = print_redirect.into_inner();
//! println!("Displayed");
//!
//! let mut buf = String::new();
//! log.seek(SeekFrom::Start(0)).unwrap();
//! log.read_to_string(&mut buf).unwrap();
//! assert_eq!(&buf[..], "Hidden\n");
//!
//! ```
//!
//! Alternatively, you can buffer stdout to a temporary file. On linux 3.11+, this file is
//! guarenteed to be stored in-memory.
//!
//! ```
//! use std::io::Read;
//! use gag::BufferRedirect;
//!
//! let mut buf = BufferRedirect::stdout().unwrap();
//! println!("Hello world!");
//!
//! let mut output = String::new();
//! buf.read_to_string(&mut output).unwrap();
//!
//! assert_eq!(&output[..], "Hello world!\n");
//! ```
//!
//! Finally, if you just want to temporarily hold std output, you can use `Hold` to hold the output
//! until dropped:
//!
//! ```
//! use gag::Hold;
//!
//! let hold = Hold::stdout().unwrap();
//! println!("first");
//! println!("second");
//! drop(hold); // printing happens here!
//! ```
#![feature(from_raw_os)]
extern crate libc;
extern crate tempdir;

mod redirect;
mod gag;
mod buffer;
mod tempfile;
mod hold;

pub use gag::Gag;
pub use redirect::{Redirect, RedirectError};
pub use buffer::{BufferRedirect, Buffer};
pub use hold::Hold;
<|endoftext|>


<commit_before>//! Compile-time assertions to ensure that invariants are met.
//!
//! # Usage
//!
//! This crate is available [on crates.io][crate] and can be used by adding the
//! following to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! static_assertions = "0.2.4"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! #[macro_use]
//! extern crate static_assertions;
//! # fn main() {}
//! ```
//!
//! # Examples
//!
//! Thorough examples are provided within the docs for each individual macro.
//! [Here](macro.const_assert.html#examples) are examples for `const_assert`.
//!
//! # Limitations
//!
//! Due to implementation details, some macros can only be used normally from
//! within the context of a function. To use these macros in other contexts, a
//! unique label must be provided.
//!
//! This issue can be followed [here][issue1]. Feedback and potential solutions
//! are welcome!
//!
//! [issue1]: https://github.com/nvzqz/static-assertions-rs/issues/1
//! [crate]: https://crates.io/crates/static_assertions

#![no_std]

#![deny(unused_macros)]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts that the configuration is set.
///
/// # Examples
///
/// A project may not support a set of configurations and thus you may want to
/// report why:
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// // We should only be compiling for Unix or Linux
/// # #[cfg(any(unix, linux))]
/// assert_cfg!(any(unix, linux));
/// # fn main() {}
/// ```
///
/// If users need to specify a database back-end:
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # #[cfg(target_pointer_width = "0")] // Impossible
/// assert_cfg!("Must exclusively use MySQL or MongoDB as database back-end",
///             all(not(all(feature = "mysql", feature = "mongodb")),
///                 any(    feature = "mysql", feature = "mongodb")));
/// # fn main() {}
/// ```
///
/// We can't be compiling for both Unix _and_ Windows simultaneously:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// assert_cfg!(all(unix, windows));
/// # }
/// ```
#[macro_export]
macro_rules! assert_cfg {
    () => {};
    ($msg:expr, $($cfg:tt)*) => {
        #[cfg(not($($cfg)*))]
        compile_error!($msg);
    };
    ($($cfg:tt)*) => {
        #[cfg(not($($cfg)*))]
        compile_error!(concat!("Cfg does not pass: ", stringify!($($cfg)*)));
    };
}

/// Asserts at compile-time that the types have equal sizes.
///
/// When performing operations such as pointer casts or dealing with [`usize`]
/// versus [`u64`] versus [`u32`], the size of your types matter. This is where
/// this macro comes into play.
///
/// # Alternatives
///
/// There are also [`assert_eq_size_val`](macro.assert_eq_size_val.html) and
/// [`assert_eq_size_ptr`](macro.assert_eq_size_ptr.html). Instead of specifying
/// types to compare, values' sizes can be directly compared against each other.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// // Can be declared outside of a function if labeled
/// assert_eq_size!(bytes; (u8, u8), u16);
///
/// fn main() {
///     // Supports unlimited arguments:
///     assert_eq_size!([u8; 4], (u16, u16), u32);
/// }
/// ```
///
/// The following produces a compilation failure because `u32` has 4 times the
/// size of `u8`:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// assert_eq_size!(u32, u8);
/// # }
/// ```
///
/// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
/// [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html
/// [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $($xs:ty),+ $(,)*) => {
        $(let _ = $crate::_core::mem::transmute::<$x, $xs>;)+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_eq_size!($($xs)+); }
    };
}

/// Asserts at compile-time that the values pointed to have equal sizes.
///
/// This especially is useful for when coercing pointers between different types
/// and ensuring the underlying values are the same size.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// fn operation(x: &(u32, u32), y: &[u16; 4]) {
///     assert_eq_size_ptr!(x, y);
/// }
/// # fn main() {}
/// ```
///
/// Byte arrays of different lengths have different sizes:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// static BYTES: &[u8; 4] = &[
///     /* ... */
///     # 0; 4
/// ];
///
/// static TABLE: &[u8; 16] = &[
///     /* ... */
///     # 0; 16
/// ];
///
/// assert_eq_size_ptr!(BYTES, TABLE);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size_ptr {
    ($x:expr, $($xs:expr),+ $(,)*) => {
        #[allow(unknown_lints, forget_copy, unused_unsafe, useless_transmute)]
        unsafe {
            use $crate::_core::{mem, ptr};
            let mut copy = ptr::read($x);
            $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+
            mem::forget(copy);
        }
    }
}

/// Asserts at compile-time that the values have equal sizes.
///
/// This macro doesn't consume its arguments and thus works for
/// non-[`Clone`]able values.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// struct Byte(u8);
///
/// let x = 10u8;
/// let y = Byte(42); // Works for non-cloneable types
///
/// assert_eq_size_val!(x, y);
/// assert_eq_size_val!(x, y, 0u8);
/// # }
/// ```
///
/// Even though both values are 0, they are of types with different sizes:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// assert_eq_size_val!(0u8, 0u32);
/// # }
/// ```
///
/// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
#[macro_export]
macro_rules! assert_eq_size_val {
    ($x:expr, $($xs:expr),+ $(,)*) => {
        assert_eq_size_ptr!(&$x, $(&$xs),+);
    }
}

/// Asserts at compile-time that the constant expression evaluates to `true`.
///
/// There also exists [`const_assert_eq`](macro.const_assert_eq.html) for
/// validating whether a sequence of expressions are equal to one another.
///
/// # Examples
///
/// Constant expressions can be ensured to have certain properties via this
/// macro If the expression evaluates to `false`, the file will fail to compile.
/// This is synonymous to [`static_assert` in C++][static_assert].
///
/// As a [limitation](index.html#limitations), a unique label is required if
/// the macro is used outside of a function.
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// const FIVE: usize = 5;
///
/// const_assert!(twenty_five; FIVE * FIVE == 25);
///
/// fn main() {
///     const_assert!(2 + 2 == 4);
///     const_assert!(FIVE - FIVE == 0);
/// }
/// ```
///
/// Some expressions are blatantly false:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// const_assert!(1 >= 2);
/// # }
/// ```
///
/// [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert
#[macro_export]
macro_rules! const_assert {
    ($($xs:expr),+ $(,)*) => {
        #[allow(unknown_lints, eq_op)]
        let _ = [(); 0 - !($($xs)&&+) as usize];
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { const_assert!($($xs)+); }
    };
}

/// Asserts at compile-time that the constants are equal in value.
///
/// # Examples
///
/// Works as a shorthand for `const_assert!(a == b)`:
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// const TWO: usize = 2;
/// const_assert_eq!(two; TWO * TWO, TWO + TWO, 4);
///
/// fn main() {
///     const NUM: usize = 32;
///     const_assert_eq!(NUM + NUM, 64);
/// }
/// ```
///
/// Just because 2 × 2 = 2 + 2 doesn't mean it holds true for other numbers:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// const_assert_eq!(4 + 4, 4 * 4);
/// # }
/// ```
#[macro_export]
macro_rules! const_assert_eq {
    ($x:expr, $($xs:expr),+ $(,)*) => {
        const_assert!($($x == $xs),+);
    };
    ($label:ident; $x:expr, $($xs:expr),+ $(,)*) => {
        const_assert!($label; $($x == $xs),+);
    };
}

/// Asserts at compile-time that the traits are object-safe.
///
/// This is useful for when changes are made to a trait that accidentally
/// prevent it from being used as an object. Such a case would be adding a
/// generic method and forgetting to add `where Self: Sized` after it. If left
/// unnoticed, that mistake will affect crate users and break both forward and
/// backward compatibility.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// assert_obj_safe!(basic; Send, Sync, AsRef<str>);
///
/// mod inner {
///     // Works with traits that are not in the calling module
///     pub trait BasicTrait {
///         fn foo(&self);
///     }
/// }
///
/// trait MySafeTrait {
///     fn bar(&self) -> u32;
/// }
///
/// fn main() {
///     assert_obj_safe!(MySafeTrait);
///     assert_obj_safe!(inner::BasicTrait);
/// }
/// ```
///
/// Generics without `where Self: Sized` are not allowed in object-safe traits:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// trait MyUnsafeTrait {
///     fn baz<T>(&self) -> T;
/// }
///
/// # fn main() {
/// assert_obj_safe!(MyUnsafeTrait);
/// # }
/// ```
#[macro_export]
macro_rules! assert_obj_safe {
    ($($xs:ty),+ $(,)*) => {
        $(let _: &$xs;)+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_obj_safe!($($xs)+); }
    };
}

/// Asserts at compile-time that the type has the given fields.
///
/// This is useful for when types have odd fields as a result of `#[cfg]`.
#[macro_export]
macro_rules! assert_fields {
    ($t:path, $($f:ident),+) => {
        $(let $t { $f: _, .. };)+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_fields!($($xs)+); }
    };
}

/// Asserts at compile-time that the type implements the given traits.
///
/// # Examples
///
/// Can be used to ensure types implement [`Send`], [`Sync`], and other traits:
///
/// ```
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {}
/// assert_impl!(str; String, Send, Sync, From<&'static str>);
/// assert_impl!(vec; &'static [u8], Into<Vec<u8>>);
/// ```
///
/// Raw pointers cannot be sent between threads safely:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// assert_impl!(*const u8, Send);
/// # }
/// ```
///
/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
#[macro_export]
macro_rules! assert_impl {
    ($x:ty, $($t:path),+ $(,)*) => {
        $({
            fn assert_impl<T: ?Sized + $t>() {}
            assert_impl::<$x>();
        })+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_impl!($($xs)+); }
    };
}
<commit_msg>Add examples to assert_fields macro<commit_after>//! Compile-time assertions to ensure that invariants are met.
//!
//! # Usage
//!
//! This crate is available [on crates.io][crate] and can be used by adding the
//! following to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! static_assertions = "0.2.4"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! #[macro_use]
//! extern crate static_assertions;
//! # fn main() {}
//! ```
//!
//! # Examples
//!
//! Thorough examples are provided within the docs for each individual macro.
//! [Here](macro.const_assert.html#examples) are examples for `const_assert`.
//!
//! # Limitations
//!
//! Due to implementation details, some macros can only be used normally from
//! within the context of a function. To use these macros in other contexts, a
//! unique label must be provided.
//!
//! This issue can be followed [here][issue1]. Feedback and potential solutions
//! are welcome!
//!
//! [issue1]: https://github.com/nvzqz/static-assertions-rs/issues/1
//! [crate]: https://crates.io/crates/static_assertions

#![no_std]

#![deny(unused_macros)]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts that the configuration is set.
///
/// # Examples
///
/// A project may not support a set of configurations and thus you may want to
/// report why:
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// // We should only be compiling for Unix or Linux
/// # #[cfg(any(unix, linux))]
/// assert_cfg!(any(unix, linux));
/// # fn main() {}
/// ```
///
/// If users need to specify a database back-end:
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # #[cfg(target_pointer_width = "0")] // Impossible
/// assert_cfg!("Must exclusively use MySQL or MongoDB as database back-end",
///             all(not(all(feature = "mysql", feature = "mongodb")),
///                 any(    feature = "mysql", feature = "mongodb")));
/// # fn main() {}
/// ```
///
/// We can't be compiling for both Unix _and_ Windows simultaneously:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// assert_cfg!(all(unix, windows));
/// # }
/// ```
#[macro_export]
macro_rules! assert_cfg {
    () => {};
    ($msg:expr, $($cfg:tt)*) => {
        #[cfg(not($($cfg)*))]
        compile_error!($msg);
    };
    ($($cfg:tt)*) => {
        #[cfg(not($($cfg)*))]
        compile_error!(concat!("Cfg does not pass: ", stringify!($($cfg)*)));
    };
}

/// Asserts at compile-time that the types have equal sizes.
///
/// When performing operations such as pointer casts or dealing with [`usize`]
/// versus [`u64`] versus [`u32`], the size of your types matter. This is where
/// this macro comes into play.
///
/// # Alternatives
///
/// There are also [`assert_eq_size_val`](macro.assert_eq_size_val.html) and
/// [`assert_eq_size_ptr`](macro.assert_eq_size_ptr.html). Instead of specifying
/// types to compare, values' sizes can be directly compared against each other.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// // Can be declared outside of a function if labeled
/// assert_eq_size!(bytes; (u8, u8), u16);
///
/// fn main() {
///     // Supports unlimited arguments:
///     assert_eq_size!([u8; 4], (u16, u16), u32);
/// }
/// ```
///
/// The following produces a compilation failure because `u32` has 4 times the
/// size of `u8`:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// assert_eq_size!(u32, u8);
/// # }
/// ```
///
/// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
/// [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html
/// [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $($xs:ty),+ $(,)*) => {
        $(let _ = $crate::_core::mem::transmute::<$x, $xs>;)+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_eq_size!($($xs)+); }
    };
}

/// Asserts at compile-time that the values pointed to have equal sizes.
///
/// This especially is useful for when coercing pointers between different types
/// and ensuring the underlying values are the same size.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// fn operation(x: &(u32, u32), y: &[u16; 4]) {
///     assert_eq_size_ptr!(x, y);
/// }
/// # fn main() {}
/// ```
///
/// Byte arrays of different lengths have different sizes:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// static BYTES: &[u8; 4] = &[
///     /* ... */
///     # 0; 4
/// ];
///
/// static TABLE: &[u8; 16] = &[
///     /* ... */
///     # 0; 16
/// ];
///
/// assert_eq_size_ptr!(BYTES, TABLE);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size_ptr {
    ($x:expr, $($xs:expr),+ $(,)*) => {
        #[allow(unknown_lints, forget_copy, unused_unsafe, useless_transmute)]
        unsafe {
            use $crate::_core::{mem, ptr};
            let mut copy = ptr::read($x);
            $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+
            mem::forget(copy);
        }
    }
}

/// Asserts at compile-time that the values have equal sizes.
///
/// This macro doesn't consume its arguments and thus works for
/// non-[`Clone`]able values.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// struct Byte(u8);
///
/// let x = 10u8;
/// let y = Byte(42); // Works for non-cloneable types
///
/// assert_eq_size_val!(x, y);
/// assert_eq_size_val!(x, y, 0u8);
/// # }
/// ```
///
/// Even though both values are 0, they are of types with different sizes:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// assert_eq_size_val!(0u8, 0u32);
/// # }
/// ```
///
/// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
#[macro_export]
macro_rules! assert_eq_size_val {
    ($x:expr, $($xs:expr),+ $(,)*) => {
        assert_eq_size_ptr!(&$x, $(&$xs),+);
    }
}

/// Asserts at compile-time that the constant expression evaluates to `true`.
///
/// There also exists [`const_assert_eq`](macro.const_assert_eq.html) for
/// validating whether a sequence of expressions are equal to one another.
///
/// # Examples
///
/// Constant expressions can be ensured to have certain properties via this
/// macro If the expression evaluates to `false`, the file will fail to compile.
/// This is synonymous to [`static_assert` in C++][static_assert].
///
/// As a [limitation](index.html#limitations), a unique label is required if
/// the macro is used outside of a function.
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// const FIVE: usize = 5;
///
/// const_assert!(twenty_five; FIVE * FIVE == 25);
///
/// fn main() {
///     const_assert!(2 + 2 == 4);
///     const_assert!(FIVE - FIVE == 0);
/// }
/// ```
///
/// Some expressions are blatantly false:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// const_assert!(1 >= 2);
/// # }
/// ```
///
/// [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert
#[macro_export]
macro_rules! const_assert {
    ($($xs:expr),+ $(,)*) => {
        #[allow(unknown_lints, eq_op)]
        let _ = [(); 0 - !($($xs)&&+) as usize];
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { const_assert!($($xs)+); }
    };
}

/// Asserts at compile-time that the constants are equal in value.
///
/// # Examples
///
/// Works as a shorthand for `const_assert!(a == b)`:
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// const TWO: usize = 2;
/// const_assert_eq!(two; TWO * TWO, TWO + TWO, 4);
///
/// fn main() {
///     const NUM: usize = 32;
///     const_assert_eq!(NUM + NUM, 64);
/// }
/// ```
///
/// Just because 2 × 2 = 2 + 2 doesn't mean it holds true for other numbers:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// const_assert_eq!(4 + 4, 4 * 4);
/// # }
/// ```
#[macro_export]
macro_rules! const_assert_eq {
    ($x:expr, $($xs:expr),+ $(,)*) => {
        const_assert!($($x == $xs),+);
    };
    ($label:ident; $x:expr, $($xs:expr),+ $(,)*) => {
        const_assert!($label; $($x == $xs),+);
    };
}

/// Asserts at compile-time that the traits are object-safe.
///
/// This is useful for when changes are made to a trait that accidentally
/// prevent it from being used as an object. Such a case would be adding a
/// generic method and forgetting to add `where Self: Sized` after it. If left
/// unnoticed, that mistake will affect crate users and break both forward and
/// backward compatibility.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// assert_obj_safe!(basic; Send, Sync, AsRef<str>);
///
/// mod inner {
///     // Works with traits that are not in the calling module
///     pub trait BasicTrait {
///         fn foo(&self);
///     }
/// }
///
/// trait MySafeTrait {
///     fn bar(&self) -> u32;
/// }
///
/// fn main() {
///     assert_obj_safe!(MySafeTrait);
///     assert_obj_safe!(inner::BasicTrait);
/// }
/// ```
///
/// Generics without `where Self: Sized` are not allowed in object-safe traits:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// trait MyUnsafeTrait {
///     fn baz<T>(&self) -> T;
/// }
///
/// # fn main() {
/// assert_obj_safe!(MyUnsafeTrait);
/// # }
/// ```
#[macro_export]
macro_rules! assert_obj_safe {
    ($($xs:ty),+ $(,)*) => {
        $(let _: &$xs;)+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_obj_safe!($($xs)+); }
    };
}

/// Asserts at compile-time that the type has the given fields.
///
/// # Examples
///
/// This may be used when types have odd fields as a result of `#[cfg]`.
///
/// ```
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// struct Ty {
///     #[cfg(windows)]
///     value: u8,
///     #[cfg(not(windows))]
///     value: usize,
/// }
///
/// /* ... */
///
/// // Always have `value` regardless of OS
/// assert_fields!(Ty, value);
/// # }
/// ```
///
/// Range does not have a field named `middle`:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// use std::ops::Range;
///
/// assert_fields!(Range<u32>, middle);
/// # }
/// ```
#[macro_export]
macro_rules! assert_fields {
    ($t:path, $($f:ident),+) => {
        $(let $t { $f: _, .. };)+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_fields!($($xs)+); }
    };
}

/// Asserts at compile-time that the type implements the given traits.
///
/// # Examples
///
/// Can be used to ensure types implement [`Send`], [`Sync`], and other traits:
///
/// ```
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {}
/// assert_impl!(str; String, Send, Sync, From<&'static str>);
/// assert_impl!(vec; &'static [u8], Into<Vec<u8>>);
/// ```
///
/// Raw pointers cannot be sent between threads safely:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// assert_impl!(*const u8, Send);
/// # }
/// ```
///
/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
#[macro_export]
macro_rules! assert_impl {
    ($x:ty, $($t:path),+ $(,)*) => {
        $({
            fn assert_impl<T: ?Sized + $t>() {}
            assert_impl::<$x>();
        })+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_impl!($($xs)+); }
    };
}
<|endoftext|>


<commit_before>//! Parse and write Iridium Short Burst Data (SBD) messages.
//!
//! Iridium is both a [satellite constellation](https://en.wikipedia.org/wiki/Iridium_satellite_constellation)
//! and a [company](https://en.wikipedia.org/wiki/Iridium_Communications) that provides satellite
//! communications. The Iridium network is used by phones, modems, and other communication devices.
//!
//! One mode of transmitting data over the Iridium network is via Short Burst Data (SBD) messages.
//! These messages carry a payload of some small number of bytes, usually less than one thousand.
//! Messages can be Mobile-Originated (MO), meaning that they are sent *from* an Iridium modem, or
//! Mobile-Terminated (MT), meaning that the are sent *to* an Iridium modem. Mobile-originated
//! messages are delivered either to an email address via MIME attachment, or directly to a given
//! IP address and port via TCP; this second method is called DirectIP.
//!
//! This is a simple library for reading mobile originated SBD messages from a stream, decoding
//! their headers and data payloads, and writing them back to a stream. This library does not
//! handle mobile terminated messages.

pub mod directip;
mod information_element;
pub mod logger;
pub mod filesystem;
pub mod message;

pub use message::Message;

extern crate byteorder;
extern crate chrono;
#[macro_use] extern crate enum_primitive;
extern crate glob;
#[macro_use] extern crate log;
extern crate num;
extern crate tempdir;
extern crate time;

use std::result;

#[derive(Debug)]
pub enum Error {
    ByteorderError(byteorder::Error),
    IoError(std::io::Error),
    InvalidImei,
    InvalidProtocolRevisionNumber(u8),
    GlobError(glob::GlobError),
    MissingMobileOriginatedHeader,
    MissingMobileOriginatedPayload,
    Oversized, // Oversized doesn't demand a size since we don't want to find out how much there really is
    PatternError(glob::PatternError),
    Undersized(usize),
}

impl From<byteorder::Error> for Error {
    fn from(err: byteorder::Error) -> Error {
        Error::ByteorderError(err)
    }
}

impl From<glob::PatternError> for Error {
    fn from(err: glob::PatternError) -> Error {
        Error::PatternError(err)
    }
}

impl From<glob::GlobError> for Error {
    fn from(err: glob::GlobError) -> Error {
        Error::GlobError(err)
    }
}

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

pub type Result<T> = result::Result<T, Error>;
<commit_msg>Add a note about the executable to the library.<commit_after>//! Parse and write Iridium Short Burst Data (SBD) messages.
//!
//! Iridium is both a [satellite constellation](https://en.wikipedia.org/wiki/Iridium_satellite_constellation)
//! and a [company](https://en.wikipedia.org/wiki/Iridium_Communications) that provides satellite
//! communications. The Iridium network is used by phones, modems, and other communication devices.
//!
//! One mode of transmitting data over the Iridium network is via Short Burst Data (SBD) messages.
//! These messages carry a payload of some small number of bytes, usually less than one thousand.
//! Messages can be Mobile-Originated (MO), meaning that they are sent *from* an Iridium modem, or
//! Mobile-Terminated (MT), meaning that the are sent *to* an Iridium modem. Mobile-originated
//! messages are delivered either to an email address via MIME attachment, or directly to a given
//! IP address and port via TCP; this second method is called DirectIP.
//!
//! This is a simple library for reading mobile originated SBD messages from a stream, decoding
//! their headers and data payloads, and writing them back to a stream. This library does not
//! handle mobile terminated messages.
//!
//! Most of the functionality of this library is exposed by a single executable, named `sbd` that
//! is part of this package. Use the `sbd` executable to inspect raw sbd files stores on a
//! filesystem, discover sbd files on a filesystem, and start a forever-running server to receive
//! Iridium SBD DirectIP messages.

pub mod directip;
mod information_element;
pub mod logger;
pub mod filesystem;
pub mod message;

pub use message::Message;

extern crate byteorder;
extern crate chrono;
#[macro_use] extern crate enum_primitive;
extern crate glob;
#[macro_use] extern crate log;
extern crate num;
extern crate tempdir;
extern crate time;

use std::result;

#[derive(Debug)]
pub enum Error {
    ByteorderError(byteorder::Error),
    IoError(std::io::Error),
    InvalidImei,
    InvalidProtocolRevisionNumber(u8),
    GlobError(glob::GlobError),
    MissingMobileOriginatedHeader,
    MissingMobileOriginatedPayload,
    Oversized, // Oversized doesn't demand a size since we don't want to find out how much there really is
    PatternError(glob::PatternError),
    Undersized(usize),
}

impl From<byteorder::Error> for Error {
    fn from(err: byteorder::Error) -> Error {
        Error::ByteorderError(err)
    }
}

impl From<glob::PatternError> for Error {
    fn from(err: glob::PatternError) -> Error {
        Error::PatternError(err)
    }
}

impl From<glob::GlobError> for Error {
    fn from(err: glob::GlobError) -> Error {
        Error::GlobError(err)
    }
}

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

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


<commit_before>#![crate_name = "msgpack"]

//#![feature(collections)]
//#![cfg_attr(test, feature(test))]

/// Unstable: this library is still in rapid development

extern crate byteorder;
extern crate rustc_serialize as serialize;

pub const MSGPACK_VERSION : u32 = 5;

pub mod core;

pub use core::{
    Marker,
};

pub use core::encode;

pub use core::encode::{
    FixedValueWriteError
};

pub use core::decode;

pub use core::decode::serialize::{
    Decoder,
};

pub use core::encode::serialize::{
    Encoder,
};

/// Temporary. Move to error.rs module.
pub use core::{Error, ReadError};

//#[cfg(test)]
//mod bench;

// Stage 1. Low-level decoding functions.
// Stage 2. Value decoding functions.
// Stage 3. Deserialization.
// Stage 4. Low-level encoding functions.
// Stage 5. Value encoding functions.
// Stage 6. Serialization.

// NOTE: Write about strict integer typing. Sized integers always encoded as sized even if they are
// fit in unsized, i.e 100 -> i32 -> posfix.
<commit_msg>[Misc] Planning note.<commit_after>#![crate_name = "msgpack"]

//#![feature(collections)]
//#![cfg_attr(test, feature(test))]

/// Unstable: this library is still in rapid development

extern crate byteorder;
extern crate rustc_serialize as serialize;

pub const MSGPACK_VERSION : u32 = 5;

pub mod core;

pub use core::{
    Marker,
};

pub use core::encode;

pub use core::encode::{
    FixedValueWriteError
};

pub use core::decode;

pub use core::decode::serialize::{
    Decoder,
};

pub use core::encode::serialize::{
    Encoder,
};

/// Temporary. Move to error.rs module.
pub use core::{Error, ReadError};

//#[cfg(test)]
//mod bench;

// Stage 1. Low-level decoding functions.
// Stage 2. Value decoding functions.
// Stage 3. Deserialization.
// Stage 4. Low-level encoding functions.
// Stage 5. Value encoding functions.
// Stage 6. Serialization.

// NOTE: Write about strict integer typing. Sized integers always encoded as sized even if they are
// fit in unsized, i.e 100 -> i32 -> posfix.

// Write about error style.
<|endoftext|>


<commit_before>extern crate libc;

use std::c_str::CString;
use libc::c_char;

#[no_mangle]
pub extern fn count_substrings(value: *const c_char, substr: *const c_char) -> i32 {
    let c_value = unsafe { CString::new(value, false) };
    let c_substr = unsafe { CString::new(substr, false) };
    match c_value.as_str() {
        Some(value) => match c_substr.as_str() {
            Some(substr) => value.match_indices(substr).count() as i32,
            None => -1,
        },
        None => -1,
    }
}
<commit_msg>extern "C"<commit_after>extern crate libc;

use std::c_str::CString;
use libc::c_char;

#[no_mangle]
pub extern "C" fn count_substrings(value: *const c_char, substr: *const c_char) -> i32 {
    let c_value = unsafe { CString::new(value, false) };
    let c_substr = unsafe { CString::new(substr, false) };
    match c_value.as_str() {
        Some(value) => match c_substr.as_str() {
            Some(substr) => value.match_indices(substr).count() as i32,
            None => -1,
        },
        None => -1,
    }
}
<|endoftext|>


<commit_before>//! A library implementing the `catchit` game
//!
extern crate vecmath;
extern crate rand;

use rand::Rng;
use std::cell::RefCell;

pub const MIN_FIELD_MARGIN: Scalar = 30.0;
pub const FIELD_VELOCITY_COEFF: Scalar = 0.4;
pub const OBSTACLE_SIZE_COEFF: Scalar = 0.3;
pub const MIN_OBSTACLE_TO_HUNTER_COEFF: Scalar = 0.1;
pub const TRANSITION_DURATION: Scalar =  0.5;

pub type Scalar = f64;

/// [width, height]
pub type Extent = vecmath::Vector2<Scalar>;
/// [x, y]
pub type Position = vecmath::Vector2<Scalar>;
pub type Velocity = vecmath::Vector2<Scalar>;

use vecmath::{vec2_len, vec2_sub, vec2_scale, vec2_add};

/// Points on screen. Usually they correspond to pixels, but might not on a
/// HiDPI display
pub type Pt = Scalar;

/// Represents a shape used for collision detection
#[derive(Debug, Clone, PartialEq)]
pub enum CollisionShape {
    Square,
    Circle
}

/// A game object which knows a few things about itself
#[derive(Debug, Clone, PartialEq)]
pub struct Object {
    pub pos: Position,
    pub half_size: Pt,
    pub shape: CollisionShape
}

impl Object {

    pub fn left(&self) -> Scalar {
        self.pos[0] - self.half_size
    }

    pub fn right(&self) -> Scalar {
        self.pos[0] + self.half_size
    }

    pub fn top(&self) -> Scalar {
        self.pos[1] - self.half_size
    }

    pub fn bottom(&self) -> Scalar {
        self.pos[1] + self.half_size
    }

    /// Returns true if both objects intersect
    pub fn intersects(&self, other: &Object) -> bool {
        match (&self.shape, &other.shape) {
            (&CollisionShape::Circle, &CollisionShape::Circle) => {
                vec2_len(vec2_sub(self.pos, other.pos)) <= self.half_size + other.half_size
            },
            _ => {
                   self.left() <= other.right()
                && self.right() >= other.left()
                && self.top() <= other.bottom()
                && self.bottom() >= other.top()
            }
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum ObstacleKind {
    /// Causes all other obstacles to hide themselves for a while
    InvisibiltySwitch,
    /// Kills the player
    Deadly,
}

/// An obstacle the hunter can collide with
#[derive(Debug, Clone, PartialEq)]
pub struct Obstacle {
    pub kind: ObstacleKind,
    pub object: Object,
    pub velocity: Velocity
}

/// It maintains the state of the game and expects to be updated with
/// time-delta information to compute the next state.
///
/// Please note that the coordinates used in the playing field start at 0
/// and grow
#[derive(Debug, Clone, PartialEq)]
pub struct State {
    /// The playing field
    pub field: Extent,
    /// The player's character
    pub hunter: Object,
    /// Hunted the player's character
    pub prey: Object,
    /// Obstacles the hunter must avoid to prevent game-over
    pub obstacles: Vec<Obstacle>,
    /// score of the current game
    pub score: u32,
    /// transition between opaque and invisible obstacles
    pub obstacle_opacity: Transition,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TransitionState {
    /// Transition is at start, which is the case right after calling `new()`
    Start,
    /// We are neither finished, nor at the start
    InProgress,
    /// We are finished
    Finished,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TransitionDirection {
    FromTo,
    ToFrom,
}

#[derive(Debug, Clone, PartialEq)]
pub struct Transition {
    pub v1: Scalar,
    pub v2: Scalar,
    pub current: Scalar,
    /// Time it takes to make transition
    pub transition_time_s: f64,
    pub direction: TransitionDirection,
}

impl Transition {
    fn new(from: Scalar, to: Scalar, transition_time_s: f64) -> Transition {
        Transition {
            v1: from,
            v2: to,
            current: from,
            transition_time_s: transition_time_s,
            direction: TransitionDirection::FromTo
        }
    }

    fn from(&self) -> Scalar {
        match self.direction {
            TransitionDirection::FromTo => self.v1,
            TransitionDirection::ToFrom => self.v2,
        }
    }

    fn to(&self) -> Scalar {
        match self.direction {
            TransitionDirection::FromTo => self.v2,
            TransitionDirection::ToFrom => self.v1,
        }
    }

    fn state(&self) -> TransitionState {
        let to = self.to();
        let from = self.from();

        if to > from {
            if self.current >= to {
                TransitionState::Finished
            } else if self.current <= from {
                TransitionState::Start
            } else {
                TransitionState::InProgress
            }
        } else {
            if self.current <= to {
                TransitionState::Finished
            } else if self.current >= from {
                TransitionState::Start
            } else {
                TransitionState::InProgress
            }
        }
    }

    /// Move transition towards the finished state
    /// `dt` is in seconds and signals the passed time since the last advance
    /// call.
    fn advance(&mut self, dt: f64) -> &mut Self {
        let to = self.to();
        let from = self.from();

        let delta = to - from;
        self.current += delta * (dt / self.transition_time_s);

        if to > from {
            if self.current > to {
                self.current = to;
            }
        } else {
            if self.current < to {
                self.current = to;
            }
        }
        self
    }

    fn reverse(&mut self) -> &mut Self {
        self.direction = match self.direction {
            TransitionDirection::FromTo => TransitionDirection::ToFrom,
            TransitionDirection::ToFrom => TransitionDirection::FromTo,
        };
        self
    }
}

/// The engine implements the game logic
///
/// It relies on user input given as 2d coordinates
pub struct Engine {
    state: Option<State>,
    min_distance: Scalar,
    rng: RefCell<rand::XorShiftRng>,
}

impl Engine {

    fn rnd_obj_pos_in_field(field: &Extent, half_size: Pt,
                            rng: &mut rand::XorShiftRng) -> Position {
        Self::clamp_to_field(field, half_size, [rng.gen_range(0.0, field[0]),
                                                rng.gen_range(0.0, field[1])])
    }

    fn clamp_to_field(field: &Extent, half_size: Pt, mut pos: Position) -> Position {
        if pos[0] - half_size < 0.0 {
            pos[0] = half_size;
        }
        if pos[0] + half_size > field[0] {
            pos[0] = field[0] - half_size;
        }
        if pos[1] - half_size < 0.0 {
            pos[1] = half_size;
        }
        if pos[1] + half_size > field[1] {
            pos[1] = field[1] - half_size;
        }
        pos
    }

    fn state_from_field(field: Extent) -> State {
        assert!(field[0].min(field[1]) >= 320.0, "Playing field is too small");
        let margin = (field[0].min(field[1]) * 0.05).max(MIN_FIELD_MARGIN);
        let half_size = (margin - (MIN_FIELD_MARGIN / 6.0)) / 2.0;

        let mut rng = rand::weak_rng();
        let prey_pos = Self::rnd_obj_pos_in_field(&field, half_size, &mut rng);

        State {
            field: field,
            hunter: Object {
                pos: [-half_size * 2.0, -half_size * 2.0],
                half_size: half_size,
                shape: CollisionShape::Circle
            },
            prey: Object {
                pos: prey_pos,
                half_size: half_size,
                shape: CollisionShape::Square
            },
            obstacles: Vec::new(),
            obstacle_opacity: Transition::new(1.0, 0.0, TRANSITION_DURATION),
            score: 0
        }
    }

    fn set_state(&mut self, state: State) {
        self.min_distance = (state.field[0].powi(2) + state.field[1].powi(2)).sqrt()
                             * MIN_OBSTACLE_TO_HUNTER_COEFF;
        self.state = Some(state);
    }

    fn new_obstacle(rng: &mut rand::XorShiftRng, s: &mut State, min_distance: Scalar) {
        s.prey.pos = Self::rnd_obj_pos_in_field(&s.field, s.prey.half_size, rng);

        let mut half_size = s.hunter.half_size * OBSTACLE_SIZE_COEFF;
        let kind = match rng.gen_range(0.0f32, 1.0) {
            _p if _p > 0.94 => {
                half_size *= 2.0;
                ObstacleKind::InvisibiltySwitch
            },
            _               => ObstacleKind::Deadly,
        };
        let vel: Velocity = [
            rng.gen_range(-s.field[0] * FIELD_VELOCITY_COEFF,
                           s.field[0] * FIELD_VELOCITY_COEFF),
            rng.gen_range(-s.field[1] * FIELD_VELOCITY_COEFF,
                           s.field[1] * FIELD_VELOCITY_COEFF),
        ];

        let mut pos = s.hunter.pos;
        while vec2_len(vec2_sub(pos, s.hunter.pos)) < min_distance {
            pos = Self::rnd_obj_pos_in_field(&s.field, s.prey.half_size, rng)
        }
        s.obstacles.push(Obstacle {
            kind: kind,
            object: Object {
                pos: Self::clamp_to_field(&s.field, half_size, pos),
                half_size: half_size,
                shape: CollisionShape::Circle,
            },
            velocity: vel,
        });
    }

    fn advect_obstacles(s: &mut State, dt: f64) {
        // Move and collide the obstacles.
        for obstacle in s.obstacles.iter_mut() {

            let obj = &mut obstacle.object;
            obj.pos = vec2_add(obj.pos, vec2_scale(obstacle.velocity, dt));

            if obj.left() <= 0.0 {
                obstacle.velocity[0] = -obstacle.velocity[0];
            } else if obj.right() >= s.field[0] {
                obstacle.velocity[0] = -obstacle.velocity[0];
            }
            if obj.top() <= 0.0 {
                obstacle.velocity[1] = -obstacle.velocity[1];
            } else if obj.bottom() >= s.field[1] {
                obstacle.velocity[1] = -obstacle.velocity[1];
            }

            obj.pos = Self::clamp_to_field(&s.field, obj.half_size,
                                            obj.pos);
        }
    }
}

impl Engine {

    pub fn from_field(field: Extent) -> Engine {
        let mut e = Engine {
            state: None,
            min_distance: 0.0,
            rng: RefCell::new(rand::weak_rng()),
        };
        e.set_state(Self::state_from_field(field));
        e
    }

    /// Reset the engine to use the given game-state.
    /// Can be used to setup a new game as well.
    pub fn reset(&mut self, field: Extent) {
        self.set_state(Self::state_from_field(field));
    }

    /// Update the game state.
    ///
    /// If the returned value is the last game-state, it indicates that the player
    /// is game-over.
    pub fn update(&mut self, dt: f64) -> Result<(), State> {
        let mut is_game_over = false;
        if let Some(ref mut s) = self.state {
            if s.hunter.intersects(&s.prey) {
                s.score += 10;
                Self::new_obstacle(&mut self.rng.borrow_mut(), s, self.min_distance);
            }// check hunter-prey intersection

            Self::advect_obstacles(s, dt);

            // advance transitions
            for t in [&mut s.obstacle_opacity].iter_mut() {
                match t.state() {
                    TransitionState::Start => {
                        if t.direction == TransitionDirection::ToFrom {
                            t.reverse();
                        }
                    }
                    TransitionState::InProgress => {
                        t.advance(dt);
                    }
                    TransitionState::Finished => {
                        let dir = t.direction.clone();
                        t.reverse();

                        if dir == TransitionDirection::FromTo {
                            t.advance(dt);
                        }
                    }
                }
            }

            // If the hunter is hit, the game is over ...
            for obstacle in &s.obstacles {
                if obstacle.object.intersects(&s.hunter) {
                    match obstacle.kind {
                        ObstacleKind::Deadly => {
                            is_game_over = true;
                            break;
                        },
                        ObstacleKind::InvisibiltySwitch => {
                            if s.obstacle_opacity.state() == TransitionState::Start &&
                               s.obstacle_opacity.direction == TransitionDirection::FromTo {
                                s.obstacle_opacity.advance(dt);
                            }
                        },
                    }
                }
            }
        } // end have game state

        if is_game_over {
            Err(self.state.take().unwrap())
        } else {
            Ok(())
        }
    }

    pub fn state(&self) -> &Option<State> {
        &self.state
    }

    /// Position will be clamped into the playing field
    pub fn set_hunter_pos(&mut self, pos: Position) {
        if let Some(ref mut s) = self.state {
            s.hunter.pos = pos;
        }
    }
}

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

    #[test]
    fn transition() {
        let mut t = Transition::new(0.0, 1.0, 1.0);
        assert_eq!(t.state(), TransitionState::Start);
        assert_eq!(t.from(), 0.0);
        assert_eq!(t.to(), 1.0);

        assert_eq!(t.advance(0.5).current, 0.5);
        assert_eq!(t.state(), TransitionState::InProgress);
        assert_eq!(t.advance(0.5).current, 1.0);
        assert_eq!(t.state(), TransitionState::Finished);

        t.reverse();

        assert_eq!(t.from(), 1.0);
        assert_eq!(t.to(), 0.0);
        assert_eq!(t.state(), TransitionState::Start);
        assert_eq!(t.current, 1.0);

        assert_eq!(t.advance(0.5).current, 0.5);
        assert_eq!(t.state(), TransitionState::InProgress);
        assert_eq!(t.advance(0.5).current, 0.0);
        assert_eq!(t.state(), TransitionState::Finished);

        t.reverse();
        assert_eq!(t.state(), TransitionState::Start);
    }
}
<commit_msg>feat(lib): invisibility duration<commit_after>//! A library implementing the `catchit` game
//!
extern crate vecmath;
extern crate rand;

use rand::Rng;
use std::cell::RefCell;

pub const MIN_FIELD_MARGIN: Scalar = 30.0;
pub const FIELD_VELOCITY_COEFF: Scalar = 0.4;
pub const OBSTACLE_SIZE_COEFF: Scalar = 0.3;
pub const MIN_OBSTACLE_TO_HUNTER_COEFF: Scalar = 0.1;
pub const TRANSITION_DURATION: Scalar =  0.5;
pub const HOLD_INVISIBILITY_DURATION: Scalar = 0.5;

pub type Scalar = f64;

/// [width, height]
pub type Extent = vecmath::Vector2<Scalar>;
/// [x, y]
pub type Position = vecmath::Vector2<Scalar>;
pub type Velocity = vecmath::Vector2<Scalar>;

use vecmath::{vec2_len, vec2_sub, vec2_scale, vec2_add};

/// Points on screen. Usually they correspond to pixels, but might not on a
/// HiDPI display
pub type Pt = Scalar;

/// Represents a shape used for collision detection
#[derive(Debug, Clone, PartialEq)]
pub enum CollisionShape {
    Square,
    Circle
}

/// A game object which knows a few things about itself
#[derive(Debug, Clone, PartialEq)]
pub struct Object {
    pub pos: Position,
    pub half_size: Pt,
    pub shape: CollisionShape
}

impl Object {

    pub fn left(&self) -> Scalar {
        self.pos[0] - self.half_size
    }

    pub fn right(&self) -> Scalar {
        self.pos[0] + self.half_size
    }

    pub fn top(&self) -> Scalar {
        self.pos[1] - self.half_size
    }

    pub fn bottom(&self) -> Scalar {
        self.pos[1] + self.half_size
    }

    /// Returns true if both objects intersect
    pub fn intersects(&self, other: &Object) -> bool {
        match (&self.shape, &other.shape) {
            (&CollisionShape::Circle, &CollisionShape::Circle) => {
                vec2_len(vec2_sub(self.pos, other.pos)) <= self.half_size + other.half_size
            },
            _ => {
                   self.left() <= other.right()
                && self.right() >= other.left()
                && self.top() <= other.bottom()
                && self.bottom() >= other.top()
            }
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum ObstacleKind {
    /// Causes all other obstacles to hide themselves for a while
    InvisibiltySwitch,
    /// Kills the player
    Deadly,
}

/// An obstacle the hunter can collide with
#[derive(Debug, Clone, PartialEq)]
pub struct Obstacle {
    pub kind: ObstacleKind,
    pub object: Object,
    pub velocity: Velocity
}

/// It maintains the state of the game and expects to be updated with
/// time-delta information to compute the next state.
///
/// Please note that the coordinates used in the playing field start at 0
/// and grow
#[derive(Debug, Clone, PartialEq)]
pub struct State {
    /// The playing field
    pub field: Extent,
    /// The player's character
    pub hunter: Object,
    /// Hunted the player's character
    pub prey: Object,
    /// Obstacles the hunter must avoid to prevent game-over
    pub obstacles: Vec<Obstacle>,
    /// score of the current game
    pub score: u32,
    /// transition between opaque and invisible obstacles
    pub obstacle_opacity: Transition,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TransitionState {
    /// Transition is at start, which is the case right after calling `new()`
    Start,
    /// We are neither finished, nor at the start
    InProgress,
    /// We are finished
    Finished,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TransitionDirection {
    FromTo,
    ToFrom,
}

#[derive(Debug, Clone, PartialEq)]
pub struct Transition {
    pub v1: Scalar,
    pub v2: Scalar,
    pub current: Scalar,
    /// Time it takes to make transition
    pub transition_time_s: f64,
    pub direction: TransitionDirection,
    /// Keeps timing information, helpful to determine how long a state is held
    pub state_time: f64,
}

impl Transition {
    fn new(from: Scalar, to: Scalar, transition_time_s: f64) -> Transition {
        Transition {
            v1: from,
            v2: to,
            current: from,
            transition_time_s: transition_time_s,
            direction: TransitionDirection::FromTo,
            state_time: 0.0,
        }
    }

    fn from(&self) -> Scalar {
        match self.direction {
            TransitionDirection::FromTo => self.v1,
            TransitionDirection::ToFrom => self.v2,
        }
    }

    fn to(&self) -> Scalar {
        match self.direction {
            TransitionDirection::FromTo => self.v2,
            TransitionDirection::ToFrom => self.v1,
        }
    }

    fn state(&self) -> TransitionState {
        let to = self.to();
        let from = self.from();

        if to > from {
            if self.current >= to {
                TransitionState::Finished
            } else if self.current <= from {
                TransitionState::Start
            } else {
                TransitionState::InProgress
            }
        } else {
            if self.current <= to {
                TransitionState::Finished
            } else if self.current >= from {
                TransitionState::Start
            } else {
                TransitionState::InProgress
            }
        }
    }

    /// Move transition towards the finished state
    /// `dt` is in seconds and signals the passed time since the last advance
    /// call.
    /// Advances the `state_time` as well
    fn advance(&mut self, dt: f64) -> &mut Self {
        self.state_time += dt;

        let to = self.to();
        let from = self.from();

        let delta = to - from;
        self.current += delta * (dt / self.transition_time_s);

        if to > from {
            if self.current > to {
                self.current = to;
            }
        } else {
            if self.current < to {
                self.current = to;
            }
        }
        self
    }

    /// Reverse direction and reset `state_time` if we are Finished
    fn reverse(&mut self) -> &mut Self {
        if self.state() == TransitionState::Finished {
            self.state_time = 0.0;
        }
        self.direction = match self.direction {
            TransitionDirection::FromTo => TransitionDirection::ToFrom,
            TransitionDirection::ToFrom => TransitionDirection::FromTo,
        };
        self
    }
}

/// The engine implements the game logic
///
/// It relies on user input given as 2d coordinates
pub struct Engine {
    state: Option<State>,
    min_distance: Scalar,
    rng: RefCell<rand::XorShiftRng>,
}

impl Engine {

    fn rnd_obj_pos_in_field(field: &Extent, half_size: Pt,
                            rng: &mut rand::XorShiftRng) -> Position {
        Self::clamp_to_field(field, half_size, [rng.gen_range(0.0, field[0]),
                                                rng.gen_range(0.0, field[1])])
    }

    fn clamp_to_field(field: &Extent, half_size: Pt, mut pos: Position) -> Position {
        if pos[0] - half_size < 0.0 {
            pos[0] = half_size;
        }
        if pos[0] + half_size > field[0] {
            pos[0] = field[0] - half_size;
        }
        if pos[1] - half_size < 0.0 {
            pos[1] = half_size;
        }
        if pos[1] + half_size > field[1] {
            pos[1] = field[1] - half_size;
        }
        pos
    }

    fn state_from_field(field: Extent) -> State {
        assert!(field[0].min(field[1]) >= 320.0, "Playing field is too small");
        let margin = (field[0].min(field[1]) * 0.05).max(MIN_FIELD_MARGIN);
        let half_size = (margin - (MIN_FIELD_MARGIN / 6.0)) / 2.0;

        let mut rng = rand::weak_rng();
        let prey_pos = Self::rnd_obj_pos_in_field(&field, half_size, &mut rng);

        State {
            field: field,
            hunter: Object {
                pos: [-half_size * 2.0, -half_size * 2.0],
                half_size: half_size,
                shape: CollisionShape::Circle
            },
            prey: Object {
                pos: prey_pos,
                half_size: half_size,
                shape: CollisionShape::Square
            },
            obstacles: Vec::new(),
            obstacle_opacity: Transition::new(1.0, 0.0, TRANSITION_DURATION),
            score: 0
        }
    }

    fn set_state(&mut self, state: State) {
        self.min_distance = (state.field[0].powi(2) + state.field[1].powi(2)).sqrt()
                             * MIN_OBSTACLE_TO_HUNTER_COEFF;
        self.state = Some(state);
    }

    fn new_obstacle(rng: &mut rand::XorShiftRng, s: &mut State, min_distance: Scalar) {
        s.prey.pos = Self::rnd_obj_pos_in_field(&s.field, s.prey.half_size, rng);

        let mut half_size = s.hunter.half_size * OBSTACLE_SIZE_COEFF;
        let kind = match rng.gen_range(0.0f32, 1.0) {
            _p if _p > 0.5 => {
                half_size *= 2.0;
                ObstacleKind::InvisibiltySwitch
            },
            _               => ObstacleKind::Deadly,
        };
        let vel: Velocity = [
            rng.gen_range(-s.field[0] * FIELD_VELOCITY_COEFF,
                           s.field[0] * FIELD_VELOCITY_COEFF),
            rng.gen_range(-s.field[1] * FIELD_VELOCITY_COEFF,
                           s.field[1] * FIELD_VELOCITY_COEFF),
        ];

        let mut pos = s.hunter.pos;
        while vec2_len(vec2_sub(pos, s.hunter.pos)) < min_distance {
            pos = Self::rnd_obj_pos_in_field(&s.field, s.prey.half_size, rng)
        }
        s.obstacles.push(Obstacle {
            kind: kind,
            object: Object {
                pos: Self::clamp_to_field(&s.field, half_size, pos),
                half_size: half_size,
                shape: CollisionShape::Circle,
            },
            velocity: vel,
        });
    }

    fn advect_obstacles(s: &mut State, dt: f64) {
        // Move and collide the obstacles.
        for obstacle in s.obstacles.iter_mut() {

            let obj = &mut obstacle.object;
            obj.pos = vec2_add(obj.pos, vec2_scale(obstacle.velocity, dt));

            if obj.left() <= 0.0 {
                obstacle.velocity[0] = -obstacle.velocity[0];
            } else if obj.right() >= s.field[0] {
                obstacle.velocity[0] = -obstacle.velocity[0];
            }
            if obj.top() <= 0.0 {
                obstacle.velocity[1] = -obstacle.velocity[1];
            } else if obj.bottom() >= s.field[1] {
                obstacle.velocity[1] = -obstacle.velocity[1];
            }

            obj.pos = Self::clamp_to_field(&s.field, obj.half_size,
                                            obj.pos);
        }
    }
}

impl Engine {

    pub fn from_field(field: Extent) -> Engine {
        let mut e = Engine {
            state: None,
            min_distance: 0.0,
            rng: RefCell::new(rand::weak_rng()),
        };
        e.set_state(Self::state_from_field(field));
        e
    }

    /// Reset the engine to use the given game-state.
    /// Can be used to setup a new game as well.
    pub fn reset(&mut self, field: Extent) {
        self.set_state(Self::state_from_field(field));
    }

    /// Update the game state.
    ///
    /// If the returned value is the last game-state, it indicates that the player
    /// is game-over.
    pub fn update(&mut self, dt: f64) -> Result<(), State> {
        let mut is_game_over = false;
        if let Some(ref mut s) = self.state {
            if s.hunter.intersects(&s.prey) {
                s.score += 10;
                Self::new_obstacle(&mut self.rng.borrow_mut(), s, self.min_distance);
            }// check hunter-prey intersection

            Self::advect_obstacles(s, dt);

            // advance transitions
            for t in [&mut s.obstacle_opacity].iter_mut() {
                match t.state() {
                    TransitionState::Start => {
                        if t.direction == TransitionDirection::ToFrom {
                            t.reverse();
                        }
                    }
                    TransitionState::InProgress => {
                        t.advance(dt);
                    }
                    TransitionState::Finished => {
                        t.state_time += dt;

                        if t.state_time >= TRANSITION_DURATION + HOLD_INVISIBILITY_DURATION {
                            let dir = t.direction.clone();
                            t.reverse();

                            if dir == TransitionDirection::FromTo {
                                t.advance(dt);
                            }
                        }
                    }
                }
            }

            // Handle obstacle hits
            for obstacle in &s.obstacles {
                if obstacle.object.intersects(&s.hunter) {
                    match obstacle.kind {
                        ObstacleKind::Deadly => {
                            is_game_over = true;
                            break;
                        },
                        ObstacleKind::InvisibiltySwitch => {
                            if s.obstacle_opacity.state() == TransitionState::Start &&
                               s.obstacle_opacity.direction == TransitionDirection::FromTo {
                                s.obstacle_opacity.advance(dt);
                            }
                        },
                    }
                }
            }
        } // end have game state

        if is_game_over {
            Err(self.state.take().unwrap())
        } else {
            Ok(())
        }
    }

    pub fn state(&self) -> &Option<State> {
        &self.state
    }

    /// Position will be clamped into the playing field
    pub fn set_hunter_pos(&mut self, pos: Position) {
        if let Some(ref mut s) = self.state {
            s.hunter.pos = pos;
        }
    }
}

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

    #[test]
    fn transition() {
        let mut t = Transition::new(0.0, 1.0, 1.0);
        assert_eq!(t.state(), TransitionState::Start);
        assert_eq!(t.from(), 0.0);
        assert_eq!(t.to(), 1.0);
        assert_eq!(t.state_time, 0.0);

        assert_eq!(t.advance(0.5).current, 0.5);
        assert_eq!(t.state_time, 0.5);
        assert_eq!(t.state(), TransitionState::InProgress);
        assert_eq!(t.advance(0.5).current, 1.0);
        assert_eq!(t.state(), TransitionState::Finished);
        assert_eq!(t.state_time, 1.0);
        assert_eq!(t.advance(0.5).current, 1.0);
        assert_eq!(t.state_time, 1.5);
        assert_eq!(t.state(), TransitionState::Finished);

        t.reverse();
        assert_eq!(t.state_time, 0.0);

        assert_eq!(t.from(), 1.0);
        assert_eq!(t.to(), 0.0);
        assert_eq!(t.state(), TransitionState::Start);
        assert_eq!(t.current, 1.0);

        assert_eq!(t.advance(0.5).current, 0.5);
        assert_eq!(t.state_time, 0.5);
        assert_eq!(t.state(), TransitionState::InProgress);
        assert_eq!(t.reverse().state_time, 0.5);
        assert_eq!(t.reverse().state_time, 0.5);
        assert_eq!(t.advance(0.5).current, 0.0);
        assert_eq!(t.state(), TransitionState::Finished);

        t.reverse();
        assert_eq!(t.state(), TransitionState::Start);
    }
}
<|endoftext|>