<commit_before>// DOCS

#![feature(path,io)]

extern crate tempdir;

use std::io;
use std::fs;
use std::borrow::Borrow;
use std::path;

use tempdir::TempDir;
pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

pub trait GenericAtomicFile {
    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.
    fn new(path: &path::Path, overwrite: OverwriteBehavior) -> Self;

    /// Get the target filepath.
    fn path(&self) -> &path::Path;

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    fn write<F: FnMut(&mut fs::File) -> io::Result<()>>(&self, mut f: F) -> io::Result<()>;
}

#[derive(Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}

pub struct AtomicFile {
    path: path::PathBuf,
    overwrite: OverwriteBehavior,
    tmpdir: path::PathBuf
}

impl AtomicFile {
    pub fn new_with_tmpdir(path: &path::Path, overwrite: OverwriteBehavior, tmpdir: &path::Path) -> Self {
        AtomicFile {
            path: path.to_path_buf(),
            overwrite: overwrite,
            tmpdir: tmpdir.to_path_buf()
        }
    }

    fn commit(&self, tmppath: &path::Path) -> io::Result<()> {
        match self.overwrite {
            AllowOverwrite => replace_atomic(tmppath, self.path()),
            DisallowOverwrite => move_atomic(tmppath, self.path())
        }
    }
}

impl GenericAtomicFile for AtomicFile {
    fn new(path: &path::Path, overwrite: OverwriteBehavior) -> Self {
        AtomicFile::new_with_tmpdir(path, overwrite, &path.parent().unwrap_or(&path))
    }

    fn path(&self) -> &path::Path { &self.path.borrow() }

    fn write<F: FnMut(&mut fs::File) -> io::Result<()>>(&self, mut f: F) -> io::Result<()> {
        let tmpdir = match TempDir::new_in(
            &self.tmpdir,
            ".atomicwrite"
        ) {
            Ok(x) => x,
            Err(_) => return Err(io::Error::new(
                io::ErrorKind::Other,
                "Failed to create a temporary directory.",
                None
            ))
        };

        let tmppath = tmpdir.path().join("tmpfile.tmp");
        {
            let mut tmpfile = try!(fs::File::create(&tmppath));
            try!(f(&mut tmpfile));
        };
        try!(self.commit(&tmppath));
        Ok(())
    }

}

#[cfg(unix)]
fn replace_atomic_impl(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    fs::rename(src, dst)
}

#[cfg(unix)]
fn move_atomic_impl(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    try!(fs::hard_link(src, dst));
    fs::remove_file(src)
}

/// Move `src` to `dst`. If `dst` exists, it will be silently overwritten.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    replace_atomic_impl(src, dst)
}

/// Move `src` to `dst`. An error will be returned if `dst` exists.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    move_atomic_impl(src, dst)
}
<commit_msg>Fix #7<commit_after>// DOCS

#![feature(path,io)]

extern crate tempdir;

use std::io;
use std::fs;
use std::borrow::Borrow;
use std::path;

use tempdir::TempDir;
pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

#[derive(Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}

pub struct AtomicFile {
    path: path::PathBuf,
    overwrite: OverwriteBehavior,
    tmpdir: path::PathBuf
}

impl AtomicFile {
    pub fn new_with_tmpdir(path: &path::Path, overwrite: OverwriteBehavior, tmpdir: &path::Path) -> Self {
        AtomicFile {
            path: path.to_path_buf(),
            overwrite: overwrite,
            tmpdir: tmpdir.to_path_buf()
        }
    }

    fn commit(&self, tmppath: &path::Path) -> io::Result<()> {
        match self.overwrite {
            AllowOverwrite => replace_atomic(tmppath, self.path()),
            DisallowOverwrite => move_atomic(tmppath, self.path())
        }
    }

    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.
    fn new(path: &path::Path, overwrite: OverwriteBehavior) -> Self {
        AtomicFile::new_with_tmpdir(path, overwrite, &path.parent().unwrap_or(&path))
    }

    /// Get the target filepath.
    fn path(&self) -> &path::Path { &self.path.borrow() }

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    fn write<F: FnMut(&mut fs::File) -> io::Result<()>>(&self, mut f: F) -> io::Result<()> {
        let tmpdir = match TempDir::new_in(
            &self.tmpdir,
            ".atomicwrite"
        ) {
            Ok(x) => x,
            Err(_) => return Err(io::Error::new(
                io::ErrorKind::Other,
                "Failed to create a temporary directory.",
                None
            ))
        };

        let tmppath = tmpdir.path().join("tmpfile.tmp");
        {
            let mut tmpfile = try!(fs::File::create(&tmppath));
            try!(f(&mut tmpfile));
        };
        try!(self.commit(&tmppath));
        Ok(())
    }
}

#[cfg(unix)]
fn replace_atomic_impl(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    fs::rename(src, dst)
}

#[cfg(unix)]
fn move_atomic_impl(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    try!(fs::hard_link(src, dst));
    fs::remove_file(src)
}

/// Move `src` to `dst`. If `dst` exists, it will be silently overwritten.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    replace_atomic_impl(src, dst)
}

/// Move `src` to `dst`. An error will be returned if `dst` exists.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    move_atomic_impl(src, dst)
}
<|endoftext|>


<commit_before>#[cfg(feature = "lua")]
extern crate lua;

#[cfg(feature = "cpython")]
#[macro_use]
extern crate cpython;

extern crate sdl2;
extern crate getopts;

extern crate nalgebra;

#[macro_use]
extern crate gfx as gfx_rs;

extern crate image;
extern crate gif;

extern crate regex;
extern crate png;
extern crate byteorder;
extern crate rand;
extern crate time;
extern crate chrono;
extern crate libc;

extern crate rusttype;

extern crate chan;

#[macro_use]
extern crate log;
extern crate fern;

#[macro_use]
extern crate lazy_static;

extern crate rustc_serialize;

#[macro_use]
pub mod config;

pub mod frontend;
pub mod renderer;
pub mod gfx;
pub mod px8;
pub mod cartridge;
pub mod plugins;
pub mod sound;<commit_msg>Update<commit_after>#[cfg(feature = "lua")]
extern crate lua;

#[cfg(feature = "cpython")]
#[macro_use]
extern crate cpython;

extern crate sdl2;
extern crate getopts;

extern crate nalgebra;

extern crate image;
extern crate gif;

extern crate regex;
extern crate png;
extern crate byteorder;
extern crate rand;
extern crate time;
extern crate chrono;
extern crate libc;

extern crate rusttype;

extern crate chan;

#[macro_use]
extern crate log;
extern crate fern;

#[macro_use]
extern crate lazy_static;

extern crate rustc_serialize;

#[macro_use]
pub mod config;

pub mod frontend;
pub mod renderer;
pub mod gfx;
pub mod px8;
pub mod cartridge;
pub mod plugins;
pub mod sound;<|endoftext|>


<commit_before>#![feature(no_std)]
#![feature(core)]
#![no_std]

#![crate_name = "multiboot"]
#![crate_type = "lib"]

extern crate core;

#[cfg(test)]
extern crate std;

use core::mem::{transmute};
use core::ops::FnMut;
use core::raw;
use core::str;

/// Value that is in rax after multiboot jumps to our entry point
pub const SIGNATURE_RAX: u64 = 0x2BADB002;

#[derive(Debug, PartialEq, Eq)]
pub enum MemType {
    RAM = 1,
    Unusable = 2,
}

/// Multiboot struct clients mainly interact with
/// To create this use Multiboot::new()
pub struct Multiboot<'a> {
    header: &'a MultibootHeader,
    paddr_to_vaddr: fn(u64) -> u64,
}

/// Representation of Multiboot header according to specification.
#[derive(Debug)]
#[repr(packed)]
struct MultibootHeader {
    flags: u32,

    mem_lower: u32,
    mem_upper: u32,

    boot_device: u32,
    cmdline: u32,

    mods_count: u32,
    mods_addr: u32,

    elf_symbols: ElfSymbols,

    mmap_length: u32,
    mmap_addr: u32,
}

/// Multiboot format of the MMAP buffer.
/// Note that size is defined to be at -4 bytes.
#[derive(Debug)]
#[repr(packed)]
struct MemEntry {
    size: u32,
    base_addr: u64,
    length: u64,
    mtype: u32
}

#[derive(Debug)]
#[repr(packed)]
struct ElfSymbols {
    num: u32,
    size: u32,
    addr: u32,
    shndx: u32,
}

/// Multiboot module structure
#[derive(Debug)]
#[repr(packed)]
struct Module {
    /// Start address of module in memory.
    start: u32,
    /// End address of module in memory.
    end: u32,
    /// Name of module.
    string: u32,
    /// Must be zero.
    reserved: u32
}

/// Convert a C string into a [u8 slice and from there into a &'static str.
/// This unsafe block builds on assumption that multiboot strings are sane.
fn convert_safe_c_string(cstring: *const u8) -> &'static str {
    unsafe {
        let mut iter = cstring;
        while *iter != 0 {
            iter = iter.offset(1);
        }

        let slice = raw::Slice { data: cstring, len: iter as usize - cstring as usize };
        let byte_array: &'static [u8] = transmute(slice);
        str::from_utf8_unchecked(byte_array)
    }
}

impl<'a> Multiboot<'a> {

    /// Initializes the multiboot structure.
    ///
    /// # Arguments
    ///
    ///  * `mboot_ptr` - The physical address of the multiboot header. On qemu for example
    ///                  this is typically at 0x9500.
    ///  * `paddr_to_vaddr` - Translation of the physical addresses into kernel addresses.
    ///
    ///  `paddr_to_vaddr` translates physical it into a kernel accessible address.
    ///  The simplest paddr_to_vaddr function would for example be just the identity
    ///  function. But this may vary depending on how your page table layout looks like.
    ///
    pub fn new(mboot_ptr: u64, paddr_to_vaddr: fn(paddr: u64) -> u64) -> Multiboot<'a> {
        let header = paddr_to_vaddr(mboot_ptr);
        let mb: &MultibootHeader = unsafe { transmute::<u64, &MultibootHeader>(header) };

        Multiboot { header: mb, paddr_to_vaddr: paddr_to_vaddr }
    }

    pub fn has_mmap(&'a self) -> bool {
        self.header.flags & 0x1 > 0
    }

    /// Discover all memory regions in the multiboot memory map.
    ///
    /// # Arguments
    ///
    ///  * `discovery_callback` - Function to notify your memory system about regions.
    ///
    pub fn find_memory<F: FnMut(u64, u64, MemType)>(&'a self, mut discovery_callback: F) {
        if !self.has_mmap() {
            return
        }

        let paddr_to_vaddr = self.paddr_to_vaddr;

        let mut current = self.header.mmap_addr;
        let end = self.header.mmap_addr + self.header.mmap_length;
        while current < end
        {
            let memory_region: &MemEntry = unsafe { transmute::<u64, &MemEntry>(paddr_to_vaddr(current as u64)) };

            let mtype = match memory_region.mtype {
                1 => MemType::RAM,
                2 => MemType::Unusable,
                _ => MemType::Unusable
            };

            discovery_callback(memory_region.base_addr, memory_region.length, mtype);
            current += memory_region.size + 4;
        }
    }

    pub fn has_modules(&'a self) -> bool {
        self.header.flags & (1<<3) > 0
    }

    /// Discover all additional modules in multiboot.
    ///
    /// # Arguments
    ///
    ///  * `discovery_callback` - Function to notify your system about modules.
    ///
    pub fn find_modules<F: FnMut(&'static str, u64, u64)>(&'a self, mut discovery_callback: F) {
        if !self.has_modules() {
            return
        }

        let paddr_to_vaddr = self.paddr_to_vaddr;

        let module_start = paddr_to_vaddr(self.header.mods_addr as u64);
        let count: usize = self.header.mods_count as usize;
        for _ in 0..count {
            let current: &Module = unsafe { transmute::<u64, &Module>(module_start) };
            let path = unsafe { convert_safe_c_string(transmute::<u64, *const u8>(paddr_to_vaddr(current.string as u64))) };

            discovery_callback(path, paddr_to_vaddr(current.start as u64), paddr_to_vaddr(current.end as u64));
        }
    }
}
<commit_msg>Add VAddr and PAddr types to make code more readable.<commit_after>#![feature(no_std)]
#![feature(core)]
#![no_std]

#![crate_name = "multiboot"]
#![crate_type = "lib"]

extern crate core;

#[cfg(test)]
extern crate std;

use core::mem::{transmute};
use core::ops::FnMut;
use core::raw;
use core::str;

/// Value that is in rax after multiboot jumps to our entry point
pub const SIGNATURE_RAX: u64 = 0x2BADB002;

#[derive(Debug, PartialEq, Eq)]
pub enum MemType {
    RAM = 1,
    Unusable = 2,
}

pub type PAddr = u64;
pub type VAddr = usize;

/// Multiboot struct clients mainly interact with
/// To create this use Multiboot::new()
pub struct Multiboot<'a> {
    header: &'a MultibootHeader,
    paddr_to_vaddr: fn(PAddr) -> VAddr,
}

/// Representation of Multiboot header according to specification.
#[derive(Debug)]
#[repr(packed)]
struct MultibootHeader {
    flags: u32,

    mem_lower: u32,
    mem_upper: u32,

    boot_device: u32,
    cmdline: u32,

    mods_count: u32,
    mods_addr: u32,

    elf_symbols: ElfSymbols,

    mmap_length: u32,
    mmap_addr: u32,
}

/// Multiboot format of the MMAP buffer.
/// Note that size is defined to be at -4 bytes.
#[derive(Debug)]
#[repr(packed)]
struct MemEntry {
    size: u32,
    base_addr: u64,
    length: u64,
    mtype: u32
}

#[derive(Debug)]
#[repr(packed)]
struct ElfSymbols {
    num: u32,
    size: u32,
    addr: u32,
    shndx: u32,
}

/// Multiboot module structure
#[derive(Debug)]
#[repr(packed)]
struct Module {
    /// Start address of module in memory.
    start: u32,
    /// End address of module in memory.
    end: u32,
    /// Name of module.
    string: u32,
    /// Must be zero.
    reserved: u32
}

/// Convert a C string into a [u8 slice and from there into a &'static str.
/// This unsafe block builds on assumption that multiboot strings are sane.
fn convert_safe_c_string(cstring: *const u8) -> &'static str {
    unsafe {
        let mut iter = cstring;
        while *iter != 0 {
            iter = iter.offset(1);
        }

        let slice = raw::Slice { data: cstring, len: iter as usize - cstring as usize };
        let byte_array: &'static [u8] = transmute(slice);
        str::from_utf8_unchecked(byte_array)
    }
}

impl<'a> Multiboot<'a> {

    /// Initializes the multiboot structure.
    ///
    /// # Arguments
    ///
    ///  * `mboot_ptr` - The physical address of the multiboot header. On qemu for example
    ///                  this is typically at 0x9500.
    ///  * `paddr_to_vaddr` - Translation of the physical addresses into kernel addresses.
    ///
    ///  `paddr_to_vaddr` translates physical it into a kernel accessible address.
    ///  The simplest paddr_to_vaddr function would for example be just the identity
    ///  function. But this may vary depending on how your page table layout looks like.
    ///
    pub fn new(mboot_ptr: u64, paddr_to_vaddr: fn(paddr: PAddr) -> VAddr) -> Multiboot<'a> {
        let header = paddr_to_vaddr(mboot_ptr);
        let mb: &MultibootHeader = unsafe { transmute::<VAddr, &MultibootHeader>(header) };

        Multiboot { header: mb, paddr_to_vaddr: paddr_to_vaddr }
    }

    pub fn has_mmap(&'a self) -> bool {
        self.header.flags & 0x1 > 0
    }

    /// Discover all memory regions in the multiboot memory map.
    ///
    /// # Arguments
    ///
    ///  * `discovery_callback` - Function to notify your memory system about regions.
    ///
    pub fn find_memory<F: FnMut(u64, u64, MemType)>(&'a self, mut discovery_callback: F) {
        if !self.has_mmap() {
            return
        }

        let paddr_to_vaddr = self.paddr_to_vaddr;

        let mut current = self.header.mmap_addr;
        let end = self.header.mmap_addr + self.header.mmap_length;
        while current < end
        {
            let memory_region: &MemEntry = unsafe { transmute::<VAddr, &MemEntry>(paddr_to_vaddr(current as u64)) };

            let mtype = match memory_region.mtype {
                1 => MemType::RAM,
                2 => MemType::Unusable,
                _ => MemType::Unusable
            };

            discovery_callback(memory_region.base_addr, memory_region.length, mtype);
            current += memory_region.size + 4;
        }
    }

    pub fn has_modules(&'a self) -> bool {
        self.header.flags & (1<<3) > 0
    }

    /// Discover all additional modules in multiboot.
    ///
    /// # Arguments
    ///
    ///  * `discovery_callback` - Function to notify your system about modules.
    ///
    pub fn find_modules<F: FnMut(&'static str, VAddr, VAddr)>(&'a self, mut discovery_callback: F) {
        if !self.has_modules() {
            return
        }

        let paddr_to_vaddr = self.paddr_to_vaddr;

        let module_start = paddr_to_vaddr(self.header.mods_addr as u64);
        let count: usize = self.header.mods_count as usize;
        for _ in 0..count {
            let current: &Module = unsafe { transmute::<VAddr, &Module>(module_start) };
            let path = unsafe { convert_safe_c_string(transmute::<VAddr, *const u8>(paddr_to_vaddr(current.string as u64))) };

            discovery_callback(path, paddr_to_vaddr(current.start as PAddr), paddr_to_vaddr(current.end as PAddr));
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

//! The simple-stream crate provides simple abstraction building blocks over any type that
//! implements [`std::io::Read`][std-io-read] + [`std::io::Write`][std-io-write].
//! Coupled with a [`FrameBuilder`][framebuilder], it provides built-in types for plain text
//! and secured streams with help from [rust-openssl][rust-openssl-repo]. It supports both
//! blocking and non-blocking modes.
//!
//! It works by handling all of the I/O on a frame based level. It includes a built-in framing
//! pattern and WebSocket based framing. The `simple_stream::frame` module includes traits for
//! using custom frames.
//!
//! ## Example Usage
//!
//! ```ignore
//! extern crate simple_stream as ss;
//!
//! use ss::frame::Frame;
//! use ss::frame::simple::{SimpleFrame, SimpleFrameBuilder};
//! use ss::{Socket, Plain, NonBlocking, SocketOptions};
//!
//!
//! fn main() {
//!     // tcp_stream is some connection established std::net::TcpStream
//!     //
//!     // Take ownership of the underlying fd to remove TcpStream's Drop being called now
//!     // that we're switching types.
//!     let fd = tcp_stream.into_raw_fd();
//!
//!     // Create a socket and set any POSIX based TCP/SOL_SOCKET options
//!     let mut socket = Socket::new(fd);
//!     socket.set_keepalive(true);
//!     socket.set_nonblocking();
//!
//!     // Create a plain text based stream that reads messages with SimpleFrame type
//!     let mut plain_stream = Plain::<Socket, SimpleFrameBuilder>::new(socket);
//!
//!     // Perform non-blocking read
//!     match plain_stream.nb_recv() {
//!         Ok(frames) => {
//!             // msgs is a Vec<Box<Frame>>
//!             for frame in frames.iter() {
//!                 // Do stuff with received things
//!             }
//!         }
//!         Err(e) => {
//!             // Error handling here
//!         }
//!     }
//!
//!     // Perform non-blocking write
//!     let frame = SimpleFrame::new(&some_buf[..]);
//!     plain_stream.nb_send(&frame).map_err(|e| {
//!         // Error handling here
//!     });
//! }
//! ```

#[macro_use] extern crate log;
#[macro_use] extern crate bitflags;
extern crate openssl;

use std::io::Error;

use frame::Frame;
pub use plain::*;
pub use secure::*;

pub mod frame;
mod plain;
mod secure;

/// The `Blocking` trait provides method definitions for use with blocking streams.
pub trait Blocking {
    /// Performs a blocking read on the underlying stream until a complete Frame has been read
    /// or an `std::io::Error` has occurred.
    fn b_recv(&mut self) -> Result<Box<Frame>, Error>;
    /// Performs a blocking send on the underlying stream until a complete frame has been sent
    /// or an `std::io::Error` has occurred.
    fn b_send(&mut self, frame: &Frame) -> Result<(), Error>;
}

/// The `NonBlocking` trait provides method definitions for use with non-blocking streams.
pub trait NonBlocking {
    /// Performs a non-blocking read on the underlying stream until `ErrorKind::WouldBlock` or an
    /// `std::io::Error` has occurred.
    ///
    /// # `simple_stream::Secure` notes
    ///
    /// Unlike its blocking counterpart, errors received on the OpenSSL level will be returned as
    /// `ErrorKind::Other` with various OpenSSL error information as strings in the description
    /// field of the `std::io::Error`.
    fn nb_recv(&mut self) -> Result<Vec<Box<Frame>>, Error>;
    /// Performs a non-blocking send on the underlying stream until `ErrorKind::WouldBlock` or an
    /// `std::io::Error` has occurred.
    ///
    /// # `simple_stream::Secure` notes
    ///
    /// Unlike its blocking counterpart, errors received on the OpenSSL level will be returned as
    /// `ErrorKind::Other` with various OpenSSL error information as strings in the description
    /// field of the `std::io::Error`.
    fn nb_send(&mut self, frame: &Frame) -> Result<(), Error>;
}
<commit_msg>Updated source code docs. Whoops.<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

//! simple-stream is a buffered stream wrapper over anything that implements
//! `std::io::Read` and `std::io::Write`. It works by buffering all reads and
//! checking the buffers against a `FrameBuilder`, which will inform the stream
//! that a complete `Frame` has been received, and removes it out of the buffer.
//!
//! The crate comes with a few types of Framing options, and provides both a plain
//! text and encrypted stream via [rust-openssl][rust-openssl-repo].
//!
//! ## Example Usage
//!
//! ```ignore
//! extern crate simple_stream as ss;
//!
//! use std::net::TcpStream;
//!
//! use ss::frame::{SimpleFrame, SimpleFrameBuilder};
//! use ss::{Plain, NonBlocking};
//!
//!
//! fn main() {
//!     // Create some non-blocking type that implements Read + Write
//!     let stream = TcpStream::connect("rust-lang.org:80").unwrap();
//!     stream.set_nonblocking(true).unwrap();
//!
//!     // Create a Plain Text stream that sends and receives messages in the
//!     // `SimpleFrame` format.
//!     let mut plain_stream = Plain::<TcpStream, SimpleFrameBuilder>::new(stream);
//!
//!     // Perform a non-blocking write
//!     let buf = vec!(1, 2, 3, 4);
//!     let frame = SimpleFrame::new(&buf[..]);
//!     match plain_stream.nb_send(&frame) {
//!         Ok(_) => { }
//!         Err(e) => println!("Error during write: {}", e)
//!     };
//!
//!     // Perform a non-blocking read
//!     match plain_stream.nb_recv() {
//!         Ok(frames) => {
//!             for _ in frames {
//!                 // Do stuff with received frames
//!             }
//!         }
//!         Err(e) => println!("Error during read: {}", e)
//!     };
//! }
//! ```
//!
//!
//! [rust-openssl-repo]: https://github.com/sfackler/rust-openssl

#[macro_use] extern crate log;
#[macro_use] extern crate bitflags;
extern crate openssl;

use std::io::Error;

use frame::Frame;
pub use plain::*;
pub use secure::*;

pub mod frame;
mod plain;
mod secure;

/// The `Blocking` trait provides method definitions for use with blocking streams.
pub trait Blocking {
    /// Performs a blocking read on the underlying stream until a complete Frame has been read
    /// or an `std::io::Error` has occurred.
    fn b_recv(&mut self) -> Result<Box<Frame>, Error>;
    /// Performs a blocking send on the underlying stream until a complete frame has been sent
    /// or an `std::io::Error` has occurred.
    fn b_send(&mut self, frame: &Frame) -> Result<(), Error>;
}

/// The `NonBlocking` trait provides method definitions for use with non-blocking streams.
pub trait NonBlocking {
    /// Performs a non-blocking read on the underlying stream until `ErrorKind::WouldBlock` or an
    /// `std::io::Error` has occurred.
    ///
    /// # `simple_stream::Secure` notes
    ///
    /// Unlike its blocking counterpart, errors received on the OpenSSL level will be returned as
    /// `ErrorKind::Other` with various OpenSSL error information as strings in the description
    /// field of the `std::io::Error`.
    fn nb_recv(&mut self) -> Result<Vec<Box<Frame>>, Error>;
    /// Performs a non-blocking send on the underlying stream until `ErrorKind::WouldBlock` or an
    /// `std::io::Error` has occurred.
    ///
    /// # `simple_stream::Secure` notes
    ///
    /// Unlike its blocking counterpart, errors received on the OpenSSL level will be returned as
    /// `ErrorKind::Other` with various OpenSSL error information as strings in the description
    /// field of the `std::io::Error`.
    fn nb_send(&mut self, frame: &Frame) -> Result<(), Error>;
}
<|endoftext|>


<commit_before>use std::collections::HashSet;

pub fn puzzle(input: &str) -> u32 {
    // let mut floor1 = HashSet::new();
    // floor1.insert(Component::Generator(Element::Thulium));
    // floor1.insert(Component::Microchip(Element::Thulium));
    // floor1.insert(Component::Generator(Element::Plutonium));
    // floor1.insert(Component::Generator(Element::Strontium));
    //
    // let mut floor2 = HashSet::new();
    // floor2.insert(Component::Microchip(Element::Plutonium));
    // floor2.insert(Component::Microchip(Element::Strontium));
    //
    // let mut floor3 = HashSet::new();
    // floor3.insert(Component::Generator(Element::Promethium));
    // floor3.insert(Component::Microchip(Element::Promethium));
    // floor3.insert(Component::Generator(Element::Ruthenium));
    // floor3.insert(Component::Microchip(Element::Ruthenium));

    let mut floor1 = HashSet::new();
    floor1.insert(Component::Microchip(Element::Hydrogen));
    floor1.insert(Component::Microchip(Element::Lithium));

    let mut floor2 = HashSet::new();
    floor2.insert(Component::Generator(Element::Hydrogen));

    let mut floor3 = HashSet::new();
    floor3.insert(Component::Generator(Element::Lithium));

    let initial_building_state = BuildingState {
        elevator_floor: 0,
        floors: [
            floor1,
            floor2,
            floor3,
            HashSet::new(),
        ],
    };
    let initial_world_state = WorldState {
        steps: 0,
        building: initial_building_state.clone()
    };
    let mut queue = vec![initial_world_state];
    let mut seen = vec![initial_building_state];
    let mut steps = 0;

    while !queue.is_empty() {
        let world = queue.remove(0);

        if world.steps != steps {
            println!("{} step(s), queue: {}", world.steps, queue.len());
            steps = world.steps;
        }

        seen.push(world.building.clone());

        if world.steps == 100 {
            panic!("too far!");
        }
        if world.in_end_state() {
            return world.steps;
        }

        let mut valid_next_moves = world.next_moves(&seen);
        queue.append(&mut valid_next_moves);
    }

    panic!("Exhausted all possible moves without finding end condition!");
}

#[derive(Debug)]
pub struct WorldState {
    steps: u32,
    building: BuildingState,
}

impl WorldState {
    pub fn in_end_state(&self) -> bool {
        self.building.in_end_state()
    }

    pub fn next_moves(&self, seen: &Vec<BuildingState>) -> Vec<WorldState> {
        self.building.next_moves(seen).into_iter().map(|b| {
            WorldState {
                steps: self.steps + 1,
                building: b,
            }
        }).collect()
    }
}

#[derive(PartialEq, Eq, Copy, Clone, Debug, PartialOrd, Ord, Hash)]
pub enum Component {
    Microchip(Element),
    Generator(Element),
}

impl Component {
    fn is_fried(&self, others: &HashSet<Component>) -> bool {
        match *self {
            Component::Generator(my_element) => {
                // There's microchip(s) that are not my element
                // and no generator that is that microchip's element
                (*others).iter().any(|&c|
                    match c {
                        Component::Microchip(e) if e != my_element && !(*others).contains(&Component::Generator(e)) => true,
                        _ => false,
                    }
                )
            },
            Component::Microchip(my_element) => {
                // There's some generator that is not my element
                (*others).iter().find(|&c| {
                    match *c {
                        Component::Generator(e) if e != my_element => true,
                        _ => false,
                    }
                }).is_some() &&
                // There is no generator that is my element
                (*others).iter().find(|&c| {
                    match *c {
                        Component::Generator(e) if e == my_element => true,
                        _ => false,
                    }
                }).is_none()
            }
        }
    }
}

#[derive(PartialEq, Eq, Copy, Clone, Debug, PartialOrd, Ord, Hash)]
pub enum Element {
    Hydrogen,
    Lithium,
    Thulium,
    Plutonium,
    Strontium,
    Promethium,
    Ruthenium,
}

#[derive(Debug, PartialEq)]
pub struct BuildingState {
    elevator_floor: usize,
    floors: [HashSet<Component>; 4],
}

// impl PartialEq for BuildingState {
//     fn eq(&self, other: &BuildingState) -> bool {
//         if self.elevator_floor != other.elevator_floor {
//             return false;
//         }
//         for (self_floor, other_floor) in self.floors.iter().zip(other.floors.iter()) {
//             let mut self_floor = self_floor.clone();
//             let mut other_floor = other_floor.clone();
//             self_floor.sort();
//             other_floor.sort();
//             if self_floor != other_floor {
//                 return false;
//             }
//         }
//
//         true
//     }
// }

impl Clone for BuildingState {
    fn clone(&self) -> BuildingState {
        BuildingState {
            elevator_floor: self.elevator_floor,
            floors: [
                self.floors[0].clone(),
                self.floors[1].clone(),
                self.floors[2].clone(),
                self.floors[3].clone(),
            ]
        }
    }
}

impl BuildingState {
    pub fn in_end_state(&self) -> bool {
        self.floors[0].is_empty() &&
            self.floors[1].is_empty() &&
            self.floors[2].is_empty()
    }

    pub fn next_floors(&self) -> Vec<usize> {
        match self.elevator_floor {
            0 => vec![1],
            1 => vec![0, 2],
            2 => vec![1, 3],
            3 => vec![2],
            other => panic!("How did you get on floor {}, elevator?", other),
        }
    }

    pub fn elevator_combos(&self) -> Vec<Vec<Component>> {
        // It sure would be nice to be able to have HashSet<HashSet<Component>>
        // here so that I don't have to filter out duplicates myself.

        let mut result = vec![];
        let mut components = self.floors[self.elevator_floor].iter();
        while let Some(&component) = components.next() {
            // Could take just this item on the elevator
            result.push(vec![component]);
            // Could take this item and one other, if they don't fry
            for &remaining_component in components.clone() {
                let mut hs = HashSet::new();
                hs.insert(remaining_component);
                if !component.is_fried(&hs) {
                    result.push(vec![component, remaining_component]);
                }
            }
        }
        result
    }

    pub fn next_moves(&self, seen: &Vec<BuildingState>) -> Vec<BuildingState> {
        let mut valid_next_moves = vec![];
        for next_floor in self.next_floors() {
            for combo in self.elevator_combos() {
                let mut bs = (*self).clone();
                for &c in combo.iter() {
                    bs.floors[self.elevator_floor].remove(&c);
                    bs.floors[next_floor].insert(c);
                }
                bs.elevator_floor = next_floor;
                if !bs.has_fried_chips() && !seen.contains(&bs) {
                    valid_next_moves.push(bs);
                }
            }
        }
        valid_next_moves
    }

    pub fn has_fried_chips(&self) -> bool {
        for floor in self.floors.iter() {
            for component in floor {
                // This is doing an extra comparison to itself :shrug:
                if component.is_fried(floor) {
                    return true
                }
            }
        }
        false
    }
}

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

    #[test]
    fn not_in_end_state() {
        let mut floor1 = HashSet::new();
        floor1.insert(Component::Microchip(Element::Hydrogen));
        floor1.insert(Component::Microchip(Element::Lithium));

        let mut floor2 = HashSet::new();
        floor2.insert(Component::Generator(Element::Hydrogen));

        let mut floor3 = HashSet::new();
        floor3.insert(Component::Generator(Element::Lithium));

        let world_state = WorldState {
            steps: 0,
            building: BuildingState {
                elevator_floor: 0,
                floors: [
                    floor1,
                    floor2,
                    floor3,
                    HashSet::new(),
                ],
            }
        };
        assert!( ! world_state.in_end_state() );
    }

    #[test]
    fn in_end_state() {
        let mut floor4 = HashSet::new();
        floor4.insert(Component::Generator(Element::Hydrogen));
        floor4.insert(Component::Microchip(Element::Hydrogen));
        floor4.insert(Component::Microchip(Element::Lithium));
        floor4.insert(Component::Generator(Element::Lithium));
        let world_state = WorldState {
            steps: 0,
            building: BuildingState {
                elevator_floor: 0,
                floors: [
                    HashSet::new(),
                    HashSet::new(),
                    HashSet::new(),
                    floor4,
                ],
            }
        };

        assert!(world_state.in_end_state());
    }

    #[test]
    fn two_microchips_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Microchip(Element::Lithium));
        assert!(
            ! Component::Microchip(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn microchip_alone_not_fried() {
        assert!(
            ! Component::Microchip(Element::Hydrogen).is_fried(
                &HashSet::new()
            )
        )
    }

    #[test]
    fn microchip_with_itself_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Microchip(Element::Hydrogen));

        assert!(
            ! Component::Microchip(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn two_generators_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Lithium));

        assert!(
            ! Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn microchip_and_matching_generator_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Hydrogen));

        assert!(
            ! Component::Microchip(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn microchip_attached_to_matching_generator_not_fried_by_other_generator() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Lithium));
        hs.insert(Component::Generator(Element::Hydrogen));

        assert!(
            ! Component::Microchip(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn microchip_without_its_generator_with_another_generator_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Lithium));

        assert!(
            Component::Microchip(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn generator_with_a_microchip_without_its_generator_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Microchip(Element::Lithium));

        assert!(
            Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn generator_with_a_generator_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Lithium));
        assert!(
            ! Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn generator_with_its_microchip_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Microchip(Element::Hydrogen));

        assert!(
            ! Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn generator_with_itself_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Hydrogen));

        assert!(
            ! Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn generator_with_a_microchip_with_its_generator_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Lithium));
        hs.insert(Component::Microchip(Element::Lithium));

        assert!(
            ! Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }
}
<commit_msg>Make seen into a hashset? maybe this will help?<commit_after>use std::collections::HashSet;
use std::hash::{Hash, Hasher};

pub fn puzzle(input: &str) -> u32 {
    // let mut floor1 = HashSet::new();
    // floor1.insert(Component::Generator(Element::Thulium));
    // floor1.insert(Component::Microchip(Element::Thulium));
    // floor1.insert(Component::Generator(Element::Plutonium));
    // floor1.insert(Component::Generator(Element::Strontium));
    //
    // let mut floor2 = HashSet::new();
    // floor2.insert(Component::Microchip(Element::Plutonium));
    // floor2.insert(Component::Microchip(Element::Strontium));
    //
    // let mut floor3 = HashSet::new();
    // floor3.insert(Component::Generator(Element::Promethium));
    // floor3.insert(Component::Microchip(Element::Promethium));
    // floor3.insert(Component::Generator(Element::Ruthenium));
    // floor3.insert(Component::Microchip(Element::Ruthenium));

    let mut floor1 = HashSet::new();
    floor1.insert(Component::Microchip(Element::Hydrogen));
    floor1.insert(Component::Microchip(Element::Lithium));

    let mut floor2 = HashSet::new();
    floor2.insert(Component::Generator(Element::Hydrogen));

    let mut floor3 = HashSet::new();
    floor3.insert(Component::Generator(Element::Lithium));

    let initial_building_state = BuildingState {
        elevator_floor: 0,
        floors: [
            floor1,
            floor2,
            floor3,
            HashSet::new(),
        ],
    };
    let initial_world_state = WorldState {
        steps: 0,
        building: initial_building_state.clone()
    };
    let mut queue = vec![initial_world_state];
    let mut seen = HashSet::new();
    seen.insert(initial_building_state);
    let mut steps = 0;

    while !queue.is_empty() {
        let world = queue.remove(0);

        if world.steps != steps {
            println!("{} step(s), queue: {}", world.steps, queue.len());
            steps = world.steps;
        }

        seen.insert(world.building.clone());

        if world.steps == 100 {
            panic!("too far!");
        }
        if world.in_end_state() {
            return world.steps;
        }

        let mut valid_next_moves = world.next_moves(&seen);
        queue.append(&mut valid_next_moves);
    }

    panic!("Exhausted all possible moves without finding end condition!");
}

#[derive(Debug)]
pub struct WorldState {
    steps: u32,
    building: BuildingState,
}

impl WorldState {
    pub fn in_end_state(&self) -> bool {
        self.building.in_end_state()
    }

    pub fn next_moves(&self, seen: &HashSet<BuildingState>) -> Vec<WorldState> {
        self.building.next_moves(seen).into_iter().map(|b| {
            WorldState {
                steps: self.steps + 1,
                building: b,
            }
        }).collect()
    }
}

#[derive(PartialEq, Eq, Copy, Clone, Debug, PartialOrd, Ord, Hash)]
pub enum Component {
    Microchip(Element),
    Generator(Element),
}

impl Component {
    fn is_fried(&self, others: &HashSet<Component>) -> bool {
        match *self {
            Component::Generator(my_element) => {
                // There's microchip(s) that are not my element
                // and no generator that is that microchip's element
                (*others).iter().any(|&c|
                    match c {
                        Component::Microchip(e) if e != my_element && !(*others).contains(&Component::Generator(e)) => true,
                        _ => false,
                    }
                )
            },
            Component::Microchip(my_element) => {
                // There's some generator that is not my element
                (*others).iter().find(|&c| {
                    match *c {
                        Component::Generator(e) if e != my_element => true,
                        _ => false,
                    }
                }).is_some() &&
                // There is no generator that is my element
                (*others).iter().find(|&c| {
                    match *c {
                        Component::Generator(e) if e == my_element => true,
                        _ => false,
                    }
                }).is_none()
            }
        }
    }
}

#[derive(PartialEq, Eq, Copy, Clone, Debug, PartialOrd, Ord, Hash)]
pub enum Element {
    Hydrogen,
    Lithium,
    Thulium,
    Plutonium,
    Strontium,
    Promethium,
    Ruthenium,
}

#[derive(Debug, PartialEq, Eq)]
pub struct BuildingState {
    elevator_floor: usize,
    floors: [HashSet<Component>; 4],
}

impl Hash for BuildingState {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.elevator_floor.hash(state);
        for floor in self.floors.iter() {
            let mut components: Vec<&Component> = floor.iter().collect();
            components.sort();
            components.hash(state);
        }
    }
}

impl Clone for BuildingState {
    fn clone(&self) -> BuildingState {
        BuildingState {
            elevator_floor: self.elevator_floor,
            floors: [
                self.floors[0].clone(),
                self.floors[1].clone(),
                self.floors[2].clone(),
                self.floors[3].clone(),
            ]
        }
    }
}

impl BuildingState {
    pub fn in_end_state(&self) -> bool {
        self.floors[0].is_empty() &&
            self.floors[1].is_empty() &&
            self.floors[2].is_empty()
    }

    pub fn next_floors(&self) -> Vec<usize> {
        match self.elevator_floor {
            0 => vec![1],
            1 => vec![0, 2],
            2 => vec![1, 3],
            3 => vec![2],
            other => panic!("How did you get on floor {}, elevator?", other),
        }
    }

    pub fn elevator_combos(&self) -> Vec<Vec<Component>> {
        // It sure would be nice to be able to have HashSet<HashSet<Component>>
        // here so that I don't have to filter out duplicates myself.

        let mut result = vec![];
        let mut components = self.floors[self.elevator_floor].iter();
        while let Some(&component) = components.next() {
            // Could take just this item on the elevator
            result.push(vec![component]);
            // Could take this item and one other, if they don't fry
            for &remaining_component in components.clone() {
                let mut hs = HashSet::new();
                hs.insert(remaining_component);
                if !component.is_fried(&hs) {
                    result.push(vec![component, remaining_component]);
                }
            }
        }
        result
    }

    pub fn next_moves(&self, seen: &HashSet<BuildingState>)
                      -> Vec<BuildingState> {
        let mut valid_next_moves = vec![];
        for next_floor in self.next_floors() {
            for combo in self.elevator_combos() {
                let mut bs = (*self).clone();
                for &c in combo.iter() {
                    bs.floors[self.elevator_floor].remove(&c);
                    bs.floors[next_floor].insert(c);
                }
                bs.elevator_floor = next_floor;
                if !bs.has_fried_chips() && !seen.contains(&bs) {
                    valid_next_moves.push(bs);
                }
            }
        }
        valid_next_moves
    }

    pub fn has_fried_chips(&self) -> bool {
        for floor in self.floors.iter() {
            for component in floor {
                // This is doing an extra comparison to itself :shrug:
                if component.is_fried(floor) {
                    return true
                }
            }
        }
        false
    }
}

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

    #[test]
    fn not_in_end_state() {
        let mut floor1 = HashSet::new();
        floor1.insert(Component::Microchip(Element::Hydrogen));
        floor1.insert(Component::Microchip(Element::Lithium));

        let mut floor2 = HashSet::new();
        floor2.insert(Component::Generator(Element::Hydrogen));

        let mut floor3 = HashSet::new();
        floor3.insert(Component::Generator(Element::Lithium));

        let world_state = WorldState {
            steps: 0,
            building: BuildingState {
                elevator_floor: 0,
                floors: [
                    floor1,
                    floor2,
                    floor3,
                    HashSet::new(),
                ],
            }
        };
        assert!( ! world_state.in_end_state() );
    }

    #[test]
    fn in_end_state() {
        let mut floor4 = HashSet::new();
        floor4.insert(Component::Generator(Element::Hydrogen));
        floor4.insert(Component::Microchip(Element::Hydrogen));
        floor4.insert(Component::Microchip(Element::Lithium));
        floor4.insert(Component::Generator(Element::Lithium));
        let world_state = WorldState {
            steps: 0,
            building: BuildingState {
                elevator_floor: 0,
                floors: [
                    HashSet::new(),
                    HashSet::new(),
                    HashSet::new(),
                    floor4,
                ],
            }
        };

        assert!(world_state.in_end_state());
    }

    #[test]
    fn two_microchips_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Microchip(Element::Lithium));
        assert!(
            ! Component::Microchip(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn microchip_alone_not_fried() {
        assert!(
            ! Component::Microchip(Element::Hydrogen).is_fried(
                &HashSet::new()
            )
        )
    }

    #[test]
    fn microchip_with_itself_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Microchip(Element::Hydrogen));

        assert!(
            ! Component::Microchip(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn two_generators_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Lithium));

        assert!(
            ! Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn microchip_and_matching_generator_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Hydrogen));

        assert!(
            ! Component::Microchip(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn microchip_attached_to_matching_generator_not_fried_by_other_generator() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Lithium));
        hs.insert(Component::Generator(Element::Hydrogen));

        assert!(
            ! Component::Microchip(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn microchip_without_its_generator_with_another_generator_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Lithium));

        assert!(
            Component::Microchip(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn generator_with_a_microchip_without_its_generator_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Microchip(Element::Lithium));

        assert!(
            Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn generator_with_a_generator_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Lithium));
        assert!(
            ! Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn generator_with_its_microchip_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Microchip(Element::Hydrogen));

        assert!(
            ! Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn generator_with_itself_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Hydrogen));

        assert!(
            ! Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }

    #[test]
    fn generator_with_a_microchip_with_its_generator_not_fried() {
        let mut hs = HashSet::new();
        hs.insert(Component::Generator(Element::Lithium));
        hs.insert(Component::Microchip(Element::Lithium));

        assert!(
            ! Component::Generator(Element::Hydrogen).is_fried(
                &hs
            )
        )
    }
}
<|endoftext|>


<commit_before>#![feature(globs)]

use std::io::*;
use std::error::*;
use std::io::net::ip::SocketAddr;
use std::str::FromStr;
use std::time::Duration;
use std::cell::RefCell;

pub struct Client {
    addr : SocketAddr,
    conn : TcpStream
}

#[deriving(Show,Clone)]
pub enum Failure {
    Io(IoError),
    Client(ClientError)
}

impl FromError<IoError> for Failure {
    fn from_error(err:IoError) -> Failure {
        Failure::Io(err)
    }
}

#[deriving(Show,Clone)]
pub struct ClientError {
    desc : String
}

impl Error for ClientError {
    fn description(&self) -> &str {
        self.desc.as_slice()
    }
}

impl FromError<ClientError> for Failure {
    fn from_error(err:ClientError) -> Failure {
        Failure::Client(err)
    }
}

pub type McResult<T> = Result<T,Failure>;

#[deriving(Show)]
pub enum Response {
    Stored,
    NotStored,
    InvalidCmd,
    ClientErr(String),
    ServerErr(String)
}

pub struct Parser<T> {
    reader : T
}

impl <'a,T:Reader> Parser<T> {

    pub fn new(reader: T) -> Parser<T> {
        Parser { reader: reader }
    }

    #[inline]
    fn expect_char(&mut self, refchar: char) -> McResult<()> {
        if try!(self.reader.read_byte()) as char == refchar {
            Ok(())
        } else {
            Err(FromError::from_error(ClientError{desc:"Invalid byte in response".into_string()}))
        }
    }

    #[inline]
    fn expect_newline(&mut self) -> McResult<()> {
        match try!(self.reader.read_byte()) as char {
            '\n' => Ok(()),
            '\r' => self.expect_char('\n'),
            _ => Err(FromError::from_error(ClientError{desc:"Expect new line,Invalid byte in response".into_string()}))
        }
    }

    fn read_line(&mut self) -> McResult<Vec<u8>> {
        let mut rv = vec![];

        loop {
            let b = try!(self.reader.read_byte());
            match b as char {
                '\n' => { break; }
                '\r' => {
                    try!(self.expect_char('\n'));
                    break;
                },
                _ => { rv.push(b) }
            };
        }

        Ok(rv)
    }

    fn read_string_line(&mut self) -> McResult<String> {
        match String::from_utf8(try!(self.read_line())) {
            Err(_) => {
                Err(FromError::from_error(ClientError{desc:"Expect string,Invalid byte in response".into_string()}))
            }
            Ok(value) => Ok(value)
        }
    }

    pub fn parse_value(&mut self) -> McResult<Response> {
        let ret = self.read_string_line().unwrap();
        let line = ret.as_slice();
        if line.len() < 5 {
            return Err(FromError::from_error(ClientError{desc:"Expect more,Invalid byte in response".into_string()}));
        }
        if line.starts_with("STORED") {
            Ok(Response::Stored)
        }
        else if line.starts_with("NOT_STORED") {
            Ok(Response::NotStored)
        }
        else if line.starts_with("ERROR") {
            Ok(Response::InvalidCmd)
        }
        else if line.starts_with("CLIENT_ERROR") {
            let err = line.slice(12,line.len()-4).into_string();
            Ok(Response::ClientErr(err))
        }
        else if line.starts_with("SERVER_ERROR") {
            let err = line.slice(12,line.len()-4).into_string();
            Ok(Response::ServerErr(err))
        }
        else {
            Err(FromError::from_error(ClientError{desc:"invalid response".into_string()}))
        }

    }

}

impl Client {

    pub fn new(addr:&str) -> McResult<Client> {
        let ad : Option<SocketAddr> = FromStr::from_str(addr);
        match ad {
            Some(addr) => {
                Ok(Client{addr:addr,
                    conn:try!(TcpStream::connect_timeout(addr,Duration::seconds(1)))
                    })
            },
            None => {
                Err(FromError::from_error(ClientError{desc:"invalid addr".into_string()}))
            }
        }
    }

    pub fn set(&mut self,key:&str,flag:u16,expire:uint,data:&str) -> McResult<Response> {
        let cmd = format_args!(std::fmt::format,"set {} {} {} {}\r\n{}\r\n",key,flag,expire,data.as_slice().as_bytes().len(),data);

        {
            let mut conn = &mut self.conn;
            conn.set_timeout(Some(1000u64));
            try!(conn.write(cmd.as_slice().as_bytes()));
        }

        let mut parser = Parser::new( &mut self.conn as &mut Reader );
        let res = try!(parser.parse_value());
        Ok(res)
    }
}

<commit_msg>add Item & get<commit_after>#![feature(globs)]

use std::io::*;
use std::error::*;
use std::io::net::ip::SocketAddr;
use std::str::FromStr;
use std::time::Duration;
use std::cell::RefCell;

pub struct Client {
    addr : SocketAddr,
    conn : TcpStream
}

#[deriving(Show,Clone)]
pub enum Failure {
    Io(IoError),
    Client(ClientError)
}

impl FromError<IoError> for Failure {
    fn from_error(err:IoError) -> Failure {
        Failure::Io(err)
    }
}

#[deriving(Show,Clone)]
pub struct ClientError {
    desc : String
}

impl Error for ClientError {
    fn description(&self) -> &str {
        self.desc.as_slice()
    }
}

impl FromError<ClientError> for Failure {
    fn from_error(err:ClientError) -> Failure {
        Failure::Client(err)
    }
}

pub type McResult<T> = Result<T,Failure>;

#[deriving(Show)]
pub struct Item {
    key:String,
    flag:u16,
    Val:String
}

#[deriving(Show)]
pub enum Response {
    Stored,
    NotStored,
    InvalidCmd,
    ClientErr(String),
    ServerErr(String),
    Value(Item)
}

pub struct Parser<T> {
    reader : T
}

impl <'a,T:Reader> Parser<T> {

    pub fn new(reader: T) -> Parser<T> {
        Parser { reader: reader }
    }

    #[inline]
    fn expect_char(&mut self, refchar: char) -> McResult<()> {
        if try!(self.reader.read_byte()) as char == refchar {
            Ok(())
        } else {
            Err(FromError::from_error(ClientError{desc:"Invalid byte in response".into_string()}))
        }
    }

    #[inline]
    fn expect_newline(&mut self) -> McResult<()> {
        match try!(self.reader.read_byte()) as char {
            '\n' => Ok(()),
            '\r' => self.expect_char('\n'),
            _ => Err(FromError::from_error(ClientError{desc:"Expect new line,Invalid byte in response".into_string()}))
        }
    }

    fn read_line(&mut self) -> McResult<Vec<u8>> {
        let mut rv = vec![];

        loop {
            let b = try!(self.reader.read_byte());
            match b as char {
                '\n' => { break; }
                '\r' => {
                    try!(self.expect_char('\n'));
                    break;
                },
                _ => { rv.push(b) }
            };
        }

        Ok(rv)
    }

    fn read_string_line(&mut self) -> McResult<String> {
        match String::from_utf8(try!(self.read_line())) {
            Err(_) => {
                Err(FromError::from_error(ClientError{desc:"Expect string,Invalid byte in response".into_string()}))
            }
            Ok(value) => Ok(value)
        }
    }

    pub fn parse_value(&mut self) -> McResult<Response> {
        let ret = self.read_string_line().unwrap();
        let line = ret.as_slice();
        if line.len() < 5 {
            return Err(FromError::from_error(ClientError{desc:"Expect more,Invalid byte in response".into_string()}));
        }
        if line.starts_with("STORED") {
            Ok(Response::Stored)
        }
        else if line.starts_with("NOT_STORED") {
            Ok(Response::NotStored)
        }
        else if line.starts_with("ERROR") {
            Ok(Response::InvalidCmd)
        }
        else if line.starts_with("CLIENT_ERROR") {
            let err = line.slice(12,line.len()-4).into_string();
            Ok(Response::ClientErr(err))
        }
        else if line.starts_with("SERVER_ERROR") {
            let err = line.slice(12,line.len()-4).into_string();
            Ok(Response::ServerErr(err))
        }
        else {
            Err(FromError::from_error(ClientError{desc:"invalid response".into_string()}))
        }

    }

}

impl Client {

    pub fn new(addr:&str) -> McResult<Client> {
        let ad : Option<SocketAddr> = FromStr::from_str(addr);
        match ad {
            Some(addr) => {
                Ok(Client{addr:addr,
                    conn:try!(TcpStream::connect_timeout(addr,Duration::seconds(1)))
                    })
            },
            None => {
                Err(FromError::from_error(ClientError{desc:"invalid addr".into_string()}))
            }
        }
    }

    pub fn set(&mut self,key:&str,flag:u16,expire:uint,data:&str) -> McResult<Response> {
        let cmd = format_args!(std::fmt::format,"set {} {} {} {}\r\n{}\r\n",key,flag,expire,data.as_slice().as_bytes().len(),data);
        {
            let mut conn = &mut self.conn;
            try!(conn.write(cmd.as_slice().as_bytes()));
        }
        self.parse()
    }

    pub fn get(&mut self,key:&str) -> McResult<Response> {
        let cmd = format_args!(std::fmt::format,"get {}\r\n",key);
        {
            let mut conn = &mut self.conn;
            try!(conn.write(cmd.as_slice().as_bytes()));
        }
        self.parse()
    }

    fn parse(&mut self) -> McResult<Response> {
        let mut parser = Parser::new( &mut self.conn as &mut Reader );
        let res = try!(parser.parse_value());
        Ok(res)
    }

}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use types::*;
use types::RispType::*;
use environment::*;
use core::create_core_environment;

pub fn eval(ast: RispType, env: &mut Environment) -> RispResult {
    match ast {
        List(list) => {
            let first_element = list.first().ok_or_else(|| error("Empty List"))?;
            match *first_element {
                Symbol(ref symbol) => {
                    match symbol.as_ref() {
                        "def" => {
                            let var = list.get(1).ok_or_else(|| error("Missing variable in def"))?;
                            match *var {
                                Symbol(ref sym_var) => {
                                    let value_ast = list.get(2).ok_or_else(|| error("Missing value in def"))?;
                                    let value = eval(value_ast.clone(), env)?;
                                    env.set(sym_var, value.clone());
                                    Ok(value)
                                }
                                _ => error_result(format!("Expected symbol in def but got {:?}", var))
                            }
                        },
                        "do" => {
                            if let Some((last, elements)) =  (&list[1..]).split_last() {
                                for child_ast in elements.iter() {
                                    eval(child_ast.clone(), env)?;
                                }
                                eval(last.clone(), env)
                            } else {
                                error_result("Empty do block")
                            }
                        }
                        _ => {
                            let evaluated_tail = list[1..].iter()
                                .map(|el| eval(el.clone(), env))
                                .collect::<Result<Vec<_>, _>>()?;
                            let env_value = env.get(symbol).ok_or_else(|| error(format!("Undefined symbol{:?}", symbol)))?;
                            match env_value {
                                Function(function) => function(evaluated_tail.to_vec()),
                                _ => error_result(format!("Expected function but got {:?}", env_value))
                            }
                        }
                    }
                }
                _ => error_result(format!("Expected symbol but got {:?}", first_element))
            }
        }
        Vector(vector) => {
            let evaluated_vector = vector.iter()
                .map(|el| eval(el.clone(), env))
                .collect::<Result<Vec<_>, _>>()?;
            Ok(Vector(evaluated_vector))
        }

        Map(map_value) => {
            let evaluated_map = map_value.iter()
                .map(|(key, val)|
                    eval(val.clone(), env).map(|evaluated_value|
                        (key.to_string(), evaluated_value)))
                .collect::<Result<HashMap<String, RispType>, _>>()?;
            Ok(Map(evaluated_map))
        }

        Symbol(symbol) => {
            env.get(&symbol).ok_or_else(|| error(format!("symbol '{:?}' is undefined", symbol)))
        }
        other => Ok(other)
    }
}

#[allow(dead_code)]
fn eval_test(ast: RispType) -> RispResult {
    eval(ast, &mut create_core_environment())
}

#[test]
fn test_eval_number() {
    assert_eq!(eval_test(Int(23)), Ok(Int(23)));
}

#[test]
fn test_eval_math() {
    assert_eq!(eval_test(List(vec![Symbol("+".to_string()), Int(1), Int(2)])), Ok(Int(3)));
}

#[test]
fn test_nested_math() {
    assert_eq!(eval_test(List(vec![
        Symbol("+".to_string()), Int(1),
        List(vec![Symbol("+".to_string()), Int(10), Int(100)])
    ])), Ok(Int(111)));
}

#[test]
fn test_mul() {
    assert_eq!(eval_test(List(vec![
        Symbol("+".to_string()), Int(1),
        List(vec![Symbol("*".to_string()), Int(10), Int(23)])
    ])), Ok(Int(231)));
}

#[test]
fn test_def() {
    let variable = "variable";
    let variable_value = Int(23);
    let mut env = create_core_environment();

    assert_eq!(eval(List(vec![
        symbol("def"),
        symbol(variable),
        variable_value.clone()
    ]), &mut env), Ok(variable_value.clone()));

    assert_eq!(env.get(variable), Some(variable_value));
}

#[test]
fn test_def_evaluated() {
    let variable = "variable";
    let mut env = create_core_environment();

    assert_eq!(eval(List(vec![
        symbol("def"),
        symbol(variable),
        List(vec![symbol("+"), Int(1), Int(2)])
    ]), &mut env), Ok(Int(3)));

    assert_eq!(env.get(variable), Some(Int(3)));
}

#[test]
fn test_eval_simple_vector() {
    let simple_vector = Vector(vec![Int(1), Int(2)]);
    assert_eq!(eval_test(simple_vector.clone()), Ok(simple_vector));
}

#[test]
fn test_eval_nested_vector() {
    let simple_vector = Vector(vec![Int(1), List(vec![symbol("+"), Int(1), Int(2)])]);
    assert_eq!(eval_test(simple_vector.clone()), Ok(Vector(vec![Int(1), Int(3)])));
}

#[test]
fn test_eval_simple_map() {
    let simple_map = map(vec![
        ("key1", Int(1)),
        ("key2", Int(2))
    ]);
    assert_eq!(eval_test(simple_map.clone()), Ok(simple_map));
}

#[test]
fn test_eval_nested_map() {
    let input_map = map(vec![
        ("key", List(vec![symbol("+"), Int(1), Int(2)]))
    ]);
    let expected_output_map = map(vec![
        ("key", Int(3))
    ]);
    assert_eq!(eval_test(input_map.clone()), Ok(expected_output_map));
}
<commit_msg>Added comment<commit_after>use std::collections::HashMap;
use types::*;
use types::RispType::*;
use environment::*;
use core::create_core_environment;

pub fn eval(ast: RispType, env: &mut Environment) -> RispResult {
    match ast {
        List(list) => {
            let first_element = list.first().ok_or_else(|| error("Empty List"))?;
            match *first_element {
                Symbol(ref symbol) => {
                    match symbol.as_ref() {
                        "def" => {
                            let var = list.get(1).ok_or_else(|| error("Missing variable in def"))?;
                            match *var {
                                Symbol(ref sym_var) => {
                                    let value_ast = list.get(2).ok_or_else(|| error("Missing value in def"))?;
                                    let value = eval(value_ast.clone(), env)?;
                                    env.set(sym_var, value.clone());
                                    Ok(value)
                                }
                                _ => error_result(format!("Expected symbol in def but got {:?}", var))
                            }
                        },
                        "do" => {
                            if let Some((last, elements)) =  (&list[1..]).split_last() {
                                for child_ast in elements.iter() {
                                    eval(child_ast.clone(), env)?;
                                }
                                eval(last.clone(), env)
                            } else {
                                error_result("Empty do block")
                            }
                        }
                        _ => {
                            let evaluated_tail = list[1..].iter()
                                .map(|el| eval(el.clone(), env))
                                .collect::<Result<Vec<_>, _>>()?;
                            let env_value = env.get(symbol).ok_or_else(|| error(format!("Undefined symbol{:?}", symbol)))?;
                            match env_value {
                                Function(function) => function(evaluated_tail.to_vec()),
                                _ => error_result(format!("Expected function but got {:?}", env_value))
                            }
                        }
                    }
                }
                _ => error_result(format!("Expected symbol but got {:?}", first_element))
            }
        }
        Vector(vector) => {
            let evaluated_vector = vector.iter()
                .map(|el| eval(el.clone(), env))
                .collect::<Result<Vec<_>, _>>()?;
            Ok(Vector(evaluated_vector))
        }

        Map(map_value) => {
            let evaluated_map = map_value.iter()
                .map(|(key, val)|
                    eval(val.clone(), env).map(|evaluated_value|
                        (key.to_string(), evaluated_value)))
                .collect::<Result<HashMap<String, RispType>, _>>()?;
            Ok(Map(evaluated_map))
        }

        Symbol(symbol) => {
            env.get(&symbol).ok_or_else(|| error(format!("symbol '{:?}' is undefined", symbol)))
        }
        other => Ok(other)
    }
}

/* ------------------------------ Tests ----------------------------------------------- */

#[allow(dead_code)]
fn eval_test(ast: RispType) -> RispResult {
    eval(ast, &mut create_core_environment())
}

#[test]
fn test_eval_number() {
    assert_eq!(eval_test(Int(23)), Ok(Int(23)));
}

#[test]
fn test_eval_math() {
    assert_eq!(eval_test(List(vec![Symbol("+".to_string()), Int(1), Int(2)])), Ok(Int(3)));
}

#[test]
fn test_nested_math() {
    assert_eq!(eval_test(List(vec![
        Symbol("+".to_string()), Int(1),
        List(vec![Symbol("+".to_string()), Int(10), Int(100)])
    ])), Ok(Int(111)));
}

#[test]
fn test_mul() {
    assert_eq!(eval_test(List(vec![
        Symbol("+".to_string()), Int(1),
        List(vec![Symbol("*".to_string()), Int(10), Int(23)])
    ])), Ok(Int(231)));
}

#[test]
fn test_def() {
    let variable = "variable";
    let variable_value = Int(23);
    let mut env = create_core_environment();

    assert_eq!(eval(List(vec![
        symbol("def"),
        symbol(variable),
        variable_value.clone()
    ]), &mut env), Ok(variable_value.clone()));

    assert_eq!(env.get(variable), Some(variable_value));
}

#[test]
fn test_def_evaluated() {
    let variable = "variable";
    let mut env = create_core_environment();

    assert_eq!(eval(List(vec![
        symbol("def"),
        symbol(variable),
        List(vec![symbol("+"), Int(1), Int(2)])
    ]), &mut env), Ok(Int(3)));

    assert_eq!(env.get(variable), Some(Int(3)));
}

#[test]
fn test_eval_simple_vector() {
    let simple_vector = Vector(vec![Int(1), Int(2)]);
    assert_eq!(eval_test(simple_vector.clone()), Ok(simple_vector));
}

#[test]
fn test_eval_nested_vector() {
    let simple_vector = Vector(vec![Int(1), List(vec![symbol("+"), Int(1), Int(2)])]);
    assert_eq!(eval_test(simple_vector.clone()), Ok(Vector(vec![Int(1), Int(3)])));
}

#[test]
fn test_eval_simple_map() {
    let simple_map = map(vec![
        ("key1", Int(1)),
        ("key2", Int(2))
    ]);
    assert_eq!(eval_test(simple_map.clone()), Ok(simple_map));
}

#[test]
fn test_eval_nested_map() {
    let input_map = map(vec![
        ("key", List(vec![symbol("+"), Int(1), Int(2)]))
    ]);
    let expected_output_map = map(vec![
        ("key", Int(3))
    ]);
    assert_eq!(eval_test(input_map.clone()), Ok(expected_output_map));
}
<|endoftext|>


<commit_before>//! Rustic bindings to [libnotify](https://developer.gnome.org/libnotify/)
//!
//! ```rust
//! extern crate libnotify;
//!
//! fn main() {
//!    let notify = libnotify::Context::new("hello").unwrap();
//!    let n = notify.new_notification("This is the summary.",
//!                                    Some("This is the optional body text."),
//!                                    None).unwrap();
//!    n.show().unwrap();
//! }
//! ```

extern crate "libnotify-sys" as sys;
extern crate "glib-2_0-sys" as glib;

use std::ffi::CString;
use std::marker::PhantomData;
use std::fmt;

use glib::types::{
    TRUE,
    FALSE
};

/// Error that can happen on context creation
#[derive(Debug)]
pub enum ContextCreationError {
    /// Context already exists
    AlreadyExists,
    InitFailure,
    NulError
}

impl fmt::Display for ContextCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        use ContextCreationError::*;
        match *self {
            AlreadyExists => write!(f, "A Libnotify context already exists."),
            InitFailure => write!(f, "Failed to initialize libnotify."),
            NulError => write!(f, "Argument contains a nul character.")
        }
    }
}

#[derive(Debug)]
pub enum NotificationCreationError {
    NulError,
    Unknown
}

impl fmt::Display for NotificationCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        use NotificationCreationError::*;
        match *self {
            NulError => write!(f, "Argument contains a nul character."),
            Unknown => write!(f, "Unknown error")
        }
    }
}

/// The context which within libnotify operates.
///
/// Only one context can exist at a time.
pub struct Context;

impl Context {
    /// Create a new context
    ///
    /// Arguments:
    ///
    /// - app_name: The name of the application using the context
    pub fn new(app_name: &str) -> Result<Context, ContextCreationError> {
        unsafe {
            if sys::notify_is_initted() == TRUE {
                return Err(ContextCreationError::AlreadyExists);
            }
            let app_name = match CString::new(app_name) {
                Ok(name) => name,
                Err(_) => return Err(ContextCreationError::NulError)
            };
            if sys::notify_init(app_name.as_ptr()) == FALSE {
                return Err(ContextCreationError::InitFailure);
            }
        }
        Ok(Context)
    }
    /// Creates a new Notification.
    ///
    /// Arguments:
    ///
    /// - summary: Required summary text
    /// - body: Optional body text
    /// - icon: Optional icon theme icon name or filename
    pub fn new_notification(&self, summary: &str,
                                   body: Option<&str>,
                                   icon: Option<&str>)
        -> Result<Notification, NotificationCreationError> {
        let summary = match CString::new(summary) {
            Ok(cstr) => cstr,
            Err(_) => return Err(NotificationCreationError::NulError)
        };
        let body = match body {
            Some(body) => match CString::new(body) {
                Ok(cstr) => Some(cstr),
                Err(_) => return Err(NotificationCreationError::NulError)
            },
            None => None
        };
        let body_ptr = match body {
            Some(body) => body.as_ptr(),
            None => std::ptr::null()
        };
        let icon = match icon {
            Some(icon) => match CString::new(icon) {
                Ok(cstr) => Some(cstr),
                Err(_) => return Err(NotificationCreationError::NulError)
            },
            None => None
        };
        let icon_ptr = match icon {
            Some(icon) => icon.as_ptr(),
            None => std::ptr::null()
        };
        unsafe {
            let n = sys::notify_notification_new(summary.as_ptr(),
                                                 body_ptr,
                                                 icon_ptr);
            if n.is_null() {
                return Err(NotificationCreationError::Unknown);
            }

            Ok(Notification{handle: n, _phantom: PhantomData})
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            sys::notify_uninit();
        }
    }
}

/// A passive pop-up notification
pub struct Notification<'a> {
    handle: *mut sys::NotifyNotification,
    _phantom: PhantomData<&'a Context>
}

impl<'a> Notification<'a> {
    /// Tells the notification server to display the notification
    /// on the screen.
    pub fn show(&'a self) -> Result<(), ()> {
        unsafe {
            let mut err: *mut glib::GError = std::ptr::null_mut();
            sys::notify_notification_show(self.handle, &mut err);
            if !err.is_null() {
                glib::g_error_free(err);
                return Err(())
            }
            return Ok(())
        }
    }
}
<commit_msg>Update doc example<commit_after>//! Rustic bindings to [libnotify](https://developer.gnome.org/libnotify/)
//!
//! ```rust
//! extern crate libnotify;
//!
//! fn main() {
//!     let notify = libnotify::Context::new("hello").unwrap_or_else(|e| {
//!         panic!("{}", e);
//!     });
//!     let body_text = Some("This is the optional body text.");
//!     let n = notify.new_notification("This is the summary.",
//!                                     body_text,
//!                                     None).unwrap_or_else(|e| {
//!         panic!("{}", e);
//!     });
//!     n.show().ok().expect("Failed to show notification");
//! }
//! ```

extern crate "libnotify-sys" as sys;
extern crate "glib-2_0-sys" as glib;

use std::ffi::CString;
use std::marker::PhantomData;
use std::fmt;

use glib::types::{
    TRUE,
    FALSE
};

/// Error that can happen on context creation
#[derive(Debug)]
pub enum ContextCreationError {
    /// Context already exists
    AlreadyExists,
    InitFailure,
    NulError
}

impl fmt::Display for ContextCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        use ContextCreationError::*;
        match *self {
            AlreadyExists => write!(f, "A Libnotify context already exists."),
            InitFailure => write!(f, "Failed to initialize libnotify."),
            NulError => write!(f, "Argument contains a nul character.")
        }
    }
}

#[derive(Debug)]
pub enum NotificationCreationError {
    NulError,
    Unknown
}

impl fmt::Display for NotificationCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        use NotificationCreationError::*;
        match *self {
            NulError => write!(f, "Argument contains a nul character."),
            Unknown => write!(f, "Unknown error")
        }
    }
}

/// The context which within libnotify operates.
///
/// Only one context can exist at a time.
pub struct Context;

impl Context {
    /// Create a new context
    ///
    /// Arguments:
    ///
    /// - app_name: The name of the application using the context
    pub fn new(app_name: &str) -> Result<Context, ContextCreationError> {
        unsafe {
            if sys::notify_is_initted() == TRUE {
                return Err(ContextCreationError::AlreadyExists);
            }
            let app_name = match CString::new(app_name) {
                Ok(name) => name,
                Err(_) => return Err(ContextCreationError::NulError)
            };
            if sys::notify_init(app_name.as_ptr()) == FALSE {
                return Err(ContextCreationError::InitFailure);
            }
        }
        Ok(Context)
    }
    /// Creates a new Notification.
    ///
    /// Arguments:
    ///
    /// - summary: Required summary text
    /// - body: Optional body text
    /// - icon: Optional icon theme icon name or filename
    pub fn new_notification(&self, summary: &str,
                                   body: Option<&str>,
                                   icon: Option<&str>)
        -> Result<Notification, NotificationCreationError> {
        let summary = match CString::new(summary) {
            Ok(cstr) => cstr,
            Err(_) => return Err(NotificationCreationError::NulError)
        };
        let body = match body {
            Some(body) => match CString::new(body) {
                Ok(cstr) => Some(cstr),
                Err(_) => return Err(NotificationCreationError::NulError)
            },
            None => None
        };
        let body_ptr = match body {
            Some(body) => body.as_ptr(),
            None => std::ptr::null()
        };
        let icon = match icon {
            Some(icon) => match CString::new(icon) {
                Ok(cstr) => Some(cstr),
                Err(_) => return Err(NotificationCreationError::NulError)
            },
            None => None
        };
        let icon_ptr = match icon {
            Some(icon) => icon.as_ptr(),
            None => std::ptr::null()
        };
        unsafe {
            let n = sys::notify_notification_new(summary.as_ptr(),
                                                 body_ptr,
                                                 icon_ptr);
            if n.is_null() {
                return Err(NotificationCreationError::Unknown);
            }

            Ok(Notification{handle: n, _phantom: PhantomData})
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            sys::notify_uninit();
        }
    }
}

/// A passive pop-up notification
pub struct Notification<'a> {
    handle: *mut sys::NotifyNotification,
    _phantom: PhantomData<&'a Context>
}

impl<'a> Notification<'a> {
    /// Tells the notification server to display the notification
    /// on the screen.
    pub fn show(&'a self) -> Result<(), ()> {
        unsafe {
            let mut err: *mut glib::GError = std::ptr::null_mut();
            sys::notify_notification_show(self.handle, &mut err);
            if !err.is_null() {
                glib::g_error_free(err);
                return Err(())
            }
            return Ok(())
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use super::atom::Atom;
use super::parser::Parser;

#[derive(Debug, PartialEq)]
pub enum Expr {
    Atom(Atom),

    // ( ... )
    Tuple(Vec<Expr>),

    // [ ... ]
    Array(Vec<Expr>),

    // { key val ... }
    Map(Vec<(Expr, Expr)>),
}

impl Expr {
    pub fn parse(s: &str) -> Result<Expr, ()> {
        let mut p = Parser::new(s);
        if let Ok(expr) = p.parse_expr() {
            if p.at_end() {
                return Ok(expr);
            }
        }
        Err(())
    }
}

impl<T> From<T> for Expr where T: Into<Atom>
{
    fn from(t: T) -> Expr {
        Expr::Atom(t.into())
    }
}

impl From<()> for Expr {
    fn from(_e: ()) -> Expr {
        Expr::Tuple(vec![])
    }
}

impl<A> From<(A,)> for Expr where A: Into<Expr>
{
    fn from(e: (A,)) -> Expr {
        Expr::Tuple(vec![e.0.into()])
    }
}

impl<A, B> From<(A, B)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>
{
    fn from(e: (A, B)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into()])
    }
}

impl<A, B, C> From<(A, B, C)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>,
          C: Into<Expr>
{
    fn from(e: (A, B, C)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into(), e.2.into()])
    }
}

impl<A, B, C, D> From<(A, B, C, D)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>,
          C: Into<Expr>,
          D: Into<Expr>
{
    fn from(e: (A, B, C, D)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into(), e.2.into(), e.3.into()])
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Expr::Atom(ref a) => write!(f, "{}", a),
            Expr::Tuple(ref t) => {
                try!(write!(f, "("));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, ")")
            }
            Expr::Array(ref t) => {
                try!(write!(f, "["));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, "]")
            }
            Expr::Map(ref t) => {
                try!(write!(f, "{}", "{"));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{} {}", space, expr.0, expr.1));
                }
                write!(f, "{}", "}")
            }

        }
    }
}

#[test]
fn test_display() {
    assert_eq!("12345", &format!("{}", Expr::Atom(Atom::UInt(12345))));
    assert_eq!("(12345)",
               &format!("{}", Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345))])));
    assert_eq!("(12345 abc)",
               &format!("{}",
                        Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345)),
                                         Expr::Atom(Atom::Str("abc".to_string()))])));
    assert_eq!("(12345 (abc))",
               &format!("{}",
                        Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345)),
                                         Expr::Tuple(vec![
                                         Expr::Atom(Atom::Str("abc".to_string()))
                                         ])])));

}

#[test]
fn test_from() {
    assert_eq!(Expr::Atom(Atom::UInt(123)), Expr::from(123u64));
    assert_eq!(Expr::Atom(Atom::SInt(123)), Expr::from(123i64));
    assert_eq!(Expr::Atom(Atom::Str("test".to_string())),
               Expr::from("test"));
    assert_eq!(Expr::Atom(Atom::Float(123.45)), Expr::from(123.45));
    assert_eq!(Expr::Tuple(vec![Expr::Atom(Atom::Float(123.45))]),
               Expr::from((123.45,)));
}

#[test]
fn test_parse() {
    assert_eq!(Ok(Expr::from(("abc", 123u64, ("-", 123.43, 11.0)))),
               Expr::parse("(abc 123 (- 123.43 11.0))"));
}
<commit_msg>Add From conversion for Vec<commit_after>use std::fmt;
use super::atom::Atom;
use super::parser::Parser;

#[derive(Debug, PartialEq)]
pub enum Expr {
    Atom(Atom),

    // ( ... )
    Tuple(Vec<Expr>),

    // [ ... ]
    Array(Vec<Expr>),

    // { key val ... }
    Map(Vec<(Expr, Expr)>),
}

impl Expr {
    pub fn parse(s: &str) -> Result<Expr, ()> {
        let mut p = Parser::new(s);
        if let Ok(expr) = p.parse_expr() {
            if p.at_end() {
                return Ok(expr);
            }
        }
        Err(())
    }
}

impl<T> From<T> for Expr where T: Into<Atom>
{
    fn from(t: T) -> Expr {
        Expr::Atom(t.into())
    }
}

impl From<()> for Expr {
    fn from(_e: ()) -> Expr {
        Expr::Tuple(vec![])
    }
}

impl<A> From<(A,)> for Expr where A: Into<Expr>
{
    fn from(e: (A,)) -> Expr {
        Expr::Tuple(vec![e.0.into()])
    }
}

impl<A, B> From<(A, B)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>
{
    fn from(e: (A, B)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into()])
    }
}

impl<A, B, C> From<(A, B, C)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>,
          C: Into<Expr>
{
    fn from(e: (A, B, C)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into(), e.2.into()])
    }
}

impl<A, B, C, D> From<(A, B, C, D)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>,
          C: Into<Expr>,
          D: Into<Expr>
{
    fn from(e: (A, B, C, D)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into(), e.2.into(), e.3.into()])
    }
}

impl<A> From<Vec<A>> for Expr where A: Into<Expr>
{
    fn from(arr: Vec<A>) -> Expr {
        Expr::Array(arr.into_iter().map(|e| e.into()).collect())
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Expr::Atom(ref a) => write!(f, "{}", a),
            Expr::Tuple(ref t) => {
                try!(write!(f, "("));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, ")")
            }
            Expr::Array(ref t) => {
                try!(write!(f, "["));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, "]")
            }
            Expr::Map(ref t) => {
                try!(write!(f, "{}", "{"));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{} {}", space, expr.0, expr.1));
                }
                write!(f, "{}", "}")
            }

        }
    }
}

#[test]
fn test_display() {
    assert_eq!("12345", &format!("{}", Expr::Atom(Atom::UInt(12345))));
    assert_eq!("(12345)",
               &format!("{}", Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345))])));
    assert_eq!("(12345 abc)",
               &format!("{}",
                        Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345)),
                                         Expr::Atom(Atom::Str("abc".to_string()))])));
    assert_eq!("(12345 (abc))",
               &format!("{}",
                        Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345)),
                                         Expr::Tuple(vec![
                                         Expr::Atom(Atom::Str("abc".to_string()))
                                         ])])));

}

#[test]
fn test_from() {
    assert_eq!(Expr::Atom(Atom::UInt(123)), Expr::from(123u64));
    assert_eq!(Expr::Atom(Atom::SInt(123)), Expr::from(123i64));
    assert_eq!(Expr::Atom(Atom::Str("test".to_string())),
               Expr::from("test"));
    assert_eq!(Expr::Atom(Atom::Float(123.45)), Expr::from(123.45));
    assert_eq!(Expr::Tuple(vec![Expr::Atom(Atom::Float(123.45))]),
               Expr::from((123.45,)));
    assert_eq!(Expr::Array(vec![Expr::Atom(Atom::Float(123.45))]),
               Expr::from(vec![123.45]));

}

#[test]
fn test_parse() {
    assert_eq!(Ok(Expr::from(("abc", 123u64, ("-", 123.43, 11.0)))),
               Expr::parse("(abc 123 (- 123.43 11.0))"));
}
<|endoftext|>


<commit_before>#![no_std]

static mut seed: u64 = 19940046431;
use core::usize::MAX;

#[inline(always)]
pub fn rand() -> usize {
    unsafe {
        seed ^= seed << 12;
        seed ^= seed << 25;
        seed ^= seed << 27;
        seed = seed * 82724793451 + 12345;
        (seed as usize) % MAX
    }
}

#[inline(always)]
pub fn srand(s: usize) {
    unsafe {
        seed = s as u64;
    }
}

#[test]
fn test_rand() {
    assert_eq!(rand(), 9480282067609464302);
    srand(9480282067609464302);
    assert_eq!(rand(), 13439875519330593459);
}
<commit_msg>updated to work on both 64 and 32 bit systems<commit_after>#![no_std]

use core::usize::MAX as USIZE_MAX;

#[cfg(target_pointer_width = "32")]
static OFFSET: usize = 1013904223;
#[cfg(target_pointer_width = "32")]
static MULTIPLIER: usize = 1664525;

#[cfg(target_pointer_width = "64")]
static OFFSET: usize = 1442695040888963407;
#[cfg(target_pointer_width = "64")]
static MULTIPLIER: usize = 6364136223846793005;

static mut SEED: usize = USIZE_MAX / 2usize;

#[inline(always)]
pub fn rand() -> usize {
    unsafe {
        SEED = (MULTIPLIER * SEED + OFFSET) % USIZE_MAX;
        SEED
    }
}

#[inline(always)]
pub fn srand(s: usize) {
    unsafe {
        SEED = s;
    }
}

#[test]
fn test_rand() {
    if cfg!(target_pointer_width = "64") {
        assert_eq!(rand(), 4301930853896946210);
        srand(4301930853896946210);
        assert_eq!(rand(), 3578485316352917321);
    } else if cfg!(target_pointer_width = "32") {
        assert_eq!(rand(), 3159723346);
        srand(3159723346);
        assert_eq!(rand(), 2954349705);
    }
}
<|endoftext|>