<commit_before>// library ~ (core/bundler file)

// Copyright (C) ~ Alex Lyon <arcterus@mail.com>
// Copyright (C) ~ Roy Ivy III <rivy.dev@gmail.com>; MIT license

// * feature-gated external crates (re-shared as public internal modules)
#[cfg(feature = "libc")]
pub extern crate libc;
#[cfg(feature = "winapi")]
pub extern crate winapi;

//## internal modules

mod features; // feature-gated code modules
mod macros; // crate macros (macro_rules-type; exported to `crate::...`)
mod mods; // core cross-platform modules
mod parser; // string parsing modules

pub use uucore_procs::*;

// * cross-platform modules
pub use crate::mods::backup_control;
pub use crate::mods::display;
pub use crate::mods::error;
pub use crate::mods::os;
pub use crate::mods::panic;
pub use crate::mods::ranges;
pub use crate::mods::version_cmp;

// * string parsing modules
pub use crate::parser::parse_size;
pub use crate::parser::parse_time;

// * feature-gated modules
#[cfg(feature = "encoding")]
pub use crate::features::encoding;
#[cfg(feature = "fs")]
pub use crate::features::fs;
#[cfg(feature = "fsext")]
pub use crate::features::fsext;
#[cfg(feature = "lines")]
pub use crate::features::lines;
#[cfg(feature = "memo")]
pub use crate::features::memo;
#[cfg(feature = "ringbuffer")]
pub use crate::features::ringbuffer;

// * (platform-specific) feature-gated modules
// ** non-windows (i.e. Unix + Fuchsia)
#[cfg(all(not(windows), feature = "mode"))]
pub use crate::features::mode;
// ** unix-only
#[cfg(all(unix, feature = "entries"))]
pub use crate::features::entries;
#[cfg(all(unix, feature = "perms"))]
pub use crate::features::perms;
#[cfg(all(unix, feature = "pipes"))]
pub use crate::features::pipes;
#[cfg(all(unix, feature = "process"))]
pub use crate::features::process;
#[cfg(all(unix, not(target_os = "fuchsia"), feature = "signals"))]
pub use crate::features::signals;
#[cfg(all(
    unix,
    not(target_os = "android"),
    not(target_os = "fuchsia"),
    not(target_os = "redox"),
    not(target_env = "musl"),
    feature = "utmpx"
))]
pub use crate::features::utmpx;
// ** windows-only
#[cfg(all(windows, feature = "wide"))]
pub use crate::features::wide;

//## core functions

use std::ffi::OsString;
use std::sync::atomic::Ordering;

use once_cell::sync::Lazy;

use crate::display::Quotable;

#[macro_export]
macro_rules! bin {
    ($util:ident) => {
        pub fn main() {
            use std::io::Write;
            uucore::panic::mute_sigpipe_panic(); // suppress extraneous error output for SIGPIPE failures/panics
            let code = $util::uumain(uucore::args_os()); // execute utility code
            std::io::stdout().flush().expect("could not flush stdout"); // (defensively) flush stdout for utility prior to exit; see <https://github.com/rust-lang/rust/issues/23818>
            std::process::exit(code);
        }
    };
}

/// Generate the usage string for clap.
///
/// This function replaces all occurrences of `{}` with the execution phrase
/// and leaks the result to return a `&'static str`. It does **not** support
/// more advanced formatting features such as `{0}`.
pub fn format_usage(s: &str) -> &'static str {
    &*Box::leak(s.replace("{}", crate::execution_phrase()).into_boxed_str())
}

pub fn get_utility_is_second_arg() -> bool {
    crate::macros::UTILITY_IS_SECOND_ARG.load(Ordering::SeqCst)
}

pub fn set_utility_is_second_arg() {
    crate::macros::UTILITY_IS_SECOND_ARG.store(true, Ordering::SeqCst);
}

// args_os() can be expensive to call, it copies all of argv before iterating.
// So if we want only the first arg or so it's overkill. We cache it.
static ARGV: Lazy<Vec<OsString>> = Lazy::new(|| wild::args_os().collect());

static UTIL_NAME: Lazy<String> = Lazy::new(|| {
    if get_utility_is_second_arg() {
        &ARGV[1]
    } else {
        &ARGV[0]
    }
    .to_string_lossy()
    .into_owned()
});

/// Derive the utility name.
pub fn util_name() -> &'static str {
    &UTIL_NAME
}

static EXECUTION_PHRASE: Lazy<String> = Lazy::new(|| {
    if get_utility_is_second_arg() {
        ARGV.iter()
            .take(2)
            .map(|os_str| os_str.to_string_lossy().into_owned())
            .collect::<Vec<_>>()
            .join(" ")
    } else {
        ARGV[0].to_string_lossy().into_owned()
    }
});

/// Derive the complete execution phrase for "usage".
pub fn execution_phrase() -> &'static str {
    &EXECUTION_PHRASE
}

pub enum InvalidEncodingHandling {
    Ignore,
    ConvertLossy,
    Panic,
}

#[must_use]
pub enum ConversionResult {
    Complete(Vec<String>),
    Lossy(Vec<String>),
}

impl ConversionResult {
    pub fn accept_any(self) -> Vec<String> {
        match self {
            Self::Complete(result) | Self::Lossy(result) => result,
        }
    }

    pub fn expect_lossy(self, msg: &str) -> Vec<String> {
        match self {
            Self::Lossy(result) => result,
            Self::Complete(_) => {
                panic!("{}", msg);
            }
        }
    }

    pub fn expect_complete(self, msg: &str) -> Vec<String> {
        match self {
            Self::Complete(result) => result,
            Self::Lossy(_) => {
                panic!("{}", msg);
            }
        }
    }
}

pub trait Args: Iterator<Item = OsString> + Sized {
    /// Converts each iterator item to a String and collects these into a vector
    /// On invalid encoding, the result will depend on the argument. This method allows to either drop entries with illegal encoding
    /// completely (```InvalidEncodingHandling::Ignore```), convert them using lossy-conversion (```InvalidEncodingHandling::Lossy```) which will
    /// result in strange strings or can chosen to panic (```InvalidEncodingHandling::Panic```).
    /// # Arguments
    /// * `handling` - This switch allows to switch the behavior, when invalid encoding is encountered
    /// # Panics
    /// * Occurs, when invalid encoding is encountered and handling is set to ```InvalidEncodingHandling::Panic```
    fn collect_str(self, handling: InvalidEncodingHandling) -> ConversionResult {
        let mut full_conversion = true;
        let result_vector: Vec<String> = self
            .map(|s| match s.into_string() {
                Ok(string) => Ok(string),
                Err(s_ret) => {
                    full_conversion = false;
                    eprintln!(
                        "Input with broken encoding occurred! (s = {}) ",
                        s_ret.quote()
                    );
                    match handling {
                        InvalidEncodingHandling::Ignore => Err(String::new()),
                        InvalidEncodingHandling::ConvertLossy => {
                            Err(s_ret.to_string_lossy().into_owned())
                        }
                        InvalidEncodingHandling::Panic => {
                            panic!("Broken encoding found but caller cannot handle it")
                        }
                    }
                }
            })
            .filter(|s| match handling {
                InvalidEncodingHandling::Ignore => s.is_ok(),
                _ => true,
            })
            .map(|s| match s {
                Ok(v) => v,
                Err(e) => e,
            })
            .collect();

        if full_conversion {
            ConversionResult::Complete(result_vector)
        } else {
            ConversionResult::Lossy(result_vector)
        }
    }

    /// convenience function for a more slim interface
    fn collect_str_lossy(self) -> ConversionResult {
        self.collect_str(InvalidEncodingHandling::ConvertLossy)
    }
}

impl<T: Iterator<Item = OsString> + Sized> Args for T {}

pub fn args_os() -> impl Iterator<Item = OsString> {
    ARGV.iter().cloned()
}

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

    fn make_os_vec(os_str: &OsStr) -> Vec<OsString> {
        vec![
            OsString::from("test"),
            OsString::from("สวัสดี"), // spell-checker:disable-line
            os_str.to_os_string(),
        ]
    }

    fn collect_os_str(vec: Vec<OsString>, handling: InvalidEncodingHandling) -> ConversionResult {
        vec.into_iter().collect_str(handling)
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn test_invalid_utf8_args_lossy(os_str: &OsStr) {
        //assert our string is invalid utf8
        assert!(os_str.to_os_string().into_string().is_err());
        let test_vec = make_os_vec(os_str);
        let collected_to_str =
            collect_os_str(test_vec.clone(), InvalidEncodingHandling::ConvertLossy)
                .expect_lossy("Lossy conversion expected in this test: bad encoding entries should be converted as good as possible");
        //conservation of length - when accepting lossy conversion no arguments may be dropped
        assert_eq!(collected_to_str.len(), test_vec.len());
        //first indices identical
        for index in 0..2 {
            assert_eq!(
                collected_to_str.get(index).unwrap(),
                test_vec.get(index).unwrap().to_str().unwrap()
            );
        }
        //lossy conversion for string with illegal encoding is done
        assert_eq!(
            *collected_to_str.get(2).unwrap(),
            os_str.to_os_string().to_string_lossy()
        );
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn test_invalid_utf8_args_ignore(os_str: &OsStr) {
        //assert our string is invalid utf8
        assert!(os_str.to_os_string().into_string().is_err());
        let test_vec = make_os_vec(os_str);
        let collected_to_str = collect_os_str(test_vec.clone(), InvalidEncodingHandling::Ignore)
            .expect_lossy(
                "Lossy conversion expected in this test: bad encoding entries should be filtered",
            );
        //assert that the broken entry is filtered out
        assert_eq!(collected_to_str.len(), test_vec.len() - 1);
        //assert that the unbroken indices are converted as expected
        for index in 0..2 {
            assert_eq!(
                collected_to_str.get(index).unwrap(),
                test_vec.get(index).unwrap().to_str().unwrap()
            );
        }
    }

    #[test]
    fn valid_utf8_encoding_args() {
        //create a vector containing only correct encoding
        let test_vec = make_os_vec(&OsString::from("test2"));
        //expect complete conversion without losses, even when lossy conversion is accepted
        let _ = collect_os_str(test_vec, InvalidEncodingHandling::ConvertLossy)
            .expect_complete("Lossy conversion not expected in this test");
    }

    #[cfg(any(unix, target_os = "redox"))]
    #[test]
    fn invalid_utf8_args_unix() {
        use std::os::unix::ffi::OsStrExt;

        let source = [0x66, 0x6f, 0x80, 0x6f];
        let os_str = OsStr::from_bytes(&source[..]);
        test_invalid_utf8_args_lossy(os_str);
        test_invalid_utf8_args_ignore(os_str);
    }
}
<commit_msg>uucore: fix invalid enum variant in docstring<commit_after>// library ~ (core/bundler file)

// Copyright (C) ~ Alex Lyon <arcterus@mail.com>
// Copyright (C) ~ Roy Ivy III <rivy.dev@gmail.com>; MIT license

// * feature-gated external crates (re-shared as public internal modules)
#[cfg(feature = "libc")]
pub extern crate libc;
#[cfg(feature = "winapi")]
pub extern crate winapi;

//## internal modules

mod features; // feature-gated code modules
mod macros; // crate macros (macro_rules-type; exported to `crate::...`)
mod mods; // core cross-platform modules
mod parser; // string parsing modules

pub use uucore_procs::*;

// * cross-platform modules
pub use crate::mods::backup_control;
pub use crate::mods::display;
pub use crate::mods::error;
pub use crate::mods::os;
pub use crate::mods::panic;
pub use crate::mods::ranges;
pub use crate::mods::version_cmp;

// * string parsing modules
pub use crate::parser::parse_size;
pub use crate::parser::parse_time;

// * feature-gated modules
#[cfg(feature = "encoding")]
pub use crate::features::encoding;
#[cfg(feature = "fs")]
pub use crate::features::fs;
#[cfg(feature = "fsext")]
pub use crate::features::fsext;
#[cfg(feature = "lines")]
pub use crate::features::lines;
#[cfg(feature = "memo")]
pub use crate::features::memo;
#[cfg(feature = "ringbuffer")]
pub use crate::features::ringbuffer;

// * (platform-specific) feature-gated modules
// ** non-windows (i.e. Unix + Fuchsia)
#[cfg(all(not(windows), feature = "mode"))]
pub use crate::features::mode;
// ** unix-only
#[cfg(all(unix, feature = "entries"))]
pub use crate::features::entries;
#[cfg(all(unix, feature = "perms"))]
pub use crate::features::perms;
#[cfg(all(unix, feature = "pipes"))]
pub use crate::features::pipes;
#[cfg(all(unix, feature = "process"))]
pub use crate::features::process;
#[cfg(all(unix, not(target_os = "fuchsia"), feature = "signals"))]
pub use crate::features::signals;
#[cfg(all(
    unix,
    not(target_os = "android"),
    not(target_os = "fuchsia"),
    not(target_os = "redox"),
    not(target_env = "musl"),
    feature = "utmpx"
))]
pub use crate::features::utmpx;
// ** windows-only
#[cfg(all(windows, feature = "wide"))]
pub use crate::features::wide;

//## core functions

use std::ffi::OsString;
use std::sync::atomic::Ordering;

use once_cell::sync::Lazy;

use crate::display::Quotable;

#[macro_export]
macro_rules! bin {
    ($util:ident) => {
        pub fn main() {
            use std::io::Write;
            uucore::panic::mute_sigpipe_panic(); // suppress extraneous error output for SIGPIPE failures/panics
            let code = $util::uumain(uucore::args_os()); // execute utility code
            std::io::stdout().flush().expect("could not flush stdout"); // (defensively) flush stdout for utility prior to exit; see <https://github.com/rust-lang/rust/issues/23818>
            std::process::exit(code);
        }
    };
}

/// Generate the usage string for clap.
///
/// This function replaces all occurrences of `{}` with the execution phrase
/// and leaks the result to return a `&'static str`. It does **not** support
/// more advanced formatting features such as `{0}`.
pub fn format_usage(s: &str) -> &'static str {
    &*Box::leak(s.replace("{}", crate::execution_phrase()).into_boxed_str())
}

pub fn get_utility_is_second_arg() -> bool {
    crate::macros::UTILITY_IS_SECOND_ARG.load(Ordering::SeqCst)
}

pub fn set_utility_is_second_arg() {
    crate::macros::UTILITY_IS_SECOND_ARG.store(true, Ordering::SeqCst);
}

// args_os() can be expensive to call, it copies all of argv before iterating.
// So if we want only the first arg or so it's overkill. We cache it.
static ARGV: Lazy<Vec<OsString>> = Lazy::new(|| wild::args_os().collect());

static UTIL_NAME: Lazy<String> = Lazy::new(|| {
    if get_utility_is_second_arg() {
        &ARGV[1]
    } else {
        &ARGV[0]
    }
    .to_string_lossy()
    .into_owned()
});

/// Derive the utility name.
pub fn util_name() -> &'static str {
    &UTIL_NAME
}

static EXECUTION_PHRASE: Lazy<String> = Lazy::new(|| {
    if get_utility_is_second_arg() {
        ARGV.iter()
            .take(2)
            .map(|os_str| os_str.to_string_lossy().into_owned())
            .collect::<Vec<_>>()
            .join(" ")
    } else {
        ARGV[0].to_string_lossy().into_owned()
    }
});

/// Derive the complete execution phrase for "usage".
pub fn execution_phrase() -> &'static str {
    &EXECUTION_PHRASE
}

pub enum InvalidEncodingHandling {
    Ignore,
    ConvertLossy,
    Panic,
}

#[must_use]
pub enum ConversionResult {
    Complete(Vec<String>),
    Lossy(Vec<String>),
}

impl ConversionResult {
    pub fn accept_any(self) -> Vec<String> {
        match self {
            Self::Complete(result) | Self::Lossy(result) => result,
        }
    }

    pub fn expect_lossy(self, msg: &str) -> Vec<String> {
        match self {
            Self::Lossy(result) => result,
            Self::Complete(_) => {
                panic!("{}", msg);
            }
        }
    }

    pub fn expect_complete(self, msg: &str) -> Vec<String> {
        match self {
            Self::Complete(result) => result,
            Self::Lossy(_) => {
                panic!("{}", msg);
            }
        }
    }
}

pub trait Args: Iterator<Item = OsString> + Sized {
    /// Converts each iterator item to a String and collects these into a vector
    /// On invalid encoding, the result will depend on the argument. This method allows to either drop entries with illegal encoding
    /// completely (```InvalidEncodingHandling::Ignore```), convert them using lossy-conversion (```InvalidEncodingHandling::ConvertLossy```)
    /// which will result in strange strings or can chosen to panic (```InvalidEncodingHandling::Panic```).
    /// # Arguments
    /// * `handling` - This switch allows to switch the behavior, when invalid encoding is encountered
    /// # Panics
    /// * Occurs, when invalid encoding is encountered and handling is set to ```InvalidEncodingHandling::Panic```
    fn collect_str(self, handling: InvalidEncodingHandling) -> ConversionResult {
        let mut full_conversion = true;
        let result_vector: Vec<String> = self
            .map(|s| match s.into_string() {
                Ok(string) => Ok(string),
                Err(s_ret) => {
                    full_conversion = false;
                    eprintln!(
                        "Input with broken encoding occurred! (s = {}) ",
                        s_ret.quote()
                    );
                    match handling {
                        InvalidEncodingHandling::Ignore => Err(String::new()),
                        InvalidEncodingHandling::ConvertLossy => {
                            Err(s_ret.to_string_lossy().into_owned())
                        }
                        InvalidEncodingHandling::Panic => {
                            panic!("Broken encoding found but caller cannot handle it")
                        }
                    }
                }
            })
            .filter(|s| match handling {
                InvalidEncodingHandling::Ignore => s.is_ok(),
                _ => true,
            })
            .map(|s| match s {
                Ok(v) => v,
                Err(e) => e,
            })
            .collect();

        if full_conversion {
            ConversionResult::Complete(result_vector)
        } else {
            ConversionResult::Lossy(result_vector)
        }
    }

    /// convenience function for a more slim interface
    fn collect_str_lossy(self) -> ConversionResult {
        self.collect_str(InvalidEncodingHandling::ConvertLossy)
    }
}

impl<T: Iterator<Item = OsString> + Sized> Args for T {}

pub fn args_os() -> impl Iterator<Item = OsString> {
    ARGV.iter().cloned()
}

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

    fn make_os_vec(os_str: &OsStr) -> Vec<OsString> {
        vec![
            OsString::from("test"),
            OsString::from("สวัสดี"), // spell-checker:disable-line
            os_str.to_os_string(),
        ]
    }

    fn collect_os_str(vec: Vec<OsString>, handling: InvalidEncodingHandling) -> ConversionResult {
        vec.into_iter().collect_str(handling)
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn test_invalid_utf8_args_lossy(os_str: &OsStr) {
        //assert our string is invalid utf8
        assert!(os_str.to_os_string().into_string().is_err());
        let test_vec = make_os_vec(os_str);
        let collected_to_str =
            collect_os_str(test_vec.clone(), InvalidEncodingHandling::ConvertLossy)
                .expect_lossy("Lossy conversion expected in this test: bad encoding entries should be converted as good as possible");
        //conservation of length - when accepting lossy conversion no arguments may be dropped
        assert_eq!(collected_to_str.len(), test_vec.len());
        //first indices identical
        for index in 0..2 {
            assert_eq!(
                collected_to_str.get(index).unwrap(),
                test_vec.get(index).unwrap().to_str().unwrap()
            );
        }
        //lossy conversion for string with illegal encoding is done
        assert_eq!(
            *collected_to_str.get(2).unwrap(),
            os_str.to_os_string().to_string_lossy()
        );
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn test_invalid_utf8_args_ignore(os_str: &OsStr) {
        //assert our string is invalid utf8
        assert!(os_str.to_os_string().into_string().is_err());
        let test_vec = make_os_vec(os_str);
        let collected_to_str = collect_os_str(test_vec.clone(), InvalidEncodingHandling::Ignore)
            .expect_lossy(
                "Lossy conversion expected in this test: bad encoding entries should be filtered",
            );
        //assert that the broken entry is filtered out
        assert_eq!(collected_to_str.len(), test_vec.len() - 1);
        //assert that the unbroken indices are converted as expected
        for index in 0..2 {
            assert_eq!(
                collected_to_str.get(index).unwrap(),
                test_vec.get(index).unwrap().to_str().unwrap()
            );
        }
    }

    #[test]
    fn valid_utf8_encoding_args() {
        //create a vector containing only correct encoding
        let test_vec = make_os_vec(&OsString::from("test2"));
        //expect complete conversion without losses, even when lossy conversion is accepted
        let _ = collect_os_str(test_vec, InvalidEncodingHandling::ConvertLossy)
            .expect_complete("Lossy conversion not expected in this test");
    }

    #[cfg(any(unix, target_os = "redox"))]
    #[test]
    fn invalid_utf8_args_unix() {
        use std::os::unix::ffi::OsStrExt;

        let source = [0x66, 0x6f, 0x80, 0x6f];
        let os_str = OsStr::from_bytes(&source[..]);
        test_invalid_utf8_args_lossy(os_str);
        test_invalid_utf8_args_ignore(os_str);
    }
}
<|endoftext|>


<commit_before>//! An enum mapping type.
//!
//! It is implemented using array, so using it is as fast as using Rust
//! arrays.

#![no_std]
#![deny(missing_docs)]

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

#[cfg(feature = "serde")]
use serde::ser::{Serialize, Serializer, SerializeMap};
#[cfg(feature = "serde")]
use serde::de::{self, Deserialize, Deserializer, Error, MapAccess};

#[cfg(feature = "serde")]
use core::fmt;
use core::hash::{Hash, Hasher};
use core::iter::Enumerate;
use core::marker::PhantomData;
use core::ops::{Index, IndexMut};
use core::slice;

// this is not stable, do not depend on this
#[doc(hidden)]
pub trait Internal<V>: Sized {
    type Array;
    fn slice(&Self::Array) -> &[V];
    fn slice_mut(&mut Self::Array) -> &mut [V];
    fn from_usize(usize) -> Self;
    fn to_usize(self) -> usize;
    fn from_function<F: FnMut(Self) -> V>(F) -> Self::Array;
}

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(EnumMap)]` from `enum_map_derive` crate.
///
/// # Examples
///
/// ```
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// use enum_map::EnumMap;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
#[derive(Debug)]
pub struct EnumMap<K: Internal<V>, V> {
    array: K::Array,
}

impl<K: Internal<V>, V> EnumMap<K, V> {
    /// Returns number of elements in enum map.
    pub fn len(&self) -> usize {
        K::slice(&self.array).len()
    }

    /// Returns an iterator over enum map.
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }
}

impl<F: FnMut(K) -> V, K: Internal<V>, V> From<F> for EnumMap<K, V> {
    fn from(f: F) -> Self {
        EnumMap { array: K::from_function(f) }
    }
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        ::enum_map::EnumMap::from(|k| match k { $($t)* })
    };
}

impl<K: Internal<V>, V: Default> EnumMap<K, V>
    where K::Array: Default
{
    /// Creates an enum map with default values.
    ///
    /// ```
    /// extern crate enum_map;
    /// #[macro_use]
    /// extern crate enum_map_derive;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    pub fn new() -> Self {
        EnumMap::default()
    }
}

// Implementations provided by derive attribute are too specific, and put requirements on K.
// This is caused by rust-lang/rust#26925.
impl<K: Internal<V>, V> Clone for EnumMap<K, V>
    where K::Array: Clone
{
    fn clone(&self) -> Self {
        EnumMap { array: self.array.clone() }
    }
}

impl<K: Internal<V>, V> Copy for EnumMap<K, V> where K::Array: Copy {}

impl<K: Internal<V>, V> PartialEq for EnumMap<K, V>
    where K::Array: PartialEq
{
    fn eq(&self, other: &Self) -> bool {
        self.array == other.array
    }
}

impl<K: Internal<V>, V> Eq for EnumMap<K, V> where K::Array: Eq {}

impl<K: Internal<V>, V> Hash for EnumMap<K, V>
    where K::Array: Hash
{
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.array.hash(state);
    }
}

impl<K: Internal<V>, V> Default for EnumMap<K, V>
    where K::Array: Default
{
    fn default() -> Self {
        EnumMap { array: K::Array::default() }
    }
}

impl<K: Internal<V>, V> Index<K> for EnumMap<K, V> {
    type Output = V;

    fn index(&self, key: K) -> &V {
        &K::slice(&self.array)[key.to_usize()]
    }
}

impl<K: Internal<V>, V> IndexMut<K> for EnumMap<K, V> {
    fn index_mut(&mut self, key: K) -> &mut V {
        &mut K::slice_mut(&mut self.array)[key.to_usize()]
    }
}

/// Immutable enum map iterator
///
/// This struct is created by `iter` method or `into_iter` on a reference
/// to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     assert_eq!(map[Example::A], 3);
///     for (key, &value) in &map {
///         assert_eq!(match key {
///             Example::A => 3,
///             _ => 0,
///         }, value);
///     }
/// }
/// ```
pub struct Iter<'a, K, V: 'a> {
    _phantom: PhantomData<K>,
    iterator: Enumerate<slice::Iter<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for Iter<'a, K, V> {
    type Item = (K, &'a V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for Iter<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for Iter<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a EnumMap<K, V> {
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        Iter {
            _phantom: PhantomData,
            iterator: K::slice(&self.array).iter().enumerate(),
        }
    }
}

/// Mutable map iterator
///
/// This struct is created by `iter_mut` method or `into_iter` on a mutable
/// reference to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(Debug, EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     for (_, value) in &mut map {
///         *value += 1;
///     }
///     assert_eq!(map, enum_map! { Example::A => 4, _ => 1 });
/// }
/// ```
pub struct IterMut<'a, K, V: 'a> {
    _phantom: PhantomData<K>,
    iterator: Enumerate<slice::IterMut<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for IterMut<'a, K, V> {
    type Item = (K, &'a mut V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for IterMut<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for IterMut<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a mut EnumMap<K, V> {
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        IterMut {
            _phantom: PhantomData,
            iterator: K::slice_mut(&mut self.array).iter_mut().enumerate(),
        }
    }
}

#[cfg(feature = "serde")]
impl<K: Internal<V> + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (key, value) in self {
            map.serialize_entry(&key, value)?;
        }
        map.end()
    }
}

#[cfg(feature = "serde")]
impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_map(Visitor(PhantomData))
    }
}

#[cfg(feature = "serde")]
struct Visitor<K: Internal<V>, V>(PhantomData<EnumMap<K, V>>);

#[cfg(feature = "serde")]
impl<'de, K, V> de::Visitor<'de> for Visitor<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    type Value = EnumMap<K, V>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "map")
    }

    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
        let mut entries = EnumMap::from(|_| None);
        while let Some((key, value)) = access.next_entry()? {
            entries[key] = Some(value);
        }
        for (_, value) in &entries {
            if value.is_none() {
                return Err(M::Error::custom("key not specified"));
            }
        }
        Ok(EnumMap::from(|key| entries[key].take().unwrap()))
    }
}
<commit_msg>Put an example of usage in crate documentation<commit_after>//! An enum mapping type.
//!
//! It is implemented using array, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! #[macro_use]
//! extern crate enum_map;
//! #[macro_use]
//! extern crate enum_map_derive;
//!
//! use enum_map::EnumMap;
//!
//! #[derive(Debug, EnumMap)]
//! enum Example {
//!     A,
//!     B,
//!     C,
//! }
//!
//! fn main() {
//!     let mut map = enum_map! {
//!         Example::A => 1,
//!         Example::B => 2,
//!         Example::C => 3,
//!     };
//!     map[Example::C] = 4;
//!
//!     assert_eq!(map[Example::A], 1);
//!
//!     for (key, &value) in &map {
//!         println!("{:?} has {} as value.", key, value);
//!     }
//! }
//! ```

#![no_std]
#![deny(missing_docs)]

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

#[cfg(feature = "serde")]
use serde::ser::{Serialize, Serializer, SerializeMap};
#[cfg(feature = "serde")]
use serde::de::{self, Deserialize, Deserializer, Error, MapAccess};

#[cfg(feature = "serde")]
use core::fmt;
use core::hash::{Hash, Hasher};
use core::iter::Enumerate;
use core::marker::PhantomData;
use core::ops::{Index, IndexMut};
use core::slice;

// this is not stable, do not depend on this
#[doc(hidden)]
pub trait Internal<V>: Sized {
    type Array;
    fn slice(&Self::Array) -> &[V];
    fn slice_mut(&mut Self::Array) -> &mut [V];
    fn from_usize(usize) -> Self;
    fn to_usize(self) -> usize;
    fn from_function<F: FnMut(Self) -> V>(F) -> Self::Array;
}

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(EnumMap)]` from `enum_map_derive` crate.
///
/// # Examples
///
/// ```
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// use enum_map::EnumMap;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
#[derive(Debug)]
pub struct EnumMap<K: Internal<V>, V> {
    array: K::Array,
}

impl<K: Internal<V>, V> EnumMap<K, V> {
    /// Returns number of elements in enum map.
    pub fn len(&self) -> usize {
        K::slice(&self.array).len()
    }

    /// Returns an iterator over enum map.
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }
}

impl<F: FnMut(K) -> V, K: Internal<V>, V> From<F> for EnumMap<K, V> {
    fn from(f: F) -> Self {
        EnumMap { array: K::from_function(f) }
    }
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        ::enum_map::EnumMap::from(|k| match k { $($t)* })
    };
}

impl<K: Internal<V>, V: Default> EnumMap<K, V>
    where K::Array: Default
{
    /// Creates an enum map with default values.
    ///
    /// ```
    /// extern crate enum_map;
    /// #[macro_use]
    /// extern crate enum_map_derive;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    pub fn new() -> Self {
        EnumMap::default()
    }
}

// Implementations provided by derive attribute are too specific, and put requirements on K.
// This is caused by rust-lang/rust#26925.
impl<K: Internal<V>, V> Clone for EnumMap<K, V>
    where K::Array: Clone
{
    fn clone(&self) -> Self {
        EnumMap { array: self.array.clone() }
    }
}

impl<K: Internal<V>, V> Copy for EnumMap<K, V> where K::Array: Copy {}

impl<K: Internal<V>, V> PartialEq for EnumMap<K, V>
    where K::Array: PartialEq
{
    fn eq(&self, other: &Self) -> bool {
        self.array == other.array
    }
}

impl<K: Internal<V>, V> Eq for EnumMap<K, V> where K::Array: Eq {}

impl<K: Internal<V>, V> Hash for EnumMap<K, V>
    where K::Array: Hash
{
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.array.hash(state);
    }
}

impl<K: Internal<V>, V> Default for EnumMap<K, V>
    where K::Array: Default
{
    fn default() -> Self {
        EnumMap { array: K::Array::default() }
    }
}

impl<K: Internal<V>, V> Index<K> for EnumMap<K, V> {
    type Output = V;

    fn index(&self, key: K) -> &V {
        &K::slice(&self.array)[key.to_usize()]
    }
}

impl<K: Internal<V>, V> IndexMut<K> for EnumMap<K, V> {
    fn index_mut(&mut self, key: K) -> &mut V {
        &mut K::slice_mut(&mut self.array)[key.to_usize()]
    }
}

/// Immutable enum map iterator
///
/// This struct is created by `iter` method or `into_iter` on a reference
/// to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     assert_eq!(map[Example::A], 3);
///     for (key, &value) in &map {
///         assert_eq!(match key {
///             Example::A => 3,
///             _ => 0,
///         }, value);
///     }
/// }
/// ```
pub struct Iter<'a, K, V: 'a> {
    _phantom: PhantomData<K>,
    iterator: Enumerate<slice::Iter<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for Iter<'a, K, V> {
    type Item = (K, &'a V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for Iter<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for Iter<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a EnumMap<K, V> {
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        Iter {
            _phantom: PhantomData,
            iterator: K::slice(&self.array).iter().enumerate(),
        }
    }
}

/// Mutable map iterator
///
/// This struct is created by `iter_mut` method or `into_iter` on a mutable
/// reference to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(Debug, EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     for (_, value) in &mut map {
///         *value += 1;
///     }
///     assert_eq!(map, enum_map! { Example::A => 4, _ => 1 });
/// }
/// ```
pub struct IterMut<'a, K, V: 'a> {
    _phantom: PhantomData<K>,
    iterator: Enumerate<slice::IterMut<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for IterMut<'a, K, V> {
    type Item = (K, &'a mut V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for IterMut<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for IterMut<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a mut EnumMap<K, V> {
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        IterMut {
            _phantom: PhantomData,
            iterator: K::slice_mut(&mut self.array).iter_mut().enumerate(),
        }
    }
}

#[cfg(feature = "serde")]
impl<K: Internal<V> + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (key, value) in self {
            map.serialize_entry(&key, value)?;
        }
        map.end()
    }
}

#[cfg(feature = "serde")]
impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_map(Visitor(PhantomData))
    }
}

#[cfg(feature = "serde")]
struct Visitor<K: Internal<V>, V>(PhantomData<EnumMap<K, V>>);

#[cfg(feature = "serde")]
impl<'de, K, V> de::Visitor<'de> for Visitor<K, V>
    where K: Internal<V> + Internal<Option<V>> + Deserialize<'de>,
          V: Deserialize<'de>
{
    type Value = EnumMap<K, V>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "map")
    }

    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
        let mut entries = EnumMap::from(|_| None);
        while let Some((key, value)) = access.next_entry()? {
            entries[key] = Some(value);
        }
        for (_, value) in &entries {
            if value.is_none() {
                return Err(M::Error::custom("key not specified"));
            }
        }
        Ok(EnumMap::from(|key| entries[key].take().unwrap()))
    }
}
<|endoftext|>


<commit_before>//! Array-based data structures using densely numbered entity references as mapping keys.
//!
//! This crate defines a number of data structures based on arrays. The arrays are not indexed by
//! `usize` as usual, but by *entity references* which are integers wrapped in new-types. This has
//! a couple advantages:
//!
//! - Improved type safety. The various map and set types accept a specific key type, so there is
//!   no confusion about the meaning of an array index, as there is with plain arrays.
//! - Smaller indexes. The normal `usize` index is often 64 bits which is way too large for most
//!   purposes. The entity reference types can be smaller, allowing for more compact data
//!   structures.
//!
//! The `EntityRef` trait should be implemented by types to be used as indexed. The `entity_impl!`
//! macro provides convenient defaults for types wrapping `u32` which is common.
//!
//! - [`PrimaryMap`](struct.PrimaryMap.html) is used to keep track of a vector of entities,
//!   assigning a unique entity reference to each.
//! - [`SecondaryMap`](struct.SecondaryMap.html) is used to associate secondary information to an entity.
//!   The map is implemented as a simple vector, so it does not keep track of which entities have
//!   been inserted. Instead, any unknown entities map to the default value.
//! - [`SparseMap`](struct.SparseMap.html) is used to associate secondary information to a small
//!   number of entities. It tracks accurately which entities have been inserted. This is a
//!   specialized data structure which can use a lot of memory, so read the documentation before
//!   using it.
//! - [`EntitySet`](struct.EntitySet.html) is used to represent a secondary set of entities.
//!   The set is implemented as a simple vector, so it does not keep track of which entities have
//!   been inserted into the primary map. Instead, any unknown entities are not in the set.
//! - [`EntityList`](struct.EntityList.html) is a compact representation of lists of entity
//!   references allocated from an associated memory pool. It has a much smaller footprint than
//!   `Vec`.

#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "std", deny(unstable_features))]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(new_without_default, new_without_default_derive)
)]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        clippy::float_arithmetic,
        clippy::mut_mut,
        clippy::nonminimal_bool,
        clippy::option_map_unwrap_or,
        clippy::option_map_unwrap_or_else,
        clippy::print_stdout,
        clippy::unicode_not_nfc,
        clippy::use_self
    )
)]
// Turns on no_std and alloc features if std is not available.
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]

/// This replaces `std` in builds with `core`.
#[cfg(not(feature = "std"))]
mod std {
    extern crate alloc;
    pub use self::alloc::{boxed, string, vec};
    pub use core::*;
}

// Re-export core so that the macros works with both std and no_std crates
#[doc(hidden)]
pub extern crate core as __core;

/// A type wrapping a small integer index should implement `EntityRef` so it can be used as the key
/// of an `SecondaryMap` or `SparseMap`.
pub trait EntityRef: Copy + Eq {
    /// Create a new entity reference from a small integer.
    /// This should crash if the requested index is not representable.
    fn new(usize) -> Self;

    /// Get the index that was used to create this entity reference.
    fn index(self) -> usize;
}

/// Macro which provides the common implementation of a 32-bit entity reference.
#[macro_export]
macro_rules! entity_impl {
    // Basic traits.
    ($entity:ident) => {
        impl $crate::EntityRef for $entity {
            fn new(index: usize) -> Self {
                debug_assert!(index < ($crate::__core::u32::MAX as usize));
                $entity(index as u32)
            }

            fn index(self) -> usize {
                self.0 as usize
            }
        }

        impl $crate::packed_option::ReservedValue for $entity {
            fn reserved_value() -> $entity {
                $entity($crate::__core::u32::MAX)
            }
        }

        impl $entity {
            /// Return the underlying index value as a `u32`.
            pub fn as_u32(self) -> u32 {
                self.0
            }
        }
    };

    // Include basic `Display` impl using the given display prefix.
    // Display an `Ebb` reference as "ebb12".
    ($entity:ident, $display_prefix:expr) => {
        entity_impl!($entity);

        impl $crate::__core::fmt::Display for $entity {
            fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
                write!(f, concat!($display_prefix, "{}"), self.0)
            }
        }

        impl $crate::__core::fmt::Debug for $entity {
            fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
                (self as &$crate::__core::fmt::Display).fmt(f)
            }
        }
    };
}

pub mod packed_option;

mod iter;
mod keys;
mod list;
mod map;
mod primary;
mod set;
mod sparse;

pub use self::iter::{Iter, IterMut};
pub use self::keys::Keys;
pub use self::list::{EntityList, ListPool};
pub use self::map::SecondaryMap;
pub use self::primary::PrimaryMap;
pub use self::set::EntitySet;
pub use self::sparse::{SparseMap, SparseMapValue, SparseSet};
<commit_msg>Suppress dead-code warnings on functions expanded from `entity_impl!`.<commit_after>//! Array-based data structures using densely numbered entity references as mapping keys.
//!
//! This crate defines a number of data structures based on arrays. The arrays are not indexed by
//! `usize` as usual, but by *entity references* which are integers wrapped in new-types. This has
//! a couple advantages:
//!
//! - Improved type safety. The various map and set types accept a specific key type, so there is
//!   no confusion about the meaning of an array index, as there is with plain arrays.
//! - Smaller indexes. The normal `usize` index is often 64 bits which is way too large for most
//!   purposes. The entity reference types can be smaller, allowing for more compact data
//!   structures.
//!
//! The `EntityRef` trait should be implemented by types to be used as indexed. The `entity_impl!`
//! macro provides convenient defaults for types wrapping `u32` which is common.
//!
//! - [`PrimaryMap`](struct.PrimaryMap.html) is used to keep track of a vector of entities,
//!   assigning a unique entity reference to each.
//! - [`SecondaryMap`](struct.SecondaryMap.html) is used to associate secondary information to an entity.
//!   The map is implemented as a simple vector, so it does not keep track of which entities have
//!   been inserted. Instead, any unknown entities map to the default value.
//! - [`SparseMap`](struct.SparseMap.html) is used to associate secondary information to a small
//!   number of entities. It tracks accurately which entities have been inserted. This is a
//!   specialized data structure which can use a lot of memory, so read the documentation before
//!   using it.
//! - [`EntitySet`](struct.EntitySet.html) is used to represent a secondary set of entities.
//!   The set is implemented as a simple vector, so it does not keep track of which entities have
//!   been inserted into the primary map. Instead, any unknown entities are not in the set.
//! - [`EntityList`](struct.EntityList.html) is a compact representation of lists of entity
//!   references allocated from an associated memory pool. It has a much smaller footprint than
//!   `Vec`.

#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "std", deny(unstable_features))]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(new_without_default, new_without_default_derive)
)]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        clippy::float_arithmetic,
        clippy::mut_mut,
        clippy::nonminimal_bool,
        clippy::option_map_unwrap_or,
        clippy::option_map_unwrap_or_else,
        clippy::print_stdout,
        clippy::unicode_not_nfc,
        clippy::use_self
    )
)]
// Turns on no_std and alloc features if std is not available.
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]

/// This replaces `std` in builds with `core`.
#[cfg(not(feature = "std"))]
mod std {
    extern crate alloc;
    pub use self::alloc::{boxed, string, vec};
    pub use core::*;
}

// Re-export core so that the macros works with both std and no_std crates
#[doc(hidden)]
pub extern crate core as __core;

/// A type wrapping a small integer index should implement `EntityRef` so it can be used as the key
/// of an `SecondaryMap` or `SparseMap`.
pub trait EntityRef: Copy + Eq {
    /// Create a new entity reference from a small integer.
    /// This should crash if the requested index is not representable.
    fn new(usize) -> Self;

    /// Get the index that was used to create this entity reference.
    fn index(self) -> usize;
}

/// Macro which provides the common implementation of a 32-bit entity reference.
#[macro_export]
macro_rules! entity_impl {
    // Basic traits.
    ($entity:ident) => {
        impl $crate::EntityRef for $entity {
            fn new(index: usize) -> Self {
                debug_assert!(index < ($crate::__core::u32::MAX as usize));
                $entity(index as u32)
            }

            fn index(self) -> usize {
                self.0 as usize
            }
        }

        impl $crate::packed_option::ReservedValue for $entity {
            fn reserved_value() -> $entity {
                $entity($crate::__core::u32::MAX)
            }
        }

        impl $entity {
            /// Return the underlying index value as a `u32`.
            #[allow(dead_code)]
            pub fn as_u32(self) -> u32 {
                self.0
            }
        }
    };

    // Include basic `Display` impl using the given display prefix.
    // Display an `Ebb` reference as "ebb12".
    ($entity:ident, $display_prefix:expr) => {
        entity_impl!($entity);

        impl $crate::__core::fmt::Display for $entity {
            fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
                write!(f, concat!($display_prefix, "{}"), self.0)
            }
        }

        impl $crate::__core::fmt::Debug for $entity {
            fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
                (self as &$crate::__core::fmt::Display).fmt(f)
            }
        }
    };
}

pub mod packed_option;

mod iter;
mod keys;
mod list;
mod map;
mod primary;
mod set;
mod sparse;

pub use self::iter::{Iter, IterMut};
pub use self::keys::Keys;
pub use self::list::{EntityList, ListPool};
pub use self::map::SecondaryMap;
pub use self::primary::PrimaryMap;
pub use self::set::EntitySet;
pub use self::sparse::{SparseMap, SparseMapValue, SparseSet};
<|endoftext|>


<commit_before>//! System operations instructions

use utils::address::Address;
use utils::bigint::{U256, M256};
use utils::gas::Gas;
use vm::{Memory, Log, Context};
use super::State;
use rlp::RlpStream;

use crypto::sha3::Sha3;
use crypto::digest::Digest;
use vm::eval::utils::copy_from_memory;

pub fn suicide<M: Memory + Default>(state: &mut State<M>) {
    pop!(state, address: Address);
    let balance = state.account_state.balance(state.context.address).unwrap();
    state.account_state.increase_balance(address, balance);
    state.account_state.remove(state.context.address).unwrap();
}

pub fn log<M: Memory + Default>(state: &mut State<M>, topic_len: usize) {
    pop!(state, index, len);
    let data = copy_from_memory(&state.memory, index, len);
    let mut topics = Vec::new();
    for _ in 0..topic_len {
        topics.push(state.stack.pop().unwrap());
    }

    state.logs.push(Log {
        address: state.context.address,
        data: data,
        topics: topics,
    });
}

pub fn sha3<M: Memory + Default>(state: &mut State<M>) {
    pop!(state, from, len);
    let data = copy_from_memory(&state.memory, from, len);
    let mut sha3 = Sha3::keccak256();
    sha3.input(data.as_slice());
    let mut ret = [0u8; 32];
    sha3.result(&mut ret);
    push!(state, M256::from(ret.as_ref()));
}

pub fn create<M: Memory + Default>(state: &mut State<M>, after_gas: Gas) -> Option<Context> {
    pop!(state, value: U256);
    pop!(state, init_start, init_len);
    if state.account_state.balance(state.context.address).unwrap() < value {
        push!(state, M256::zero());
        return None;
    }

    let init = copy_from_memory(&state.memory, init_start, init_len);
    let nonce = state.account_state.nonce(state.context.address).unwrap();
    let mut rlp = RlpStream::new();
    rlp.begin_list(2);
    rlp.append(&state.context.address);
    rlp.append(&nonce);
    let mut address_array = [0u8; 32];
    let mut sha3 = Sha3::keccak256();
    sha3.input(rlp.out().as_slice());
    sha3.result(&mut address_array);
    let address = Address::from(M256::from(address_array));
    let context = Context {
        address: address,
        caller: state.context.address,
        code: init,
        data: Vec::new(),
        gas_limit: after_gas,
        gas_price: state.context.gas_price,
        origin: state.context.origin,
        value: value,
    };
    push!(state, address.into());
    Some(context)
}

#[allow(unused_variables)]
pub fn call<M: Memory + Default>(state: &mut State<M>, stipend_gas: Gas, after_gas: Gas) -> Option<(Context, (M256, M256))> {
    pop!(state, gas: Gas, to: Address, value: U256);
    pop!(state, in_start, in_len, out_start, out_len);
    if state.account_state.balance(state.context.address).unwrap() < value {
        push!(state, M256::zero());
        return None;
    }

    let input = copy_from_memory(&state.memory, in_start, in_len);
    let gas_limit = gas + stipend_gas;
    let context = Context {
        address: to,
        caller: state.context.address,
        code: state.account_state.code(to).unwrap().into(),
        data: input,
        gas_limit: gas_limit,
        gas_price: state.context.gas_price,
        origin: state.context.origin,
        value: value,
    };
    push!(state, M256::zero());
    Some((context, (out_start, out_len)))
}

#[allow(unused_variables)]
pub fn callcode<M: Memory + Default>(state: &mut State<M>, stipend_gas: Gas, after_gas: Gas) -> Option<(Context, (M256, M256))> {
    pop!(state, gas: Gas, to: Address, value: U256);
    pop!(state, in_start, in_len, out_start, out_len);
    if state.account_state.balance(state.context.address).unwrap() < value {
        push!(state, M256::zero());
        return None;
    }

    let input = copy_from_memory(&state.memory, in_start, in_len);
    let gas_limit = gas + stipend_gas;
    let context = Context {
        address: state.context.address,
        caller: state.context.address,
        code: state.account_state.code(to).unwrap().into(),
        data: input,
        gas_limit: gas_limit,
        gas_price: state.context.gas_price,
        origin: state.context.origin,
        value: value,
    };
    push!(state, M256::zero());
    Some((context, (out_start, out_len)))
}
<commit_msg>Problem: CALL/CALLCODE should use the Transaction struct<commit_after>//! System operations instructions

use utils::address::Address;
use utils::bigint::{U256, M256};
use utils::gas::Gas;
use vm::{Memory, Log, Context, Transaction};
use super::State;
use rlp::RlpStream;

use crypto::sha3::Sha3;
use crypto::digest::Digest;
use vm::eval::utils::copy_from_memory;

pub fn suicide<M: Memory + Default>(state: &mut State<M>) {
    pop!(state, address: Address);
    let balance = state.account_state.balance(state.context.address).unwrap();
    state.account_state.increase_balance(address, balance);
    state.account_state.remove(state.context.address).unwrap();
}

pub fn log<M: Memory + Default>(state: &mut State<M>, topic_len: usize) {
    pop!(state, index, len);
    let data = copy_from_memory(&state.memory, index, len);
    let mut topics = Vec::new();
    for _ in 0..topic_len {
        topics.push(state.stack.pop().unwrap());
    }

    state.logs.push(Log {
        address: state.context.address,
        data: data,
        topics: topics,
    });
}

pub fn sha3<M: Memory + Default>(state: &mut State<M>) {
    pop!(state, from, len);
    let data = copy_from_memory(&state.memory, from, len);
    let mut sha3 = Sha3::keccak256();
    sha3.input(data.as_slice());
    let mut ret = [0u8; 32];
    sha3.result(&mut ret);
    push!(state, M256::from(ret.as_ref()));
}

pub fn create<M: Memory + Default>(state: &mut State<M>, after_gas: Gas) -> Option<Context> {
    pop!(state, value: U256);
    pop!(state, init_start, init_len);
    if state.account_state.balance(state.context.address).unwrap() < value {
        push!(state, M256::zero());
        return None;
    }

    let init = copy_from_memory(&state.memory, init_start, init_len);
    let nonce = state.account_state.nonce(state.context.address).unwrap();
    let mut rlp = RlpStream::new();
    rlp.begin_list(2);
    rlp.append(&state.context.address);
    rlp.append(&nonce);
    let mut address_array = [0u8; 32];
    let mut sha3 = Sha3::keccak256();
    sha3.input(rlp.out().as_slice());
    sha3.result(&mut address_array);
    let address = Address::from(M256::from(address_array));
    let context = Context {
        address: address,
        caller: state.context.address,
        code: init,
        data: Vec::new(),
        gas_limit: after_gas,
        gas_price: state.context.gas_price,
        origin: state.context.origin,
        value: value,
    };
    push!(state, address.into());
    Some(context)
}

#[allow(unused_variables)]
pub fn call<M: Memory + Default>(state: &mut State<M>, stipend_gas: Gas, after_gas: Gas) -> Option<(Context, (M256, M256))> {
    pop!(state, gas: Gas, to: Address, value: U256);
    pop!(state, in_start, in_len, out_start, out_len);
    if state.account_state.balance(state.context.address).unwrap() < value {
        push!(state, M256::zero());
        return None;
    }

    let input = copy_from_memory(&state.memory, in_start, in_len);
    let gas_limit = gas + stipend_gas;

    let transaction = Transaction::MessageCall {
        address: to,
        caller: state.context.address,
        gas_price: state.context.gas_price,
        gas_limit: gas_limit,
        value: value,
        data: input,
    };
    let context = transaction.into_context(
        Gas::zero(), Some(state.context.origin), &state.account_state
    ).unwrap();
    push!(state, M256::zero());
    Some((context, (out_start, out_len)))
}

#[allow(unused_variables)]
pub fn callcode<M: Memory + Default>(state: &mut State<M>, stipend_gas: Gas, after_gas: Gas) -> Option<(Context, (M256, M256))> {
    pop!(state, gas: Gas, to: Address, value: U256);
    pop!(state, in_start, in_len, out_start, out_len);
    if state.account_state.balance(state.context.address).unwrap() < value {
        push!(state, M256::zero());
        return None;
    }

    let input = copy_from_memory(&state.memory, in_start, in_len);
    let gas_limit = gas + stipend_gas;
    let transaction = Transaction::MessageCall {
        address: state.context.address,
        caller: state.context.address,
        gas_price: state.context.gas_price,
        gas_limit: gas_limit,
        value: value,
        data: input,
    };
    let context = transaction.into_context(
        Gas::zero(), Some(state.context.origin), &state.account_state
    ).unwrap();
    push!(state, M256::zero());
    Some((context, (out_start, out_len)))
}
<|endoftext|>


<commit_before><commit_msg>Implement day23 part 2.<commit_after><|endoftext|>


<commit_before>use clingo::*;
use std::env;

fn print_model(model: &Model) {
    // retrieve the symbols in the model
    let atoms = model
        .symbols(ShowType::SHOWN)
        .expect("Failed to retrieve symbols in the model.");

    print!("Model:");

    for atom in atoms {
        // retrieve and print the symbol's string
        print!(" {}", atom.to_string().unwrap());
    }
    println!();
}

fn solve(ctl: &mut Control) {
    // get a solve handle
    let mut handle = ctl
        .solve(SolveMode::YIELD, &[])
        .expect("Failed retrieving solve handle.");

    // loop over all models
    loop {
        handle.resume().expect("Failed resume on solve handle.");
        match handle.model() {
            // print the model
            Ok(Some(model)) => print_model(model),
            // stop if there are no more models
            Ok(None) => break,
            Err(e) => panic!("Error: {}", e),
        }
    }

    // close the solve handle
    handle
        .get()
        .expect("Failed to get result from solve handle.");
    handle.close().expect("Failed to close solve handle.");
}

fn main() {
    // collect clingo options from the command line
    let options = env::args().skip(1).collect();

    // create a control object and pass command line arguments
    let mut ctl = Control::new(options).expect("Failed creating Control.");

    // add a logic program to the base part
    ctl.add("base", &[], "a :- not b. b :- not a.")
        .expect("Failed to add a logic program.");;

    // ground the base part
    let part = Part::new("base", &[]).unwrap();
    let parts = vec![part];
    ctl.ground(&parts)
        .expect("Failed to ground a logic program.");

    // solve
    solve(&mut ctl);
}
<commit_msg>Fix warning in example<commit_after>use clingo::*;
use std::env;

fn print_model(model: &Model) {
    // retrieve the symbols in the model
    let atoms = model
        .symbols(ShowType::SHOWN)
        .expect("Failed to retrieve symbols in the model.");

    print!("Model:");

    for atom in atoms {
        // retrieve and print the symbol's string
        print!(" {}", atom.to_string().unwrap());
    }
    println!();
}

fn solve(ctl: &mut Control) {
    // get a solve handle
    let mut handle = ctl
        .solve(SolveMode::YIELD, &[])
        .expect("Failed retrieving solve handle.");

    // loop over all models
    loop {
        handle.resume().expect("Failed resume on solve handle.");
        match handle.model() {
            // print the model
            Ok(Some(model)) => print_model(model),
            // stop if there are no more models
            Ok(None) => break,
            Err(e) => panic!("Error: {}", e),
        }
    }

    // close the solve handle
    handle
        .get()
        .expect("Failed to get result from solve handle.");
    handle.close().expect("Failed to close solve handle.");
}

fn main() {
    // collect clingo options from the command line
    let options = env::args().skip(1).collect();

    // create a control object and pass command line arguments
    let mut ctl = Control::new(options).expect("Failed creating Control.");

    // add a logic program to the base part
    ctl.add("base", &[], "a :- not b. b :- not a.")
        .expect("Failed to add a logic program.");

    // ground the base part
    let part = Part::new("base", &[]).unwrap();
    let parts = vec![part];
    ctl.ground(&parts)
        .expect("Failed to ground a logic program.");

    // solve
    solve(&mut ctl);
}
<|endoftext|>


<commit_before>#[macro_use] extern crate unwrap;

extern crate tempdir;

extern crate rs_utils;

fn main () {
  let exe_name = std::env::current_exe().unwrap();
  println!("{:?} main...", exe_name);

  let temp_dir = unwrap!{ tempdir::TempDir::new_in ("examples", "tmp") };

  let file_path = temp_dir.path().join (
    std::path::Path::new ("myfile"));
  let file_path = file_path.as_path();

  println!("file_path_incremental \"{}\": {}", file_path.display(),
    unwrap!{ rs_utils::file::file_path_incremental (file_path) }.display()
  );
  println!("file_new_append_incremental \"{}\"...", file_path.display());
  unwrap!{ rs_utils::file::file_new_append_incremental (file_path) };

  println!("file_path_incremental \"{}\": {}", file_path.display(),
    unwrap!{ rs_utils::file::file_path_incremental (file_path) }.display()
  );
  println!("file_new_append_incremental \"{}\"...", file_path.display());
  unwrap!{ rs_utils::file::file_new_append_incremental (file_path) };

  println!("file_path_incremental \"{}\": {}", file_path.display(),
    unwrap!{ rs_utils::file::file_path_incremental (file_path) }.display()
  );
  println!("file_path_incremental and then file_new_append \"{}\"...",
    file_path.display()
  );
  unwrap!{
    // file_new_append_incremental is equivalent to:
    rs_utils::file::file_path_incremental (file_path).and_then (
      |path_buf| rs_utils::file::file_new_append (path_buf.as_path())
    )
  };

  println!("!ls {}", temp_dir.path().display());
  assert!{
    unwrap!{
      std::process::Command::new ("ls").arg (temp_dir.path().as_os_str())
        .status()
    }.success()
  };

  println!("...{:?} main", exe_name);
}
<commit_msg>example<commit_after>#[macro_use] extern crate unwrap;

extern crate tempdir;

extern crate rs_utils;

fn main () {
  let exe_name = std::env::current_exe().unwrap().file_name().unwrap()
    .to_owned();
  println!("{:?} main...", exe_name);

  let temp_dir = unwrap!{ tempdir::TempDir::new_in ("examples", "tmp") };

  let file_path = temp_dir.path().join (
    std::path::Path::new ("myfile"));
  let file_path = file_path.as_path();

  println!("file_path_incremental \"{}\": {}", file_path.display(),
    unwrap!{ rs_utils::file::file_path_incremental (file_path) }.display()
  );
  println!("file_new_append_incremental \"{}\"...", file_path.display());
  unwrap!{ rs_utils::file::file_new_append_incremental (file_path) };

  println!("file_path_incremental \"{}\": {}", file_path.display(),
    unwrap!{ rs_utils::file::file_path_incremental (file_path) }.display()
  );
  println!("file_new_append_incremental \"{}\"...", file_path.display());
  unwrap!{ rs_utils::file::file_new_append_incremental (file_path) };

  println!("file_path_incremental \"{}\": {}", file_path.display(),
    unwrap!{ rs_utils::file::file_path_incremental (file_path) }.display()
  );
  println!("file_path_incremental and then file_new_append \"{}\"...",
    file_path.display()
  );
  unwrap!{
    // file_new_append_incremental is equivalent to:
    rs_utils::file::file_path_incremental (file_path).and_then (
      |path_buf| rs_utils::file::file_new_append (path_buf.as_path())
    )
  };

  println!("!ls {}", temp_dir.path().display());
  assert!{
    unwrap!{
      std::process::Command::new ("ls").arg (temp_dir.path().as_os_str())
        .status()
    }.success()
  };

  println!("...{:?} main", exe_name);
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate libc;

use std::io;
use std::time::Duration;
use std::os::unix::io::{ RawFd, AsRawFd };
use libc::{ c_int, c_void, timespec, time_t };

/*
 * libc timer implementation
 */
#[allow(non_camel_case_types)]
#[repr(C)]
struct itimerspec {
    it_interval: timespec,
    it_value: timespec,
}

#[allow(non_camel_case_types)]
pub struct Itimerspec {
    pub it_interval: Duration,
    pub it_value: Duration,
}

extern "C" {
    fn timerfd_create(clockid: c_int, flags: c_int) -> RawFd;
    fn timerfd_settime(fd: RawFd, flags: c_int,
                       new_value: *const itimerspec, old_value: *mut itimerspec) -> libc::c_int;
    fn timerfd_gettime(fd: RawFd, curr_value: *mut itimerspec) -> libc::c_int;
}

pub struct Timerfd(RawFd);

impl Timerfd {
    pub fn create(clockid: c_int, flags: c_int) -> io::Result<Self> {
        let timerfd = unsafe { timerfd_create(clockid, flags) };
        if timerfd == -1 {
            return Err(io::Error::last_os_error())
        }
        Ok(Timerfd(timerfd))
    }

    pub fn settime(&self, flags: c_int, new_value: &Itimerspec) -> io::Result<Itimerspec> {
        let new_raw = itimerspec{
            it_interval: timespec {
                tv_sec: new_value.it_interval.as_secs() as time_t,
                tv_nsec: new_value.it_interval.subsec_nanos() as i64,
            },
            it_value: timespec {
                tv_sec: new_value.it_value.as_secs() as time_t,
                tv_nsec: new_value.it_value.subsec_nanos() as i64,
            },
        };
        let mut old_raw = itimerspec { it_interval: timespec { tv_sec: 0, tv_nsec: 0 },
                                       it_value: timespec { tv_sec: 0, tv_nsec: 0 } };

        if unsafe { timerfd_settime(self.0, flags, &new_raw, &mut old_raw) } == -1 {
            return Err(io::Error::last_os_error());
        }
        Ok(Itimerspec{
            it_interval: Duration::new(old_raw.it_interval.tv_sec as u64,
                                       old_raw.it_interval.tv_nsec as u32),
            it_value: Duration::new(old_raw.it_value.tv_sec as u64,
                                    old_raw.it_value.tv_nsec as u32),
        })
    }

    pub fn gettime(&self) -> io::Result<Itimerspec> {
        let mut raw = itimerspec { it_interval: timespec { tv_sec: 0, tv_nsec: 0 },
                                   it_value: timespec { tv_sec: 0, tv_nsec: 0 } };
        if unsafe { timerfd_gettime(self.0, &mut raw) } == -1 {
            return Err(io::Error::last_os_error());
        }

        Ok(Itimerspec{
            it_interval: Duration::new(raw.it_interval.tv_sec as u64,
                                       raw.it_interval.tv_nsec as u32),
            it_value: Duration::new(raw.it_value.tv_sec as u64,
                                    raw.it_value.tv_nsec as u32),
        })
    }

    pub fn read(&self) -> io::Result<u64> {
        let mut buf = 0u64;
        let nr = unsafe {
            libc::read(self.0, &mut buf as *mut _ as *mut c_void, ::std::mem::size_of::<u64>())
        };
        if nr == ::std::mem::size_of::<u64>() as isize {
            return Ok(buf);
        }
        Err(io::Error::last_os_error())
    }
}

impl Drop for Timerfd {
    fn drop(&mut self) {
        unsafe { libc::close(self.0) };
    }
}

impl AsRawFd for Timerfd {
    fn as_raw_fd(&self) -> RawFd {
        self.0
    }
}

/*
 * mio Evented implementation
 */
extern crate mio;

use mio::{ Ready, Poll, PollOpt, Token };
use mio::unix::EventedFd;
use mio::event::Evented;

impl Evented for Timerfd {
    fn register(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
        EventedFd(&self.0).register(poll, token, interest, opts)
    }

    fn reregister(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
        EventedFd(&self.0).reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &Poll) -> io::Result<()> {
        EventedFd(&self.0).deregister(poll)
    }
}

fn main() {}
<commit_msg>examples: update mio crate description<commit_after>#![allow(dead_code)]

extern crate libc;

use std::io;
use std::time::Duration;
use std::os::unix::io::{ RawFd, AsRawFd };
use libc::{ c_int, c_void, timespec, time_t };

/*
 * libc timer implementation
 */
#[allow(non_camel_case_types)]
#[repr(C)]
struct itimerspec {
    it_interval: timespec,
    it_value: timespec,
}

#[allow(non_camel_case_types)]
pub struct Itimerspec {
    pub it_interval: Duration,
    pub it_value: Duration,
}

extern "C" {
    fn timerfd_create(clockid: c_int, flags: c_int) -> RawFd;
    fn timerfd_settime(fd: RawFd, flags: c_int,
                       new_value: *const itimerspec, old_value: *mut itimerspec) -> libc::c_int;
    fn timerfd_gettime(fd: RawFd, curr_value: *mut itimerspec) -> libc::c_int;
}

pub struct Timerfd(RawFd);

impl Timerfd {
    pub fn create(clockid: c_int, flags: c_int) -> io::Result<Self> {
        let timerfd = unsafe { timerfd_create(clockid, flags) };
        if timerfd == -1 {
            return Err(io::Error::last_os_error())
        }
        Ok(Timerfd(timerfd))
    }

    pub fn settime(&self, flags: c_int, new_value: &Itimerspec) -> io::Result<Itimerspec> {
        let new_raw = itimerspec{
            it_interval: timespec {
                tv_sec: new_value.it_interval.as_secs() as time_t,
                tv_nsec: new_value.it_interval.subsec_nanos() as i64,
            },
            it_value: timespec {
                tv_sec: new_value.it_value.as_secs() as time_t,
                tv_nsec: new_value.it_value.subsec_nanos() as i64,
            },
        };
        let mut old_raw = itimerspec { it_interval: timespec { tv_sec: 0, tv_nsec: 0 },
                                       it_value: timespec { tv_sec: 0, tv_nsec: 0 } };

        if unsafe { timerfd_settime(self.0, flags, &new_raw, &mut old_raw) } == -1 {
            return Err(io::Error::last_os_error());
        }
        Ok(Itimerspec{
            it_interval: Duration::new(old_raw.it_interval.tv_sec as u64,
                                       old_raw.it_interval.tv_nsec as u32),
            it_value: Duration::new(old_raw.it_value.tv_sec as u64,
                                    old_raw.it_value.tv_nsec as u32),
        })
    }

    pub fn gettime(&self) -> io::Result<Itimerspec> {
        let mut raw = itimerspec { it_interval: timespec { tv_sec: 0, tv_nsec: 0 },
                                   it_value: timespec { tv_sec: 0, tv_nsec: 0 } };
        if unsafe { timerfd_gettime(self.0, &mut raw) } == -1 {
            return Err(io::Error::last_os_error());
        }

        Ok(Itimerspec{
            it_interval: Duration::new(raw.it_interval.tv_sec as u64,
                                       raw.it_interval.tv_nsec as u32),
            it_value: Duration::new(raw.it_value.tv_sec as u64,
                                    raw.it_value.tv_nsec as u32),
        })
    }

    pub fn read(&self) -> io::Result<u64> {
        let mut buf = 0u64;
        let nr = unsafe {
            libc::read(self.0, &mut buf as *mut _ as *mut c_void, ::std::mem::size_of::<u64>())
        };
        if nr == ::std::mem::size_of::<u64>() as isize {
            return Ok(buf);
        }
        Err(io::Error::last_os_error())
    }
}

impl Drop for Timerfd {
    fn drop(&mut self) {
        unsafe { libc::close(self.0) };
    }
}

impl AsRawFd for Timerfd {
    fn as_raw_fd(&self) -> RawFd {
        self.0
    }
}

/*
 * mio Evented implementation
 */
extern crate mio;

impl mio::event::Evented for Timerfd {
    fn register(&self, poll: &mio::Poll, token: mio::Token, interest: mio::Ready, opts: mio::PollOpt) -> io::Result<()> {
        mio::unix::EventedFd(&self.0).register(poll, token, interest, opts)
    }

    fn reregister(&self, poll: &mio::Poll, token: mio::Token, interest: mio::Ready, opts: mio::PollOpt) -> io::Result<()> {
        mio::unix::EventedFd(&self.0).reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        mio::unix::EventedFd(&self.0).deregister(poll)
    }
}

fn main() {}
<|endoftext|>


<commit_before>use std::cell::Cell;

use orbtk::prelude::*;

pub struct MainViewState {
    counter: Cell<i32>,
    list: Vec<String>,
}

impl Default for MainViewState {
    fn default() -> Self {
        MainViewState {
            counter: Cell::new(0),
            list: vec![
                "Item 1".to_string(),
                "Item 2".to_string(),
                "Item 3".to_string(),
                "Last Item".to_string(),
            ],
        }
    }
}

impl MainViewState {
    fn increment(&self) {
        self.counter.set(self.counter.get() + 1)
    }
}

impl State for MainViewState {
    fn update(&self, context: &mut Context<'_>) {
        if let Some(button_count_text) = context.widget().try_get_mut::<Text>() {
            button_count_text.0 = String16::from(format!("Button count: {}", self.counter.get()));
        }
    }
}

fn create_header(context: &mut BuildContext, text: &str, grid: usize, column: usize) -> Entity {
    TextBlock::create()
        .text(text)
        .selector(SelectorValue::new().with("text-block").class("h1"))
        .attach(GridColumn(grid))
        .attach(GridRow(column))
        .build(context)
}

widget!(
    MainView<MainViewState> {
        count_text: Text
    }
);

impl Template for MainView {
    fn template(self, id: Entity, context: &mut BuildContext) -> Self {
        let state = self.clone_state();

        let list_state = self.clone_state();

        self.name("MainView").count_text("Button count: 0").child(
            Grid::create()
                .margin(8.0)
                .columns(
                    Columns::create()
                        .column("Auto")
                        .column(32.0)
                        .column("Auto")
                        .column(32.0)
                        .column(120.0)
                        .column("*")
                        .build(),
                )
                .rows(
                    Rows::create()
                        .row("Auto")
                        .row("Auto")
                        .row("Auto")
                        .row("Auto")
                        .row("Auto")
                        .row("Auto")
                        .row("*")
                        .build(),
                )
                // Column 0
                .child(create_header(context, "Button", 0, 0))
                .child(
                    Button::create()
                        .text("Button")
                        .margin((0.0, 8.0, 0.0, 0.0))
                        .icon(material_font_icons::CHECK_FONT_ICON)
                        .attach(GridColumn(0))
                        .attach(GridRow(1))
                        .on_click(move |_| {
                            state.increment();
                            true
                        })
                        .build(context),
                )
                .child(
                    Button::create()
                        .text("Primary")
                        .selector(SelectorValue::new().with("button").class("primary"))
                        .margin((0.0, 8.0, 0.0, 0.0))
                        .icon(material_font_icons::CHECK_FONT_ICON)
                        .attach(GridColumn(0))
                        .attach(GridRow(2))
                        .build(context),
                )
                .child(
                    ToggleButton::create()
                        .text("ToggleButton")
                        .margin((0.0, 8.0, 0.0, 0.0))
                        .attach(GridColumn(0))
                        .attach(GridRow(3))
                        .build(context),
                )
                .child(
                    CheckBox::create()
                        .text("CheckBox")
                        .margin((0.0, 8.0, 0.0, 0.0))
                        .attach(GridColumn(0))
                        .attach(GridRow(4))
                        .build(context),
                )
                .child(
                    Switch::create()
                        .margin((0.0, 8.0, 0.0, 0.0))
                        .attach(GridColumn(0))
                        .attach(GridRow(5))
                        .build(context),
                )
                // Column 2
                .child(create_header(context, "Text", 2, 0))
                .child(
                    TextBlock::create()
                        .selector(SelectorValue::new().class("body"))
                        .text(id)
                        .margin((0.0, 8.0, 0.0, 0.0))
                        .attach(GridColumn(2))
                        .attach(GridRow(1))
                        .build(context),
                )
                .child(
                    TextBox::create()
                        .placeholder("TextBox...")
                        .text("")
                        .margin((0.0, 8.0, 0.0, 0.0))
                        .attach(GridColumn(2))
                        .attach(GridRow(2))
                        .build(context),
                )
                // Column 4
                .child(create_header(context, "Items", 4, 0))
                .child(
                    ItemsWidget::create()
                        .max_height(192.0)
                        .margin((0.0, 8.0, 0.0, 0.0))
                        .items_builder(move |bc, index| {
                            Button::create()
                                .text(list_state.list[index].as_str())
                                .build(bc)
                        })
                        .items_count(4)
                        .attach(GridColumn(4))
                        .attach(GridRow(1))
                        .attach(RowSpan(5))
                        .build(context),
                )
                .build(context),
        )
    }
}

fn main() {
    // use this only if you want to run it as web application.
    orbtk::initialize();

    Application::new()
        .window(|ctx| {
            Window::create()
                .title("OrbTk - widgets example")
                .position((100.0, 100.0))
                .size(468.0, 730.0)
                .resizeable(true)
                .child(MainView::create().build(ctx))
                .build(ctx)
        })
        .run();
}
<commit_msg>Widget exampel update.<commit_after>use std::cell::Cell;

use orbtk::prelude::*;

pub struct MainViewState {
    counter: Cell<i32>,
    list: Vec<String>,
}

impl Default for MainViewState {
    fn default() -> Self {
        MainViewState {
            counter: Cell::new(0),
            list: vec![
                "Item 1".to_string(),
                "Item 2".to_string(),
                "Item 3".to_string(),
                "Last Item".to_string(),
                "Last Item".to_string(),
                "Last Item".to_string(),
            ],
        }
    }
}

impl MainViewState {
    fn increment(&self) {
        self.counter.set(self.counter.get() + 1)
    }
}

impl State for MainViewState {
    fn update(&self, context: &mut Context<'_>) {
        if let Some(button_count_text) = context.widget().try_get_mut::<Text>() {
            button_count_text.0 = String16::from(format!("Button count: {}", self.counter.get()));
        }
    }
}

fn create_header(context: &mut BuildContext, text: &str, grid: usize, column: usize) -> Entity {
    TextBlock::create()
        .text(text)
        .selector(SelectorValue::new().with("text-block").class("h1"))
        .attach(GridColumn(grid))
        .attach(GridRow(column))
        .build(context)
}

widget!(
    MainView<MainViewState> {
        count_text: Text
    }
);

impl Template for MainView {
    fn template(self, id: Entity, context: &mut BuildContext) -> Self {
        let state = self.clone_state();
        let list_state = self.clone_state();
        let list_count = list_state.list.len();

        self.name("MainView").count_text("Button count: 0").child(
            Grid::create()
                .margin(8.0)
                .columns(
                    Columns::create()
                        .column("Auto")
                        .column(16.0)
                        .column("Auto")
                        .column(16.0)
                        .column("Auto")
                        .build(),
                )
                .child(
                    Stack::create()
                        .attach(GridColumn(0))

                        // Column 0
                        .child(create_header(context, "Button", 0, 0))
                        .child(
                            Button::create()
                                .text("Button")
                                .margin((0.0, 8.0, 0.0, 0.0))
                                .icon(material_font_icons::CHECK_FONT_ICON)
                                .attach(GridColumn(0))
                                .attach(GridRow(1))
                                .on_click(move |_| {
                                    state.increment();
                                    true
                                })
                                .build(context),
                        )
                        .child(
                            Button::create()
                                .text("Primary")
                                .selector(SelectorValue::new().with("button").class("primary"))
                                .margin((0.0, 8.0, 0.0, 0.0))
                                .icon(material_font_icons::CHECK_FONT_ICON)
                                .attach(GridColumn(0))
                                .attach(GridRow(2))
                                .build(context),
                        )
                        .child(
                            ToggleButton::create()
                                .text("ToggleButton")
                                .margin((0.0, 8.0, 0.0, 0.0))
                                .attach(GridColumn(0))
                                .attach(GridRow(3))
                                .build(context),
                        )
                        .child(
                            CheckBox::create()
                                .text("CheckBox")
                                .margin((0.0, 8.0, 0.0, 0.0))
                                .attach(GridColumn(0))
                                .attach(GridRow(4))
                                .build(context),
                        )
                        .child(
                            Switch::create()
                                .margin((0.0, 8.0, 0.0, 0.0))
                                .attach(GridColumn(0))
                                .attach(GridRow(5))
                                .build(context),
                        )

                        .build(context),
                )
                .child(
                    Stack::create()
                    .attach(GridColumn(2))
                        .child(create_header(context, "Text", 2, 0))
                        .child(
                            TextBlock::create()
                                .selector(SelectorValue::new().class("body"))
                                .text(id)
                                .margin((0.0, 8.0, 0.0, 0.0))
                                .attach(GridColumn(2))
                                .attach(GridRow(1))
                                .build(context),
                        )
                        .child(
                            TextBox::create()
                                .placeholder("TextBox...")
                                .text("")
                                .margin((0.0, 8.0, 0.0, 0.0))
                                .attach(GridColumn(2))
                                .attach(GridRow(2))
                                .build(context),
                        ).build(context)
                )
                .child(
                    Grid::create()
                        .rows(Rows::create().row("Auto").row("*").build())
                        .attach(GridColumn(4))
                        .child(create_header(context, "Items", 0, 0))
                        .child(
                            ItemsWidget::create()
                                .attach(GridRow(1))
                                .vertical_alignment("Start")
                                .margin((0.0, 8.0, 0.0, 0.0))
                                .items_builder(move |bc, index| {
                                    Button::create()
                                        .text(list_state.list[index].as_str())
                                        .build(bc)
                                })
                                .items_count(list_count)
                                .build(context),
                        )
                        .build(context),
                )
                .build(context),
        )
    }
}

fn main() {
    // use this only if you want to run it as web application.
    orbtk::initialize();

    Application::new()
        .window(|ctx| {
            Window::create()
                .title("OrbTk - widgets example")
                .position((100.0, 100.0))
                .size(468.0, 730.0)
                .resizeable(true)
                .child(MainView::create().build(ctx))
                .build(ctx)
        })
        .run();
}
<|endoftext|>


<commit_before>use std::io::Read;

use itertools::Itertools;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::combinator::map;
use nom::multi::many0;
use nom::sequence::preceded;
use nom::sequence::separated_pair;
use nom::sequence::terminated;
use nom::IResult;

use crate::common::read_input;

type Coords = (u16, u16);

#[derive(Copy, Clone)]
enum Fold {
    X(u16),
    Y(u16),
}

fn parse_input(input: &[u8]) -> IResult<&[u8], (Vec<Coords>, Vec<Fold>)> {
    use nom::character::complete::char;

    let parse_coordinates = many0(terminated(parse_coordinate, char('\n')));
    let parse_folds = many0(terminated(parse_fold, char('\n')));

    separated_pair(parse_coordinates, char('\n'), parse_folds)(input)
}

fn parse_coordinate(input: &[u8]) -> IResult<&[u8], Coords> {
    use nom::character::complete::char;
    use nom::character::complete::u16;

    separated_pair(u16, char(','), u16)(input)
}

fn parse_fold(input: &[u8]) -> IResult<&[u8], Fold> {
    use nom::character::complete::u16;

    preceded(
        tag("fold along "),
        alt((
            preceded(tag("x="), map(u16, Fold::X)),
            preceded(tag("y="), map(u16, Fold::Y)),
        )),
    )(input)
}

fn apply_fold(dots: &mut Vec<Coords>, fold: Fold) {
    match fold {
        Fold::X(coord) => dots.iter_mut().for_each(|(x, _)| {
            if *x >= coord {
                *x = 2 * coord - *x;
            }
        }),
        Fold::Y(coord) => dots.iter_mut().for_each(|(_, y)| {
            if *y >= coord {
                *y = 2 * coord - *y;
            }
        }),
    }
}

fn print_dots(dots: &[Coords]) -> String {
    let (width, height) = dots.iter().fold((0, 0), |(xc, yc), &(xn, yn)| {
        (xc.max(xn as usize + 1), yc.max(yn as usize + 1))
    });

    let mut buffer = vec![b' '; (width + 1) * height - 1];

    for &(x, y) in dots {
        buffer[x as usize + (width + 1) * y as usize] = b'#';
    }

    for line in buffer.chunks_exact_mut(width + 1) {
        line[width] = b'\n';
    }

    String::from_utf8(buffer).unwrap()
}

pub fn part1(input: &mut dyn Read) -> String {
    let (mut dots, folds) = read_input(input, parse_input);

    apply_fold(&mut dots, folds[0]);

    dots.sort_unstable();

    dots.into_iter().unique().count().to_string()
}

pub fn part2(input: &mut dyn Read) -> String {
    let (mut dots, folds) = read_input(input, parse_input);

    folds
        .into_iter()
        .for_each(|fold| apply_fold(&mut dots, fold));

    print_dots(&dots)
}

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

    use crate::test_implementation;

    const SAMPLE: &[u8] = include_bytes!("samples/13.txt");

    #[test]
    fn sample_part() {
        test_implementation(part1, SAMPLE, 17);
    }
}
<commit_msg>Replace unnecessary Vec with slice<commit_after>use std::io::Read;

use itertools::Itertools;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::combinator::map;
use nom::multi::many0;
use nom::sequence::preceded;
use nom::sequence::separated_pair;
use nom::sequence::terminated;
use nom::IResult;

use crate::common::read_input;

type Coords = (u16, u16);

#[derive(Copy, Clone)]
enum Fold {
    X(u16),
    Y(u16),
}

fn parse_input(input: &[u8]) -> IResult<&[u8], (Vec<Coords>, Vec<Fold>)> {
    use nom::character::complete::char;

    let parse_coordinates = many0(terminated(parse_coordinate, char('\n')));
    let parse_folds = many0(terminated(parse_fold, char('\n')));

    separated_pair(parse_coordinates, char('\n'), parse_folds)(input)
}

fn parse_coordinate(input: &[u8]) -> IResult<&[u8], Coords> {
    use nom::character::complete::char;
    use nom::character::complete::u16;

    separated_pair(u16, char(','), u16)(input)
}

fn parse_fold(input: &[u8]) -> IResult<&[u8], Fold> {
    use nom::character::complete::u16;

    preceded(
        tag("fold along "),
        alt((
            preceded(tag("x="), map(u16, Fold::X)),
            preceded(tag("y="), map(u16, Fold::Y)),
        )),
    )(input)
}

fn apply_fold(dots: &mut [Coords], fold: Fold) {
    match fold {
        Fold::X(coord) => dots.iter_mut().for_each(|(x, _)| {
            if *x >= coord {
                *x = 2 * coord - *x;
            }
        }),
        Fold::Y(coord) => dots.iter_mut().for_each(|(_, y)| {
            if *y >= coord {
                *y = 2 * coord - *y;
            }
        }),
    }
}

fn print_dots(dots: &[Coords]) -> String {
    let (width, height) = dots.iter().fold((0, 0), |(xc, yc), &(xn, yn)| {
        (xc.max(xn as usize + 1), yc.max(yn as usize + 1))
    });

    let mut buffer = vec![b' '; (width + 1) * height - 1];

    for &(x, y) in dots {
        buffer[x as usize + (width + 1) * y as usize] = b'#';
    }

    for line in buffer.chunks_exact_mut(width + 1) {
        line[width] = b'\n';
    }

    String::from_utf8(buffer).unwrap()
}

pub fn part1(input: &mut dyn Read) -> String {
    let (mut dots, folds) = read_input(input, parse_input);

    apply_fold(&mut dots, folds[0]);

    dots.sort_unstable();

    dots.into_iter().unique().count().to_string()
}

pub fn part2(input: &mut dyn Read) -> String {
    let (mut dots, folds) = read_input(input, parse_input);

    folds
        .into_iter()
        .for_each(|fold| apply_fold(&mut dots, fold));

    print_dots(&dots)
}

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

    use crate::test_implementation;

    const SAMPLE: &[u8] = include_bytes!("samples/13.txt");

    #[test]
    fn sample_part() {
        test_implementation(part1, SAMPLE, 17);
    }
}
<|endoftext|>