<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `Default` trait for types which may have meaningful default values

#![stable]

/// A trait that types which have a useful default value should implement.
pub trait Default {
    /// Return the "default value" for a type.
    ///
    /// # Example
    ///
    /// ```
    /// use std::default::Default;
    ///
    /// let i: i8 = Default::default();
    /// let (x, y): (Option<String>, f64) = Default::default();
    /// let (a, b, (c, d)): (int, uint, (bool, bool)) = Default::default();
    /// ```
    fn default() -> Self;
}

macro_rules! default_impl(
    ($t:ty, $v:expr) => {
        impl Default for $t {
            #[inline]
            fn default() -> $t { $v }
        }
    }
)

default_impl!((), ())
default_impl!(bool, false)
default_impl!(char, '\x00')

default_impl!(uint, 0u)
default_impl!(u8,  0u8)
default_impl!(u16, 0u16)
default_impl!(u32, 0u32)
default_impl!(u64, 0u64)

default_impl!(int, 0i)
default_impl!(i8,  0i8)
default_impl!(i16, 0i16)
default_impl!(i32, 0i32)
default_impl!(i64, 0i64)

default_impl!(f32, 0.0f32)
default_impl!(f64, 0.0f64)
<commit_msg>auto merge of #17455 : steveklabnik/rust/document_default, r=alexcrichton<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `Default` trait for types which may have meaningful default values.
//!
//! Sometimes, you want to fall back to some kind of default value, and
//! don't particularly care what it is. This comes up often with `struct`s
//! that define a set of options:
//!
//! ```
//! struct SomeOptions {
//!     foo: int,
//!     bar: f32,
//! }
//! ```
//!
//! How can we define some default values? You can use `Default`:
//!
//! ```
//! use std::default::Default;
//!
//! #[deriving(Default)]
//! struct SomeOptions {
//!     foo: int,
//!     bar: f32,
//! }
//!
//!
//! fn main() {
//!     let options: SomeOptions = Default::default();
//! }
//! ```
//!
//! Now, you get all of the default values. Rust implements `Default` for various primitives types.
//! If you have your own type, you need to implement `Default` yourself:
//!
//! ```
//! use std::default::Default;
//!
//! enum Kind {
//!     A,
//!     B,
//!     C,
//! }
//!
//! impl Default for Kind {
//!     fn default() -> Kind { A }
//! }
//!
//! #[deriving(Default)]
//! struct SomeOptions {
//!     foo: int,
//!     bar: f32,
//!     baz: Kind,
//! }
//!
//!
//! fn main() {
//!     let options: SomeOptions = Default::default();
//! }
//! ```
//!
//! If you want to override a particular option, but still retain the other defaults:
//!
//! ```
//! # use std::default::Default;
//! # #[deriving(Default)]
//! # struct SomeOptions {
//! #     foo: int,
//! #     bar: f32,
//! # }
//! fn main() {
//!     let options = SomeOptions { foo: 42, ..Default::default() };
//! }
//! ```

#![stable]

/// A trait that types which have a useful default value should implement.
///
/// A struct can derive default implementations of `Default` for basic types using
/// `#[deriving(Default)]`.
///
/// # Examples
///
/// ```
/// #[deriving(Default)]
/// struct SomeOptions {
///     foo: int,
///     bar: f32,
/// }
/// ```
pub trait Default {
    /// Returns the "default value" for a type.
    ///
    /// Default values are often some kind of initial value, identity value, or anything else that
    /// may make sense as a default.
    ///
    /// # Examples
    ///
    /// Using built-in default values:
    ///
    /// ```
    /// use std::default::Default;
    ///
    /// let i: i8 = Default::default();
    /// let (x, y): (Option<String>, f64) = Default::default();
    /// let (a, b, (c, d)): (int, uint, (bool, bool)) = Default::default();
    /// ```
    ///
    /// Making your own:
    ///
    /// ```
    /// use std::default::Default;
    ///
    /// enum Kind {
    ///     A,
    ///     B,
    ///     C,
    /// }
    ///
    /// impl Default for Kind {
    ///     fn default() -> Kind { A }
    /// }
    /// ```
    fn default() -> Self;
}

macro_rules! default_impl(
    ($t:ty, $v:expr) => {
        impl Default for $t {
            #[inline]
            fn default() -> $t { $v }
        }
    }
)

default_impl!((), ())
default_impl!(bool, false)
default_impl!(char, '\x00')

default_impl!(uint, 0u)
default_impl!(u8,  0u8)
default_impl!(u16, 0u16)
default_impl!(u32, 0u32)
default_impl!(u64, 0u64)

default_impl!(int, 0i)
default_impl!(i8,  0i8)
default_impl!(i16, 0i16)
default_impl!(i32, 0i32)
default_impl!(i64, 0i64)

default_impl!(f32, 0.0f32)
default_impl!(f64, 0.0f64)
<|endoftext|>


<commit_before>/*
 * Copyright 2019 Sanguk Park
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use core::fmt;

use crate::arch::*;
use crate::types::*;

// TODO: Refactor type names and remove this.
#[allow(non_camel_case_types)]
// TODO: Some codes (mm.rs, mpool.rs, page.rs and etc.) treats memory address
// with primitive types (usually usize.) Refactor them to use `*addr_t` types.

/// An opaque type for a physical address.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct paddr_t {
    pa: uintpaddr_t,
}

/// An opaque type for an intermediate physical address.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ipaddr_t {
    ipa: uintpaddr_t,
}

/// An opaque type for a virtual address.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct vaddr_t {
    va: uintvaddr_t,
}

impl fmt::Display for paddr_t {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:x}", self.pa)
    }
}

impl fmt::Display for ipaddr_t {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:x}", self.ipa)
    }
}

impl fmt::Display for vaddr_t {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:x}", self.va)
    }
}

// TODO: Move following functions into resepective types, in Rust-idiomatic way.

/// Initializes a physical address.
#[inline]
pub fn pa_init(p: uintpaddr_t) -> paddr_t {
    paddr_t { pa: p }
}

/// Extracts the absolute physical address.
#[inline]
pub fn pa_addr(pa: paddr_t) -> uintpaddr_t {
    pa.pa
}

/// Advances a physical address.
#[inline]
pub fn pa_add(pa: paddr_t, n: size_t) -> paddr_t {
    pa_init(pa_addr(pa) + n)
}

/// Returns the difference between two physical addresses.
#[inline]
pub fn pa_difference(start: paddr_t, end: paddr_t) -> size_t {
    pa_addr(end) - pa_addr(start)
}

/// Initializes an intermediate physical address.
#[inline]
pub fn ipa_init(ipa: uintpaddr_t) -> ipaddr_t {
    ipaddr_t { ipa: ipa }
}

/// Extracts the absolute intermediate physical address.
#[inline]
pub fn ipa_addr(ipa: ipaddr_t) -> uintpaddr_t {
    ipa.ipa
}

/// Advances an intermediate physical address.
#[inline]
pub fn ipa_add(ipa: ipaddr_t, n: size_t) -> ipaddr_t {
    ipa_init(ipa_addr(ipa) + n)
}

/// Initializes a virtual address.
#[inline]
pub fn va_init(v: uintvaddr_t) -> vaddr_t {
    vaddr_t { va: v }
}

/// Extracts the absolute virtual address.
#[inline]
pub fn va_addr(va: vaddr_t) -> uintvaddr_t {
    va.va
}

/// Casts a physical address to a virtual address.
#[inline]
pub fn va_from_pa(pa: paddr_t) -> vaddr_t {
    va_init(pa_addr(pa))
}

/// Casts a physical address to an intermediate physical address.
#[inline]
pub fn ipa_from_pa(pa: paddr_t) -> ipaddr_t {
    ipa_init(pa_addr(pa))
}

/// Casts a virtual address to a physical address.
#[inline]
pub fn pa_from_va(va: vaddr_t) -> paddr_t {
    pa_init(va_addr(va))
}

/// Casts an intermediate physical address to a physical address.
#[inline]
pub fn pa_from_ipa(ipa: ipaddr_t) -> paddr_t {
    pa_init(ipa_addr(ipa))
}

/// Casts a pointer to a virtual address.
#[inline]
pub fn va_from_ptr(p: *const c_void) -> vaddr_t {
    vaddr_t {
        va: p as uintvaddr_t,
    }
}

/// Casts a virtual address to a pointer. Only use when the virtual address is
/// mapped for the calling context.
/// TODO: check the mapping for a range and return a memiter?
#[inline]
pub fn ptr_from_va(va: vaddr_t) -> *mut c_void {
    va_addr(va) as *mut c_void
}
<commit_msg>Typo on space<commit_after>/*
 * Copyright 2019 Sanguk Park
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use core::fmt;

use crate::arch::*;
use crate::types::*;

// TODO: Refactor type names and remove this.
#[allow(non_camel_case_types)]

// TODO: Some codes (mm.rs, mpool.rs, page.rs and etc.) treats memory address
// with primitive types (usually usize.) Refactor them to use `*addr_t` types.

/// An opaque type for a physical address.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct paddr_t {
    pa: uintpaddr_t,
}

/// An opaque type for an intermediate physical address.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ipaddr_t {
    ipa: uintpaddr_t,
}

/// An opaque type for a virtual address.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct vaddr_t {
    va: uintvaddr_t,
}

impl fmt::Display for paddr_t {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:x}", self.pa)
    }
}

impl fmt::Display for ipaddr_t {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:x}", self.ipa)
    }
}

impl fmt::Display for vaddr_t {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:x}", self.va)
    }
}

// TODO: Move following functions into resepective types, in Rust-idiomatic way.

/// Initializes a physical address.
#[inline]
pub fn pa_init(p: uintpaddr_t) -> paddr_t {
    paddr_t { pa: p }
}

/// Extracts the absolute physical address.
#[inline]
pub fn pa_addr(pa: paddr_t) -> uintpaddr_t {
    pa.pa
}

/// Advances a physical address.
#[inline]
pub fn pa_add(pa: paddr_t, n: size_t) -> paddr_t {
    pa_init(pa_addr(pa) + n)
}

/// Returns the difference between two physical addresses.
#[inline]
pub fn pa_difference(start: paddr_t, end: paddr_t) -> size_t {
    pa_addr(end) - pa_addr(start)
}

/// Initializes an intermediate physical address.
#[inline]
pub fn ipa_init(ipa: uintpaddr_t) -> ipaddr_t {
    ipaddr_t { ipa: ipa }
}

/// Extracts the absolute intermediate physical address.
#[inline]
pub fn ipa_addr(ipa: ipaddr_t) -> uintpaddr_t {
    ipa.ipa
}

/// Advances an intermediate physical address.
#[inline]
pub fn ipa_add(ipa: ipaddr_t, n: size_t) -> ipaddr_t {
    ipa_init(ipa_addr(ipa) + n)
}

/// Initializes a virtual address.
#[inline]
pub fn va_init(v: uintvaddr_t) -> vaddr_t {
    vaddr_t { va: v }
}

/// Extracts the absolute virtual address.
#[inline]
pub fn va_addr(va: vaddr_t) -> uintvaddr_t {
    va.va
}

/// Casts a physical address to a virtual address.
#[inline]
pub fn va_from_pa(pa: paddr_t) -> vaddr_t {
    va_init(pa_addr(pa))
}

/// Casts a physical address to an intermediate physical address.
#[inline]
pub fn ipa_from_pa(pa: paddr_t) -> ipaddr_t {
    ipa_init(pa_addr(pa))
}

/// Casts a virtual address to a physical address.
#[inline]
pub fn pa_from_va(va: vaddr_t) -> paddr_t {
    pa_init(va_addr(va))
}

/// Casts an intermediate physical address to a physical address.
#[inline]
pub fn pa_from_ipa(ipa: ipaddr_t) -> paddr_t {
    pa_init(ipa_addr(ipa))
}

/// Casts a pointer to a virtual address.
#[inline]
pub fn va_from_ptr(p: *const c_void) -> vaddr_t {
    vaddr_t {
        va: p as uintvaddr_t,
    }
}

/// Casts a virtual address to a pointer. Only use when the virtual address is
/// mapped for the calling context.
/// TODO: check the mapping for a range and return a memiter?
#[inline]
pub fn ptr_from_va(va: vaddr_t) -> *mut c_void {
    va_addr(va) as *mut c_void
}
<|endoftext|>


<commit_before>use crate::io::DecodeError;

pub enum VisitError<E> {
    LazyDecode(DecodeError),
    Custom(E),
}

impl<E: std::fmt::Display> std::fmt::Display for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::fmt::Debug> std::fmt::Debug for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::error::Error> std::error::Error for VisitError<E> {}

#[cfg(feature = "nightly")]
pub type NeverError = !;

#[cfg(not(feature = "nightly"))]
#[allow(clippy::empty_enum)]
pub enum NeverError {}

impl From<VisitError<NeverError>> for DecodeError {
    fn from(err: VisitError<NeverError>) -> Self {
        match err {
            VisitError::Custom(err) => match err {},
            VisitError::LazyDecode(err) => err,
        }
    }
}

pub trait VisitResult {
    type Error;

    fn as_result(self) -> Result<(), Self::Error>;
}

impl VisitResult for () {
    type Error = NeverError;

    fn as_result(self) -> Result<(), Self::Error> {
        Ok(())
    }
}

impl VisitResult for bool {
    type Error = ();

    fn as_result(self) -> Result<(), Self::Error> {
        match self {
            true => Ok(()),
            false => Err(()),
        }
    }
}

impl<E> VisitResult for Result<(), E> {
    type Error = E;

    fn as_result(self) -> Result<(), Self::Error> {
        self
    }
}

pub use wasmbin_derive::Visit;
pub trait Visit: 'static + Sized {
    fn visit<'a, T: 'static, R: VisitResult, F: FnMut(&'a T) -> R>(
        &'a self,
        mut f: F,
    ) -> Result<(), VisitError<R::Error>> {
        self.visit_child(&mut move |item| f(item).as_result())
    }

    fn visit_mut<T: 'static, R: VisitResult, F: FnMut(&mut T) -> R>(
        &mut self,
        mut f: F,
    ) -> Result<(), VisitError<R::Error>> {
        self.visit_child_mut(&mut move |item| f(item).as_result())
    }

    fn visit_child<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        if let Some(v) = std::any::Any::downcast_ref(self) {
            f(v).map_err(VisitError::Custom)?;
        }
        self.visit_children(f)
    }

    fn visit_child_mut<T: 'static, E, F: FnMut(&mut T) -> Result<(), E>>(
        &mut self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        if let Some(v) = std::any::Any::downcast_mut(self) {
            f(v).map_err(VisitError::Custom)?;
        }
        self.visit_children_mut(f)
    }

    fn visit_children<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }

    fn visit_children_mut<T: 'static, E, F: FnMut(&mut T) -> Result<(), E>>(
        &mut self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }
}
<commit_msg>Add Debug for NeverError<commit_after>use crate::io::DecodeError;

pub enum VisitError<E> {
    LazyDecode(DecodeError),
    Custom(E),
}

impl<E: std::fmt::Display> std::fmt::Display for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::fmt::Debug> std::fmt::Debug for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::error::Error> std::error::Error for VisitError<E> {}

#[cfg(feature = "nightly")]
pub type NeverError = !;

#[cfg(not(feature = "nightly"))]
#[allow(clippy::empty_enum)]
#[derive(Debug)]
pub enum NeverError {}

impl From<VisitError<NeverError>> for DecodeError {
    fn from(err: VisitError<NeverError>) -> Self {
        match err {
            VisitError::Custom(err) => match err {},
            VisitError::LazyDecode(err) => err,
        }
    }
}

pub trait VisitResult {
    type Error;

    fn as_result(self) -> Result<(), Self::Error>;
}

impl VisitResult for () {
    type Error = NeverError;

    fn as_result(self) -> Result<(), Self::Error> {
        Ok(())
    }
}

impl VisitResult for bool {
    type Error = ();

    fn as_result(self) -> Result<(), Self::Error> {
        match self {
            true => Ok(()),
            false => Err(()),
        }
    }
}

impl<E> VisitResult for Result<(), E> {
    type Error = E;

    fn as_result(self) -> Result<(), Self::Error> {
        self
    }
}

pub use wasmbin_derive::Visit;
pub trait Visit: 'static + Sized {
    fn visit<'a, T: 'static, R: VisitResult, F: FnMut(&'a T) -> R>(
        &'a self,
        mut f: F,
    ) -> Result<(), VisitError<R::Error>> {
        self.visit_child(&mut move |item| f(item).as_result())
    }

    fn visit_mut<T: 'static, R: VisitResult, F: FnMut(&mut T) -> R>(
        &mut self,
        mut f: F,
    ) -> Result<(), VisitError<R::Error>> {
        self.visit_child_mut(&mut move |item| f(item).as_result())
    }

    fn visit_child<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        if let Some(v) = std::any::Any::downcast_ref(self) {
            f(v).map_err(VisitError::Custom)?;
        }
        self.visit_children(f)
    }

    fn visit_child_mut<T: 'static, E, F: FnMut(&mut T) -> Result<(), E>>(
        &mut self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        if let Some(v) = std::any::Any::downcast_mut(self) {
            f(v).map_err(VisitError::Custom)?;
        }
        self.visit_children_mut(f)
    }

    fn visit_children<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }

    fn visit_children_mut<T: 'static, E, F: FnMut(&mut T) -> Result<(), E>>(
        &mut self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Encode binary data into human-readable random words.
use self::Decode::{V, C};

static VS: [char; 5] = ['a', 'e', 'i', 'o', 'u'];
static CS: [char; 14] = ['b', 'd', 'f', 'g', 'j', 'k', 'm', 'n', 'p', 'r', 's', 't', 'v', 'z'];

#[derive(Copy, Clone)]
enum Decode {
    V(u16),
    C(u16),
}

static LUT: [Option<Decode>; 26] = [Some(V(0)), // a (ASCII 97)
                                    Some(C(0)), // b
                                    None, // c
                                    Some(C(1)), // d
                                    Some(V(1)), // e
                                    Some(C(2)), // f
                                    Some(C(3)), // g
                                    None, // h
                                    Some(V(2)), // i
                                    Some(C(4)), // j
                                    Some(C(5)), // k
                                    None, // l
                                    Some(C(6)), // m
                                    Some(C(7)), // n
                                    Some(V(3)), // o
                                    Some(C(8)), // p
                                    None, // q
                                    Some(C(9)), // r
                                    Some(C(10)), // s
                                    Some(C(11)), // t
                                    Some(V(4)), // u
                                    Some(C(12)), // v
                                    None, // w
                                    None, // x
                                    None, // y
                                    Some(C(13)) /* z */];

fn vorud_chunk(data: u16) -> String {
    let (data, c5) = (data / CS.len() as u16, data % CS.len() as u16);
    let (data, v4) = (data / VS.len() as u16, data % VS.len() as u16);
    let (data, c3) = (data / CS.len() as u16, data % CS.len() as u16);
    let (data, v2) = (data / VS.len() as u16, data % VS.len() as u16);
    let (_, c1) = (data / CS.len() as u16, data % CS.len() as u16);
    [CS[c1 as usize], VS[v2 as usize], CS[c3 as usize], VS[v4 as usize], CS[c5 as usize]]
        .iter()
        .map(|&x| x)
        .collect()
}

fn decode(c: char) -> Option<Decode> {
    let idx = c as isize - 97;
    if idx < 0 || idx >= LUT.len() as isize {
        return None;
    }
    LUT[idx as usize]
}

fn v(c: char) -> Result<u16, ()> {
    match decode(c) {
        Some(V(i)) => Ok(i),
        _ => Err(()),
    }
}

fn c(c: char) -> Result<u16, ()> {
    match decode(c) {
        Some(C(i)) => Ok(i),
        _ => Err(()),
    }
}

fn durov_chunk(s: &str) -> Result<u16, ()> {
    if s.len() != 5 {
        return Err(());
    }
    let s: Vec<char> = s.chars().collect();
    let (mut ret, mut n) = (0u16, 1u16);
    ret += try!(c(s[4])) * n;
    n *= CS.len() as u16;
    ret += try!(v(s[3])) * n;
    n *= VS.len() as u16;
    ret += try!(c(s[2])) * n;
    n *= CS.len() as u16;
    ret += try!(v(s[1])) * n;
    n *= VS.len() as u16;
    ret += try!(c(s[0])) * n;

    Ok(ret)
}

/// A vorud string.
#[derive(PartialEq, Eq, Debug)]
pub struct Vorud(String);

impl Vorud {
    pub fn new(s: String) -> Result<Vorud, ()> {
        if s.len() == 0 {
            return Ok(Vorud("".to_string()));
        }
        let ch = &s[..].chars().collect::<Vec<char>>();
        let mut i = 0;
        loop {
            if i > ch.len() - 5 {
                return Err(());
            }
            try!(c(ch[i]));
            try!(v(ch[i + 1]));
            try!(c(ch[i + 2]));
            try!(v(ch[i + 3]));
            try!(c(ch[i + 4]));
            if i == ch.len() - 5 {
                return Ok(Vorud(s));
            }
            if ch[i + 5] != '-' {
                return Err(());
            }
            i += 6;
        }
    }
}

/// Convert vorud into data.
pub trait FromVorud<E>: Sized {
    fn from_vorud(v: &Vorud) -> Result<Self, E>;
}

/// Convert data into vorud.
pub trait ToVorud {
    fn to_vorud(&self) -> Vorud;
}

impl<'a> ToVorud for &'a [u8] {
    fn to_vorud(&self) -> Vorud {
        let mut ret = String::new();
        for i in 0..(self.len() / 2) {
            if ret.len() > 0 {
                ret.push_str("-");
            }
            let b0 = self[i * 2] as u16;
            let b1 = if self.len() == i * 2 + 1 {
                0
            } else {
                self[i * 2 + 1] as u16
            };
            ret.push_str(&vorud_chunk(b1 + (b0 << 8))[..]);
        }
        Vorud(ret)
    }
}

impl FromVorud<()> for Vec<u8> {
    fn from_vorud(&Vorud(ref s): &Vorud) -> Result<Vec<u8>, ()> {
        let mut ret = Vec::new();
        for chunk in (&s[..]).split('-') {
            let x = try!(durov_chunk(chunk));
            ret.push((x / 0xff) as u8);
            ret.push((x % 0xff) as u8);
        }
        Ok(ret)
    }
}

impl ToVorud for u32 {
    fn to_vorud(&self) -> Vorud {
        let mut vec = Vec::new();
        vec.push(((*self >> 24) % 0xff) as u8);
        vec.push(((*self >> 16) % 0xff) as u8);
        vec.push(((*self >> 8) % 0xff) as u8);
        vec.push((*self % 0xff) as u8);
        (&vec[..]).to_vorud()
    }
}

impl FromVorud<()> for u32 {
    fn from_vorud(v: &Vorud) -> Result<u32, ()> {
        let v: Vec<u8> = try!(FromVorud::from_vorud(v));
        if v.len() != 4 {
            return Err(());
        }
        Ok(v[3] as u32 + ((v[2] as u32) << 8) + ((v[1] as u32) << 16) + ((v[0] as u32) << 24))
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_vorud() {
        use super::ToVorud;

        assert_eq!("babab", &super::vorud_chunk(0)[..]);
        assert_eq!("babad", &super::vorud_chunk(1)[..]);
        assert_eq!(Ok(0u16), super::durov_chunk("babab"));
        assert_eq!(Ok(1234u16),
                   super::durov_chunk(&super::vorud_chunk(1234)[..]));
        assert_eq!("togas",
                   &super::vorud_chunk(super::durov_chunk("togas").unwrap())[..]);
        assert_eq!(super::Vorud("babab-babab".to_string()), 0u32.to_vorud());
        assert_eq!(super::Vorud("babab-babad".to_string()), 1u32.to_vorud());
        assert_eq!(Ok(1u32),
                   super::FromVorud::from_vorud(&super::Vorud("babab-babad".to_string())));
    }
}
<commit_msg>Remove vorud, just use any string and take a hash for game seed<commit_after><|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use basicblock::BasicBlock;
use instruction::Instruction;
use symbol::Symbol;

/// A function within a program.
#[derive(Debug)]
pub struct Function<'f> {
    /// The [symbol] for this function. This provides the name and `Address`.
    ///
    /// [symbol]: struct.Symbol.html
    pub symbol: Symbol,
    /// The instructions that comprise this function.
    pub instructions: Vec<Box<Instruction>>,
    /// The basic blocks that comprise this function. These are algorithmically
    /// determined from the `instructions` via `fn build_basic_blocks`.
    ///
    /// The `basic_blocks` of a `Function` make up a [control flow graph].
    ///
    /// [control flow graph]: https://en.wikipedia.org/wiki/Control_flow_graph
    pub basic_blocks: Vec<BasicBlock<'f>>,
}

impl<'f> Function<'f> {
    /// Build the actual basic blocks for this function.
    ///
    /// This usually happens during construction of the `Function`.
    pub fn build_basic_blocks(&'f mut self) {
        // For now, let's just put all instructions into a single basic
        // block. In the future, we'll implement this correctly.
        let mut bb = BasicBlock::new(self.basic_blocks.len(), "anonymous");
        for inst in &self.instructions {
            bb.instructions.push(inst);
        }
        self.basic_blocks.push(bb);
    }
}
<commit_msg>Add Function.entry_block, improve docs.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use basicblock::BasicBlock;
use instruction::Instruction;
use symbol::Symbol;

/// A function within a program.
#[derive(Debug)]
pub struct Function<'f> {
    /// The [symbol] for this function. This provides the name and [`Address`].
    ///
    /// [`Address`]: struct.Symbol.html
    /// [symbol]: struct.Symbol.html
    pub symbol: Symbol,
    /// The [instructions] that comprise this function.
    ///
    /// [instructions]: trait.Instruction.html
    pub instructions: Vec<Box<Instruction>>,
    /// The [basic blocks] that comprise this function. These are algorithmically
    /// determined from the `instructions` via `fn build_basic_blocks`.
    ///
    /// The `basic_blocks` of a `Function` make up a [control flow graph].
    ///
    /// [basic blocks]: struct.BasicBlock.html
    /// [control flow graph]: https://en.wikipedia.org/wiki/Control_flow_graph
    pub basic_blocks: Vec<BasicBlock<'f>>,
    /// The entry [`BasicBlock`] for this function.
    ///
    /// [`BasicBlock`]: struct.BasicBlock.html
    pub entry_block: Option<&'f BasicBlock<'f>>,
}

impl<'f> Function<'f> {
    /// Build the actual basic blocks for this function.
    ///
    /// This usually happens during construction of the `Function`.
    pub fn build_basic_blocks(&'f mut self) {
        // For now, let's just put all instructions into a single basic
        // block. In the future, we'll implement this correctly.
        let mut bb = BasicBlock::new(self.basic_blocks.len(), "anonymous");
        for inst in &self.instructions {
            bb.instructions.push(inst);
        }
        self.basic_blocks.push(bb);
        self.entry_block = Some(&self.basic_blocks[0]);
    }
}
<|endoftext|>


<commit_before>use std::cmp::{min, max};
use std::ops::{Add, Mul, Div, Sub, Neg};
use grid::WIDTH;

#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct Point(pub i32, pub i32);

impl Point {
    pub fn of_byte(index: u8) -> Point {
        Point(index as i32 % WIDTH as i32, index as i32 / WIDTH as i32)
    }
    pub fn as_byte(self) -> u8 {
        let Point(x, y) = self;
        y as u8 * WIDTH as u8 + x as u8
    }
    pub fn cheby_norm(self) -> i32 {
        let Point(x, y) = self;
        max(x.abs(), y.abs())
    }
    pub fn cheby_dist(self, other: Point) -> i32 {
        (self - other).cheby_norm()
    }
    pub fn taxi_norm(self) -> i32 {
        let Point(x, y) = self;
        x.abs() + y.abs()
    }
    pub fn taxi_dist(self, other: Point) -> i32 {
        (self - other).taxi_norm()
    }
    pub fn direction(self) -> Point {
        let Point(x, y) = self;
        Point(x.signum(), y.signum())
    }
    pub fn step_towards(self, other: Point) -> Point {
        self + (other - self).direction()
    }
}

impl Add for Point {
    type Output = Point;
    fn add(self, other: Point) -> Point {
        match (self, other) {
            (Point(x1, y1), Point(x2, y2)) => Point(x1 + x2, y1 + y2)
        }
    }
}

impl Mul<i32> for Point {
    type Output = Point;
    fn mul(self, scale: i32) -> Point {
        match self {
            Point(x, y) => Point(scale * x, scale * y)
        }
    }
}

impl Div<i32> for Point {
    type Output = Point;
    fn div(self, scale: i32) -> Point {
        match self {
            Point(x, y) => Point(x / scale, y / scale)
        }
    }
}

impl Neg for Point {
    type Output = Point;
    fn neg(self) -> Point {
        match self {
            Point(x, y) => Point(-x, -y)
        }
    }
}

impl Sub for Point {
    type Output = Point;
    fn sub(self, other: Point) -> Point {
        self + (-other)
    }
}

#[derive(Clone, Copy)]
pub struct Rectangle(pub Point, pub Point);

impl Rectangle{
    pub fn correct(self) -> Rectangle {
        let Rectangle(Point(x1, y1), Point(x2, y2)) = self;
        Rectangle(
            Point(min(x1, x2), min(y1, y2)),
            Point(max(x1, x2), max(y1, y2)) )
    }

    pub fn point(position: Point) -> Rectangle {
        Rectangle(position, position)
    }

    pub fn grow(self, r: i32) -> Rectangle {
        Rectangle(self.0 - Point(r, r), self.1 + Point(r, r))
    }

    pub fn shrink(self, r: i32) -> Rectangle {
        self.grow(-r)
    }

    pub fn width(self) -> i32 {
        let Rectangle(Point(x1, _), Point(x2, _)) = self;
        x2 - x1 + 1
    }

    pub fn height(self) -> i32 {
        let Rectangle(Point(_, y1), Point(_, y2)) = self;
        y2 - y1 + 1
    }

    pub fn area(self) -> i32 {
        self.width() * self.height()
    }

    pub fn contains(self, position: Point) -> bool {
        let Rectangle(Point(x1, y1), Point(x2, y2)) = self;
        let Point(x, y) = position;
        // TODO: use inclusive range syntax syntax once stable
        x1 <= x && x <= x2 && y1 <= y && y <= y2
    }

    pub fn edges(self) -> Box<Iterator<Item=Point>> {
        if self.width() <= 2 || self.height() <= 2 {
            Box::new(self.into_iter())
        } else {
            let Rectangle(Point(x1, y1), Point(x2, y2)) = self;
            Box::new(Rectangle(Point(x1, y1), Point(x2 - 1, y1)).into_iter()
                .chain(Rectangle(Point(x2, y1), Point(x2, y2 - 1)).into_iter())
                .chain(Rectangle(Point(x1 + 1, y1), Point(x2, y2)).into_iter())
                .chain(Rectangle(Point(x1, y1 + 1), Point(x1, y1)).into_iter()))
        }
    }
}

pub struct RectangleIter {
    start: Point,
    width: i32,
    end_index: i32,
    current_index: i32
}

impl Iterator for RectangleIter {
    type Item = Point;
    fn next(&mut self) -> Option<Point> {
        if self.current_index < self.end_index {
            let current_point = self.start + Point(
                self.current_index % self.width,
                self.current_index / self.width );
            self.current_index += 1;
            Some(current_point)
        } else {
            None
        }
    }
}

impl IntoIterator for Rectangle {
    type Item = Point;
    type IntoIter = RectangleIter;
    fn into_iter(self) -> RectangleIter {
        let Rectangle(start, _) = self;
        RectangleIter {
            start: start,
            width: self.width(),
            end_index: self.area(),
            current_index: 0
        }
    }
}
<commit_msg>remaining length of RectangleIter is always known<commit_after>use std::cmp::{min, max};
use std::ops::{Add, Mul, Div, Sub, Neg};
use grid::WIDTH;

#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct Point(pub i32, pub i32);

impl Point {
    pub fn of_byte(index: u8) -> Point {
        Point(index as i32 % WIDTH as i32, index as i32 / WIDTH as i32)
    }
    pub fn as_byte(self) -> u8 {
        let Point(x, y) = self;
        y as u8 * WIDTH as u8 + x as u8
    }
    pub fn cheby_norm(self) -> i32 {
        let Point(x, y) = self;
        max(x.abs(), y.abs())
    }
    pub fn cheby_dist(self, other: Point) -> i32 {
        (self - other).cheby_norm()
    }
    pub fn taxi_norm(self) -> i32 {
        let Point(x, y) = self;
        x.abs() + y.abs()
    }
    pub fn taxi_dist(self, other: Point) -> i32 {
        (self - other).taxi_norm()
    }
    pub fn direction(self) -> Point {
        let Point(x, y) = self;
        Point(x.signum(), y.signum())
    }
    pub fn step_towards(self, other: Point) -> Point {
        self + (other - self).direction()
    }
}

impl Add for Point {
    type Output = Point;
    fn add(self, other: Point) -> Point {
        match (self, other) {
            (Point(x1, y1), Point(x2, y2)) => Point(x1 + x2, y1 + y2)
        }
    }
}

impl Mul<i32> for Point {
    type Output = Point;
    fn mul(self, scale: i32) -> Point {
        match self {
            Point(x, y) => Point(scale * x, scale * y)
        }
    }
}

impl Div<i32> for Point {
    type Output = Point;
    fn div(self, scale: i32) -> Point {
        match self {
            Point(x, y) => Point(x / scale, y / scale)
        }
    }
}

impl Neg for Point {
    type Output = Point;
    fn neg(self) -> Point {
        match self {
            Point(x, y) => Point(-x, -y)
        }
    }
}

impl Sub for Point {
    type Output = Point;
    fn sub(self, other: Point) -> Point {
        self + (-other)
    }
}

#[derive(Clone, Copy)]
pub struct Rectangle(pub Point, pub Point);

impl Rectangle{
    pub fn correct(self) -> Rectangle {
        let Rectangle(Point(x1, y1), Point(x2, y2)) = self;
        Rectangle(
            Point(min(x1, x2), min(y1, y2)),
            Point(max(x1, x2), max(y1, y2)) )
    }

    pub fn point(position: Point) -> Rectangle {
        Rectangle(position, position)
    }

    pub fn grow(self, r: i32) -> Rectangle {
        Rectangle(self.0 - Point(r, r), self.1 + Point(r, r))
    }

    pub fn shrink(self, r: i32) -> Rectangle {
        self.grow(-r)
    }

    pub fn width(self) -> i32 {
        let Rectangle(Point(x1, _), Point(x2, _)) = self;
        x2 - x1 + 1
    }

    pub fn height(self) -> i32 {
        let Rectangle(Point(_, y1), Point(_, y2)) = self;
        y2 - y1 + 1
    }

    pub fn area(self) -> i32 {
        self.width() * self.height()
    }

    pub fn contains(self, position: Point) -> bool {
        let Rectangle(Point(x1, y1), Point(x2, y2)) = self;
        let Point(x, y) = position;
        // TODO: use inclusive range syntax syntax once stable
        x1 <= x && x <= x2 && y1 <= y && y <= y2
    }

    pub fn edges(self) -> Box<Iterator<Item=Point>> {
        if self.width() <= 2 || self.height() <= 2 {
            Box::new(self.into_iter())
        } else {
            let Rectangle(Point(x1, y1), Point(x2, y2)) = self;
            Box::new(Rectangle(Point(x1, y1), Point(x2 - 1, y1)).into_iter()
                .chain(Rectangle(Point(x2, y1), Point(x2, y2 - 1)).into_iter())
                .chain(Rectangle(Point(x1 + 1, y1), Point(x2, y2)).into_iter())
                .chain(Rectangle(Point(x1, y1 + 1), Point(x1, y1)).into_iter()))
        }
    }
}

pub struct RectangleIter {
    start: Point,
    width: i32,
    end_index: i32,
    current_index: i32
}

impl Iterator for RectangleIter {
    type Item = Point;
    fn next(&mut self) -> Option<Point> {
        if self.current_index < self.end_index {
            let current_point = self.start + Point(
                self.current_index % self.width,
                self.current_index / self.width );
            self.current_index += 1;
            Some(current_point)
        } else {
            None
        }
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        let size = (self.end_index - self.current_index) as usize;
        (size, Some(size))
    }
}

impl ExactSizeIterator for RectangleIter {}

impl IntoIterator for Rectangle {
    type Item = Point;
    type IntoIter = RectangleIter;
    fn into_iter(self) -> RectangleIter {
        let Rectangle(start, _) = self;
        RectangleIter {
            start: start,
            width: self.width(),
            end_index: self.area(),
            current_index: 0
        }
    }
}
<|endoftext|>


<commit_before>use futures::future::Future;
use futures::stream::Stream;
use glob::glob;
use hyper::{header, Chunk, Client, Method, Request, Response};
use hyper_rustls::HttpsConnector;
use serde_json;
use statics::TEMP_DIRNAME;
use std;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use structs::{CliError, Config, Member, PublicKey, Repo, Sector, SectorGroup, Team};
use tokio_core::reactor;

pub struct GithubClient {
    pub conf: Config,
}

impl GithubClient {
    pub fn new(config: &Config) -> GithubClient {
        if std::env::var("SSL_CERT_FILE").is_err() {
            std::env::set_var("SSL_CERT_FILE", &config.cert_path);
        }
        GithubClient { conf: config.clone() }
    }

    fn get_cache_path(url: &str) -> std::path::PathBuf {
        let mut path = std::env::temp_dir();
        path.push(TEMP_DIRNAME);
        path.push(url);
        path
    }

    fn load_contents_from_cache(&self, url: &str) -> Result<(std::fs::Metadata, String), CliError> {
        let path = Self::get_cache_path(url);
        let metadata = std::fs::metadata(path.to_str().unwrap())?;
        let mut f = File::open(path.to_str().unwrap())?;
        let mut contents = String::new();
        f.read_to_string(&mut contents)?;
        Ok((metadata, contents))
    }

    fn store_contents_to_cache(&self, url: &str, contents: &str) -> Result<(), CliError> {
        let path = Self::get_cache_path(url);
        std::fs::create_dir_all(path.parent().unwrap_or(std::path::Path::new("/")))?;
        let mut f = File::create(path.to_str().unwrap())?;
        f.write(contents.as_bytes())?;
        Ok(())
    }

    fn get_contents_from_url(&self, url: &str) -> Result<String, CliError> {
        let mut all_contents: Vec<serde_json::value::Value> = Vec::new();
        let mut page = 1;
        loop {
            let mut new_array = self.get_contents_from_url_page(url, page)?;
            if new_array.is_empty() {
                break;
            }
            all_contents.append(&mut new_array);
            page += 1;
        }
        let contents = serde_json::ser::to_string(&all_contents)?;
        self.store_contents_to_cache(url, &contents)?;
        Ok(contents)
    }

    fn build_request(&self, url: &str) -> Request {
        let token = String::from("token ") + &self.conf.token;
        let mut req: Request = Request::new(Method::Get, url.parse().unwrap());
        req.headers_mut().set(header::Authorization(token));
        req.headers_mut().set(header::UserAgent::new("sectora"));
        req
    }

    fn build_page_request(&self, url: &str, page: u64) -> Request {
        let sep = if url.contains("?") { "&" } else { "?" };
        let url_p = format!("{}{}page={}", url, sep, page);
        self.build_request(&url_p)
    }

    fn get_contents_from_url_page(&self, url: &str, page: u64) -> Result<Vec<serde_json::value::Value>, CliError> {
        let req = self.build_page_request(url, page);
        let mut core = reactor::Core::new()?;
        let client = Client::configure().connector(HttpsConnector::new(4, &core.handle()))
                                        .build(&core.handle());
        let to_io = |e| std::io::Error::new(std::io::ErrorKind::Other, e);
        let parse_body = |body: Chunk| Ok(serde_json::from_slice::<Vec<_>>(&body).map_err(to_io)?);
        let handle_response = |res: Response| res.body().concat2().and_then(parse_body);
        Ok(core.run(client.request(req).and_then(handle_response))?)
    }

    fn get_contents(&self, url: &str) -> Result<String, CliError> {
        match self.load_contents_from_cache(url) {
            Ok((metadata, cache_contents)) => match std::time::SystemTime::now().duration_since(metadata.modified()?) {
                Ok(caching_duration) => {
                    if caching_duration.as_secs() > self.conf.cache_duration {
                        match self.get_contents_from_url(url) {
                            Ok(contents_from_url) => Ok(contents_from_url),
                            Err(_) => Ok(cache_contents),
                        }
                    } else {
                        Ok(cache_contents)
                    }
                }
                Err(_) => Ok(cache_contents),
            },
            Err(_) => self.get_contents_from_url(url),
        }
    }

    #[allow(dead_code)]
    pub fn print_user_public_key(&self, user: &str) -> Result<(), CliError> {
        let keys = self.get_user_public_key(user)?;
        println!("{}", keys);
        Ok(())
    }

    fn get_user_public_key(&self, user: &str) -> Result<String, CliError> {
        let url = format!("{}/users/{}/keys", self.conf.endpoint, user);
        let contents = self.get_contents(&url)?;
        let keys = serde_json::from_str::<Vec<PublicKey>>(&contents)?;
        Ok(keys.iter().map(|k| k.key.clone()).collect::<Vec<String>>().join("\n"))
    }

    #[allow(dead_code)]
    pub fn check_pam(&self, user: &str) -> Result<bool, CliError> {
        let sectors = self.get_sectors()?;
        Ok(sectors.iter().any(|team| team.members.contains_key(user)))
    }

    pub fn get_sectors(&self) -> Result<Vec<SectorGroup>, CliError> {
        let mut sectors: Vec<SectorGroup> = self.get_teams_result()?;
        sectors.append(&mut self.get_repos_result()?);
        Ok(sectors)
    }

    fn get_teams_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_teams = self.get_team_map()?;
        let mut teams = Vec::new();
        for team_conf in &self.conf.team {
            if let &Some(gh_team) = &gh_teams.get(&team_conf.name) {
                teams.push(SectorGroup { sector: Sector::from(gh_team.clone()),
                                         gid: team_conf.gid.clone(),
                                         group: team_conf.group.clone(),
                                         members: self.get_team_members(gh_team.id)?, });
            }
        }
        Ok(teams)
    }

    fn get_team_map(&self) -> Result<HashMap<String, Team>, CliError> {
        let url = format!("{}/orgs/{}/teams", self.conf.endpoint, self.conf.org);
        let contents = self.get_contents(&url)?;
        let teams = serde_json::from_str::<Vec<Team>>(&contents)?;
        Ok(teams.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_team_members(&self, mid: u64) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/teams/{}/members", self.conf.endpoint, mid);
        let contents = self.get_contents(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&contents)?;
        Ok(members.iter().map(|m| (m.login.clone(), m.clone())).collect())
    }

    fn get_repos_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_repos = self.get_repo_map()?;
        let mut repos = Vec::new();
        for repo_conf in &self.conf.repo {
            if let &Some(gh_repo) = &gh_repos.get(&repo_conf.name) {
                repos.push(SectorGroup { sector: Sector::from(gh_repo.clone()),
                                         gid: repo_conf.gid.clone(),
                                         group: repo_conf.group.clone(),
                                         members: self.get_repo_collaborators(&gh_repo.name)?, });
            }
        }
        Ok(repos)
    }

    fn get_repo_map(&self) -> Result<HashMap<String, Repo>, CliError> {
        let url = format!("{}/orgs/{}/repos", self.conf.endpoint, self.conf.org);
        let contents = self.get_contents(&url)?;
        let repos = serde_json::from_str::<Vec<Repo>>(&contents)?;
        Ok(repos.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_repo_collaborators(&self, repo_name: &str) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/repos/{}/{}/collaborators?affiliation=outside",
                          self.conf.endpoint, self.conf.org, repo_name);
        let contents = self.get_contents(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&contents)?;
        Ok(members.iter().map(|m| (m.login.clone(), m.clone())).collect())
    }

    #[allow(dead_code)]
    pub fn clear_all_caches(&self) -> Result<(), CliError> {
        let mut path = std::env::temp_dir();
        path.push(TEMP_DIRNAME);
        path.push("**/*");
        for entry in glob(&path.to_str().unwrap()).unwrap() {
            match entry {
                Ok(path) => {
                    if path.is_file() {
                        std::fs::remove_file(path)?
                    }
                }
                Err(e) => println!("{:?}", e),
            }
        }
        Ok(())
    }
}
<commit_msg>Refactor run_request method<commit_after>use futures::future::Future;
use futures::stream::Stream;
use glob::glob;
use hyper::{header, Chunk, Client, Method, Request, Response};
use hyper_rustls::HttpsConnector;
use serde_json;
use statics::TEMP_DIRNAME;
use std;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use structs::{CliError, Config, Member, PublicKey, Repo, Sector, SectorGroup, Team};
use tokio_core::reactor;

pub struct GithubClient {
    pub conf: Config,
}

impl GithubClient {
    pub fn new(config: &Config) -> GithubClient {
        if std::env::var("SSL_CERT_FILE").is_err() {
            std::env::set_var("SSL_CERT_FILE", &config.cert_path);
        }
        GithubClient { conf: config.clone() }
    }

    fn get_cache_path(url: &str) -> std::path::PathBuf {
        let mut path = std::env::temp_dir();
        path.push(TEMP_DIRNAME);
        path.push(url);
        path
    }

    fn load_contents_from_cache(&self, url: &str) -> Result<(std::fs::Metadata, String), CliError> {
        let path = Self::get_cache_path(url);
        let metadata = std::fs::metadata(path.to_str().unwrap())?;
        let mut f = File::open(path.to_str().unwrap())?;
        let mut contents = String::new();
        f.read_to_string(&mut contents)?;
        Ok((metadata, contents))
    }

    fn store_contents_to_cache(&self, url: &str, contents: &str) -> Result<(), CliError> {
        let path = Self::get_cache_path(url);
        std::fs::create_dir_all(path.parent().unwrap_or(std::path::Path::new("/")))?;
        let mut f = File::create(path.to_str().unwrap())?;
        f.write(contents.as_bytes())?;
        Ok(())
    }

    fn get_contents_from_url(&self, url: &str) -> Result<String, CliError> {
        let mut all_contents: Vec<serde_json::value::Value> = Vec::new();
        let mut page = 1;
        loop {
            let mut new_array = self.get_contents_from_url_page(url, page)?;
            if new_array.is_empty() {
                break;
            }
            all_contents.append(&mut new_array);
            page += 1;
        }
        let contents = serde_json::ser::to_string(&all_contents)?;
        self.store_contents_to_cache(url, &contents)?;
        Ok(contents)
    }

    fn build_request(&self, url: &str) -> Request {
        let token = String::from("token ") + &self.conf.token;
        let mut req: Request = Request::new(Method::Get, url.parse().unwrap());
        req.headers_mut().set(header::Authorization(token));
        req.headers_mut().set(header::UserAgent::new("sectora"));
        req
    }

    fn build_page_request(&self, url: &str, page: u64) -> Request {
        let sep = if url.contains("?") { "&" } else { "?" };
        let url_p = format!("{}{}page={}", url, sep, page);
        self.build_request(&url_p)
    }

    fn run_request(&self, req: Request) -> Result<serde_json::value::Value, CliError> {
        let mut core = reactor::Core::new()?;
        let client = Client::configure().connector(HttpsConnector::new(4, &core.handle()))
                                        .build(&core.handle());
        let to_io = |e| std::io::Error::new(std::io::ErrorKind::Other, e);
        let parse_body = |body: Chunk| Ok(serde_json::from_slice(&body).map_err(to_io)?);
        let handle_response = |res: Response| res.body().concat2().and_then(parse_body);
        Ok(core.run(client.request(req).and_then(handle_response))?)
    }

    fn get_contents_from_url_page(&self, url: &str, page: u64) -> Result<Vec<serde_json::value::Value>, CliError> {
        let req = self.build_page_request(url, page);
        self.run_request(req).and_then(|v| serde_json::from_value(v).map_err(CliError::from))
    }

    fn get_contents(&self, url: &str) -> Result<String, CliError> {
        match self.load_contents_from_cache(url) {
            Ok((metadata, cache_contents)) => match std::time::SystemTime::now().duration_since(metadata.modified()?) {
                Ok(caching_duration) => {
                    if caching_duration.as_secs() > self.conf.cache_duration {
                        match self.get_contents_from_url(url) {
                            Ok(contents_from_url) => Ok(contents_from_url),
                            Err(_) => Ok(cache_contents),
                        }
                    } else {
                        Ok(cache_contents)
                    }
                }
                Err(_) => Ok(cache_contents),
            },
            Err(_) => self.get_contents_from_url(url),
        }
    }

    #[allow(dead_code)]
    pub fn print_user_public_key(&self, user: &str) -> Result<(), CliError> {
        let keys = self.get_user_public_key(user)?;
        println!("{}", keys);
        Ok(())
    }

    fn get_user_public_key(&self, user: &str) -> Result<String, CliError> {
        let url = format!("{}/users/{}/keys", self.conf.endpoint, user);
        let contents = self.get_contents(&url)?;
        let keys = serde_json::from_str::<Vec<PublicKey>>(&contents)?;
        Ok(keys.iter().map(|k| k.key.clone()).collect::<Vec<String>>().join("\n"))
    }

    #[allow(dead_code)]
    pub fn check_pam(&self, user: &str) -> Result<bool, CliError> {
        let sectors = self.get_sectors()?;
        Ok(sectors.iter().any(|team| team.members.contains_key(user)))
    }

    pub fn get_sectors(&self) -> Result<Vec<SectorGroup>, CliError> {
        let mut sectors: Vec<SectorGroup> = self.get_teams_result()?;
        sectors.append(&mut self.get_repos_result()?);
        Ok(sectors)
    }

    fn get_teams_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_teams = self.get_team_map()?;
        let mut teams = Vec::new();
        for team_conf in &self.conf.team {
            if let &Some(gh_team) = &gh_teams.get(&team_conf.name) {
                teams.push(SectorGroup { sector: Sector::from(gh_team.clone()),
                                         gid: team_conf.gid.clone(),
                                         group: team_conf.group.clone(),
                                         members: self.get_team_members(gh_team.id)?, });
            }
        }
        Ok(teams)
    }

    fn get_team_map(&self) -> Result<HashMap<String, Team>, CliError> {
        let url = format!("{}/orgs/{}/teams", self.conf.endpoint, self.conf.org);
        let contents = self.get_contents(&url)?;
        let teams = serde_json::from_str::<Vec<Team>>(&contents)?;
        Ok(teams.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_team_members(&self, mid: u64) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/teams/{}/members", self.conf.endpoint, mid);
        let contents = self.get_contents(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&contents)?;
        Ok(members.iter().map(|m| (m.login.clone(), m.clone())).collect())
    }

    fn get_repos_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_repos = self.get_repo_map()?;
        let mut repos = Vec::new();
        for repo_conf in &self.conf.repo {
            if let &Some(gh_repo) = &gh_repos.get(&repo_conf.name) {
                repos.push(SectorGroup { sector: Sector::from(gh_repo.clone()),
                                         gid: repo_conf.gid.clone(),
                                         group: repo_conf.group.clone(),
                                         members: self.get_repo_collaborators(&gh_repo.name)?, });
            }
        }
        Ok(repos)
    }

    fn get_repo_map(&self) -> Result<HashMap<String, Repo>, CliError> {
        let url = format!("{}/orgs/{}/repos", self.conf.endpoint, self.conf.org);
        let contents = self.get_contents(&url)?;
        let repos = serde_json::from_str::<Vec<Repo>>(&contents)?;
        Ok(repos.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_repo_collaborators(&self, repo_name: &str) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/repos/{}/{}/collaborators?affiliation=outside",
                          self.conf.endpoint, self.conf.org, repo_name);
        let contents = self.get_contents(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&contents)?;
        Ok(members.iter().map(|m| (m.login.clone(), m.clone())).collect())
    }

    #[allow(dead_code)]
    pub fn clear_all_caches(&self) -> Result<(), CliError> {
        let mut path = std::env::temp_dir();
        path.push(TEMP_DIRNAME);
        path.push("**/*");
        for entry in glob(&path.to_str().unwrap()).unwrap() {
            match entry {
                Ok(path) => {
                    if path.is_file() {
                        std::fs::remove_file(path)?
                    }
                }
                Err(e) => println!("{:?}", e),
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `bitflags!` macro generates a `struct` that holds a set of C-style
//! bitmask flags. It is useful for creating typesafe wrappers for C APIs.
//!
//! The flags should only be defined for integer types, otherwise unexpected
//! type errors may occur at compile time.
//!
//! # Example
//!
//! ~~~rust
//! bitflags!(
//!     flags Flags: u32 {
//!         static FlagA       = 0x00000001,
//!         static FlagB       = 0x00000010,
//!         static FlagC       = 0x00000100,
//!         static FlagABC     = FlagA.bits
//!                            | FlagB.bits
//!                            | FlagC.bits,
//!     }
//! )
//!
//! fn main() {
//!     let e1 = FlagA | FlagC;
//!     let e2 = FlagB | FlagC;
//!     assert!((e1 | e2) == FlagABC);   // union
//!     assert!((e1 & e2) == FlagC);     // intersection
//!     assert!((e1 - e2) == FlagA);     // set difference
//!     assert!(!e2 == FlagA);           // set complement
//! }
//! ~~~
//!
//! The generated `struct`s can also be extended with type and trait implementations:
//!
//! ~~~rust
//! use std::fmt;
//!
//! bitflags!(
//!     flags Flags: u32 {
//!         static FlagA   = 0x00000001,
//!         static FlagB   = 0x00000010,
//!     }
//! )
//!
//! impl Flags {
//!     pub fn clear(&mut self) {
//!         self.bits = 0;  // The `bits` field can be accessed from within the
//!                         // same module where the `bitflags!` macro was invoked.
//!     }
//! }
//!
//! impl fmt::Show for Flags {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f, "hi!")
//!     }
//! }
//!
//! fn main() {
//!     let mut flags = FlagA | FlagB;
//!     flags.clear();
//!     assert!(flags.is_empty());
//!     assert_eq!(format!("{}", flags).as_slice(), "hi!");
//! }
//! ~~~
//!
//! # Attributes
//!
//! Attributes can be attached to the generated `struct` by placing them
//! before the `flags` keyword.
//!
//! # Derived traits
//!
//! The `PartialEq` and `Clone` traits are automatically derived for the `struct` using
//! the `deriving` attribute. Additional traits can be derived by providing an
//! explicit `deriving` attribute on `flags`.
//!
//! # Operators
//!
//! The following operator traits are implemented for the generated `struct`:
//!
//! - `BitOr`: union
//! - `BitAnd`: intersection
//! - `Sub`: set difference
//! - `Not`: set complement
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//!
//! - `empty`: an empty set of flags
//! - `all`: the set of all flags
//! - `bits`: the raw value of the flags currently stored
//! - `is_empty`: `true` if no flags are currently stored
//! - `is_all`: `true` if all flags are currently set
//! - `intersects`: `true` if there are flags common to both `self` and `other`
//! - `contains`: `true` all of the flags in `other` are contained within `self`
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place

#![experimental]
#![macro_escape]

#[macro_export]
macro_rules! bitflags(
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* static $Flag:ident = $value:expr),+
    }) => (
        #[deriving(PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
        $(#[$attr])*
        pub struct $BitFlags {
            bits: $T,
        }

        $($(#[$Flag_attr])* pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the set containing all flags.
            pub fn all() -> $BitFlags {
                $BitFlags { bits: $($value)|+ }
            }

            /// Returns the raw value of the flags currently stored.
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Convert from underlying bit representation, unless that
            /// representation contains bits that do not correspond to a flag.
            pub fn from_bits(bits: $T) -> ::std::option::Option<$BitFlags> {
                if (bits & !$BitFlags::all().bits()) != 0 {
                    ::std::option::None
                } else {
                    ::std::option::Some($BitFlags { bits: bits })
                }
            }

            /// Convert from underlying bit representation, dropping any bits
            /// that do not correspond to flags.
            pub fn from_bits_truncate(bits: $T) -> $BitFlags {
                $BitFlags { bits: bits } & $BitFlags::all()
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if all flags are currently set.
            pub fn is_all(&self) -> bool {
                *self == $BitFlags::all()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            pub fn contains(&self, other: $BitFlags) -> bool {
                (self & other) == other
            }

            /// Inserts the specified flags in-place.
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }
        }

        impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl Sub<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }

        impl Not<$BitFlags> for $BitFlags {
            /// Returns the complement of this set of flags.
            #[inline]
            fn not(&self) -> $BitFlags {
                $BitFlags { bits: !self.bits } & $BitFlags::all()
            }
        }
    );
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* static $Flag:ident = $value:expr),+,
    }) => (
        bitflags!(
            $(#[$attr])*
            flags $BitFlags: u32 {
                $($(#[$Flag_attr])* static $Flag = $value),+
            }
        )
    );
)

#[cfg(test)]
mod tests {
    use hash;
    use option::{Some, None};
    use ops::{BitOr, BitAnd, Sub, Not};

    bitflags!(
        flags Flags: u32 {
            static FlagA       = 0x00000001,
            static FlagB       = 0x00000010,
            static FlagC       = 0x00000100,
            static FlagABC     = FlagA.bits
                               | FlagB.bits
                               | FlagC.bits,
        }
    )

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0x00000000);
        assert_eq!(FlagA.bits(), 0x00000001);
        assert_eq!(FlagABC.bits(), 0x00000111);
    }

    #[test]
    fn test_from_bits() {
        assert!(Flags::from_bits(0) == Some(Flags::empty()));
        assert!(Flags::from_bits(0x1) == Some(FlagA));
        assert!(Flags::from_bits(0x10) == Some(FlagB));
        assert!(Flags::from_bits(0x11) == Some(FlagA | FlagB));
        assert!(Flags::from_bits(0x1000) == None);
    }

    #[test]
    fn test_from_bits_truncate() {
        assert!(Flags::from_bits_truncate(0) == Flags::empty());
        assert!(Flags::from_bits_truncate(0x1) == FlagA);
        assert!(Flags::from_bits_truncate(0x10) == FlagB);
        assert!(Flags::from_bits_truncate(0x11) == (FlagA | FlagB));
        assert!(Flags::from_bits_truncate(0x1000) == Flags::empty());
        assert!(Flags::from_bits_truncate(0x1001) == FlagA);
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());
    }

    #[test]
    fn test_is_all() {
        assert!(Flags::all().is_all());
        assert!(!FlagA.is_all());
        assert!(FlagABC.is_all());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);   // union
        assert!((e1 & e2) == FlagC);     // intersection
        assert!((e1 - e2) == FlagA);     // set difference
        assert!(!e2 == FlagA);           // set complement
    }

    #[test]
    fn test_lt() {
        let mut a = Flags::empty();
        let mut b = Flags::empty();

        assert!(!(a < b) && !(b < a));
        b = FlagB;
        assert!(a < b);
        a = FlagC;
        assert!(!(a < b) && b < a);
        b = FlagC | FlagB;
        assert!(a < b);
    }

    #[test]
    fn test_ord() {
        let mut a = Flags::empty();
        let mut b = Flags::empty();

        assert!(a <= b && a >= b);
        a = FlagA;
        assert!(a > b && a >= b);
        assert!(b < a && b <= a);
        b = FlagB;
        assert!(b > a && b >= a);
        assert!(a < b && a <= b);
    }

    #[test]
    fn test_hash() {
      let mut x = Flags::empty();
      let mut y = Flags::empty();
      assert!(hash::hash(&x) == hash::hash(&y));
      x = Flags::all();
      y = FlagABC;
      assert!(hash::hash(&x) == hash::hash(&y));
    }
}
<commit_msg>Test attributes<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `bitflags!` macro generates a `struct` that holds a set of C-style
//! bitmask flags. It is useful for creating typesafe wrappers for C APIs.
//!
//! The flags should only be defined for integer types, otherwise unexpected
//! type errors may occur at compile time.
//!
//! # Example
//!
//! ~~~rust
//! bitflags!(
//!     flags Flags: u32 {
//!         static FlagA       = 0x00000001,
//!         static FlagB       = 0x00000010,
//!         static FlagC       = 0x00000100,
//!         static FlagABC     = FlagA.bits
//!                            | FlagB.bits
//!                            | FlagC.bits,
//!     }
//! )
//!
//! fn main() {
//!     let e1 = FlagA | FlagC;
//!     let e2 = FlagB | FlagC;
//!     assert!((e1 | e2) == FlagABC);   // union
//!     assert!((e1 & e2) == FlagC);     // intersection
//!     assert!((e1 - e2) == FlagA);     // set difference
//!     assert!(!e2 == FlagA);           // set complement
//! }
//! ~~~
//!
//! The generated `struct`s can also be extended with type and trait implementations:
//!
//! ~~~rust
//! use std::fmt;
//!
//! bitflags!(
//!     flags Flags: u32 {
//!         static FlagA   = 0x00000001,
//!         static FlagB   = 0x00000010,
//!     }
//! )
//!
//! impl Flags {
//!     pub fn clear(&mut self) {
//!         self.bits = 0;  // The `bits` field can be accessed from within the
//!                         // same module where the `bitflags!` macro was invoked.
//!     }
//! }
//!
//! impl fmt::Show for Flags {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f, "hi!")
//!     }
//! }
//!
//! fn main() {
//!     let mut flags = FlagA | FlagB;
//!     flags.clear();
//!     assert!(flags.is_empty());
//!     assert_eq!(format!("{}", flags).as_slice(), "hi!");
//! }
//! ~~~
//!
//! # Attributes
//!
//! Attributes can be attached to the generated `struct` by placing them
//! before the `flags` keyword.
//!
//! # Derived traits
//!
//! The `PartialEq` and `Clone` traits are automatically derived for the `struct` using
//! the `deriving` attribute. Additional traits can be derived by providing an
//! explicit `deriving` attribute on `flags`.
//!
//! # Operators
//!
//! The following operator traits are implemented for the generated `struct`:
//!
//! - `BitOr`: union
//! - `BitAnd`: intersection
//! - `Sub`: set difference
//! - `Not`: set complement
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//!
//! - `empty`: an empty set of flags
//! - `all`: the set of all flags
//! - `bits`: the raw value of the flags currently stored
//! - `is_empty`: `true` if no flags are currently stored
//! - `is_all`: `true` if all flags are currently set
//! - `intersects`: `true` if there are flags common to both `self` and `other`
//! - `contains`: `true` all of the flags in `other` are contained within `self`
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place

#![experimental]
#![macro_escape]

#[macro_export]
macro_rules! bitflags(
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* static $Flag:ident = $value:expr),+
    }) => (
        #[deriving(PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
        $(#[$attr])*
        pub struct $BitFlags {
            bits: $T,
        }

        $($(#[$Flag_attr])* pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the set containing all flags.
            pub fn all() -> $BitFlags {
                $BitFlags { bits: $($value)|+ }
            }

            /// Returns the raw value of the flags currently stored.
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Convert from underlying bit representation, unless that
            /// representation contains bits that do not correspond to a flag.
            pub fn from_bits(bits: $T) -> ::std::option::Option<$BitFlags> {
                if (bits & !$BitFlags::all().bits()) != 0 {
                    ::std::option::None
                } else {
                    ::std::option::Some($BitFlags { bits: bits })
                }
            }

            /// Convert from underlying bit representation, dropping any bits
            /// that do not correspond to flags.
            pub fn from_bits_truncate(bits: $T) -> $BitFlags {
                $BitFlags { bits: bits } & $BitFlags::all()
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if all flags are currently set.
            pub fn is_all(&self) -> bool {
                *self == $BitFlags::all()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            pub fn contains(&self, other: $BitFlags) -> bool {
                (self & other) == other
            }

            /// Inserts the specified flags in-place.
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }
        }

        impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl Sub<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }

        impl Not<$BitFlags> for $BitFlags {
            /// Returns the complement of this set of flags.
            #[inline]
            fn not(&self) -> $BitFlags {
                $BitFlags { bits: !self.bits } & $BitFlags::all()
            }
        }
    );
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* static $Flag:ident = $value:expr),+,
    }) => (
        bitflags!(
            $(#[$attr])*
            flags $BitFlags: u32 {
                $($(#[$Flag_attr])* static $Flag = $value),+
            }
        )
    );
)

#[cfg(test)]
mod tests {
    use hash;
    use option::{Some, None};
    use ops::{BitOr, BitAnd, Sub, Not};

    bitflags!(
        #[doc = "> The first principle is that you must not fool yourself — and"]
        #[doc = "> you are the easiest person to fool."]
        #[doc = "> "]
        #[doc = "> - Richard Feynman"]
        flags Flags: u32 {
            static FlagA       = 0x00000001,
            #[doc = "<pcwalton> macros are way better at generating code than trans is"]
            static FlagB       = 0x00000010,
            static FlagC       = 0x00000100,
            #[doc = "* cmr bed"]
            #[doc = "* strcat table"]
            #[doc = "<strcat> wait what?"]
            static FlagABC     = FlagA.bits
                               | FlagB.bits
                               | FlagC.bits,
        }
    )

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0x00000000);
        assert_eq!(FlagA.bits(), 0x00000001);
        assert_eq!(FlagABC.bits(), 0x00000111);
    }

    #[test]
    fn test_from_bits() {
        assert!(Flags::from_bits(0) == Some(Flags::empty()));
        assert!(Flags::from_bits(0x1) == Some(FlagA));
        assert!(Flags::from_bits(0x10) == Some(FlagB));
        assert!(Flags::from_bits(0x11) == Some(FlagA | FlagB));
        assert!(Flags::from_bits(0x1000) == None);
    }

    #[test]
    fn test_from_bits_truncate() {
        assert!(Flags::from_bits_truncate(0) == Flags::empty());
        assert!(Flags::from_bits_truncate(0x1) == FlagA);
        assert!(Flags::from_bits_truncate(0x10) == FlagB);
        assert!(Flags::from_bits_truncate(0x11) == (FlagA | FlagB));
        assert!(Flags::from_bits_truncate(0x1000) == Flags::empty());
        assert!(Flags::from_bits_truncate(0x1001) == FlagA);
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());
    }

    #[test]
    fn test_is_all() {
        assert!(Flags::all().is_all());
        assert!(!FlagA.is_all());
        assert!(FlagABC.is_all());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);   // union
        assert!((e1 & e2) == FlagC);     // intersection
        assert!((e1 - e2) == FlagA);     // set difference
        assert!(!e2 == FlagA);           // set complement
    }

    #[test]
    fn test_lt() {
        let mut a = Flags::empty();
        let mut b = Flags::empty();

        assert!(!(a < b) && !(b < a));
        b = FlagB;
        assert!(a < b);
        a = FlagC;
        assert!(!(a < b) && b < a);
        b = FlagC | FlagB;
        assert!(a < b);
    }

    #[test]
    fn test_ord() {
        let mut a = Flags::empty();
        let mut b = Flags::empty();

        assert!(a <= b && a >= b);
        a = FlagA;
        assert!(a > b && a >= b);
        assert!(b < a && b <= a);
        b = FlagB;
        assert!(b > a && b >= a);
        assert!(a < b && a <= b);
    }

    #[test]
    fn test_hash() {
      let mut x = Flags::empty();
      let mut y = Flags::empty();
      assert!(hash::hash(&x) == hash::hash(&y));
      x = Flags::all();
      y = FlagABC;
      assert!(hash::hash(&x) == hash::hash(&y));
    }
}
<|endoftext|>