<commit_before>#![deny(missing_docs)]
#![deny(missing_copy_implementations)]
#![feature(globs)]
#![feature(default_type_params)]

//! Window abstraction

extern crate input;
extern crate quack;
extern crate event_loop;

use input::Input;
use quack::{ ActOn, GetFrom, SetAt };

// Reexport everything from event_loop.
pub use event_loop::*;

/// The title of the window.
pub struct Title(pub String);

/// The anti-aliasing samples when rendering.
#[deriving(Copy)]
pub struct Samples(pub u8);

/// Whether window is opened in full screen mode.
#[deriving(Copy)]
pub struct Fullscreen(pub bool);

/// Whether to exit when pressing the Esc keyboard button.
#[deriving(Copy)]
pub struct ExitOnEsc(pub bool);

/// Whether to capture the mouse cursor.
#[deriving(Copy)]
pub struct CaptureCursor(pub bool);

/// The draw size of the window.
#[deriving(Copy)]
pub struct DrawSize(pub [u32, ..2]);

/// Settings for window behavior.
pub struct WindowSettings {
    /// Title of the window.
    pub title: String,
    /// The size of the window.
    pub size: [u32, ..2],
    /// Number samples per pixel (anti-aliasing).
    pub samples: u8,
    /// If true, the window is fullscreen.
    pub fullscreen: bool,
    /// If true, exit when pressing Esc.
    pub exit_on_esc: bool,
}

impl WindowSettings {
    /// Gets default settings.
    ///
    /// This exits the window when pressing `Esc`.
    /// The background color is set to black.
    pub fn default() -> WindowSettings {
        WindowSettings {
            title: "Piston".to_string(),
            size: [640, 480],
            samples: 0,
            fullscreen: false,
            exit_on_esc: true,
        }
    }
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    should_close: bool,
    title: String,
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: WindowSettings) -> NoWindow {
        let title = settings.title.clone();
        NoWindow {
            should_close: false,
            title: title,
        }
    }
}

impl ActOn<NoWindow, ()> for SwapBuffers {
    fn act_on(self, _window: &mut NoWindow) {}
}

impl ActOn<NoWindow, Option<Input>> for PollEvent {
    fn act_on(self, _window: &mut NoWindow) -> Option<Input> { None }
}

impl GetFrom<NoWindow> for ShouldClose {
    fn get_from(obj: &NoWindow) -> ShouldClose {
        ShouldClose(obj.should_close)
    }
}

impl GetFrom<NoWindow> for Size {
    fn get_from(_obj: &NoWindow) -> Size {
        Size([0, 0])
    }
}

impl SetAt<NoWindow> for CaptureCursor {
    fn set_at(self, _window: &mut NoWindow) {}
}

impl SetAt<NoWindow> for ShouldClose {
    fn set_at(self, window: &mut NoWindow) {
        let ShouldClose(val) = self;
        window.should_close = val;
    }
}

impl GetFrom<NoWindow> for DrawSize {
    fn get_from(obj: &NoWindow) -> DrawSize {
        let Size(val) = GetFrom::get_from(obj);
        DrawSize(val)
    }
}

impl GetFrom<NoWindow> for Title {
    fn get_from(obj: &NoWindow) -> Title {
        Title(obj.title.clone())
    }
}

impl SetAt<NoWindow> for Title {
    fn set_at(self, window: &mut NoWindow) {
        let Title(val) = self;
        window.title = val;
    }
}

impl GetFrom<NoWindow> for ExitOnEsc {
    fn get_from(_obj: &NoWindow) -> ExitOnEsc {
        ExitOnEsc(false)
    }
}

impl SetAt<NoWindow> for ExitOnEsc {
    // Ignore attempt to exit by pressing Esc.
    fn set_at(self, _window: &mut NoWindow) {}
}
<commit_msg>Upgrade to latest Rust<commit_after>#![deny(missing_docs)]
#![deny(missing_copy_implementations)]
#![feature(globs)]
#![feature(default_type_params)]

//! Window abstraction

extern crate input;
extern crate quack;
extern crate event_loop;

use input::Input;
use quack::{ ActOn, GetFrom, SetAt };

// Reexport everything from event_loop.
pub use event_loop::*;

/// The title of the window.
pub struct Title(pub String);

/// The anti-aliasing samples when rendering.
#[derive(Copy)]
pub struct Samples(pub u8);

/// Whether window is opened in full screen mode.
#[derive(Copy)]
pub struct Fullscreen(pub bool);

/// Whether to exit when pressing the Esc keyboard button.
#[derive(Copy)]
pub struct ExitOnEsc(pub bool);

/// Whether to capture the mouse cursor.
#[derive(Copy)]
pub struct CaptureCursor(pub bool);

/// The draw size of the window.
#[derive(Copy)]
pub struct DrawSize(pub [u32; 2]);

/// Settings for window behavior.
pub struct WindowSettings {
    /// Title of the window.
    pub title: String,
    /// The size of the window.
    pub size: [u32; 2],
    /// Number samples per pixel (anti-aliasing).
    pub samples: u8,
    /// If true, the window is fullscreen.
    pub fullscreen: bool,
    /// If true, exit when pressing Esc.
    pub exit_on_esc: bool,
}

impl WindowSettings {
    /// Gets default settings.
    ///
    /// This exits the window when pressing `Esc`.
    /// The background color is set to black.
    pub fn default() -> WindowSettings {
        WindowSettings {
            title: "Piston".to_string(),
            size: [640, 480],
            samples: 0,
            fullscreen: false,
            exit_on_esc: true,
        }
    }
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    should_close: bool,
    title: String,
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: WindowSettings) -> NoWindow {
        let title = settings.title.clone();
        NoWindow {
            should_close: false,
            title: title,
        }
    }
}

impl ActOn<NoWindow, ()> for SwapBuffers {
    fn act_on(self, _window: &mut NoWindow) {}
}

impl ActOn<NoWindow, Option<Input>> for PollEvent {
    fn act_on(self, _window: &mut NoWindow) -> Option<Input> { None }
}

impl GetFrom<NoWindow> for ShouldClose {
    fn get_from(obj: &NoWindow) -> ShouldClose {
        ShouldClose(obj.should_close)
    }
}

impl GetFrom<NoWindow> for Size {
    fn get_from(_obj: &NoWindow) -> Size {
        Size([0, 0])
    }
}

impl SetAt<NoWindow> for CaptureCursor {
    fn set_at(self, _window: &mut NoWindow) {}
}

impl SetAt<NoWindow> for ShouldClose {
    fn set_at(self, window: &mut NoWindow) {
        let ShouldClose(val) = self;
        window.should_close = val;
    }
}

impl GetFrom<NoWindow> for DrawSize {
    fn get_from(obj: &NoWindow) -> DrawSize {
        let Size(val) = GetFrom::get_from(obj);
        DrawSize(val)
    }
}

impl GetFrom<NoWindow> for Title {
    fn get_from(obj: &NoWindow) -> Title {
        Title(obj.title.clone())
    }
}

impl SetAt<NoWindow> for Title {
    fn set_at(self, window: &mut NoWindow) {
        let Title(val) = self;
        window.title = val;
    }
}

impl GetFrom<NoWindow> for ExitOnEsc {
    fn get_from(_obj: &NoWindow) -> ExitOnEsc {
        ExitOnEsc(false)
    }
}

impl SetAt<NoWindow> for ExitOnEsc {
    // Ignore attempt to exit by pressing Esc.
    fn set_at(self, _window: &mut NoWindow) {}
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Runtime Library
//!
//! [Cap'n Proto](https://capnproto.org) is an extremely efficient protocol for
//! sharing data and capabilities.
//!
//! The Rust implementation is split into three separate crates.
//!
//! Code generation is handled by [capnpc-rust](https://github.com/dwrensha/capnpc-rust).
//!
//! The present crate is the runtime library required by that generated code. It is hosted on Github
//! [here](https://github.com/dwrensha/capnproto-rust).
//!
//! [capnp-rpc-rust](https://github.com/dwrensha/capnp-rpc-rust) is an implementation of a
//! distributed object-capability layer.

#![allow(raw_pointer_derive)]

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

extern crate byteorder;

#[cfg(test)]
extern crate quickcheck;

pub mod any_pointer;
pub mod capability;
pub mod data;
pub mod data_list;
pub mod enum_list;
pub mod list_list;
pub mod message;
pub mod primitive_list;
pub mod private;
pub mod serialize;
pub mod serialize_packed;
pub mod struct_list;
pub mod text;
pub mod text_list;
pub mod traits;

mod util;

/// Eight bytes of memory with opaque interior.
///
/// This type is used to ensure that the data of a message is properly aligned.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct Word(u64);

impl Word {
    /// Does this, but faster:
    /// `::std::iter::repeat(Word(0)).take(length).collect()`
    pub fn allocate_zeroed_vec(length: usize) -> Vec<Word> {
        let mut result : Vec<Word> = Vec::with_capacity(length);
        unsafe {
            result.set_len(length);
            let p : *mut u8 = result.as_mut_ptr() as *mut u8;
            ::std::ptr::write_bytes(p, 0u8, length * ::std::mem::size_of::<Word>());
        }
        result
    }

    pub fn bytes_to_words<'a>(bytes: &'a [u8]) -> &'a [Word] {
        unsafe {
            ::std::slice::from_raw_parts(bytes.as_ptr() as *const Word, bytes.len() / 8)
        }
    }

    pub fn words_to_bytes<'a>(words: &'a [Word]) -> &'a [u8] {
        unsafe {
            ::std::slice::from_raw_parts(words.as_ptr() as *const u8, words.len() * 8)
        }
    }

    pub fn words_to_bytes_mut<'a>(words: &'a mut [Word]) -> &'a mut [u8] {
        unsafe {
            ::std::slice::from_raw_parts_mut(words.as_mut_ptr() as *mut u8, words.len() * 8)
        }
    }

    #[cfg(test)]
    pub fn from(n: u64) -> Word {
        Word(n)
    }
}

#[cfg(test)]
impl quickcheck::Arbitrary for Word {
    fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Word {
        Word(quickcheck::Arbitrary::arbitrary(g))
    }
    fn shrink(&self) -> Box<Iterator<Item=Word>+'static> {
        Box::new(quickcheck::Arbitrary::shrink(&self.0).map(|value| Word(value)))
    }
}

/// Size of a message. Every generated struct has a method `.total_size()` that returns this.
#[derive(Clone, Copy, PartialEq)]
pub struct MessageSize {
    pub word_count : u64,

    /// Size of the capability table.
    pub cap_count : u32
}

impl MessageSize {
    pub fn plus_eq(&mut self, other : MessageSize) {
        self.word_count += other.word_count;
        self.cap_count += other.cap_count;
    }
}

/// An enum value or union discriminant that was not found among those defined in a schema.
#[derive(PartialEq, Clone, Copy, Debug)]
pub struct NotInSchema(pub u16);

impl ::std::fmt::Display for NotInSchema {
    fn fmt(&self, fmt : &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        write!(fmt, "Enum value or union discriminant {} was not present in the schema.", self.0)
    }
}

impl ::std::error::Error for NotInSchema {
    fn description(&self) -> &str {
        "Enum value or union disriminant was not present in schema."
    }
}

/// Because messages are lazily validated, the return type of any method that reads a pointer field
/// must be wrapped in a Result.
pub type Result<T> = ::std::result::Result<T, Error>;

/// Things that can go wrong when you read a message.
#[derive(Debug)]
pub enum Error {
    Decode { description : &'static str,
             detail : Option<String> },
    Io(std::io::Error),
}

impl Error {
    pub fn new_decode_error(description : &'static str, detail : Option<String>) -> Error {
        Error::Decode { description : description, detail : detail}
    }
}

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

impl ::std::convert::From<NotInSchema> for Error {
    fn from(e : NotInSchema) -> Error {
        Error::new_decode_error("Enum value or union discriminant was not present in schema.",
                                Some(format!("value : {}", e.0)))
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, fmt : &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        match *self {
            Error::Decode { ref description, detail : Some(ref detail) } => {
                write!(fmt, "{} {}", description, detail)
            },
            Error::Decode { ref description, .. } => write!(fmt, "{}", description),
            Error::Io(ref io) => io.fmt(fmt),
        }
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Decode { ref description, .. } => description,
            Error::Io(ref io) => ::std::error::Error::description(io),
        }
    }
    fn cause(&self) -> Option<&::std::error::Error> {
        match *self {
            Error::Decode { .. } => None,
            Error::Io(ref io) => io.cause(),
        }
    }
}

/// Helper struct that allows `MessageBuilder::get_segments_for_output()` to avoid heap allocations
/// in the single-segment case.
pub enum OutputSegments<'a> {
    #[doc(hidden)]
    SingleSegment([&'a [Word]; 1]),

    #[doc(hidden)]
    MultiSegment(Vec<&'a [Word]>),
}

impl <'a> ::std::ops::Deref for OutputSegments<'a> {
    type Target = [&'a [Word]];
    fn deref<'b>(&'b self) -> &'b [&'a [Word]] {
        match self {
            &OutputSegments::SingleSegment(ref s) => {
                s
            }
            &OutputSegments::MultiSegment(ref v) => {
                &*v
            }
        }
    }
}
<commit_msg>Remove unneeded attributes.<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Runtime Library
//!
//! [Cap'n Proto](https://capnproto.org) is an extremely efficient protocol for
//! sharing data and capabilities.
//!
//! The Rust implementation is split into three separate crates.
//!
//! Code generation is handled by [capnpc-rust](https://github.com/dwrensha/capnpc-rust).
//!
//! The present crate is the runtime library required by that generated code. It is hosted on Github
//! [here](https://github.com/dwrensha/capnproto-rust).
//!
//! [capnp-rpc-rust](https://github.com/dwrensha/capnp-rpc-rust) is an implementation of a
//! distributed object-capability layer.

#![allow(raw_pointer_derive)]

extern crate byteorder;

#[cfg(test)]
extern crate quickcheck;

pub mod any_pointer;
pub mod capability;
pub mod data;
pub mod data_list;
pub mod enum_list;
pub mod list_list;
pub mod message;
pub mod primitive_list;
pub mod private;
pub mod serialize;
pub mod serialize_packed;
pub mod struct_list;
pub mod text;
pub mod text_list;
pub mod traits;

mod util;

/// Eight bytes of memory with opaque interior.
///
/// This type is used to ensure that the data of a message is properly aligned.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct Word(u64);

impl Word {
    /// Does this, but faster:
    /// `::std::iter::repeat(Word(0)).take(length).collect()`
    pub fn allocate_zeroed_vec(length: usize) -> Vec<Word> {
        let mut result : Vec<Word> = Vec::with_capacity(length);
        unsafe {
            result.set_len(length);
            let p : *mut u8 = result.as_mut_ptr() as *mut u8;
            ::std::ptr::write_bytes(p, 0u8, length * ::std::mem::size_of::<Word>());
        }
        result
    }

    pub fn bytes_to_words<'a>(bytes: &'a [u8]) -> &'a [Word] {
        unsafe {
            ::std::slice::from_raw_parts(bytes.as_ptr() as *const Word, bytes.len() / 8)
        }
    }

    pub fn words_to_bytes<'a>(words: &'a [Word]) -> &'a [u8] {
        unsafe {
            ::std::slice::from_raw_parts(words.as_ptr() as *const u8, words.len() * 8)
        }
    }

    pub fn words_to_bytes_mut<'a>(words: &'a mut [Word]) -> &'a mut [u8] {
        unsafe {
            ::std::slice::from_raw_parts_mut(words.as_mut_ptr() as *mut u8, words.len() * 8)
        }
    }

    #[cfg(test)]
    pub fn from(n: u64) -> Word {
        Word(n)
    }
}

#[cfg(test)]
impl quickcheck::Arbitrary for Word {
    fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Word {
        Word(quickcheck::Arbitrary::arbitrary(g))
    }
    fn shrink(&self) -> Box<Iterator<Item=Word>+'static> {
        Box::new(quickcheck::Arbitrary::shrink(&self.0).map(|value| Word(value)))
    }
}

/// Size of a message. Every generated struct has a method `.total_size()` that returns this.
#[derive(Clone, Copy, PartialEq)]
pub struct MessageSize {
    pub word_count : u64,

    /// Size of the capability table.
    pub cap_count : u32
}

impl MessageSize {
    pub fn plus_eq(&mut self, other : MessageSize) {
        self.word_count += other.word_count;
        self.cap_count += other.cap_count;
    }
}

/// An enum value or union discriminant that was not found among those defined in a schema.
#[derive(PartialEq, Clone, Copy, Debug)]
pub struct NotInSchema(pub u16);

impl ::std::fmt::Display for NotInSchema {
    fn fmt(&self, fmt : &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        write!(fmt, "Enum value or union discriminant {} was not present in the schema.", self.0)
    }
}

impl ::std::error::Error for NotInSchema {
    fn description(&self) -> &str {
        "Enum value or union disriminant was not present in schema."
    }
}

/// Because messages are lazily validated, the return type of any method that reads a pointer field
/// must be wrapped in a Result.
pub type Result<T> = ::std::result::Result<T, Error>;

/// Things that can go wrong when you read a message.
#[derive(Debug)]
pub enum Error {
    Decode { description : &'static str,
             detail : Option<String> },
    Io(std::io::Error),
}

impl Error {
    pub fn new_decode_error(description : &'static str, detail : Option<String>) -> Error {
        Error::Decode { description : description, detail : detail}
    }
}

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

impl ::std::convert::From<NotInSchema> for Error {
    fn from(e : NotInSchema) -> Error {
        Error::new_decode_error("Enum value or union discriminant was not present in schema.",
                                Some(format!("value : {}", e.0)))
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, fmt : &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        match *self {
            Error::Decode { ref description, detail : Some(ref detail) } => {
                write!(fmt, "{} {}", description, detail)
            },
            Error::Decode { ref description, .. } => write!(fmt, "{}", description),
            Error::Io(ref io) => io.fmt(fmt),
        }
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Decode { ref description, .. } => description,
            Error::Io(ref io) => ::std::error::Error::description(io),
        }
    }
    fn cause(&self) -> Option<&::std::error::Error> {
        match *self {
            Error::Decode { .. } => None,
            Error::Io(ref io) => io.cause(),
        }
    }
}

/// Helper struct that allows `MessageBuilder::get_segments_for_output()` to avoid heap allocations
/// in the single-segment case.
pub enum OutputSegments<'a> {
    #[doc(hidden)]
    SingleSegment([&'a [Word]; 1]),

    #[doc(hidden)]
    MultiSegment(Vec<&'a [Word]>),
}

impl <'a> ::std::ops::Deref for OutputSegments<'a> {
    type Target = [&'a [Word]];
    fn deref<'b>(&'b self) -> &'b [&'a [Word]] {
        match self {
            &OutputSegments::SingleSegment(ref s) => {
                s
            }
            &OutputSegments::MultiSegment(ref v) => {
                &*v
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(convert, from_raw_os)]
#![cfg_attr(windows, feature(fs_ext))]
//! Securely create and manage temporary files. Temporary files created by this create are
//! automatically deleted.
extern crate libc;
extern crate rand;

use std::io::{self, Read, Write, Seek, SeekFrom};
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::error;
use std::fmt;
use std::env;

mod imp;
mod util;

/// An unnamed temporary file.
///
/// This variant is secure/reliable in the presence of a pathological temporary file cleaner.
///
/// Deletion:
///
/// Linux >= 3.11: The temporary file is never linked into the filesystem so it can't be leaked.
///
/// Other *nix: The temporary file is immediately unlinked on create. The OS will delete it when
/// the last open copy of it is closed (the last TempFile reference to it is dropped).
///
/// Windows: The temporary file is marked DeleteOnClose and, again, will be deleted when the last
/// open copy of it is closed. Unlike *nix operating systems, the file is not immediately unlinked
/// from the filesystem.
pub struct TempFile(File);

impl TempFile {
    /// Create a new temporary file.
    #[inline]
    pub fn new() -> io::Result<TempFile> {
        Self::new_in(&env::temp_dir())
    }

    /// Create a new temporary file in the specified directory.
    #[inline]
    pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<TempFile> {
        imp::create(dir.as_ref()).map(|f| TempFile(f))
    }

    /// Create a new temporary file and open it `count` times returning `count` independent
    /// references to the same file.
    ///
    /// This can be useful if you want multiple seek positions in the same temporary file.
    /// Additionally, this function guarantees that all of the returned temporary file objects
    /// refer to the same underlying temporary file even in the presence of a pathological
    /// temporary file cleaner.
    #[inline]
    pub fn shared(count: usize) -> io::Result<Vec<TempFile>> {
        Self::shared_in(&env::temp_dir(), count)
    }

    /// Same as `shared` but creates the file in the specified directory.
    #[inline]
    pub fn shared_in<P: AsRef<Path>>(dir: P, count: usize) -> io::Result<Vec<TempFile>> {
        imp::create_shared(dir.as_ref(), count).map(|files| {
            files.into_iter().map(|f|TempFile(f)).collect()
        })
    }

    /// Number of bytes in the file.
    #[inline]
    pub fn len(&self) -> io::Result<u64> {
        self.0.metadata().map(|m| m.len())
    }

    /// Truncate the file to `size` bytes.
    #[inline(always)]
    pub fn set_len(&self, size: u64) -> io::Result<()> {
        self.0.set_len(size)
    }

    /// Re-open the temporary file. The returned TempFile will refer to the same underlying
    /// temporary file but will have an independent offset.
    ///
    /// This method is only available on windows and Linux, not FreeBSD/MacOS. Unfortunately, it is
    /// impossible to reliably implement this method on those operating systems.
    ///
    /// If you need your code to be cross-platform, please use `shared`/`shared_in` defined above.
    ///
    /// **Unstable**: This is platform specific and may go away in the future.
    #[cfg(any(windows, target_os = "linux"))]
    #[inline]
    pub fn reopen(&self) -> io::Result<TempFile> {
        imp::reopen(&self.0).map(|f|TempFile(f))
    }
}

impl Read for TempFile {
    #[inline(always)]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl Write for TempFile {
    #[inline(always)]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }
    #[inline(always)]
    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

impl Seek for TempFile {
    #[inline(always)]
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.0.seek(pos)
    }
}

#[cfg(unix)]
impl std::os::unix::io::AsRawFd for TempFile {
    #[inline(always)]
    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
        self.0.as_raw_fd()
    }
}

#[cfg(windows)]
impl std::os::windows::io::AsRawHandle for TempFile {
    #[inline(always)]
    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
        self.0.as_raw_handle()
    }
}

/// A named temporary file.
///
/// This variant is *NOT* secure/reliable in the presence of a pathological temporary file cleaner.
///
/// NamedTempFiles are deleted on drop. As rust doesn't guarantee that a struct will ever be
/// dropped, these temporary files will not be deleted on abort, resource leak, early exit, etc.
///
/// Please use TempFile unless you absolutely need a named file.
///
pub struct NamedTempFile(Option<NamedTempFileInner>);

struct NamedTempFileInner {
    file: File,
    path: PathBuf,
}

impl fmt::Debug for NamedTempFile {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "NamedTempFile({:?})", self.0.as_ref().unwrap().path)
    }
}

#[derive(Debug)]
pub struct PersistError {
    pub error: io::Error,
    pub file: NamedTempFile,
}

impl From<PersistError> for io::Error {
    #[inline]
    fn from(error: PersistError) -> io::Error {
        error.error
    }
}

impl fmt::Display for PersistError {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "failed to persist temporary file: {}", self.error)
    }
}

impl error::Error for PersistError {
    #[inline]
    fn description(&self) -> &str {
        "failed to persist temporary file"
    }
    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        Some(&self.error)
    }
}

impl NamedTempFile {
    /// Create a new temporary file.
    #[inline]
    pub fn new() -> io::Result<NamedTempFile> {
        Self::new_in(&env::temp_dir())
    }

    /// Create a new temporary file in the specified directory.
    #[inline]
    pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<NamedTempFile> {
        loop {
            let path = dir.as_ref().join(&util::tmpname());
            return match imp::create_named(&path) {
                Ok(file) => Ok(NamedTempFile(Some(NamedTempFileInner { path: path, file: file, }))),
                Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => continue,
                Err(e) => Err(e),
            }
        }
    }

    /// Number of bytes in the file.
    #[inline]
    pub fn len(&self) -> io::Result<u64> {
        self.0.as_ref().unwrap().file.metadata().map(|m| m.len())
    }

    /// Truncate the file to `size` bytes.
    #[inline]
    pub fn set_len(&self, size: u64) -> io::Result<()> {
        self.0.as_ref().unwrap().file.set_len(size)
    }

    /// Get the temporary file's path.
    #[inline]
    pub fn path(&self) -> &Path {
        &self.0.as_ref().unwrap().path
    }

    /// Close and remove the temporary file.
    ///
    /// Use this if you want to detect errors in deleting the file.
    #[inline]
    pub fn close(mut self) -> io::Result<()> {
        let NamedTempFileInner { path, file } = self.0.take().unwrap();
        drop(file);
        fs::remove_file(path)
    }

    /// Extract the path to the temporary file. Calling this will prevent the temporary file from
    /// being automatically deleted.
    #[inline]
    pub fn into_path(mut self) -> PathBuf {
        let NamedTempFileInner { path, .. } = self.0.take().unwrap();
        path
    }

    /// Persist the temporary file at the target path.
    ///
    /// If a file exists at the target path, persist will atomically replace it. If this method
    /// fails, it will return `self` in the resulting PersistError.
    #[inline]
    pub fn persist<P: AsRef<Path>>(mut self, new_path: P) -> Result<File, PersistError> {
        match fs::rename(&self.0.as_ref().unwrap().path, new_path) {
            Ok(_) => Ok(self.0.take().unwrap().file),
            Err(e) => Err(PersistError { file: self, error: e }),
        }
    }
}

impl Drop for NamedTempFile {
    #[inline]
    fn drop(&mut self) {
        if let Some(NamedTempFileInner { file, path }) = self.0.take() {
            drop(file);
            let _ = fs::remove_file(path);
        }
    }
}

impl Read for NamedTempFile {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.as_mut().unwrap().file.read(buf)
    }
}

impl Write for NamedTempFile {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.as_mut().unwrap().file.write(buf)
    }
    #[inline]
    fn flush(&mut self) -> io::Result<()> {
        self.0.as_mut().unwrap().file.flush()
    }
}

impl Seek for NamedTempFile {
    #[inline]
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.0.as_mut().unwrap().file.seek(pos)
    }
}

#[cfg(unix)]
impl std::os::unix::io::AsRawFd for NamedTempFile {
    #[inline]
    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
        self.0.as_ref().unwrap().file.as_raw_fd()
    }
}

#[cfg(windows)]
impl std::os::windows::io::AsRawHandle for NamedTempFile {
    #[inline]
    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
        self.0.as_ref().unwrap().file.as_raw_handle()
    }
}
<commit_msg>Note that temporary files cannot be persisted across filesystem boundries.<commit_after>#![feature(convert, from_raw_os)]
#![cfg_attr(windows, feature(fs_ext))]
//! Securely create and manage temporary files. Temporary files created by this create are
//! automatically deleted.
extern crate libc;
extern crate rand;

use std::io::{self, Read, Write, Seek, SeekFrom};
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::error;
use std::fmt;
use std::env;

mod imp;
mod util;

/// An unnamed temporary file.
///
/// This variant is secure/reliable in the presence of a pathological temporary file cleaner.
///
/// Deletion:
///
/// Linux >= 3.11: The temporary file is never linked into the filesystem so it can't be leaked.
///
/// Other *nix: The temporary file is immediately unlinked on create. The OS will delete it when
/// the last open copy of it is closed (the last TempFile reference to it is dropped).
///
/// Windows: The temporary file is marked DeleteOnClose and, again, will be deleted when the last
/// open copy of it is closed. Unlike *nix operating systems, the file is not immediately unlinked
/// from the filesystem.
pub struct TempFile(File);

impl TempFile {
    /// Create a new temporary file.
    #[inline]
    pub fn new() -> io::Result<TempFile> {
        Self::new_in(&env::temp_dir())
    }

    /// Create a new temporary file in the specified directory.
    #[inline]
    pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<TempFile> {
        imp::create(dir.as_ref()).map(|f| TempFile(f))
    }

    /// Create a new temporary file and open it `count` times returning `count` independent
    /// references to the same file.
    ///
    /// This can be useful if you want multiple seek positions in the same temporary file.
    /// Additionally, this function guarantees that all of the returned temporary file objects
    /// refer to the same underlying temporary file even in the presence of a pathological
    /// temporary file cleaner.
    #[inline]
    pub fn shared(count: usize) -> io::Result<Vec<TempFile>> {
        Self::shared_in(&env::temp_dir(), count)
    }

    /// Same as `shared` but creates the file in the specified directory.
    #[inline]
    pub fn shared_in<P: AsRef<Path>>(dir: P, count: usize) -> io::Result<Vec<TempFile>> {
        imp::create_shared(dir.as_ref(), count).map(|files| {
            files.into_iter().map(|f|TempFile(f)).collect()
        })
    }

    /// Number of bytes in the file.
    #[inline]
    pub fn len(&self) -> io::Result<u64> {
        self.0.metadata().map(|m| m.len())
    }

    /// Truncate the file to `size` bytes.
    #[inline(always)]
    pub fn set_len(&self, size: u64) -> io::Result<()> {
        self.0.set_len(size)
    }

    /// Re-open the temporary file. The returned TempFile will refer to the same underlying
    /// temporary file but will have an independent offset.
    ///
    /// This method is only available on windows and Linux, not FreeBSD/MacOS. Unfortunately, it is
    /// impossible to reliably implement this method on those operating systems.
    ///
    /// If you need your code to be cross-platform, please use `shared`/`shared_in` defined above.
    ///
    /// **Unstable**: This is platform specific and may go away in the future.
    #[cfg(any(windows, target_os = "linux"))]
    #[inline]
    pub fn reopen(&self) -> io::Result<TempFile> {
        imp::reopen(&self.0).map(|f|TempFile(f))
    }
}

impl Read for TempFile {
    #[inline(always)]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl Write for TempFile {
    #[inline(always)]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }
    #[inline(always)]
    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

impl Seek for TempFile {
    #[inline(always)]
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.0.seek(pos)
    }
}

#[cfg(unix)]
impl std::os::unix::io::AsRawFd for TempFile {
    #[inline(always)]
    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
        self.0.as_raw_fd()
    }
}

#[cfg(windows)]
impl std::os::windows::io::AsRawHandle for TempFile {
    #[inline(always)]
    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
        self.0.as_raw_handle()
    }
}

/// A named temporary file.
///
/// This variant is *NOT* secure/reliable in the presence of a pathological temporary file cleaner.
///
/// NamedTempFiles are deleted on drop. As rust doesn't guarantee that a struct will ever be
/// dropped, these temporary files will not be deleted on abort, resource leak, early exit, etc.
///
/// Please use TempFile unless you absolutely need a named file.
///
pub struct NamedTempFile(Option<NamedTempFileInner>);

struct NamedTempFileInner {
    file: File,
    path: PathBuf,
}

impl fmt::Debug for NamedTempFile {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "NamedTempFile({:?})", self.0.as_ref().unwrap().path)
    }
}

#[derive(Debug)]
pub struct PersistError {
    pub error: io::Error,
    pub file: NamedTempFile,
}

impl From<PersistError> for io::Error {
    #[inline]
    fn from(error: PersistError) -> io::Error {
        error.error
    }
}

impl fmt::Display for PersistError {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "failed to persist temporary file: {}", self.error)
    }
}

impl error::Error for PersistError {
    #[inline]
    fn description(&self) -> &str {
        "failed to persist temporary file"
    }
    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        Some(&self.error)
    }
}

impl NamedTempFile {
    /// Create a new temporary file.
    #[inline]
    pub fn new() -> io::Result<NamedTempFile> {
        Self::new_in(&env::temp_dir())
    }

    /// Create a new temporary file in the specified directory.
    #[inline]
    pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<NamedTempFile> {
        loop {
            let path = dir.as_ref().join(&util::tmpname());
            return match imp::create_named(&path) {
                Ok(file) => Ok(NamedTempFile(Some(NamedTempFileInner { path: path, file: file, }))),
                Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => continue,
                Err(e) => Err(e),
            }
        }
    }

    /// Number of bytes in the file.
    #[inline]
    pub fn len(&self) -> io::Result<u64> {
        self.0.as_ref().unwrap().file.metadata().map(|m| m.len())
    }

    /// Truncate the file to `size` bytes.
    #[inline]
    pub fn set_len(&self, size: u64) -> io::Result<()> {
        self.0.as_ref().unwrap().file.set_len(size)
    }

    /// Get the temporary file's path.
    #[inline]
    pub fn path(&self) -> &Path {
        &self.0.as_ref().unwrap().path
    }

    /// Close and remove the temporary file.
    ///
    /// Use this if you want to detect errors in deleting the file.
    #[inline]
    pub fn close(mut self) -> io::Result<()> {
        let NamedTempFileInner { path, file } = self.0.take().unwrap();
        drop(file);
        fs::remove_file(path)
    }

    /// Extract the path to the temporary file. Calling this will prevent the temporary file from
    /// being automatically deleted.
    #[inline]
    pub fn into_path(mut self) -> PathBuf {
        let NamedTempFileInner { path, .. } = self.0.take().unwrap();
        path
    }

    /// Persist the temporary file at the target path.
    ///
    /// If a file exists at the target path, persist will atomically replace it. If this method
    /// fails, it will return `self` in the resulting PersistError.
    ///
    /// Note: Temporary files cannot be persisted across filesystems.
    #[inline]
    pub fn persist<P: AsRef<Path>>(mut self, new_path: P) -> Result<File, PersistError> {
        match fs::rename(&self.0.as_ref().unwrap().path, new_path) {
            Ok(_) => Ok(self.0.take().unwrap().file),
            Err(e) => Err(PersistError { file: self, error: e }),
        }
    }
}

impl Drop for NamedTempFile {
    #[inline]
    fn drop(&mut self) {
        if let Some(NamedTempFileInner { file, path }) = self.0.take() {
            drop(file);
            let _ = fs::remove_file(path);
        }
    }
}

impl Read for NamedTempFile {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.as_mut().unwrap().file.read(buf)
    }
}

impl Write for NamedTempFile {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.as_mut().unwrap().file.write(buf)
    }
    #[inline]
    fn flush(&mut self) -> io::Result<()> {
        self.0.as_mut().unwrap().file.flush()
    }
}

impl Seek for NamedTempFile {
    #[inline]
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.0.as_mut().unwrap().file.seek(pos)
    }
}

#[cfg(unix)]
impl std::os::unix::io::AsRawFd for NamedTempFile {
    #[inline]
    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
        self.0.as_ref().unwrap().file.as_raw_fd()
    }
}

#[cfg(windows)]
impl std::os::windows::io::AsRawHandle for NamedTempFile {
    #[inline]
    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
        self.0.as_ref().unwrap().file.as_raw_handle()
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;
use byteorder::{LittleEndian, ReadBytesExt};

use std::collections::HashMap;
use std::io::{self, BufRead};

#[derive(Debug)]
pub struct BigArchive {
    pub format: Format,
    pub size: u32,

    _entries: HashMap<String, BigEntry>,
}

#[derive(Debug)]
pub enum ReadError {
    StdIoError(io::Error),
    UnknownFormat(Vec<u8>),
}

impl From<io::Error> for ReadError {
    fn from(e: io::Error) -> Self {
        ReadError::StdIoError(e)
    }
}

impl BigArchive {
    pub fn new(mut data: &mut BufRead) -> Result<BigArchive, ReadError> {
        let format = read_format(&mut data).expect("Failed to read format");

        if let Format::Unknown(bytes) = format {
            return Err(ReadError::UnknownFormat(bytes));
        }

        let size = invert_endianness(data.read_u32::<LittleEndian>().expect("Failed to read size"));
        let num_entries = invert_endianness(data.read_u32::<LittleEndian>()
            .expect("Failed to read num_entries"));
        let _first = data.read_u32::<LittleEndian>();

        let mut entries = HashMap::new();

        for i in 0..num_entries {
            let entry_num = i + 1;
            let offset = invert_endianness(data.read_u32::<LittleEndian>()
                .expect(&format!("Failed to read offset of entry {}", entry_num)));
            let size = invert_endianness(data.read_u32::<LittleEndian>()
                .expect(&format!("Failed to read size of entry {}", entry_num)));

            let mut buf = Vec::new();
            data.read_until(b'\0', &mut buf)
                .expect(&format!("Failed to read name for entry {}", entry_num));

            let name = String::from_utf8_lossy(&buf[..buf.len() - 1]);

            let entry = BigEntry {
                offset: offset,
                size: size,
                name: name.to_string(),
            };

            entries.insert(entry.name.clone(), entry);
        }

        Ok(BigArchive {
            format: format,
            size: size,
            _entries: entries,
        })
    }

    pub fn get_entry(&self, entry_name: &str) -> Option<&BigEntry> {
        self._entries.get(entry_name)
    }

    pub fn get_entry_mut(&mut self, entry_name: &str) -> Option<&mut BigEntry> {
        self._entries.get_mut(entry_name)
    }

    pub fn get_all_entry_names(&self) -> std::collections::hash_map::Keys<String, BigEntry> {
        self._entries.keys()
    }
}

#[derive(Debug)]
pub struct BigEntry {
    pub offset: u32,
    pub size: u32,
    pub name: String,
}

#[derive(Debug, PartialEq)]
pub enum Format {
    Unknown(Vec<u8>),
    Big4,
    BigF,
}

impl<'a> From<&'a mut BufRead> for Format {
    fn from(data: &'a mut BufRead) -> Self {
        let mut buf = [0; 4];
        let _ = data.read_exact(&mut buf);
        match &buf {
            b"BIG4" => Format::Big4,
            b"BIGf" => Format::BigF,
            _ => Format::Unknown(Vec::from(&buf[..])),
        }
    }
}

fn read_format(data: &mut BufRead) -> Result<Format, io::Error> {
    Ok(Format::from(data))
}

fn invert_endianness(v: u32) -> u32 {
    (v << 24) | (v << 8 & 0xff0000) | (v >> 8 & 0xff00) | (v >> 24)
}

#[cfg(test)]
mod tests {
    const TEST_BYTES: &'static [u8] = include_bytes!("../test.big");

    use std::io::BufReader;
    use super::{read_format, Format, BigArchive};

    #[test]
    fn is_big4() {
        let mut reader = BufReader::new(TEST_BYTES);
        assert_eq!(read_format(&mut reader).expect("Failed to load file"),
                   Format::Big4);
    }

    #[test]
    fn has_two_entries() {
        let mut reader = BufReader::new(TEST_BYTES);
        let archive = BigArchive::new(&mut reader).unwrap();
        assert_eq!(archive.get_all_entry_names().len(), 2);
    }
}
<commit_msg>Use try! instead of Result::expect in some places<commit_after>extern crate byteorder;
use byteorder::{LittleEndian, ReadBytesExt};

use std::collections::HashMap;
use std::io::{self, BufRead};

#[derive(Debug)]
pub struct BigArchive {
    pub format: Format,
    pub size: u32,

    _entries: HashMap<String, BigEntry>,
}

#[derive(Debug)]
pub enum ReadError {
    StdIoError(io::Error),
    UnknownFormat(Vec<u8>),
}

impl From<io::Error> for ReadError {
    fn from(e: io::Error) -> Self {
        ReadError::StdIoError(e)
    }
}

impl BigArchive {
    pub fn new(mut data: &mut BufRead) -> Result<BigArchive, ReadError> {
        let format = read_format(&mut data).expect("Failed to read format");

        if let Format::Unknown(bytes) = format {
            return Err(ReadError::UnknownFormat(bytes));
        }

        let size = try!(data.read_u32::<LittleEndian>());
        let size = invert_endianness(size);

        let num_entries = try!(data.read_u32::<LittleEndian>());
        let num_entries = invert_endianness(num_entries);

        // Offset to the first entry, I think.
        let _ = data.read_u32::<LittleEndian>();

        let mut entries = HashMap::new();

        for i in 0..num_entries {
            let entry_num = i + 1;
            let offset = try!(data.read_u32::<LittleEndian>());
            let offset = invert_endianness(offset);

            let size = try!(data.read_u32::<LittleEndian>());
            let size = invert_endianness(size);

            let mut buf = Vec::new();
            data.read_until(b'\0', &mut buf)
                .expect(&format!("Failed to read name for entry {}", entry_num));

            let name = String::from_utf8_lossy(&buf[..buf.len() - 1]);

            let entry = BigEntry {
                offset: offset,
                size: size,
                name: name.to_string(),
            };

            entries.insert(entry.name.clone(), entry);
        }

        Ok(BigArchive {
            format: format,
            size: size,
            _entries: entries,
        })
    }

    pub fn get_entry(&self, entry_name: &str) -> Option<&BigEntry> {
        self._entries.get(entry_name)
    }

    pub fn get_entry_mut(&mut self, entry_name: &str) -> Option<&mut BigEntry> {
        self._entries.get_mut(entry_name)
    }

    pub fn get_all_entry_names(&self) -> std::collections::hash_map::Keys<String, BigEntry> {
        self._entries.keys()
    }
}

#[derive(Debug)]
pub struct BigEntry {
    pub offset: u32,
    pub size: u32,
    pub name: String,
}

#[derive(Debug, PartialEq)]
pub enum Format {
    Unknown(Vec<u8>),
    Big4,
    BigF,
}

impl<'a> From<&'a mut BufRead> for Format {
    fn from(data: &'a mut BufRead) -> Self {
        let mut buf = [0; 4];
        let _ = data.read_exact(&mut buf);
        match &buf {
            b"BIG4" => Format::Big4,
            b"BIGf" => Format::BigF,
            _ => Format::Unknown(Vec::from(&buf[..])),
        }
    }
}

fn read_format(data: &mut BufRead) -> Result<Format, io::Error> {
    Ok(Format::from(data))
}

fn invert_endianness(v: u32) -> u32 {
    (v << 24) | (v << 8 & 0xff0000) | (v >> 8 & 0xff00) | (v >> 24)
}

#[cfg(test)]
mod tests {
    const TEST_BYTES: &'static [u8] = include_bytes!("../test.big");

    use std::io::BufReader;
    use super::{read_format, Format, BigArchive};

    #[test]
    fn is_big4() {
        let mut reader = BufReader::new(TEST_BYTES);
        assert_eq!(read_format(&mut reader).expect("Failed to load file"),
                   Format::Big4);
    }

    #[test]
    fn has_two_entries() {
        let mut reader = BufReader::new(TEST_BYTES);
        let archive = BigArchive::new(&mut reader).unwrap();
        assert_eq!(archive.get_all_entry_names().len(), 2);
    }
}
<|endoftext|>


<commit_before>use rand::seq::SliceRandom;

/// Convenience function to generate a new petname from default word lists.
#[allow(dead_code)]
pub fn petname(words: u8, separator: &str) -> String {
    Petnames::default().generate_one(words, separator)
}

/// Word lists and the logic to combine them into _petnames_.
///
/// A _petname_ with `n` words will contain, in order:
///
///   * 1 adjective when `n >= 2`, otherwise 0 adjectives.
///   * `n - 2` adverbs when `n >= 2`.
///   * 1 name / noun.
///
pub struct Petnames<'a> {
    pub adjectives: Vec<&'a str>,
    pub adverbs: Vec<&'a str>,
    pub names: Vec<&'a str>,
}

impl<'a> Petnames<'a> {
    /// Constructs a new `Petnames` from the default (small) word lists.
    pub fn default() -> Petnames<'a> {
        Self::small()
    }

    /// Constructs a new `Petnames` from the small word lists.
    pub fn small() -> Petnames<'a> {
        Self::init(
            include_str!("../words/small/adjectives.txt"),
            include_str!("../words/small/adverbs.txt"),
            include_str!("../words/small/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the medium word lists.
    pub fn medium() -> Petnames<'a> {
        Self::init(
            include_str!("../words/medium/adjectives.txt"),
            include_str!("../words/medium/adverbs.txt"),
            include_str!("../words/medium/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the large word lists.
    pub fn large() -> Petnames<'a> {
        Self::init(
            include_str!("../words/large/adjectives.txt"),
            include_str!("../words/large/adverbs.txt"),
            include_str!("../words/large/names.txt"),
        )
    }

    fn init(adjectives: &'a str, adverbs: &'a str, names: &'a str) -> Petnames<'a> {
        Self {
            adjectives: adjectives.split_whitespace().collect(),
            adverbs: adverbs.split_whitespace().collect(),
            names: names.split_whitespace().collect(),
        }
    }

    /// Keep words matching a predicate.
    ///
    /// This is just a convenience wrapper that applies the same predicate to
    /// the adjectives, adverbs, and names lists.
    pub fn retain<F>(&mut self, predicate: F)
    where
        F: Fn(&&str) -> bool,
    {
        self.adjectives.retain(&predicate);
        self.adverbs.retain(&predicate);
        self.names.retain(&predicate);
    }

    /// Generate a new petname.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut rng = rand::thread_rng();
    /// petname::Petnames::default().generate(&mut rng, 7, ":");
    /// ```
    pub fn generate<RNG>(&self, rng: &mut RNG, words: u8, separator: &str) -> String
    where
        RNG: rand::Rng,
    {
        // Adverbs all the way, finishing with adjective then name.
        let mut parts = Vec::with_capacity(words as usize);
        for num in (0..words).rev() {
            parts.push(*match num {
                0 => self.names.choose(rng).unwrap(),
                1 => self.adjectives.choose(rng).unwrap(),
                _ => self.adverbs.choose(rng).unwrap(),
            });
        }
        parts.join(separator)
    }

    /// Generate a single new petname.
    ///
    /// This is like `generate` but uses `rand::thread_rng` as the random
    /// source. For efficiency use `generate` when creating multiple names, or
    /// when you want to use a custom source of randomness.
    pub fn generate_one(&self, words: u8, separator: &str) -> String {
        self.generate(&mut rand::thread_rng(), words, separator)
    }
}

impl<'a> Default for Petnames<'a> {
    fn default() -> Self { Self::default() }
}

#[cfg(test)]
mod tests {

    use rand;
    use super::{petname, Petnames};

    #[test]
    fn default_petnames_has_adjectives() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adjectives.len(), 0);
    }

    #[test]
    fn default_petnames_has_adverbs() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adverbs.len(), 0);
    }

    #[test]
    fn default_petnames_has_names() {
        let petnames = Petnames::default();
        assert_ne!(petnames.names.len(), 0);
    }

    #[test]
    fn generate_uses_adverb_adjective_name() {
        let petnames = Petnames {
            adjectives: vec!["adjective"],
            adverbs: vec!["adverb"],
            names: vec!["name"],
        };
        assert_eq!(
            petnames.generate(&mut rand::thread_rng(), 3, "-"),
            "adverb-adjective-name"
        );
    }

    #[test]
    fn petname_renders_desired_number_of_words() {
        assert_eq!(petname(7, "-").split("-").count(), 7);
    }

    #[test]
    fn petname_renders_with_desired_separator() {
        assert_eq!(petname(7, "@").split("@").count(), 7);
    }
}
<commit_msg>Format source.<commit_after>use rand::seq::SliceRandom;

/// Convenience function to generate a new petname from default word lists.
#[allow(dead_code)]
pub fn petname(words: u8, separator: &str) -> String {
    Petnames::default().generate_one(words, separator)
}

/// Word lists and the logic to combine them into _petnames_.
///
/// A _petname_ with `n` words will contain, in order:
///
///   * 1 adjective when `n >= 2`, otherwise 0 adjectives.
///   * `n - 2` adverbs when `n >= 2`.
///   * 1 name / noun.
///
pub struct Petnames<'a> {
    pub adjectives: Vec<&'a str>,
    pub adverbs: Vec<&'a str>,
    pub names: Vec<&'a str>,
}

impl<'a> Petnames<'a> {
    /// Constructs a new `Petnames` from the default (small) word lists.
    pub fn default() -> Petnames<'a> {
        Self::small()
    }

    /// Constructs a new `Petnames` from the small word lists.
    pub fn small() -> Petnames<'a> {
        Self::init(
            include_str!("../words/small/adjectives.txt"),
            include_str!("../words/small/adverbs.txt"),
            include_str!("../words/small/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the medium word lists.
    pub fn medium() -> Petnames<'a> {
        Self::init(
            include_str!("../words/medium/adjectives.txt"),
            include_str!("../words/medium/adverbs.txt"),
            include_str!("../words/medium/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the large word lists.
    pub fn large() -> Petnames<'a> {
        Self::init(
            include_str!("../words/large/adjectives.txt"),
            include_str!("../words/large/adverbs.txt"),
            include_str!("../words/large/names.txt"),
        )
    }

    fn init(adjectives: &'a str, adverbs: &'a str, names: &'a str) -> Petnames<'a> {
        Self {
            adjectives: adjectives.split_whitespace().collect(),
            adverbs: adverbs.split_whitespace().collect(),
            names: names.split_whitespace().collect(),
        }
    }

    /// Keep words matching a predicate.
    ///
    /// This is just a convenience wrapper that applies the same predicate to
    /// the adjectives, adverbs, and names lists.
    pub fn retain<F>(&mut self, predicate: F)
    where
        F: Fn(&&str) -> bool,
    {
        self.adjectives.retain(&predicate);
        self.adverbs.retain(&predicate);
        self.names.retain(&predicate);
    }

    /// Generate a new petname.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut rng = rand::thread_rng();
    /// petname::Petnames::default().generate(&mut rng, 7, ":");
    /// ```
    pub fn generate<RNG>(&self, rng: &mut RNG, words: u8, separator: &str) -> String
    where
        RNG: rand::Rng,
    {
        // Adverbs all the way, finishing with adjective then name.
        let mut parts = Vec::with_capacity(words as usize);
        for num in (0..words).rev() {
            parts.push(*match num {
                0 => self.names.choose(rng).unwrap(),
                1 => self.adjectives.choose(rng).unwrap(),
                _ => self.adverbs.choose(rng).unwrap(),
            });
        }
        parts.join(separator)
    }

    /// Generate a single new petname.
    ///
    /// This is like `generate` but uses `rand::thread_rng` as the random
    /// source. For efficiency use `generate` when creating multiple names, or
    /// when you want to use a custom source of randomness.
    pub fn generate_one(&self, words: u8, separator: &str) -> String {
        self.generate(&mut rand::thread_rng(), words, separator)
    }
}

impl<'a> Default for Petnames<'a> {
    fn default() -> Self {
        Self::default()
    }
}

#[cfg(test)]
mod tests {

    use super::{petname, Petnames};
    use rand;

    #[test]
    fn default_petnames_has_adjectives() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adjectives.len(), 0);
    }

    #[test]
    fn default_petnames_has_adverbs() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adverbs.len(), 0);
    }

    #[test]
    fn default_petnames_has_names() {
        let petnames = Petnames::default();
        assert_ne!(petnames.names.len(), 0);
    }

    #[test]
    fn generate_uses_adverb_adjective_name() {
        let petnames = Petnames {
            adjectives: vec!["adjective"],
            adverbs: vec!["adverb"],
            names: vec!["name"],
        };
        assert_eq!(
            petnames.generate(&mut rand::thread_rng(), 3, "-"),
            "adverb-adjective-name"
        );
    }

    #[test]
    fn petname_renders_desired_number_of_words() {
        assert_eq!(petname(7, "-").split("-").count(), 7);
    }

    #[test]
    fn petname_renders_with_desired_separator() {
        assert_eq!(petname(7, "@").split("@").count(), 7);
    }
}
<|endoftext|>


<commit_before>#![warn(missing_docs)]

//! A `Pinboard` is a shared, mutable, eventually consistent, lock-free data-structure.  This
//! allows multiple threads to communicate in a decoupled way by publishing data to the pinboard
//! which other threads can then read in an eventually consistent way.
//!
//! This is not a silver bullet though, there are various limitations of `Pinboard` that trade off
//! the nice behaviour described above.
//!
//! * Eventual consistency:
//!     * Writes from one thread are not guaranteed to be seen by reads from another thread
//!     * Writes from one thread can overwrite writes from another thread
//! * No in-place mutation:
//!     * The only write primitive completely overwrites the data on the `Pinboard`
//! * Requires `Clone`:
//!     * All reads return a clone of the data, decoupling the lifetime of the read value from the
//!     data stored in the global reference.

extern crate crossbeam_epoch as epoch;

use epoch::{Atomic, Owned, Shared, pin};
use std::sync::atomic::Ordering::*;

/// An instance of a `Pinboard`, holds a shared, mutable, eventually-consistent reference to a `T`.
pub struct Pinboard<T: Clone + 'static>(Atomic<T>);

impl<T: Clone + 'static> Pinboard<T> {
    /// Create a new `Pinboard` instance holding the given value.
    pub fn new(t: T) -> Pinboard<T> {
        let t = Owned::new(t);
        let p = Pinboard::default();
        p.0.store(t, Release);
        p
    }

    /// Update the value stored in the `Pinboard`.
    pub fn set(&self, t: T) {
        let guard = pin();
        let t = Owned::new(t);
        let t = self.0.swap(t, AcqRel, &guard);
        unsafe {
            if !t.is_null() {
                guard.defer(move || drop(t.into_owned()));
            }
        }
    }

    /// Clear out the `Pinboard` so its no longer holding any data.
    pub fn clear(&self) {
        let guard = pin();
        let t = self.0.swap(Shared::null(), AcqRel, &guard);
        unsafe {
            if !t.is_null() {
                guard.defer(move || drop(t.into_owned()));
            }
        }
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    pub fn read(&self) -> Option<T> {
        let guard = pin();
        unsafe {
            let t = self.0.load(Acquire, &guard);
            if t.is_null() {
                None
            } else {
                Some(t.deref().clone())
            }
        }
    }
}

impl<T: Clone + 'static> Default for Pinboard<T> {
    fn default() -> Pinboard<T> {
        Pinboard(Atomic::null())
    }
}

impl<T: Clone + 'static> Drop for Pinboard<T> {
    fn drop(&mut self) {
        // Make sure any stored data is marked for deletion
        self.clear();
    }
}

impl<T: Clone + 'static> From<Option<T>> for Pinboard<T> {
    fn from(src: Option<T>) -> Pinboard<T> {
        src.map(Pinboard::new).unwrap_or_default()
    }
}

/// An wrapper around a `Pinboard` which provides the guarantee it is never empty.
pub struct NonEmptyPinboard<T: Clone + 'static>(Pinboard<T>);

impl<T: Clone + 'static> NonEmptyPinboard<T> {
    /// Create a new `NonEmptyPinboard` instance holding the given value.
    pub fn new(t: T) -> NonEmptyPinboard<T> {
        NonEmptyPinboard(Pinboard::new(t))
    }

    /// Update the value stored in the `NonEmptyPinboard`.
    #[inline]
    pub fn set(&self, t: T) {
        self.0.set(t)
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    #[inline]
    pub fn read(&self) -> T {
        // Unwrap the option returned by the inner `Pinboard`. This will never panic, because it's
        // impossible for this `Pinboard` to be empty (though it's not possible to prove this to the
        // compiler).
        match self.0.read() {
            Some(t) => t,
            None => unreachable!("Inner pointer was unexpectedly null"),
        }
    }
}

macro_rules! debuggable {
    ($struct:ident, $trait:ident) => {
        impl<T: Clone + 'static> ::std::fmt::$trait for $struct<T> where T: ::std::fmt::$trait {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                write!(f, "{}(", stringify!($struct))?;
                ::std::fmt::$trait::fmt(&self.read(), f)?;
                write!(f, ")")
            }
        }
    }
}

debuggable!(Pinboard, Debug);
debuggable!(NonEmptyPinboard, Debug);
debuggable!(NonEmptyPinboard, Binary);
debuggable!(NonEmptyPinboard, Display);
debuggable!(NonEmptyPinboard, LowerExp);
debuggable!(NonEmptyPinboard, LowerHex);
debuggable!(NonEmptyPinboard, Octal);
debuggable!(NonEmptyPinboard, Pointer);
debuggable!(NonEmptyPinboard, UpperExp);
debuggable!(NonEmptyPinboard, UpperHex);

#[cfg(test)]
mod tests {
    extern crate crossbeam;
    use super::*;
    use std::fmt::Display;

    fn consume<T: Clone + Display>(t: &Pinboard<T>) {
        loop {
            match t.read() {
                Some(_) => {}
                None => break,
            }
            std::thread::sleep(std::time::Duration::from_millis(1));
        }
    }

    fn produce(t: &Pinboard<u32>) {
        for i in 1..100 {
            t.set(i);
            std::thread::sleep(std::time::Duration::from_millis(2));
        }
        t.clear();
    }

    fn check_debug<T: ::std::fmt::Debug>(_: T) {}

    #[test]
    fn it_works() {
        let t = Pinboard::<u32>::default();
        assert_eq!(None, t.read());
        t.set(3);
        assert_eq!(Some(3), t.read());
        t.clear();
        assert_eq!(None, t.read());
    }

    #[test]
    fn single_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn multi_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn single_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn multi_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn non_empty_pinboard() {
        let t = NonEmptyPinboard::<u32>::new(3);
        assert_eq!(3, t.read());
        t.set(4);
        assert_eq!(4, t.read());
    }

    #[test]
    fn debuggable() {
        let t = Pinboard::<i32>::new(3);
        check_debug(t);
        let t = NonEmptyPinboard::<i32>::new(2);
        check_debug(t);
    }
}
<commit_msg>Fix update breakages<commit_after>#![warn(missing_docs)]

//! A `Pinboard` is a shared, mutable, eventually consistent, lock-free data-structure.  This
//! allows multiple threads to communicate in a decoupled way by publishing data to the pinboard
//! which other threads can then read in an eventually consistent way.
//!
//! This is not a silver bullet though, there are various limitations of `Pinboard` that trade off
//! the nice behaviour described above.
//!
//! * Eventual consistency:
//!     * Writes from one thread are not guaranteed to be seen by reads from another thread
//!     * Writes from one thread can overwrite writes from another thread
//! * No in-place mutation:
//!     * The only write primitive completely overwrites the data on the `Pinboard`
//! * Requires `Clone`:
//!     * All reads return a clone of the data, decoupling the lifetime of the read value from the
//!     data stored in the global reference.

extern crate crossbeam_epoch as epoch;

use epoch::{Atomic, Owned, Shared, pin};
use std::sync::atomic::Ordering::*;

/// An instance of a `Pinboard`, holds a shared, mutable, eventually-consistent reference to a `T`.
pub struct Pinboard<T: Clone + 'static>(Atomic<T>);

impl<T: Clone + 'static> Pinboard<T> {
    /// Create a new `Pinboard` instance holding the given value.
    pub fn new(t: T) -> Pinboard<T> {
        let t = Owned::new(t);
        let p = Pinboard::default();
        p.0.store(t, Release);
        p
    }

    /// Update the value stored in the `Pinboard`.
    pub fn set(&self, t: T) {
        let guard = pin();
        let t = Owned::new(t);
        let t = self.0.swap(t, AcqRel, &guard);
        unsafe {
            if !t.is_null() {
                guard.defer_unchecked(move || drop(t.into_owned()));
            }
        }
    }

    /// Clear out the `Pinboard` so its no longer holding any data.
    pub fn clear(&self) {
        let guard = pin();
        let t = self.0.swap(Shared::null(), AcqRel, &guard);
        unsafe {
            if !t.is_null() {
                guard.defer_unchecked(move || drop(t.into_owned()));
            }
        }
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    pub fn read(&self) -> Option<T> {
        let guard = pin();
        unsafe {
            let t = self.0.load(Acquire, &guard);
            if t.is_null() {
                None
            } else {
                Some(t.deref().clone())
            }
        }
    }
}

impl<T: Clone + 'static> Default for Pinboard<T> {
    fn default() -> Pinboard<T> {
        Pinboard(Atomic::null())
    }
}

impl<T: Clone + 'static> Drop for Pinboard<T> {
    fn drop(&mut self) {
        // Make sure any stored data is marked for deletion
        self.clear();
    }
}

impl<T: Clone + 'static> From<Option<T>> for Pinboard<T> {
    fn from(src: Option<T>) -> Pinboard<T> {
        src.map(Pinboard::new).unwrap_or_default()
    }
}

/// An wrapper around a `Pinboard` which provides the guarantee it is never empty.
pub struct NonEmptyPinboard<T: Clone + 'static>(Pinboard<T>);

impl<T: Clone + 'static> NonEmptyPinboard<T> {
    /// Create a new `NonEmptyPinboard` instance holding the given value.
    pub fn new(t: T) -> NonEmptyPinboard<T> {
        NonEmptyPinboard(Pinboard::new(t))
    }

    /// Update the value stored in the `NonEmptyPinboard`.
    #[inline]
    pub fn set(&self, t: T) {
        self.0.set(t)
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    #[inline]
    pub fn read(&self) -> T {
        // Unwrap the option returned by the inner `Pinboard`. This will never panic, because it's
        // impossible for this `Pinboard` to be empty (though it's not possible to prove this to the
        // compiler).
        match self.0.read() {
            Some(t) => t,
            None => unreachable!("Inner pointer was unexpectedly null"),
        }
    }
}

macro_rules! debuggable {
    ($struct:ident, $trait:ident) => {
        impl<T: Clone + 'static> ::std::fmt::$trait for $struct<T> where T: ::std::fmt::$trait {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                write!(f, "{}(", stringify!($struct))?;
                ::std::fmt::$trait::fmt(&self.read(), f)?;
                write!(f, ")")
            }
        }
    }
}

debuggable!(Pinboard, Debug);
debuggable!(NonEmptyPinboard, Debug);
debuggable!(NonEmptyPinboard, Binary);
debuggable!(NonEmptyPinboard, Display);
debuggable!(NonEmptyPinboard, LowerExp);
debuggable!(NonEmptyPinboard, LowerHex);
debuggable!(NonEmptyPinboard, Octal);
debuggable!(NonEmptyPinboard, Pointer);
debuggable!(NonEmptyPinboard, UpperExp);
debuggable!(NonEmptyPinboard, UpperHex);

#[cfg(test)]
mod tests {
    extern crate crossbeam;
    use super::*;
    use std::fmt::Display;

    fn consume<T: Clone + Display>(t: &Pinboard<T>) {
        loop {
            match t.read() {
                Some(_) => {}
                None => break,
            }
            std::thread::sleep(std::time::Duration::from_millis(1));
        }
    }

    fn produce(t: &Pinboard<u32>) {
        for i in 1..100 {
            t.set(i);
            std::thread::sleep(std::time::Duration::from_millis(2));
        }
        t.clear();
    }

    fn check_debug<T: ::std::fmt::Debug>(_: T) {}

    #[test]
    fn it_works() {
        let t = Pinboard::<u32>::default();
        assert_eq!(None, t.read());
        t.set(3);
        assert_eq!(Some(3), t.read());
        t.clear();
        assert_eq!(None, t.read());
    }

    #[test]
    fn single_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn multi_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn single_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn multi_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn non_empty_pinboard() {
        let t = NonEmptyPinboard::<u32>::new(3);
        assert_eq!(3, t.read());
        t.set(4);
        assert_eq!(4, t.read());
    }

    #[test]
    fn debuggable() {
        let t = Pinboard::<i32>::new(3);
        check_debug(t);
        let t = NonEmptyPinboard::<i32>::new(2);
        check_debug(t);
    }
}
<|endoftext|>


<commit_before>//#![crate_name="celix_rust"]
//#![feature(libc)]
#![allow(non_camel_case_types,non_snake_case)]

//! A bundle to test Celix and Rust interaction.
//!
//! TODO: Allow more Rust like usage, preferably through use as (more optimised) library.

extern crate libc;
use libc::{c_void,malloc};

use std::fmt;
use std::sync::mpsc::Sender;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
use std::mem::size_of;

extern crate celix;
// #[macro_use]
// mod celix;
use celix::{celix_status_t,bundle_context_pt,CELIX_SUCCESS};
//const CELIX_SUCCESS: celix_status_t = 0;

// manifest!(SYMBOLIC_NAME = rust_celix);

/// Default thread count
const DEFAULT_THREADS: u64 = 4;

/// Data to be sent between Celix and this code.
///
/// `tx` is used to control the main worker thread: by sending `()`, the thread will stop.
#[repr(C)]
pub struct uData {
	t1: i32,
	t2: i32,
	/// A `Sender` for closing the worker thread (cannot drop a dereference of a raw pointer safely!)
	tx: Sender<()>
}

impl uData {
	/// Unused print method
	pub fn print(&self, prefix: &str) {
		println!("{} {}", prefix, self.t1);
	}
}

impl fmt::Debug for uData {
	/// Allows formatting
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "
uData {{
	t1: {:?},
	t2: {:?}
}}", self.t1, self.t2)
	}
}

/// Create this bundle
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn bundleActivator_create(context_ptr: bundle_context_pt, userData: *mut *mut c_void) -> celix_status_t {
	println!("create rust");
	// println!("{}", SYMBOLIC_NAME);
	unsafe {
		*userData = malloc(size_of::<uData>()); // C style malloc because the function receives a pointer
		(*(*userData as *mut uData)).t1 = 12;
		(*(*userData as *mut uData)).t2 = 100;
	}
	CELIX_SUCCESS
}

/// Start this bundle.
///
/// Create the main worker thread, and let that create it's own child threads.
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn bundleActivator_start(userData: *mut c_void, context: bundle_context_pt) -> celix_status_t {
	println!("start rust");
	let d : *mut uData;
	d = userData as *mut uData;
	println!("casted d");
	unsafe {
		println!("{:?}", (*d));
		let (tx, rx) = mpsc::channel();
		println!("created channel");
		(*d).tx = tx; // This seems to cause a SIGTRAP without compiler optimisations, will eventually have to find out why
		thread::spawn(move ||{
			println!("started thread");
			// Aditional threads should be created here to allow proper control over them.
			let (ltx,lrx) = mpsc::channel();
			let mut threads = vec![];
			let NTHREADS: u64 = match std::env::var("RUST_THREADS") {
				Ok(s) => match s.parse::<u64>() {
					Ok(i) => i,
					Err(_) => DEFAULT_THREADS,
				},
				Err(_) => DEFAULT_THREADS,
			};

			for i in 0..NTHREADS { // in a..b, b is exclusive, so 0..2 == [0,1]
				let ltx = ltx.clone();
				threads.push(thread::spawn(move || {
					loop {
						match ltx.send(()) {
							Err(SendError) => { // lrx has been dropped, so time to stop this thread
								println!("Stopping worker thread {}", i);
								return;
							},
							Ok(_) => {
								println!("worker thread {} working...", i);
								thread::sleep(Duration::new(0,100));
							},
						}
					}
				}));
			}
			loop {
				match rx.try_recv() {
					Ok(_)|Err(mpsc::TryRecvError::Disconnected) => {
						drop(lrx);
						for t in threads {
							let _ = t.join();
							println!("thread stopped");
						}
						println!("Terminated main worker thread");
						return;
					},
					Err(mpsc::TryRecvError::Empty) => {
						// println!("Working...");
						// thread::sleep(Duration::new(1,0));
					},
				}
			}
		});
	}
	println!("Hello {}", unsafe{(*d).t1});
	CELIX_SUCCESS
}

/// Stop this bundle
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn bundleActivator_stop(userData: *mut c_void, context: bundle_context_pt) -> celix_status_t {
	println!("stop rust");
	let d : *const uData;
	d = userData as *const uData;
	unsafe {
		println!("{:?}", (*d));
		match (*d).tx.send(()) {
			Ok(_) => println!("Sent kill signal to worker thread..."),
			Err(_) => println!("Failed to send kill signal to worker thread..."),
		}
	}
	println!("Goodbye {}", unsafe{(*d).t1});
	CELIX_SUCCESS
}

/// Destroy this bundle
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn bundleActivator_destroy(userData: *mut c_void, context: bundle_context_pt) -> celix_status_t {
	println!("destroy rust");
	CELIX_SUCCESS
}
<commit_msg>worker function support<commit_after>//#![crate_name="celix_rust"]
//#![feature(libc)]
#![allow(non_camel_case_types,non_snake_case)]

//! A bundle to test Celix and Rust interaction.
//!
//! TODO: Allow more Rust like usage, preferably through use as (more optimised) library.

extern crate libc;
use libc::{c_void,malloc};

use std::fmt;
use std::sync::mpsc::Sender;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
use std::mem::size_of;
use std::default::Default;

extern crate celix;
// #[macro_use]
// mod celix;
use celix::{celix_status_t,bundle_context_pt,CELIX_SUCCESS};
//const CELIX_SUCCESS: celix_status_t = 0;

// manifest!(SYMBOLIC_NAME = rust_celix);

/// Default thread count
const DEFAULT_THREADS: u64 = 4;

/// Data to be sent between Celix and this code.
///
/// `tx` is used to control the main worker thread: by sending `()`, the thread will stop.
#[repr(C)]
pub struct uData {
	t1: i32,
	t2: i32,
	/// A `Sender` for closing the worker thread (cannot drop a dereference of a raw pointer safely!)
	tx: Sender<()>,
	work: *const Fn() -> i32
}

impl uData {
	pub fn work() {
		println!("Worker function called");
	}
}

impl Default for uData {
	fn default() -> uData {
		let (tmptx,_) = mpsc::channel();
		uData {
			t1:0,
			t2:0,
			tx:tmptx,
			work:&(||{0})
		}
	}
}

impl fmt::Debug for uData {
	/// Allows formatting
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "
uData {{
	t1: {:?},
	t2: {:?}
}}", self.t1, self.t2)
	}
}

fn blah() -> i32 {
	println!("Working...");
	0
}

/// Create this bundle
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn bundleActivator_create(context_ptr: bundle_context_pt, userData: *mut *mut c_void) -> celix_status_t {
	println!("create rust");
	// println!("{}", SYMBOLIC_NAME);
	unsafe {
		*userData = malloc(size_of::<uData>()); // C style malloc because the function receives a pointer
		(*(*userData as *mut uData)).t1 = 12;
		(*(*userData as *mut uData)).t2 = 100;
		(*(*userData as *mut uData)).work = & (|| { println!("Working..."); 0 });
		(*(*userData as *mut uData)).work = &blah; // Both approaches work
	}
	CELIX_SUCCESS
}

// pub extern "C" fn bundleActivator_create(context_ptr: bundle_context_pt, userData: *mut uData) -> celix_status_t {
// 	println!("create rust");
// 	let d = uData {
// 		t1: 12,
// 		t2: 100,
// 		work: &blah,
// 		..Default::default()
// 	};
// 	unsafe { (*userData) = d; }
// 	CELIX_SUCCESS
// }

/// Start this bundle.
///
/// Create the main worker thread, and let that create it's own child threads.
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn bundleActivator_start(userData: *mut c_void, context: bundle_context_pt) -> celix_status_t {
	println!("start rust");
	let d : *mut uData;
	d = userData as *mut uData;
	println!("casted d");
	unsafe {
		println!("{:?}", (*d));
		let (tx, rx) = mpsc::channel();
		println!("created channel");
		(*d).tx = tx; // This seems to cause a SIGTRAP without compiler optimisations, will eventually have to find out why
		(*(*d).work)();
		thread::spawn(move ||{
			println!("started thread");
			// Aditional threads should be created here to allow proper control over them.
			let (ltx,lrx) = mpsc::channel();
			let mut threads = vec![];
			let NTHREADS: u64 = match std::env::var("RUST_THREADS") {
				Ok(s) => match s.parse::<u64>() {
					Ok(i) => i,
					Err(_) => DEFAULT_THREADS,
				},
				Err(_) => DEFAULT_THREADS,
			};

			for i in 0..NTHREADS { // in a..b, b is exclusive, so 0..2 == [0,1]
				let ltx = ltx.clone();
				threads.push(thread::spawn(move || {
					loop {
						match ltx.send(()) {
							Err(SendError) => { // lrx has been dropped, so time to stop this thread
								println!("Stopping worker thread {}", i);
								return;
							},
							Ok(_) => {
								println!("worker thread {} working...", i);
								thread::sleep(Duration::new(0,100));
							},
						}
					}
				}));
			}
			loop {
				match rx.try_recv() {
					Ok(_)|Err(mpsc::TryRecvError::Disconnected) => {
						drop(lrx);
						for t in threads {
							let _ = t.join();
							println!("thread stopped");
						}
						println!("Terminated main worker thread");
						return;
					},
					Err(mpsc::TryRecvError::Empty) => {
						// println!("Working...");
						// thread::sleep(Duration::new(1,0));
					},
				}
			}
		});
	}
	println!("Hello {}", unsafe{(*d).t1});
	CELIX_SUCCESS
}

/// Stop this bundle
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn bundleActivator_stop(userData: *mut c_void, context: bundle_context_pt) -> celix_status_t {
	println!("stop rust");
	let d : *const uData;
	d = userData as *const uData;
	unsafe {
		println!("{:?}", (*d));
		(*(*d).work)();
		match (*d).tx.send(()) {
			Ok(_) => println!("Sent kill signal to worker thread..."),
			Err(_) => println!("Failed to send kill signal to worker thread..."),
		}
	}
	println!("Goodbye {}", unsafe{(*d).t1});
	CELIX_SUCCESS
}

/// Destroy this bundle
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn bundleActivator_destroy(userData: *mut c_void, context: bundle_context_pt) -> celix_status_t {
	println!("destroy rust");
	CELIX_SUCCESS
}
<|endoftext|>


<commit_before>extern crate argparse;
extern crate humantime;
extern crate fern;
extern crate ipnetwork;
extern crate libc;
extern crate libcantal;
extern crate libmount;
extern crate nix;
extern crate quire;
extern crate serde;
extern crate serde_json;
extern crate serde_str;
extern crate signal;
extern crate syslog;
#[macro_use] extern crate failure;
#[macro_use] extern crate log;
#[macro_use] extern crate serde_derive;

pub mod master_config;
pub mod sandbox_config;
pub mod container_config;
pub mod child_config;
pub mod mount;
pub mod utils;
pub mod network;
pub mod setup;
pub mod pipe;
pub mod limits;
pub mod cgroup;
pub mod itertools;
pub mod timer_queue;
pub mod id_map;
pub mod metrics;
pub mod range;
pub mod knot_options;
pub mod tree_options;

pub const MAX_CONFIG_LOGS: u32 = 100;
<commit_msg>Add a comment<commit_after>//! This is internal module not intended to be used as a library
//!
//! See [Documentation](http://lithos.readthedocs.io) for the actual usage.
//!
extern crate argparse;
extern crate humantime;
extern crate fern;
extern crate ipnetwork;
extern crate libc;
extern crate libcantal;
extern crate libmount;
extern crate nix;
extern crate quire;
extern crate serde;
extern crate serde_json;
extern crate serde_str;
extern crate signal;
extern crate syslog;
#[macro_use] extern crate failure;
#[macro_use] extern crate log;
#[macro_use] extern crate serde_derive;

pub mod master_config;
pub mod sandbox_config;
pub mod container_config;
pub mod child_config;
pub mod mount;
pub mod utils;
pub mod network;
pub mod setup;
pub mod pipe;
pub mod limits;
pub mod cgroup;
pub mod itertools;
pub mod timer_queue;
pub mod id_map;
pub mod metrics;
pub mod range;
pub mod knot_options;
pub mod tree_options;

pub const MAX_CONFIG_LOGS: u32 = 100;
<|endoftext|>


<commit_before>#![no_std]

#[macro_export]
macro_rules! simple_bitfield_fields {
   ($t:ty,) => {};
   ($t:ty, _, $setter:ident: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       pub fn $setter(&mut self, value: $t) {
           use $crate::BitRange;
           self.set_bit_range($msb, $lsb, value);
       }
       simple_bitfield_fields!{$t, $($rest)*}
   };
   ($t:ty, _, $setter:ident: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
       #[allow(unknown_lints)]
       #[allow(eq_op)]
       pub fn $setter(&mut self, index: usize, value: $t) {
           use $crate::BitRange;
           debug_assert!(index < $count);
           let width = $msb - $lsb + 1;
           let lsb = $lsb + index*width;
           let msb = lsb + width - 1;
           self.set_bit_range(msb, lsb, value);
       }
       simple_bitfield_fields!{$t, $($rest)*}
   };
   ($t:ty, $getter:ident, _: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       pub fn $getter(&self) -> $t {
           use $crate::BitRange;
           self.bit_range($msb, $lsb)
       }
       simple_bitfield_fields!{$t, $($rest)*}
   };
   ($t:ty, $getter:ident, _: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
       #[allow(unknown_lints)]
       #[allow(eq_op)]
       pub fn $getter(&self, index: usize) -> $t {
           use $crate::BitRange;
           debug_assert!(index < $count);
           let width = $msb - $lsb + 1;
           let lsb = $lsb + index*width;
           let msb = lsb + width - 1;
           self.bit_range(msb, lsb)
       }
       simple_bitfield_fields!{$t, $($rest)*}
   };
   ($t:ty, $getter:ident, $setter:ident: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       simple_bitfield_fields!{$t, $getter, _: $msb, $lsb, }
       simple_bitfield_fields!{$t, _, $setter: $msb, $lsb, }
       simple_bitfield_fields!{$t, $($rest)*}
   };
   ($t:ty, $getter:ident, $setter:ident: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
         simple_bitfield_fields!{$t, $getter, _: $msb, $lsb; $count, }
         simple_bitfield_fields!{$t, _, $setter: $msb, $lsb; $count, }
         simple_bitfield_fields!{$t, $($rest)*}
   };
}

#[macro_export]
macro_rules! simple_bitfield {
    ($name:ident, [$t:ty]; $($rest:tt)*) => {
        pub struct $name<T>(pub T);

        impl<T: AsMut<[$t]> + AsRef<[$t]>> $crate::BitRange<u64> for $name<T> {
            fn bit_range(&self, msb: usize, lsb: usize) -> u64 {
                let bit_len = $crate::size_of::<$t>()*8;
                let mut value = 0;
                for i in (lsb..msb+1).rev() {
                    value <<= 1;
                    value |= ((self.0.as_ref()[i/bit_len] >> (i%bit_len)) & 1) as u64;
                }
                value
            }

            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: u64) {
                let bit_len = $crate::size_of::<$t>()*8;
                let mut value = value;
                for i in lsb..msb+1 {
                    self.0.as_mut()[i/bit_len] &= !(1 << (i%bit_len));
                    self.0.as_mut()[i/bit_len] |= (value & 1) as $t << (i%bit_len);
                    value >>= 1;
                }
            }
        }

        impl<T: AsMut<[$t]> + AsRef<[$t]>> $name<T> {
            simple_bitfield_fields!{u64, $($rest)*}
        }
    };
    ($name:ident, $t:ty; $($rest:tt)*) => {
        #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
        #[repr(C)]
        pub struct $name(pub $t);

        impl $crate::BitRange<$t> for $name {
            fn bit_range(&self, msb: usize, lsb: usize) -> $t {
                self.0.bit_range(msb, lsb)
            }
            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $t) {
                self.0.set_bit_range(msb, lsb, value);
            }
        }

        impl $name {
            simple_bitfield_fields!{$t, $($rest)*}
         }
    };
}

#[doc(hidden)]
pub fn size_of<T>() -> usize {
    core::mem::size_of::<T>()
}

/// A trait to get or set ranges of bits.
pub trait BitRange<T> {
    /// Get a range of bits.
    fn bit_range(&self, msb: usize, lsb: usize) -> T;
    /// Set a range of bits.
    fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T);
}

macro_rules! impl_bitrange_for_u {
    ($t:ty) => {
        impl BitRange<$t> for $t {
            #[inline]
            fn bit_range(&self, msb: usize, lsb: usize) -> $t {
                let bit_len = size_of::<$t>()*8;
                (*self << (bit_len - msb - 1)) >> (bit_len - msb - 1 + lsb)
            }

            #[inline]
            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $t) {
                let bit_len = size_of::<$t>()*8;
                let mask: $t = !(0 as $t)
                    << (bit_len - msb - 1)
                    >> (bit_len - msb - 1 + lsb)
                        << (lsb);
                *self &= !mask;
                *self |= (value << lsb) & mask;
            }
        }
    }
}

impl_bitrange_for_u!{u8}
impl_bitrange_for_u!{u16}
impl_bitrange_for_u!{u32}
impl_bitrange_for_u!{u64}
<commit_msg>Rexport size_of instead of redefining it<commit_after>#![no_std]

#[macro_export]
macro_rules! simple_bitfield_fields {
   ($t:ty,) => {};
   ($t:ty, _, $setter:ident: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       pub fn $setter(&mut self, value: $t) {
           use $crate::BitRange;
           self.set_bit_range($msb, $lsb, value);
       }
       simple_bitfield_fields!{$t, $($rest)*}
   };
   ($t:ty, _, $setter:ident: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
       #[allow(unknown_lints)]
       #[allow(eq_op)]
       pub fn $setter(&mut self, index: usize, value: $t) {
           use $crate::BitRange;
           debug_assert!(index < $count);
           let width = $msb - $lsb + 1;
           let lsb = $lsb + index*width;
           let msb = lsb + width - 1;
           self.set_bit_range(msb, lsb, value);
       }
       simple_bitfield_fields!{$t, $($rest)*}
   };
   ($t:ty, $getter:ident, _: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       pub fn $getter(&self) -> $t {
           use $crate::BitRange;
           self.bit_range($msb, $lsb)
       }
       simple_bitfield_fields!{$t, $($rest)*}
   };
   ($t:ty, $getter:ident, _: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
       #[allow(unknown_lints)]
       #[allow(eq_op)]
       pub fn $getter(&self, index: usize) -> $t {
           use $crate::BitRange;
           debug_assert!(index < $count);
           let width = $msb - $lsb + 1;
           let lsb = $lsb + index*width;
           let msb = lsb + width - 1;
           self.bit_range(msb, lsb)
       }
       simple_bitfield_fields!{$t, $($rest)*}
   };
   ($t:ty, $getter:ident, $setter:ident: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       simple_bitfield_fields!{$t, $getter, _: $msb, $lsb, }
       simple_bitfield_fields!{$t, _, $setter: $msb, $lsb, }
       simple_bitfield_fields!{$t, $($rest)*}
   };
   ($t:ty, $getter:ident, $setter:ident: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
         simple_bitfield_fields!{$t, $getter, _: $msb, $lsb; $count, }
         simple_bitfield_fields!{$t, _, $setter: $msb, $lsb; $count, }
         simple_bitfield_fields!{$t, $($rest)*}
   };
}

#[macro_export]
macro_rules! simple_bitfield {
    ($name:ident, [$t:ty]; $($rest:tt)*) => {
        pub struct $name<T>(pub T);

        impl<T: AsMut<[$t]> + AsRef<[$t]>> $crate::BitRange<u64> for $name<T> {
            fn bit_range(&self, msb: usize, lsb: usize) -> u64 {
                let bit_len = $crate::size_of::<$t>()*8;
                let mut value = 0;
                for i in (lsb..msb+1).rev() {
                    value <<= 1;
                    value |= ((self.0.as_ref()[i/bit_len] >> (i%bit_len)) & 1) as u64;
                }
                value
            }

            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: u64) {
                let bit_len = $crate::size_of::<$t>()*8;
                let mut value = value;
                for i in lsb..msb+1 {
                    self.0.as_mut()[i/bit_len] &= !(1 << (i%bit_len));
                    self.0.as_mut()[i/bit_len] |= (value & 1) as $t << (i%bit_len);
                    value >>= 1;
                }
            }
        }

        impl<T: AsMut<[$t]> + AsRef<[$t]>> $name<T> {
            simple_bitfield_fields!{u64, $($rest)*}
        }
    };
    ($name:ident, $t:ty; $($rest:tt)*) => {
        #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
        #[repr(C)]
        pub struct $name(pub $t);

        impl $crate::BitRange<$t> for $name {
            fn bit_range(&self, msb: usize, lsb: usize) -> $t {
                self.0.bit_range(msb, lsb)
            }
            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $t) {
                self.0.set_bit_range(msb, lsb, value);
            }
        }

        impl $name {
            simple_bitfield_fields!{$t, $($rest)*}
         }
    };
}

#[doc(hidden)]
pub use core::mem::size_of;

/// A trait to get or set ranges of bits.
pub trait BitRange<T> {
    /// Get a range of bits.
    fn bit_range(&self, msb: usize, lsb: usize) -> T;
    /// Set a range of bits.
    fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T);
}

macro_rules! impl_bitrange_for_u {
    ($t:ty) => {
        impl BitRange<$t> for $t {
            #[inline]
            fn bit_range(&self, msb: usize, lsb: usize) -> $t {
                let bit_len = size_of::<$t>()*8;
                (*self << (bit_len - msb - 1)) >> (bit_len - msb - 1 + lsb)
            }

            #[inline]
            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $t) {
                let bit_len = size_of::<$t>()*8;
                let mask: $t = !(0 as $t)
                    << (bit_len - msb - 1)
                    >> (bit_len - msb - 1 + lsb)
                        << (lsb);
                *self &= !mask;
                *self |= (value << lsb) & mask;
            }
        }
    }
}

impl_bitrange_for_u!{u8}
impl_bitrange_for_u!{u16}
impl_bitrange_for_u!{u32}
impl_bitrange_for_u!{u64}
<|endoftext|>