<commit_before>//! An undo-redo library with dynamic dispatch and automatic command merging.
//! It uses the [command pattern](https://en.wikipedia.org/wiki/Command_pattern)
//! where the user modifies a receiver by applying commands on it.
//!
//! The library has currently two data structures that can be used to modify the receiver:
//!
//! * A stack that can push and pop commands to modify the receiver.
//! * A record that can roll the state of the receiver forwards and backwards.

#![forbid(unstable_features, bad_style)]
#![deny(missing_debug_implementations, unused_import_braces, unused_qualifications, unsafe_code)]

mod group;
mod record;
mod stack;

use std::error;
use std::fmt::{self, Debug, Display, Formatter};

pub use group::{Group, GroupBuilder};
pub use record::{Commands, Record, RecordBuilder, Signal};
pub use stack::Stack;

/// Base functionality for all commands.
#[cfg(not(feature = "display"))]
pub trait Command<R>: Debug {
    /// Executes the desired command and returns `Ok` if everything went fine, and `Err` if
    /// something went wrong.
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    /// Restores the state as it was before [`exec`] was called and returns `Ok` if everything
    /// went fine, and `Err` if something went wrong.
    ///
    /// [`exec`]: trait.Command.html#tymethod.exec
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    /// Used for automatic merging of commands.
    ///
    /// Two commands are merged together when a command is pushed, and it has
    /// the same id as the top command already on the stack or record. When commands are merged together,
    /// undoing and redoing them are done in one step.
    ///
    /// # Examples
    /// ```
    /// use std::error::Error;
    /// use undo::{Command, Record};
    ///
    /// #[derive(Debug)]
    /// struct Add(char);
    ///
    /// impl Command<String> for Add {
    ///     fn exec(&mut self, s: &mut String) -> Result<(), Box<Error>> {
    ///         s.push(self.0);
    ///         Ok(())
    ///     }
    ///
    ///     fn undo(&mut self, s: &mut String) -> Result<(), Box<Error>> {
    ///         self.0 = s.pop().ok_or("`String` is unexpectedly empty")?;
    ///         Ok(())
    ///     }
    ///
    ///     fn id(&self) -> Option<u32> {
    ///         Some(1)
    ///     }
    /// }
    ///
    /// fn foo() -> Result<(), Box<Error>> {
    ///     let mut record = Record::default();
    ///
    ///     // 'a', 'b', and 'c' are merged.
    ///     record.exec(Add('a'))?;
    ///     record.exec(Add('b'))?;
    ///     record.exec(Add('c'))?;
    ///     assert_eq!(record.len(), 1);
    ///     assert_eq!(record.as_receiver(), "abc");
    ///
    ///     // Calling `undo` once will undo all merged commands.
    ///     record.undo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "");
    ///
    ///     // Calling `redo` once will redo all merged commands.
    ///     record.redo().unwrap()?;
    ///     assert_eq!(record.into_receiver(), "abc");
    ///
    ///     Ok(())
    /// }
    /// # foo().unwrap();
    /// ```
    #[inline]
    fn id(&self) -> Option<u32> {
        None
    }
}

/// Base functionality for all commands.
#[cfg(feature = "display")]
pub trait Command<R>: Debug + Display {
    /// Executes the desired command and returns `Ok` if everything went fine, and `Err` if
    /// something went wrong.
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    /// Restores the state as it was before [`exec`] was called and returns `Ok` if everything
    /// went fine, and `Err` if something went wrong.
    ///
    /// [`exec`]: trait.Command.html#tymethod.exec
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    /// Used for automatic merging of commands.
    ///
    /// Two commands are merged together when a command is pushed, and it has
    /// the same id as the top command already on the stack or record. When commands are merged together,
    /// undoing and redoing them are done in one step.
    ///
    /// # Examples
    /// ```
    /// use std::error::Error;
    /// use std::fmt::{self, Display, Formatter};
    /// use undo::{Command, Record};
    ///
    /// #[derive(Debug)]
    /// struct Add(char);
    ///
    /// impl Command<String> for Add {
    ///     fn exec(&mut self, s: &mut String) -> Result<(), Box<Error>> {
    ///         s.push(self.0);
    ///         Ok(())
    ///     }
    ///
    ///     fn undo(&mut self, s: &mut String) -> Result<(), Box<Error>> {
    ///         self.0 = s.pop().ok_or("`String` is unexpectedly empty")?;
    ///         Ok(())
    ///     }
    ///
    ///     fn id(&self) -> Option<u32> {
    ///         Some(1)
    ///     }
    /// }
    ///
    /// impl Display for Add {
    ///     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    ///         write!(f, "Add `{}`", self.0)
    ///     }
    /// }
    ///
    /// fn foo() -> Result<(), Box<Error>> {
    ///     let mut record = Record::default();
    ///
    ///     // 'a', 'b', and 'c' are merged.
    ///     record.exec(Add('a'))?;
    ///     record.exec(Add('b'))?;
    ///     record.exec(Add('c'))?;
    ///     assert_eq!(record.len(), 1);
    ///     assert_eq!(record.as_receiver(), "abc");
    ///
    ///     // Calling `undo` once will undo all merged commands.
    ///     record.undo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "");
    ///
    ///     // Calling `redo` once will redo all merged commands.
    ///     record.redo().unwrap()?;
    ///     assert_eq!(record.into_receiver(), "abc");
    ///
    ///     Ok(())
    /// }
    /// # foo().unwrap();
    /// ```
    #[inline]
    fn id(&self) -> Option<u32> {
        None
    }
}

impl<R, C: Command<R> + ?Sized> Command<R> for Box<C> {
    #[inline]
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        (**self).exec(receiver)
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        (**self).undo(receiver)
    }

    #[inline]
    fn id(&self) -> Option<u32> {
        (**self).id()
    }
}

struct Merger<R> {
    cmd1: Box<Command<R>>,
    cmd2: Box<Command<R>>,
}

impl<R> Command<R> for Merger<R> {
    #[inline]
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        self.cmd1.exec(receiver)?;
        self.cmd2.exec(receiver)
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        self.cmd2.undo(receiver)?;
        self.cmd1.undo(receiver)
    }

    #[inline]
    fn id(&self) -> Option<u32> {
        self.cmd1.id()
    }
}

impl<R> Debug for Merger<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Merger")
            .field("cmd1", &self.cmd1)
            .field("cmd2", &self.cmd2)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<R> Display for Merger<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{} + {}", self.cmd1, self.cmd2)
    }
}

/// An error kind that holds the error and the command that caused the error.
#[derive(Debug)]
pub struct Error<R>(pub Box<Command<R>>, pub Box<error::Error>);

impl<R> Display for Error<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.1)
    }
}

impl<R: Debug> error::Error for Error<R> {
    #[inline]
    fn description(&self) -> &str {
        self.1.description()
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        self.1.cause()
    }
}
<commit_msg>Remove docs from display version of Command<commit_after>//! An undo-redo library with dynamic dispatch and automatic command merging.
//! It uses the [command pattern](https://en.wikipedia.org/wiki/Command_pattern)
//! where the user modifies a receiver by applying commands on it.
//!
//! The library has currently two data structures that can be used to modify the receiver:
//!
//! * A stack that can push and pop commands to modify the receiver.
//! * A record that can roll the state of the receiver forwards and backwards.

#![forbid(unstable_features, bad_style)]
#![deny(missing_debug_implementations, unused_import_braces, unused_qualifications, unsafe_code)]

mod group;
mod record;
mod stack;

use std::error;
use std::fmt::{self, Debug, Display, Formatter};

pub use group::{Group, GroupBuilder};
pub use record::{Commands, Record, RecordBuilder, Signal};
pub use stack::Stack;

/// Base functionality for all commands.
#[cfg(not(feature = "display"))]
pub trait Command<R>: Debug {
    /// Executes the desired command and returns `Ok` if everything went fine, and `Err` if
    /// something went wrong.
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    /// Restores the state as it was before [`exec`] was called and returns `Ok` if everything
    /// went fine, and `Err` if something went wrong.
    ///
    /// [`exec`]: trait.Command.html#tymethod.exec
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    /// Used for automatic merging of commands.
    ///
    /// Two commands are merged together when a command is pushed, and it has
    /// the same id as the top command already on the stack or record. When commands are merged together,
    /// undoing and redoing them are done in one step.
    ///
    /// # Examples
    /// ```
    /// use std::error::Error;
    /// use undo::{Command, Record};
    ///
    /// #[derive(Debug)]
    /// struct Add(char);
    ///
    /// impl Command<String> for Add {
    ///     fn exec(&mut self, s: &mut String) -> Result<(), Box<Error>> {
    ///         s.push(self.0);
    ///         Ok(())
    ///     }
    ///
    ///     fn undo(&mut self, s: &mut String) -> Result<(), Box<Error>> {
    ///         self.0 = s.pop().ok_or("`String` is unexpectedly empty")?;
    ///         Ok(())
    ///     }
    ///
    ///     fn id(&self) -> Option<u32> {
    ///         Some(1)
    ///     }
    /// }
    ///
    /// fn foo() -> Result<(), Box<Error>> {
    ///     let mut record = Record::default();
    ///
    ///     // 'a', 'b', and 'c' are merged.
    ///     record.exec(Add('a'))?;
    ///     record.exec(Add('b'))?;
    ///     record.exec(Add('c'))?;
    ///     assert_eq!(record.len(), 1);
    ///     assert_eq!(record.as_receiver(), "abc");
    ///
    ///     // Calling `undo` once will undo all merged commands.
    ///     record.undo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "");
    ///
    ///     // Calling `redo` once will redo all merged commands.
    ///     record.redo().unwrap()?;
    ///     assert_eq!(record.into_receiver(), "abc");
    ///
    ///     Ok(())
    /// }
    /// # foo().unwrap();
    /// ```
    #[inline]
    fn id(&self) -> Option<u32> {
        None
    }
}

/// Base functionality for all commands.
#[cfg(feature = "display")]
pub trait Command<R>: Debug + Display {
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>>;

    #[inline]
    fn id(&self) -> Option<u32> {
        None
    }
}

impl<R, C: Command<R> + ?Sized> Command<R> for Box<C> {
    #[inline]
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        (**self).exec(receiver)
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        (**self).undo(receiver)
    }

    #[inline]
    fn id(&self) -> Option<u32> {
        (**self).id()
    }
}

struct Merger<R> {
    cmd1: Box<Command<R>>,
    cmd2: Box<Command<R>>,
}

impl<R> Command<R> for Merger<R> {
    #[inline]
    fn exec(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        self.cmd1.exec(receiver)?;
        self.cmd2.exec(receiver)
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> Result<(), Box<error::Error>> {
        self.cmd2.undo(receiver)?;
        self.cmd1.undo(receiver)
    }

    #[inline]
    fn id(&self) -> Option<u32> {
        self.cmd1.id()
    }
}

impl<R> Debug for Merger<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Merger")
            .field("cmd1", &self.cmd1)
            .field("cmd2", &self.cmd2)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<R> Display for Merger<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{} + {}", self.cmd1, self.cmd2)
    }
}

/// An error kind that holds the error and the command that caused the error.
#[derive(Debug)]
pub struct Error<R>(pub Box<Command<R>>, pub Box<error::Error>);

impl<R> Display for Error<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.1)
    }
}

impl<R: Debug> error::Error for Error<R> {
    #[inline]
    fn description(&self) -> &str {
        self.1.description()
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        self.1.cause()
    }
}
<|endoftext|>


<commit_before>#![crate_name = "sos_kernel"]
#![crate_type = "staticlib"]
#![feature(asm)]
#![feature(no_std, lang_items)]
#![feature(const_fn)]
#![no_std]

extern crate rlibc;

pub mod arch;
pub mod io;
use io::term::{ Terminal, CONSOLE };

/// Kernel main loop
#[no_mangle]
pub extern fn kernel_main() {
    use core::fmt::Write;
    CONSOLE.lock().clear();
    CONSOLE.lock().write_str("Hello from the kernel!");
    loop { }
}

/// Required for Rust stack unwinding
#[lang = "eh_personality"]
extern fn eh_personality() {
    // TODO: add support for stack unwinding
}

#[lang = "panic_fmt"]
extern fn panic_fmt() -> ! {
    // TODO: actually format panics (waiting for robust VGA support)
    loop{}
}
<commit_msg>Actually import spinlocks crate (OOPS)<commit_after>#![crate_name = "sos_kernel"]
#![crate_type = "staticlib"]
#![feature(asm)]
#![feature(no_std, lang_items)]
#![feature(const_fn)]
#![no_std]

extern crate rlibc;
extern crate spin;

pub mod arch;
pub mod io;
use io::term::{ Terminal, CONSOLE };

/// Kernel main loop
#[no_mangle]
pub extern fn kernel_main() {
    use core::fmt::Write;
    CONSOLE.lock().clear();
    CONSOLE.lock().write_str("Hello from the kernel!");
    loop { }
}

/// Required for Rust stack unwinding
#[lang = "eh_personality"]
extern fn eh_personality() {
    // TODO: add support for stack unwinding
}

#[lang = "panic_fmt"]
extern fn panic_fmt() -> ! {
    // TODO: actually format panics (waiting for robust VGA support)
    loop{}
}
<|endoftext|>


<commit_before>// Copyright 2017 Ethan Welker
//
// 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
//
//     http://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.

//! Provides Cidr and Inet support for [`postgres`][1].
//!
//! Unlike several other names of this pattern, this is not affiliated
//! with or supported by the [author][2] of [`postgres`][1].
//!
//! Please see the `examples/` folder in the crate root for a simple example.
//!
//! [1]: https://crates.io/crates/postgres
//! [2]: https://github.com/sfackler
#![doc(html_root_url="https://docs.rs/postgres-inet")]
#![warn(missing_docs)]

#[macro_use]
extern crate postgres;

extern crate byteorder;

mod tests;

use postgres::types::{self, Type, ToSql, FromSql, IsNull};
use std::error::Error;
use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

const IPV4_NETMASK_FULL: u8 = 32;
const IPV4_ADDRESS_FAMILY: u8 = 2; // Should be AF_INET; See Issue #1
const IPV4_ADDRESS_SIZE: u8 = 4;

const IPV6_NETMASK_FULL: u8 = 128;
// AF_INET + 1, not AF_INET6; see postgres src/include/utils/inet.h
const IPV6_ADDRESS_FAMILY: u8 = 3;
const IPV6_ADDRESS_SIZE: u8 = 16;

#[derive(Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
/// An IP address with a netmask.
pub struct MaskedIpAddr {
    addr: IpAddr,
    mask: u8,
}

impl MaskedIpAddr {
    /// Creates a new `MaskedIpAddr` from components.
    ///
    /// # Panics
    ///
    /// Panics if the netmask is greater than 32 for an IPv4 address, or is
    /// greater than 128 for an IPv6 address.
    ///
    /// # Examples
    ///
    /// To represent an address:
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::Ipv4Addr;
    /// let ip = Ipv4Addr::new(192, 0, 2, 142);
    /// MaskedIpAddr::new(ip, 32);
    /// ```
    ///
    /// To represent a network:
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::Ipv6Addr;
    /// let network = Ipv6Addr::new(0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0);
    /// MaskedIpAddr::new(network, 32);
    /// ```
    pub fn new<I: Into<IpAddr>>(addr: I, mask: u8) -> MaskedIpAddr {
        let addr = addr.into();

        if match addr {
            IpAddr::V4(_) => mask > IPV4_NETMASK_FULL,
            IpAddr::V6(_) => mask > IPV6_NETMASK_FULL,
        } {
            panic!("Mask too big for IP type!");
        }

        MaskedIpAddr {
            addr: addr,
            mask: mask,
        }
    }

    /// Returns true for the special 'unspecified' address.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::{Ipv4Addr, Ipv6Addr};
    /// assert!(MaskedIpAddr::new(Ipv4Addr::new(0, 0, 0, 0), 32).is_unspecified());
    /// assert!(MaskedIpAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128).is_unspecified());
    /// ```
    pub fn is_unspecified(&self) -> bool {
        self.addr.is_unspecified()
    }

    /// Returns true if this is a loopback address.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::{Ipv4Addr, Ipv6Addr};
    /// assert!(MaskedIpAddr::new(Ipv4Addr::new(127, 0, 0, 1), 32).is_loopback());
    /// assert!(MaskedIpAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 128).is_loopback());
    /// ```
    pub fn is_loopback(&self) -> bool {
        self.addr.is_loopback()
    }

    /// Returns true if this is a multicast address.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::{Ipv4Addr, Ipv6Addr};
    /// assert!(MaskedIpAddr::new(Ipv4Addr::new(224, 254, 0, 0), 32).is_multicast());
    /// assert!(MaskedIpAddr::new(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0), 128).is_multicast());
    /// ```
    pub fn is_multicast(&self) -> bool {
        self.addr.is_multicast()
    }

    /// Consumes the `MaskedIpAddr`, returning the IP address and netmask.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::Ipv4Addr;
    /// let network = Ipv4Addr::new(198, 51, 100, 0);
    /// let (network_b, netmask) = MaskedIpAddr::new(network.clone(), 24).into_inner();
    /// assert_eq!(network, network_b);
    /// assert_eq!(netmask, 24);
    /// ```
    pub fn into_inner(self) -> (IpAddr, u8) {
        (self.addr, self.mask)
    }
}

impl From<Ipv4Addr> for MaskedIpAddr {
    fn from(ipv4: Ipv4Addr) -> MaskedIpAddr {
        MaskedIpAddr {
            addr: IpAddr::V4(ipv4),
            mask: IPV4_NETMASK_FULL,
        }
    }
}

impl From<Ipv6Addr> for MaskedIpAddr {
    fn from(ipv6: Ipv6Addr) -> MaskedIpAddr {
        MaskedIpAddr {
            addr: IpAddr::V6(ipv6),
            mask: IPV6_NETMASK_FULL,
        }
    }
}

impl From<IpAddr> for MaskedIpAddr {
    fn from(ip: IpAddr) -> MaskedIpAddr {
        MaskedIpAddr {
            mask: match ip {
                IpAddr::V4(_) => IPV4_NETMASK_FULL,
                IpAddr::V6(_) => IPV6_NETMASK_FULL,
            },
            addr: ip,
        }
    }
}

impl From<MaskedIpAddr> for IpAddr {
    fn from(mip: MaskedIpAddr) -> IpAddr {
        mip.addr
    }
}

impl fmt::Display for MaskedIpAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.addr {
            IpAddr::V4(ipv4) => {
                match self.mask {
                    IPV4_NETMASK_FULL => ipv4.fmt(f),
                    _ => write!(f, "{}/{}", ipv4, self.mask),
                }
            }
            IpAddr::V6(ipv6) => {
                match self.mask {
                    IPV6_NETMASK_FULL => ipv6.fmt(f),
                    _ => write!(f, "{}/{}", ipv6, self.mask),
                }
            }
        }

    }
}

impl fmt::Debug for MaskedIpAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}/{}", self.addr, self.mask)
    }
}

impl FromSql for MaskedIpAddr {
    fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<Error + 'static + Sync + Send>> {
        // The address family is at raw[0], as AF_INET for ipv4 or (AF_INET + 1)
        // for ipv6.  It's unneeded, as `nb` at raw[3] tells us the version just as
        // well. A bool of the `cidr`ness is at raw[2]. It's also unneeded, as it
        // doesn't affect our codepath in any way whatsoever.

        Ok(MaskedIpAddr {
            addr: match raw[3] {
                IPV4_ADDRESS_SIZE => IpAddr::V4(Ipv4Addr::new(raw[4], raw[5], raw[6], raw[7])),
                IPV6_ADDRESS_SIZE => {
                    // The IPv6 is sent in network byte order, so we need to convert it to the host
                    // order.
                    use byteorder::{NetworkEndian, ReadBytesExt};
                    use std::io::Read;

                    let mut raw = raw;
                    raw.read_exact(&mut [0u8; 4])?; // throw away the first four bytes
                    IpAddr::V6(Ipv6Addr::new(raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?))
                }
                _ => panic!("Unknown Internet Protocol Version!"),
            },
            mask: raw[1],
        })
    }

    fn accepts(ty: &Type) -> bool {
        match *ty {
            types::CIDR | types::INET => true,
            _ => false,
        }
    }
}

impl ToSql for MaskedIpAddr {
    fn to_sql(&self, ty: &Type, w: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
        // We're relying on the optimizer to clean this up.

        w.push(match self.addr { // Address Family
            IpAddr::V4(_) => IPV4_ADDRESS_FAMILY,
            IpAddr::V6(_) => IPV6_ADDRESS_FAMILY,
        });
        w.push(self.mask); // Subnet mask
        w.push(match *ty { // cidr
            types::CIDR => true as u8,
            types::INET => false as u8,
            _ => unreachable!(),
        });
        w.push(match self.addr {
            IpAddr::V4(_) => IPV4_ADDRESS_SIZE,
            IpAddr::V6(_) => IPV6_ADDRESS_SIZE,
        });
        match self.addr { // Luckily, ipv6.octets() outputs in Network Byte Order.
            IpAddr::V4(ipv4) => w.append(&mut ipv4.octets().to_vec()),
            IpAddr::V6(ipv6) => w.append(&mut ipv6.octets().to_vec()),
        };

        Ok(IsNull::No)
    }

    accepts!(types::CIDR, types::INET);
    to_sql_checked!();
}
<commit_msg>Use `extend_from_slice` instead of append vector (#2)<commit_after>// Copyright 2017 Ethan Welker
//
// 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
//
//     http://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.

//! Provides Cidr and Inet support for [`postgres`][1].
//!
//! Unlike several other names of this pattern, this is not affiliated
//! with or supported by the [author][2] of [`postgres`][1].
//!
//! Please see the `examples/` folder in the crate root for a simple example.
//!
//! [1]: https://crates.io/crates/postgres
//! [2]: https://github.com/sfackler
#![doc(html_root_url="https://docs.rs/postgres-inet")]
#![warn(missing_docs)]

#[macro_use]
extern crate postgres;

extern crate byteorder;

mod tests;

use postgres::types::{self, Type, ToSql, FromSql, IsNull};
use std::error::Error;
use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

const IPV4_NETMASK_FULL: u8 = 32;
const IPV4_ADDRESS_FAMILY: u8 = 2; // Should be AF_INET; See Issue #1
const IPV4_ADDRESS_SIZE: u8 = 4;

const IPV6_NETMASK_FULL: u8 = 128;
// AF_INET + 1, not AF_INET6; see postgres src/include/utils/inet.h
const IPV6_ADDRESS_FAMILY: u8 = 3;
const IPV6_ADDRESS_SIZE: u8 = 16;

#[derive(Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
/// An IP address with a netmask.
pub struct MaskedIpAddr {
    addr: IpAddr,
    mask: u8,
}

impl MaskedIpAddr {
    /// Creates a new `MaskedIpAddr` from components.
    ///
    /// # Panics
    ///
    /// Panics if the netmask is greater than 32 for an IPv4 address, or is
    /// greater than 128 for an IPv6 address.
    ///
    /// # Examples
    ///
    /// To represent an address:
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::Ipv4Addr;
    /// let ip = Ipv4Addr::new(192, 0, 2, 142);
    /// MaskedIpAddr::new(ip, 32);
    /// ```
    ///
    /// To represent a network:
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::Ipv6Addr;
    /// let network = Ipv6Addr::new(0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0);
    /// MaskedIpAddr::new(network, 32);
    /// ```
    pub fn new<I: Into<IpAddr>>(addr: I, mask: u8) -> MaskedIpAddr {
        let addr = addr.into();

        if match addr {
            IpAddr::V4(_) => mask > IPV4_NETMASK_FULL,
            IpAddr::V6(_) => mask > IPV6_NETMASK_FULL,
        } {
            panic!("Mask too big for IP type!");
        }

        MaskedIpAddr {
            addr: addr,
            mask: mask,
        }
    }

    /// Returns true for the special 'unspecified' address.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::{Ipv4Addr, Ipv6Addr};
    /// assert!(MaskedIpAddr::new(Ipv4Addr::new(0, 0, 0, 0), 32).is_unspecified());
    /// assert!(MaskedIpAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128).is_unspecified());
    /// ```
    pub fn is_unspecified(&self) -> bool {
        self.addr.is_unspecified()
    }

    /// Returns true if this is a loopback address.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::{Ipv4Addr, Ipv6Addr};
    /// assert!(MaskedIpAddr::new(Ipv4Addr::new(127, 0, 0, 1), 32).is_loopback());
    /// assert!(MaskedIpAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 128).is_loopback());
    /// ```
    pub fn is_loopback(&self) -> bool {
        self.addr.is_loopback()
    }

    /// Returns true if this is a multicast address.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::{Ipv4Addr, Ipv6Addr};
    /// assert!(MaskedIpAddr::new(Ipv4Addr::new(224, 254, 0, 0), 32).is_multicast());
    /// assert!(MaskedIpAddr::new(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0), 128).is_multicast());
    /// ```
    pub fn is_multicast(&self) -> bool {
        self.addr.is_multicast()
    }

    /// Consumes the `MaskedIpAddr`, returning the IP address and netmask.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use postgres_inet::MaskedIpAddr;
    /// # use std::net::Ipv4Addr;
    /// let network = Ipv4Addr::new(198, 51, 100, 0);
    /// let (network_b, netmask) = MaskedIpAddr::new(network.clone(), 24).into_inner();
    /// assert_eq!(network, network_b);
    /// assert_eq!(netmask, 24);
    /// ```
    pub fn into_inner(self) -> (IpAddr, u8) {
        (self.addr, self.mask)
    }
}

impl From<Ipv4Addr> for MaskedIpAddr {
    fn from(ipv4: Ipv4Addr) -> MaskedIpAddr {
        MaskedIpAddr {
            addr: IpAddr::V4(ipv4),
            mask: IPV4_NETMASK_FULL,
        }
    }
}

impl From<Ipv6Addr> for MaskedIpAddr {
    fn from(ipv6: Ipv6Addr) -> MaskedIpAddr {
        MaskedIpAddr {
            addr: IpAddr::V6(ipv6),
            mask: IPV6_NETMASK_FULL,
        }
    }
}

impl From<IpAddr> for MaskedIpAddr {
    fn from(ip: IpAddr) -> MaskedIpAddr {
        MaskedIpAddr {
            mask: match ip {
                IpAddr::V4(_) => IPV4_NETMASK_FULL,
                IpAddr::V6(_) => IPV6_NETMASK_FULL,
            },
            addr: ip,
        }
    }
}

impl From<MaskedIpAddr> for IpAddr {
    fn from(mip: MaskedIpAddr) -> IpAddr {
        mip.addr
    }
}

impl fmt::Display for MaskedIpAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.addr {
            IpAddr::V4(ipv4) => {
                match self.mask {
                    IPV4_NETMASK_FULL => ipv4.fmt(f),
                    _ => write!(f, "{}/{}", ipv4, self.mask),
                }
            }
            IpAddr::V6(ipv6) => {
                match self.mask {
                    IPV6_NETMASK_FULL => ipv6.fmt(f),
                    _ => write!(f, "{}/{}", ipv6, self.mask),
                }
            }
        }

    }
}

impl fmt::Debug for MaskedIpAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}/{}", self.addr, self.mask)
    }
}

impl FromSql for MaskedIpAddr {
    fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<Error + 'static + Sync + Send>> {
        // The address family is at raw[0], as AF_INET for ipv4 or (AF_INET + 1)
        // for ipv6.  It's unneeded, as `nb` at raw[3] tells us the version just as
        // well. A bool of the `cidr`ness is at raw[2]. It's also unneeded, as it
        // doesn't affect our codepath in any way whatsoever.

        Ok(MaskedIpAddr {
            addr: match raw[3] {
                IPV4_ADDRESS_SIZE => IpAddr::V4(Ipv4Addr::new(raw[4], raw[5], raw[6], raw[7])),
                IPV6_ADDRESS_SIZE => {
                    // The IPv6 is sent in network byte order, so we need to convert it to the host
                    // order.
                    use byteorder::{NetworkEndian, ReadBytesExt};
                    use std::io::Read;

                    let mut raw = raw;
                    raw.read_exact(&mut [0u8; 4])?; // throw away the first four bytes
                    IpAddr::V6(Ipv6Addr::new(raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?,
                                             raw.read_u16::<NetworkEndian>()?))
                }
                _ => panic!("Unknown Internet Protocol Version!"),
            },
            mask: raw[1],
        })
    }

    fn accepts(ty: &Type) -> bool {
        match *ty {
            types::CIDR | types::INET => true,
            _ => false,
        }
    }
}

impl ToSql for MaskedIpAddr {
    fn to_sql(&self, ty: &Type, w: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
        // We're relying on the optimizer to clean this up.

        w.push(match self.addr { // Address Family
            IpAddr::V4(_) => IPV4_ADDRESS_FAMILY,
            IpAddr::V6(_) => IPV6_ADDRESS_FAMILY,
        });
        w.push(self.mask); // Subnet mask
        w.push(match *ty { // cidr
            types::CIDR => true as u8,
            types::INET => false as u8,
            _ => unreachable!(),
        });
        w.push(match self.addr {
            IpAddr::V4(_) => IPV4_ADDRESS_SIZE,
            IpAddr::V6(_) => IPV6_ADDRESS_SIZE,
        });
        match self.addr { // Luckily, ipv6.octets() outputs in Network Byte Order.
            IpAddr::V4(ipv4) => w.extend_from_slice(&ipv4.octets()),
            IpAddr::V6(ipv6) => w.extend_from_slice(&ipv6.octets()),
        };

        Ok(IsNull::No)
    }

    accepts!(types::CIDR, types::INET);
    to_sql_checked!();
}
<|endoftext|>


<commit_before>//! Timestamps for files in Rust
//!
//! This library provides platform-agnostic inspection of the various timestamps
//! present in the standard `fs::Metadata` structure.
//!
//! # Installation
//!
//! Add this to you `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! filetime = "0.1"
//! ```
//!
//! # Usage
//!
//! ```no_run
//! use std::fs;
//! use filetime::FileTime;
//!
//! let metadata = fs::metadata("foo.txt").unwrap();
//!
//! let mtime = FileTime::from_last_modification_time(&metadata);
//! println!("{}", mtime);
//!
//! let atime = FileTime::from_last_access_time(&metadata);
//! assert!(mtime < atime);
//!
//! // Inspect values that can be interpreted across platforms
//! println!("{}", mtime.seconds_relative_to_1970());
//! println!("{}", mtime.nanoseconds());
//!
//! // Print the platform-specific value of seconds
//! println!("{}", mtime.seconds());
//! ```

extern crate libc;

#[cfg(unix)] use std::os::unix::prelude::*;
#[cfg(windows)] use std::os::windows::prelude::*;

use std::fmt;
use std::fs;
use std::io;
use std::path::Path;

/// A helper structure to represent a timestamp for a file.
///
/// The actual value contined within is platform-specific and does not have the
/// same meaning across platforms, but comparisons and stringification can be
/// significant among the same platform.
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone, Hash)]
pub struct FileTime {
    seconds: u64,
    nanos: u32,
}

impl FileTime {
    /// Creates a new timestamp representing a 0 time.
    ///
    /// Useful for creating the base of a cmp::max chain of times.
    pub fn zero() -> FileTime {
        FileTime { seconds: 0, nanos: 0 }
    }

    /// Creates a new instance of `FileTime` with a number of seconds and
    /// nanoseconds relative to January 1, 1970.
    ///
    /// Note that this is typically the relative point that Unix time stamps are
    /// from, but on Windows the native time stamp is relative to January 1,
    /// 1601 so the return value of `seconds` from the returned `FileTime`
    /// instance may not be the same as that passed in.
    pub fn from_seconds_since_1970(seconds: u64, nanos: u32) -> FileTime {
        FileTime {
            seconds: seconds + if cfg!(windows) {11644473600} else {0},
            nanos: nanos,
        }
    }

    /// Creates a new timestamp from the last modification time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `mtime` field of `stat` on Unix
    /// platforms and the `ftLastWriteTime` field on Windows platforms.
    pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.mtime() as u64, meta.mtime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_write_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the last access time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `atime` field of `stat` on Unix
    /// platforms and the `ftLastAccessTime` field on Windows platforms.
    pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.atime() as u64, meta.atime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_access_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the creation time listed in the specified
    /// metadata.
    ///
    /// The returned value corresponds to the `birthtime` field of `stat` on
    /// Unix platforms and the `ftCreationTime` field on Windows platforms. Note
    /// that not all Unix platforms have this field available and may return
    /// `None` in some circumstances.
    pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
        macro_rules! birthtim {
            ($(($e:expr, $i:ident)),*) => {
                #[cfg(any($(target_os = $e),*))]
                fn imp(meta: &fs::Metadata) -> Option<FileTime> {
                    $(
                        #[cfg(target_os = $e)]
                        use std::os::$i::fs::MetadataExt;
                    )*
                    let raw = meta.as_raw_stat();
                    Some(FileTime::from_os_repr(raw.st_birthtime as u64,
                                                raw.st_birthtime_nsec as u32))
                }

                #[cfg(all(not(windows),
                          $(not(target_os = $e)),*))]
                fn imp(_meta: &fs::Metadata) -> Option<FileTime> {
                    None
                }
            }
        }

        birthtim! {
            ("bitrig", bitrig),
            ("freebsd", freebsd),
            ("ios", ios),
            ("macos", macos),
            ("openbsd", openbsd)
        }

        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> Option<FileTime> {
            Some(FileTime::from_os_repr(meta.last_access_time()))
        }
        imp(meta)
    }

    #[cfg(windows)]
    fn from_os_repr(time: u64) -> FileTime {
        // Windows write times are in 100ns intervals, so do a little math to
        // get it into the right representation.
        FileTime {
            seconds: time / (1_000_000_000 / 100),
            nanos: ((time % (1_000_000_000 / 100)) * 100) as u32,
        }
    }

    #[cfg(unix)]
    fn from_os_repr(seconds: u64, nanos: u32) -> FileTime {
        FileTime { seconds: seconds, nanos: nanos }
    }

    /// Returns the whole number of seconds represented by this timestamp.
    ///
    /// Note that this value's meaning is **platform specific**. On Unix
    /// platform time stamps are typically relative to January 1, 1970, but on
    /// Windows platforms time stamps are relative to January 1, 1601.
    pub fn seconds(&self) -> u64 { self.seconds }

    /// Returns the whole number of seconds represented by this timestamp,
    /// relative to the Unix epoch start of January 1, 1970.
    ///
    /// Note that this does not return the same value as `seconds` for Windows
    /// platforms as seconds are relative to a different date there.
    pub fn seconds_relative_to_1970(&self) -> u64 {
        self.seconds - if cfg!(windows) {11644473600} else {0}
    }

    /// Returns the nanosecond precision of this timestamp.
    ///
    /// The returned value is always less than one billion and represents a
    /// portion of a second forward from the seconds returned by the `seconds`
    /// method.
    pub fn nanoseconds(&self) -> u32 { self.nanos }
}

impl fmt::Display for FileTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}.{:09}s", self.seconds, self.nanos)
    }
}

/// Set the last access and modification times for a file on the filesystem.
///
/// This function will set the `atime` and `mtime` metadata fields for a file
/// on the local filesystem, returning any error encountered.
pub fn set_file_times<P>(p: P, atime: FileTime, mtime: FileTime)
                         -> io::Result<()> where P: AsRef<Path> {
    set_file_times_(p.as_ref(), atime, mtime)
}

#[cfg(unix)]
fn set_file_times_(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    use std::ffi::CString;
    use libc::{timeval, time_t, suseconds_t, utimes};

    let times = [to_timeval(&atime), to_timeval(&mtime)];
    let p = try!(CString::new(p.as_os_str().as_bytes()));
    return unsafe {
        if utimes(p.as_ptr() as *const _, times.as_ptr()) == 0 {
            Ok(())
        } else {
            Err(io::Error::last_os_error())
        }
    };

    fn to_timeval(ft: &FileTime) -> timeval {
        timeval {
            tv_sec: ft.seconds() as time_t,
            tv_usec: (ft.nanoseconds() / 1000) as suseconds_t,
        }
    }
}

#[cfg(windows)]
#[allow(bad_style)]
fn set_file_times_(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    use std::fs::OpenOptions;

    type BOOL = i32;
    type HANDLE = *mut u8;
    type DWORD = u32;
    #[repr(C)]
    struct FILETIME {
        dwLowDateTime: u32,
        dwHighDateTime: u32,
    }
    extern "system" {
        fn SetFileTime(hFile: HANDLE,
                       lpCreationTime: *const FILETIME,
                       lpLastAccessTime: *const FILETIME,
                       lpLastWriteTime: *const FILETIME) -> BOOL;
    }

    let f = try!(OpenOptions::new().write(true).open(p));
    let atime = to_filetime(&atime);
    let mtime = to_filetime(&mtime);
    return unsafe {
        let ret = SetFileTime(f.as_raw_handle() as *mut _,
                              0 as *const _,
                              &atime, &mtime);
        if ret != 0 {
            Ok(())
        } else {
            Err(io::Error::last_os_error())
        }
    };

    fn to_filetime(ft: &FileTime) -> FILETIME {
        let intervals = ft.seconds() * (1_000_000_000 / 100) +
                        ((ft.nanoseconds() as u64) / 100);
        FILETIME {
            dwLowDateTime: intervals as DWORD,
            dwHighDateTime: (intervals >> 32) as DWORD,
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use std::fs::{self, File};
    use self::tempdir::TempDir;
    use super::{FileTime, set_file_times};

    #[test]
    fn set_file_times_test() {
        let td = TempDir::new("filetime").unwrap();
        let path = td.path().join("foo.txt");
        File::create(&path).unwrap();

        let metadata = fs::metadata(&path).unwrap();
        let mtime = FileTime::from_last_modification_time(&metadata);
        let atime = FileTime::from_last_access_time(&metadata);
        set_file_times(&path, atime, mtime).unwrap();

        let new_mtime = FileTime::from_seconds_since_1970(10_000, 0);
        set_file_times(&path, atime, new_mtime).unwrap();

        let metadata = fs::metadata(&path).unwrap();
        let mtime = FileTime::from_last_modification_time(&metadata);
        assert_eq!(mtime, new_mtime);
    }
}
<commit_msg>Fix typo in doc comment<commit_after>//! Timestamps for files in Rust
//!
//! This library provides platform-agnostic inspection of the various timestamps
//! present in the standard `fs::Metadata` structure.
//!
//! # Installation
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! filetime = "0.1"
//! ```
//!
//! # Usage
//!
//! ```no_run
//! use std::fs;
//! use filetime::FileTime;
//!
//! let metadata = fs::metadata("foo.txt").unwrap();
//!
//! let mtime = FileTime::from_last_modification_time(&metadata);
//! println!("{}", mtime);
//!
//! let atime = FileTime::from_last_access_time(&metadata);
//! assert!(mtime < atime);
//!
//! // Inspect values that can be interpreted across platforms
//! println!("{}", mtime.seconds_relative_to_1970());
//! println!("{}", mtime.nanoseconds());
//!
//! // Print the platform-specific value of seconds
//! println!("{}", mtime.seconds());
//! ```

extern crate libc;

#[cfg(unix)] use std::os::unix::prelude::*;
#[cfg(windows)] use std::os::windows::prelude::*;

use std::fmt;
use std::fs;
use std::io;
use std::path::Path;

/// A helper structure to represent a timestamp for a file.
///
/// The actual value contined within is platform-specific and does not have the
/// same meaning across platforms, but comparisons and stringification can be
/// significant among the same platform.
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone, Hash)]
pub struct FileTime {
    seconds: u64,
    nanos: u32,
}

impl FileTime {
    /// Creates a new timestamp representing a 0 time.
    ///
    /// Useful for creating the base of a cmp::max chain of times.
    pub fn zero() -> FileTime {
        FileTime { seconds: 0, nanos: 0 }
    }

    /// Creates a new instance of `FileTime` with a number of seconds and
    /// nanoseconds relative to January 1, 1970.
    ///
    /// Note that this is typically the relative point that Unix time stamps are
    /// from, but on Windows the native time stamp is relative to January 1,
    /// 1601 so the return value of `seconds` from the returned `FileTime`
    /// instance may not be the same as that passed in.
    pub fn from_seconds_since_1970(seconds: u64, nanos: u32) -> FileTime {
        FileTime {
            seconds: seconds + if cfg!(windows) {11644473600} else {0},
            nanos: nanos,
        }
    }

    /// Creates a new timestamp from the last modification time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `mtime` field of `stat` on Unix
    /// platforms and the `ftLastWriteTime` field on Windows platforms.
    pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.mtime() as u64, meta.mtime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_write_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the last access time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `atime` field of `stat` on Unix
    /// platforms and the `ftLastAccessTime` field on Windows platforms.
    pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.atime() as u64, meta.atime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_access_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the creation time listed in the specified
    /// metadata.
    ///
    /// The returned value corresponds to the `birthtime` field of `stat` on
    /// Unix platforms and the `ftCreationTime` field on Windows platforms. Note
    /// that not all Unix platforms have this field available and may return
    /// `None` in some circumstances.
    pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
        macro_rules! birthtim {
            ($(($e:expr, $i:ident)),*) => {
                #[cfg(any($(target_os = $e),*))]
                fn imp(meta: &fs::Metadata) -> Option<FileTime> {
                    $(
                        #[cfg(target_os = $e)]
                        use std::os::$i::fs::MetadataExt;
                    )*
                    let raw = meta.as_raw_stat();
                    Some(FileTime::from_os_repr(raw.st_birthtime as u64,
                                                raw.st_birthtime_nsec as u32))
                }

                #[cfg(all(not(windows),
                          $(not(target_os = $e)),*))]
                fn imp(_meta: &fs::Metadata) -> Option<FileTime> {
                    None
                }
            }
        }

        birthtim! {
            ("bitrig", bitrig),
            ("freebsd", freebsd),
            ("ios", ios),
            ("macos", macos),
            ("openbsd", openbsd)
        }

        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> Option<FileTime> {
            Some(FileTime::from_os_repr(meta.last_access_time()))
        }
        imp(meta)
    }

    #[cfg(windows)]
    fn from_os_repr(time: u64) -> FileTime {
        // Windows write times are in 100ns intervals, so do a little math to
        // get it into the right representation.
        FileTime {
            seconds: time / (1_000_000_000 / 100),
            nanos: ((time % (1_000_000_000 / 100)) * 100) as u32,
        }
    }

    #[cfg(unix)]
    fn from_os_repr(seconds: u64, nanos: u32) -> FileTime {
        FileTime { seconds: seconds, nanos: nanos }
    }

    /// Returns the whole number of seconds represented by this timestamp.
    ///
    /// Note that this value's meaning is **platform specific**. On Unix
    /// platform time stamps are typically relative to January 1, 1970, but on
    /// Windows platforms time stamps are relative to January 1, 1601.
    pub fn seconds(&self) -> u64 { self.seconds }

    /// Returns the whole number of seconds represented by this timestamp,
    /// relative to the Unix epoch start of January 1, 1970.
    ///
    /// Note that this does not return the same value as `seconds` for Windows
    /// platforms as seconds are relative to a different date there.
    pub fn seconds_relative_to_1970(&self) -> u64 {
        self.seconds - if cfg!(windows) {11644473600} else {0}
    }

    /// Returns the nanosecond precision of this timestamp.
    ///
    /// The returned value is always less than one billion and represents a
    /// portion of a second forward from the seconds returned by the `seconds`
    /// method.
    pub fn nanoseconds(&self) -> u32 { self.nanos }
}

impl fmt::Display for FileTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}.{:09}s", self.seconds, self.nanos)
    }
}

/// Set the last access and modification times for a file on the filesystem.
///
/// This function will set the `atime` and `mtime` metadata fields for a file
/// on the local filesystem, returning any error encountered.
pub fn set_file_times<P>(p: P, atime: FileTime, mtime: FileTime)
                         -> io::Result<()> where P: AsRef<Path> {
    set_file_times_(p.as_ref(), atime, mtime)
}

#[cfg(unix)]
fn set_file_times_(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    use std::ffi::CString;
    use libc::{timeval, time_t, suseconds_t, utimes};

    let times = [to_timeval(&atime), to_timeval(&mtime)];
    let p = try!(CString::new(p.as_os_str().as_bytes()));
    return unsafe {
        if utimes(p.as_ptr() as *const _, times.as_ptr()) == 0 {
            Ok(())
        } else {
            Err(io::Error::last_os_error())
        }
    };

    fn to_timeval(ft: &FileTime) -> timeval {
        timeval {
            tv_sec: ft.seconds() as time_t,
            tv_usec: (ft.nanoseconds() / 1000) as suseconds_t,
        }
    }
}

#[cfg(windows)]
#[allow(bad_style)]
fn set_file_times_(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    use std::fs::OpenOptions;

    type BOOL = i32;
    type HANDLE = *mut u8;
    type DWORD = u32;
    #[repr(C)]
    struct FILETIME {
        dwLowDateTime: u32,
        dwHighDateTime: u32,
    }
    extern "system" {
        fn SetFileTime(hFile: HANDLE,
                       lpCreationTime: *const FILETIME,
                       lpLastAccessTime: *const FILETIME,
                       lpLastWriteTime: *const FILETIME) -> BOOL;
    }

    let f = try!(OpenOptions::new().write(true).open(p));
    let atime = to_filetime(&atime);
    let mtime = to_filetime(&mtime);
    return unsafe {
        let ret = SetFileTime(f.as_raw_handle() as *mut _,
                              0 as *const _,
                              &atime, &mtime);
        if ret != 0 {
            Ok(())
        } else {
            Err(io::Error::last_os_error())
        }
    };

    fn to_filetime(ft: &FileTime) -> FILETIME {
        let intervals = ft.seconds() * (1_000_000_000 / 100) +
                        ((ft.nanoseconds() as u64) / 100);
        FILETIME {
            dwLowDateTime: intervals as DWORD,
            dwHighDateTime: (intervals >> 32) as DWORD,
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use std::fs::{self, File};
    use self::tempdir::TempDir;
    use super::{FileTime, set_file_times};

    #[test]
    fn set_file_times_test() {
        let td = TempDir::new("filetime").unwrap();
        let path = td.path().join("foo.txt");
        File::create(&path).unwrap();

        let metadata = fs::metadata(&path).unwrap();
        let mtime = FileTime::from_last_modification_time(&metadata);
        let atime = FileTime::from_last_access_time(&metadata);
        set_file_times(&path, atime, mtime).unwrap();

        let new_mtime = FileTime::from_seconds_since_1970(10_000, 0);
        set_file_times(&path, atime, new_mtime).unwrap();

        let metadata = fs::metadata(&path).unwrap();
        let mtime = FileTime::from_last_modification_time(&metadata);
        assert_eq!(mtime, new_mtime);
    }
}
<|endoftext|>


<commit_before>extern crate crypto;
extern crate rustc_serialize;

use crypto::{buffer, blockmodes};
use crypto::aes::{cbc_decryptor, KeySize as AesKeySize};
use crypto::buffer::{WriteBuffer, ReadBuffer, BufferResult};
use crypto::hmac::Hmac;
use crypto::mac::{Mac};
use crypto::sha1::Sha1;
use crypto::pbkdf2::pbkdf2;
use crypto::util::fixed_time_eq;

use rustc_serialize::hex::FromHex;
use rustc_serialize::base64::FromBase64;

use std::str::from_utf8;

pub struct Verifier {
    secret_key: Vec<u8>
}

#[derive(Debug, PartialEq)]
pub enum VerifierError {
    MessageParse,
    InvalidSignature,
    DecodePayload
}

pub fn create_derived_keys(secret: &str, salts: &Vec<&str>, key_iters: u32, key_sz: u32) -> Vec<Vec<u8>> {
    let mut mac = Hmac::new(Sha1::new(), secret.as_bytes());

    salts.iter().map(|salt| {
        let mut result: Vec<u8> = vec![0; key_sz as usize];

        pbkdf2(&mut mac, salt.as_bytes(), key_iters, &mut result);

        result
    }).collect()
}

fn split_by_dashes(message: &str) -> Option<(&str, &str)> {
    let split: Vec<&str> = message.splitn(2, "--").collect();

    match split.len() {
        2 => Some((split.first().unwrap(), split.last().unwrap())),
        _ => None
    }
}

fn split_by_dashes_from_u8_slice(slice: &[u8]) -> Option<(&str, &str)> {
    match from_utf8(slice) {
        Ok(string) => split_by_dashes(string),
        Err(_) => None
    }
}

impl Verifier {
    pub fn new(secret: &str) -> Verifier {
        Verifier {
            secret_key: secret.bytes().collect()
        }
    }

    pub fn verify(&self, message: &str) -> Result<Vec<u8>, VerifierError> {
        match split_by_dashes(&message) {
            Some((encoded_data, signature)) => {
                match self.is_valid_message(encoded_data, signature) {
                    true => {
                        match encoded_data.from_base64() {
                            Ok(decoded) => Ok(decoded),
                            Err(_) => Err(VerifierError::DecodePayload)
                        }
                    },

                    false => Err(VerifierError::InvalidSignature)
                }
            },

            None => Err(VerifierError::MessageParse)
        }
    }

    pub fn is_valid_message(&self, encoded_data: &str, signature: &str) -> bool {
        match signature.from_hex() {
            Ok(sig_bytes) => {
                let mut mac = Hmac::new(Sha1::new(), &self.secret_key);

                mac.input(encoded_data.as_bytes());

                fixed_time_eq(mac.result().code(), &sig_bytes)
            },

            Err(_) => false
        }
    }
}

pub struct Encryptor {
    secret_key: Vec<u8>,
    verifier: Verifier
}

#[derive(Debug, PartialEq)]
pub enum EncryptorError {
    InvalidSignature,
    MessageParse,
    MessageDecode,
    DecryptError
}

impl Encryptor {
    pub fn new(secret: &str, salt: &str, sign_salt: &str, key_iters: u32, key_sz: u32) -> Encryptor {
        let salts = vec![salt, sign_salt];
        let keys = create_derived_keys(secret, &salts, key_iters, key_sz);

        match (keys.first(), keys.last()) {
            (Some(cipher_key), Some(sig_key)) => {
                Encryptor {
                    secret_key: cipher_key.to_vec(),
                    verifier: Verifier {
                        secret_key: sig_key.to_vec()
                    }
                }
            }

            _ => panic!("KDF Failed for Encryptor")
        }
    }

    pub fn decrypt_and_verify(&self, message: &str) -> Result<Vec<u8>, EncryptorError>  {
        match self.verifier.verify(message) {
            Ok(decoded) => {
                match split_by_dashes_from_u8_slice(&decoded) {
                    Some((encoded_cipher_text, encoded_iv)) => {
                        println!("{:?}", encoded_cipher_text);
                        println!("{:?}", encoded_iv);

                        match (encoded_cipher_text.from_base64(), encoded_iv.from_base64()) {
                            (Ok(cipher_text), Ok(iv)) => {
                                let key_sz = AesKeySize::KeySize256; // TODO make configurable
                                let mut decryptor = cbc_decryptor(key_sz, &self.secret_key, &iv, blockmodes::PkcsPadding);

                                let mut final_result: Vec<u8> = Vec::new();
                                let mut buffer = [0; 4096];

                                let mut read_buffer = buffer::RefReadBuffer::new(&cipher_text);
                                let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

                                loop {
                                    match decryptor.decrypt(&mut read_buffer, &mut write_buffer, true) {
                                        Ok(buffer_result) => {
                                            final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));

                                            match buffer_result {
                                                BufferResult::BufferUnderflow => break,
                                                BufferResult::BufferOverflow => continue
                                            }
                                        }

                                        Err(_) => return Err(EncryptorError::DecryptError)
                                    }
                                }

                                Ok(final_result)
                            },

                            _ => Err(EncryptorError::MessageDecode)
                        }
                    },

                    None => Err(EncryptorError::MessageParse)
                }
            }

            Err(_) => Err(EncryptorError::InvalidSignature)
        }

    }
}

#[cfg(test)]
mod tests {
    use std::str;

    use Verifier;
    use VerifierError;

    use Encryptor;
    use EncryptorError;

    #[test]
    fn is_valid_message_returns_true_for_valid_signatures() {
        let data = "eyJrZXkiOiJ2YWx1ZSJ9";
        let sig  = "fa115453dbb4a28277b1ba07ef4c7437621f5d72";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.is_valid_message(data, sig), true);
    }

    #[test]
    fn is_valid_message_returns_false_for_invalid_signatures() {
        let data = "eyJrZXkiOiJ2YWx1ZSJ9";
        let sig  = "05330518df0e21fb9beec7a71a5f5f951c3f5254";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.is_valid_message(data, sig), false);
    }

    #[test]
    fn is_valid_message_returns_false_for_invalid_messages() {
        let data = "baddata";
        let sig  = "badsig";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.is_valid_message(data, sig), false);
    }

    #[test]
    fn verify_returns_decoded_message_for_valid_signatures() {
        let msg = "eyJrZXkiOiJ2YWx1ZSJ9--fa115453dbb4a28277b1ba07ef4c7437621f5d72";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.verify(msg).unwrap(), "{\"key\":\"value\"}".as_bytes());
    }

    #[test]
    fn verify_returns_invalid_signature_error_for_wrong_key() {
        let msg = "eyJrZXkiOiJ2YWx1ZSJ9--05330518df0e21fb9beec7a71a5f5f951c3f5254";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.verify(msg).unwrap_err(), VerifierError::InvalidSignature);
    }

    #[test]
    fn verify_returns_message_parse_error_for_empty_message() {
        let msg = "";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.verify(msg).unwrap_err(), VerifierError::MessageParse);
    }

    #[test]
    fn decrypt_and_verify_returns_decoded_message_for_valid_messages() {
        let msg = "c20wSnp6Z1o1U2MyWDVjU3BPeWNNQT09LS1JOWNyR25LdDRpZUUvcmoxVTdoSTNRPT0=--a79c9522355e55bf8e4302c66d8bf5638f1a50ec";

        let encryptor = Encryptor::new("helloworld", "test salt", "test signed salt", 1000, 64);

        assert_eq!(encryptor.decrypt_and_verify(msg).unwrap(), "{\"key\":\"value\"}".as_bytes());
    }

    #[test]
    fn decrypt_and_verify_returns_invalid_signature_error_for_wrong_key(){
        let msg = "SnRXQXFhOE9WSGg2QmVGUDdHdkhNZz09LS1vcjFWcm53VU40YmV0SVcwdWFlK2NRPT0=--c879b51cbd92559d4d684c406b3aaebfbc958e9d";

        let encryptor = Encryptor::new("helloworld", "test salt", "test signed salt", 1000, 64);

        assert_eq!(encryptor.decrypt_and_verify(msg).unwrap_err(), EncryptorError::InvalidSignature);
    }

    #[test]
    fn decrypt_and_verify_returns_invalid_signature_for_empty_message(){
        let msg = "";

        let encryptor = Encryptor::new("helloworld", "test salt", "test signed salt", 1000, 64);

        assert_eq!(encryptor.decrypt_and_verify(msg).unwrap_err(), EncryptorError::InvalidSignature);
    }
}
<commit_msg>Remove println statements<commit_after>extern crate crypto;
extern crate rustc_serialize;

use crypto::{buffer, blockmodes};
use crypto::aes::{cbc_decryptor, KeySize as AesKeySize};
use crypto::buffer::{WriteBuffer, ReadBuffer, BufferResult};
use crypto::hmac::Hmac;
use crypto::mac::{Mac};
use crypto::sha1::Sha1;
use crypto::pbkdf2::pbkdf2;
use crypto::util::fixed_time_eq;

use rustc_serialize::hex::FromHex;
use rustc_serialize::base64::FromBase64;

use std::str::from_utf8;

pub struct Verifier {
    secret_key: Vec<u8>
}

#[derive(Debug, PartialEq)]
pub enum VerifierError {
    MessageParse,
    InvalidSignature,
    DecodePayload
}

pub fn create_derived_keys(secret: &str, salts: &Vec<&str>, key_iters: u32, key_sz: u32) -> Vec<Vec<u8>> {
    let mut mac = Hmac::new(Sha1::new(), secret.as_bytes());

    salts.iter().map(|salt| {
        let mut result: Vec<u8> = vec![0; key_sz as usize];

        pbkdf2(&mut mac, salt.as_bytes(), key_iters, &mut result);

        result
    }).collect()
}

fn split_by_dashes(message: &str) -> Option<(&str, &str)> {
    let split: Vec<&str> = message.splitn(2, "--").collect();

    match split.len() {
        2 => Some((split.first().unwrap(), split.last().unwrap())),
        _ => None
    }
}

fn split_by_dashes_from_u8_slice(slice: &[u8]) -> Option<(&str, &str)> {
    match from_utf8(slice) {
        Ok(string) => split_by_dashes(string),
        Err(_) => None
    }
}

impl Verifier {
    pub fn new(secret: &str) -> Verifier {
        Verifier {
            secret_key: secret.bytes().collect()
        }
    }

    pub fn verify(&self, message: &str) -> Result<Vec<u8>, VerifierError> {
        match split_by_dashes(&message) {
            Some((encoded_data, signature)) => {
                match self.is_valid_message(encoded_data, signature) {
                    true => {
                        match encoded_data.from_base64() {
                            Ok(decoded) => Ok(decoded),
                            Err(_) => Err(VerifierError::DecodePayload)
                        }
                    },

                    false => Err(VerifierError::InvalidSignature)
                }
            },

            None => Err(VerifierError::MessageParse)
        }
    }

    pub fn is_valid_message(&self, encoded_data: &str, signature: &str) -> bool {
        match signature.from_hex() {
            Ok(sig_bytes) => {
                let mut mac = Hmac::new(Sha1::new(), &self.secret_key);

                mac.input(encoded_data.as_bytes());

                fixed_time_eq(mac.result().code(), &sig_bytes)
            },

            Err(_) => false
        }
    }
}

pub struct Encryptor {
    secret_key: Vec<u8>,
    verifier: Verifier
}

#[derive(Debug, PartialEq)]
pub enum EncryptorError {
    InvalidSignature,
    MessageParse,
    MessageDecode,
    DecryptError
}

impl Encryptor {
    pub fn new(secret: &str, salt: &str, sign_salt: &str, key_iters: u32, key_sz: u32) -> Encryptor {
        let salts = vec![salt, sign_salt];
        let keys = create_derived_keys(secret, &salts, key_iters, key_sz);

        match (keys.first(), keys.last()) {
            (Some(cipher_key), Some(sig_key)) => {
                Encryptor {
                    secret_key: cipher_key.to_vec(),
                    verifier: Verifier {
                        secret_key: sig_key.to_vec()
                    }
                }
            }

            _ => panic!("KDF Failed for Encryptor")
        }
    }

    pub fn decrypt_and_verify(&self, message: &str) -> Result<Vec<u8>, EncryptorError>  {
        match self.verifier.verify(message) {
            Ok(decoded) => {
                match split_by_dashes_from_u8_slice(&decoded) {
                    Some((encoded_cipher_text, encoded_iv)) => {
                        match (encoded_cipher_text.from_base64(), encoded_iv.from_base64()) {
                            (Ok(cipher_text), Ok(iv)) => {
                                let key_sz = AesKeySize::KeySize256; // TODO make configurable
                                let mut decryptor = cbc_decryptor(key_sz, &self.secret_key, &iv, blockmodes::PkcsPadding);

                                let mut final_result: Vec<u8> = Vec::new();
                                let mut buffer = [0; 4096];

                                let mut read_buffer = buffer::RefReadBuffer::new(&cipher_text);
                                let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

                                loop {
                                    match decryptor.decrypt(&mut read_buffer, &mut write_buffer, true) {
                                        Ok(buffer_result) => {
                                            final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));

                                            match buffer_result {
                                                BufferResult::BufferUnderflow => break,
                                                BufferResult::BufferOverflow => continue
                                            }
                                        }

                                        Err(_) => return Err(EncryptorError::DecryptError)
                                    }
                                }

                                Ok(final_result)
                            },

                            _ => Err(EncryptorError::MessageDecode)
                        }
                    },

                    None => Err(EncryptorError::MessageParse)
                }
            }

            Err(_) => Err(EncryptorError::InvalidSignature)
        }

    }
}

#[cfg(test)]
mod tests {
    use std::str;

    use Verifier;
    use VerifierError;

    use Encryptor;
    use EncryptorError;

    #[test]
    fn is_valid_message_returns_true_for_valid_signatures() {
        let data = "eyJrZXkiOiJ2YWx1ZSJ9";
        let sig  = "fa115453dbb4a28277b1ba07ef4c7437621f5d72";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.is_valid_message(data, sig), true);
    }

    #[test]
    fn is_valid_message_returns_false_for_invalid_signatures() {
        let data = "eyJrZXkiOiJ2YWx1ZSJ9";
        let sig  = "05330518df0e21fb9beec7a71a5f5f951c3f5254";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.is_valid_message(data, sig), false);
    }

    #[test]
    fn is_valid_message_returns_false_for_invalid_messages() {
        let data = "baddata";
        let sig  = "badsig";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.is_valid_message(data, sig), false);
    }

    #[test]
    fn verify_returns_decoded_message_for_valid_signatures() {
        let msg = "eyJrZXkiOiJ2YWx1ZSJ9--fa115453dbb4a28277b1ba07ef4c7437621f5d72";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.verify(msg).unwrap(), "{\"key\":\"value\"}".as_bytes());
    }

    #[test]
    fn verify_returns_invalid_signature_error_for_wrong_key() {
        let msg = "eyJrZXkiOiJ2YWx1ZSJ9--05330518df0e21fb9beec7a71a5f5f951c3f5254";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.verify(msg).unwrap_err(), VerifierError::InvalidSignature);
    }

    #[test]
    fn verify_returns_message_parse_error_for_empty_message() {
        let msg = "";

        let verifier = Verifier::new("helloworld");

        assert_eq!(verifier.verify(msg).unwrap_err(), VerifierError::MessageParse);
    }

    #[test]
    fn decrypt_and_verify_returns_decoded_message_for_valid_messages() {
        let msg = "c20wSnp6Z1o1U2MyWDVjU3BPeWNNQT09LS1JOWNyR25LdDRpZUUvcmoxVTdoSTNRPT0=--a79c9522355e55bf8e4302c66d8bf5638f1a50ec";

        let encryptor = Encryptor::new("helloworld", "test salt", "test signed salt", 1000, 64);

        assert_eq!(encryptor.decrypt_and_verify(msg).unwrap(), "{\"key\":\"value\"}".as_bytes());
    }

    #[test]
    fn decrypt_and_verify_returns_invalid_signature_error_for_wrong_key(){
        let msg = "SnRXQXFhOE9WSGg2QmVGUDdHdkhNZz09LS1vcjFWcm53VU40YmV0SVcwdWFlK2NRPT0=--c879b51cbd92559d4d684c406b3aaebfbc958e9d";

        let encryptor = Encryptor::new("helloworld", "test salt", "test signed salt", 1000, 64);

        assert_eq!(encryptor.decrypt_and_verify(msg).unwrap_err(), EncryptorError::InvalidSignature);
    }

    #[test]
    fn decrypt_and_verify_returns_invalid_signature_for_empty_message(){
        let msg = "";

        let encryptor = Encryptor::new("helloworld", "test salt", "test signed salt", 1000, 64);

        assert_eq!(encryptor.decrypt_and_verify(msg).unwrap_err(), EncryptorError::InvalidSignature);
    }
}
<|endoftext|>


<commit_before>extern crate futures;

use futures::{Async, AsyncSink, Poll, Sink, StartSend};

/// Encapsulate errors from both Sinks
pub enum RouterSinkError<A, B> {
    Left(A),
    Right(B),
}

/// Marker to decide which route the item has to take
pub enum Route<A, B> {
    Left(A),
    Right(B),
}

/// A sink capable of routing incoming items to one of two sinks
pub struct RouterSink<A, B> {
    left_sink: A,
    right_sink: B,
}

/// Poll the given sink and map the error to an appropriate type with
/// the given conversion function
fn poll_complete<S, F, E>(sink: &mut S, f: F) -> Poll<(), E>
    where S: Sink,
          F: Fn(S::SinkError) -> E
{
    match sink.poll_complete() {
            Ok(Async::Ready(x)) => Ok(Async::Ready(x)),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(e),
        }
        .map_err(f)
}

/// Start sending an item on the given sink, map the item back to its route
/// if `NotReady` and map the error to an appropriate type
/// with the given conversion function
fn start_send<S, F, E, G, I>(sink: &mut S, item: S::SinkItem, f: F, g: G) -> StartSend<I, E>
    where S: Sink,
          F: Fn(S::SinkError) -> E,
          G: Fn(S::SinkItem) -> I
{
    sink.start_send(item)
        .map(|x| match x {
                 AsyncSink::Ready => AsyncSink::Ready,
                 AsyncSink::NotReady(x) => AsyncSink::NotReady(g(x)),
             })
        .map_err(f)
}

impl<A, B> RouterSink<A, B> {
    /// Create a new RouterrSink for the two given sinks
    pub fn new(left_sink: A, right_sink: B) -> RouterSink<A, B> {
        RouterSink {
            left_sink,
            right_sink,
        }
    }
}

impl<A, B> Sink for RouterSink<A, B>
    where A: Sink,
          B: Sink
{
    type SinkItem = Route<A::SinkItem, B::SinkItem>;
    type SinkError = RouterSinkError<A::SinkError, B::SinkError>;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        match item {
            Route::Left(x) => {
                start_send(&mut self.left_sink, x, RouterSinkError::Left, Route::Left)
            }
            Route::Right(x) => {
                start_send(&mut self.right_sink,
                           x,
                           RouterSinkError::Right,
                           Route::Right)
            }
        }
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        match (poll_complete(&mut self.left_sink, RouterSinkError::Left),
               poll_complete(&mut self.right_sink, RouterSinkError::Right)) {
            (Ok(Async::Ready(())), Ok(Async::Ready(()))) => Ok(Async::Ready(())),
            (Err(e), _) | (_, Err(e)) => Err(e),
            (Ok(Async::NotReady), _) |
            (_, Ok(Async::NotReady)) => Ok(Async::NotReady),
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Route, RouterSink, RouterSinkError};
    use futures::{Future, stream, Stream};

    #[test]
    fn poll_all() {
        let a: Vec<u32> = Vec::new();
        let b: Vec<u32> = Vec::new();

        let input: Vec<Result<_, ()>> = vec![Ok(Route::Left(23)), Ok(Route::Right(42))];
        let stream = stream::iter(input);

        let router = RouterSink::new(a, b);

        match stream
                  .map_err(|_| RouterSinkError::Left(()))
                  .forward(router)
                  .wait() {
            Ok((_, router)) => {
                assert_eq!(router.left_sink[0], 23);
                assert_eq!(router.right_sink[0], 42);
            }
            Err(_) => assert!(false),
        }
    }

    #[test]
    fn poll_err() {
        let a: Vec<u32> = Vec::new();
        let b: Vec<u32> = Vec::new();

        let input = vec![Ok(Route::Left(23)), Err(())];
        let stream = stream::iter(input);

        let router = RouterSink::new(a, b);

        assert_eq!(true,
                   stream
                       .map_err(|_| RouterSinkError::Left(()))
                       .forward(router)
                       .wait()
                       .is_err());
    }
}
<commit_msg>docs: add doc tests<commit_after>//! Router Sink
//!
//! # Example
//!
//! ```no_run
//! # extern crate futures;
//! # extern crate futures_router_sink;
//! # fn main() {
//! use futures::{stream, Stream};
//! use futures_router_sink::{Route, RouterSink, RouterSinkError};
//!
//! let even = Vec::<usize>::new();
//! let odd = Vec::<usize>::new();
//!
//! let router = RouterSink::new(even, odd);
//!
//! let input = (0..10).map(|x| {
//!     if x % 2 == 0 {
//!         Route::Left(x)
//!     } else {
//!         Route::Right(x)
//!     }
//! })
//! .map(Ok::<_, ()>)
//! .collect::<Vec<_>>();
//!
//! let stream = stream::iter(input);
//! stream
//!     .map_err(|_| RouterSinkError::Left(()))
//!     .forward(router);
//! # }
//! ```

extern crate futures;

use futures::{Async, AsyncSink, Poll, Sink, StartSend};

/// Encapsulate errors from both Sinks
pub enum RouterSinkError<A, B> {
    Left(A),
    Right(B),
}

/// Marker to decide which route the item has to take
pub enum Route<A, B> {
    Left(A),
    Right(B),
}

/// A sink capable of routing incoming items to one of two sinks
pub struct RouterSink<A, B> {
    left_sink: A,
    right_sink: B,
}

/// Poll the given sink and map the error to an appropriate type with
/// the given conversion function
fn poll_complete<S, F, E>(sink: &mut S, f: F) -> Poll<(), E>
    where S: Sink,
          F: Fn(S::SinkError) -> E
{
    match sink.poll_complete() {
            Ok(Async::Ready(x)) => Ok(Async::Ready(x)),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(e),
        }
        .map_err(f)
}

/// Start sending an item on the given sink, map the item back to its route
/// if `NotReady` and map the error to an appropriate type
/// with the given conversion function
fn start_send<S, F, E, G, I>(sink: &mut S, item: S::SinkItem, f: F, g: G) -> StartSend<I, E>
    where S: Sink,
          F: Fn(S::SinkError) -> E,
          G: Fn(S::SinkItem) -> I
{
    sink.start_send(item)
        .map(|x| match x {
                 AsyncSink::Ready => AsyncSink::Ready,
                 AsyncSink::NotReady(x) => AsyncSink::NotReady(g(x)),
             })
        .map_err(f)
}

impl<A, B> RouterSink<A, B> {
    /// Create a new RouterrSink for the two given sinks
    ///
    /// # Example
    ///
    /// ```
    /// use futures_router_sink::RouterSink;
    ///
    /// let left = Vec::<usize>::new();
    /// let right = Vec::<usize>::new();
    ///
    /// let router = RouterSink::new(left, right);
    /// ```
    ///
    /// # Arguments
    ///
    /// - `left_sink`: The sink chosen by the router if an item is tagged as `Left`
    /// - `right_sink`: The sink chosen by the router if an item is tagged as `Right`
    pub fn new(left_sink: A, right_sink: B) -> RouterSink<A, B> {
        RouterSink {
            left_sink,
            right_sink,
        }
    }
}

impl<A, B> Sink for RouterSink<A, B>
    where A: Sink,
          B: Sink
{
    type SinkItem = Route<A::SinkItem, B::SinkItem>;
    type SinkError = RouterSinkError<A::SinkError, B::SinkError>;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        match item {
            Route::Left(x) => {
                start_send(&mut self.left_sink, x, RouterSinkError::Left, Route::Left)
            }
            Route::Right(x) => {
                start_send(&mut self.right_sink,
                           x,
                           RouterSinkError::Right,
                           Route::Right)
            }
        }
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        match (poll_complete(&mut self.left_sink, RouterSinkError::Left),
               poll_complete(&mut self.right_sink, RouterSinkError::Right)) {
            (Ok(Async::Ready(())), Ok(Async::Ready(()))) => Ok(Async::Ready(())),
            (Err(e), _) | (_, Err(e)) => Err(e),
            (Ok(Async::NotReady), _) |
            (_, Ok(Async::NotReady)) => Ok(Async::NotReady),
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Route, RouterSink, RouterSinkError};
    use futures::{Future, stream, Stream};

    #[test]
    fn poll_all() {
        let a: Vec<u32> = Vec::new();
        let b: Vec<u32> = Vec::new();

        let input: Vec<Result<_, ()>> = vec![Ok(Route::Left(23)), Ok(Route::Right(42))];
        let stream = stream::iter(input);

        let router = RouterSink::new(a, b);

        match stream
                  .map_err(|_| RouterSinkError::Left(()))
                  .forward(router)
                  .wait() {
            Ok((_, router)) => {
                assert_eq!(router.left_sink[0], 23);
                assert_eq!(router.right_sink[0], 42);
            }
            Err(_) => assert!(false),
        }
    }

    #[test]
    fn poll_err() {
        let a: Vec<u32> = Vec::new();
        let b: Vec<u32> = Vec::new();

        let input = vec![Ok(Route::Left(23)), Err(())];
        let stream = stream::iter(input);

        let router = RouterSink::new(a, b);

        assert_eq!(true,
                   stream
                       .map_err(|_| RouterSinkError::Left(()))
                       .forward(router)
                       .wait()
                       .is_err());
    }
}
<|endoftext|>


<commit_before>//! Replaces the deprecated functionality of std::os::num_cpus.
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of CPUs of the current machine.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(
    any(
        target_os = "freebsd",
        target_os = "dragonfly",
        target_os = "bitrig",
        target_os = "openbsd",
        target_os = "netbsd"
    )
)]
fn get_num_cpus() -> usize {
    use libc::{c_int, c_uint};
    use libc::sysctl;
    use std::ptr;

    //XXX: uplift to libc?
    const CTL_HW: c_int = 6;
    const HW_AVAILCPU: c_int = 25;
    const HW_NCPU: c_int = 3;

    let mut cpus: c_uint = 0;
    let mut CPUS_SIZE = ::std::mem::size_of::<c_uint>();
    let mut mib: [c_int; 4] = [CTL_HW, HW_AVAILCPU, 0, 0];

    unsafe {
        sysctl(mib.as_mut_ptr(), 2,
               &mut cpus as *mut _ as *mut _, &mut CPUS_SIZE as *mut _ as *mut _,
               ptr::null_mut(), 0);
    }

    if cpus < 1 {
        mib[1] = HW_NCPU;
        unsafe {
            sysctl(mib.as_mut_ptr(), 2,
                   &mut cpus as *mut _ as *mut _, &mut CPUS_SIZE as *mut _ as *mut _,
                   ptr::null_mut(), 0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }

    cpus as usize
}

#[cfg(
    any(
        target_os = "linux",
        target_os = "nacl",
        target_os = "macos",
        target_os = "ios",
        target_os = "android",
    )
)]
fn get_num_cpus() -> usize {
    unsafe {
        libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
    }
}

#[test]
fn lower_bound() {
    assert!(get() > 0);
}

#[test]
fn upper_bound() {
    assert!(get() < 236_451);
}
<commit_msg>Sync BSD definitions with libtest<commit_after>//! Replaces the deprecated functionality of std::os::num_cpus.
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of CPUs of the current machine.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(
    any(
        target_os = "linux",
        target_os = "nacl",
        target_os = "macos",
        target_os = "ios",
        target_os = "android",
    )
)]
fn get_num_cpus() -> usize {
    unsafe {
        libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
    }
}

#[test]
fn lower_bound() {
    assert!(get() > 0);
}

#[test]
fn upper_bound() {
    assert!(get() < 236_451);
}
<|endoftext|>


<commit_before>// DOCS

#![feature(path,io)]
use std::old_io;
pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

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

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

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

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

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

pub mod posix {
    use super::{GenericAtomicFile,OverwriteBehavior,AllowOverwrite,DisallowOverwrite};
    use std::old_io;

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

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

        fn commit(&self, tmppath: &Path) -> old_io::IoResult<()> {
            match self.overwrite {
                AllowOverwrite => old_io::fs::rename(&tmppath, &self.path),
                DisallowOverwrite => old_io::fs::link(&tmppath, &self.path)
            }
        }
    }

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

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

        fn write<F: FnMut(&mut old_io::File) -> old_io::IoResult<()>>(&self, mut f: F) -> old_io::IoResult<()> {
            let tmpdir = try!(old_io::TempDir::new_in(&self.tmpdir, ".atomicwrite"));
            let tmppath = tmpdir.path().join(Path::new("tmpfile.tmp"));
            {
                let mut tmpfile = try!(old_io::File::create(&tmppath));
                try!(f(&mut tmpfile));
            };
            try!(self.commit(&tmppath));
            Ok(())
        }

    }
}

pub use self::posix::AtomicFile as PosixAtomicFile;

#[cfg(all(unix))]
pub use self::posix::AtomicFile as AtomicFile;
<commit_msg>Create stub for Windows<commit_after>// DOCS

#![feature(path,io)]
use std::old_io;
pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

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

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

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

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

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

pub mod posix {
    use super::{GenericAtomicFile,OverwriteBehavior,AllowOverwrite,DisallowOverwrite};
    use std::old_io;

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

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

        fn commit(&self, tmppath: &Path) -> old_io::IoResult<()> {
            match self.overwrite {
                AllowOverwrite => old_io::fs::rename(&tmppath, &self.path),
                DisallowOverwrite => old_io::fs::link(&tmppath, &self.path)
            }
        }
    }

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

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

        fn write<F: FnMut(&mut old_io::File) -> old_io::IoResult<()>>(&self, mut f: F) -> old_io::IoResult<()> {
            let tmpdir = try!(old_io::TempDir::new_in(&self.tmpdir, ".atomicwrite"));
            let tmppath = tmpdir.path().join(Path::new("tmpfile.tmp"));
            {
                let mut tmpfile = try!(old_io::File::create(&tmppath));
                try!(f(&mut tmpfile));
            };
            try!(self.commit(&tmppath));
            Ok(())
        }

    }
}

pub mod windows {
    use super::OverwriteBehavior;

    /// Currently a stub. Windows support is not implemented yet.
    pub struct AtomicFile {
        path: Path,
        overwrite: OverwriteBehavior
    }
}

pub use self::posix::AtomicFile as PosixAtomicFile;
pub use self::windows::AtomicFile as WindowsAtomicFile;

#[cfg(unix)]
pub use self::posix::AtomicFile as AtomicFile;

#[cfg(windows)]
pub use self::windows::AtomicFile as AtomicFile;
<|endoftext|>


<commit_before>//! This crate provides x86_64 specific functions and data structures,
//! and access to various system registers.

#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "const_fn", feature(const_fn))] // Needed for generic access to associated consts
#![cfg_attr(feature = "const_fn", feature(const_panic))]
#![cfg_attr(feature = "const_fn", feature(const_mut_refs))]
#![cfg_attr(feature = "const_fn", feature(const_fn_fn_ptr_basics))]
#![cfg_attr(feature = "inline_asm", feature(asm))]
#![cfg_attr(feature = "abi_x86_interrupt", feature(abi_x86_interrupt))]
#![warn(missing_docs)]
#![deny(missing_debug_implementations)]

pub use crate::addr::{align_down, align_up, PhysAddr, VirtAddr};

/// Makes a function const only when `feature = "const_fn"` is enabled.
///
/// This is needed for const functions with bounds on their generic parameters,
/// such as those in `Page` and `PhysFrame` and many more.
macro_rules! const_fn {
    (
        $(#[$attr:meta])*
        $sv:vis fn $($fn:tt)*
    ) => {
        $(#[$attr])*
        #[cfg(feature = "const_fn")]
        $sv const fn $($fn)*

        $(#[$attr])*
        #[cfg(not(feature = "const_fn"))]
        $sv fn $($fn)*
    };
    (
        $(#[$attr:meta])*
        $sv:vis unsafe fn $($fn:tt)*
    ) => {
        $(#[$attr])*
        #[cfg(feature = "const_fn")]
        $sv const unsafe fn $($fn)*

        $(#[$attr])*
        #[cfg(not(feature = "const_fn"))]
        $sv unsafe fn $($fn)*
    };
}

#[cfg(all(feature = "instructions", feature = "external_asm"))]
pub(crate) mod asm;

pub mod addr;
pub mod instructions;
pub mod registers;
pub mod structures;

/// Represents a protection ring level.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum PrivilegeLevel {
    /// Privilege-level 0 (most privilege): This level is used by critical system-software
    /// components that require direct access to, and control over, all processor and system
    /// resources. This can include BIOS, memory-management functions, and interrupt handlers.
    Ring0 = 0,

    /// Privilege-level 1 (moderate privilege): This level is used by less-critical system-
    /// software services that can access and control a limited scope of processor and system
    /// resources. Software running at these privilege levels might include some device drivers
    /// and library routines. The actual privileges of this level are defined by the
    /// operating system.
    Ring1 = 1,

    /// Privilege-level 2 (moderate privilege): Like level 1, this level is used by
    /// less-critical system-software services that can access and control a limited scope of
    /// processor and system resources. The actual privileges of this level are defined by the
    /// operating system.
    Ring2 = 2,

    /// Privilege-level 3 (least privilege): This level is used by application software.
    /// Software running at privilege-level 3 is normally prevented from directly accessing
    /// most processor and system resources. Instead, applications request access to the
    /// protected processor and system resources by calling more-privileged service routines
    /// to perform the accesses.
    Ring3 = 3,
}

impl PrivilegeLevel {
    /// Creates a `PrivilegeLevel` from a numeric value. The value must be in the range 0..4.
    ///
    /// This function panics if the passed value is >3.
    #[inline]
    pub fn from_u16(value: u16) -> PrivilegeLevel {
        match value {
            0 => PrivilegeLevel::Ring0,
            1 => PrivilegeLevel::Ring1,
            2 => PrivilegeLevel::Ring2,
            3 => PrivilegeLevel::Ring3,
            i => panic!("{} is not a valid privilege level", i),
        }
    }
}
<commit_msg>Use new `const_fn_trait_bound` feature to fix build on latest nightly<commit_after>//! This crate provides x86_64 specific functions and data structures,
//! and access to various system registers.

#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "const_fn", feature(const_panic))]
#![cfg_attr(feature = "const_fn", feature(const_mut_refs))]
#![cfg_attr(feature = "const_fn", feature(const_fn_fn_ptr_basics))]
#![cfg_attr(feature = "const_fn", feature(const_fn_trait_bound))]
#![cfg_attr(feature = "inline_asm", feature(asm))]
#![cfg_attr(feature = "abi_x86_interrupt", feature(abi_x86_interrupt))]
#![warn(missing_docs)]
#![deny(missing_debug_implementations)]

pub use crate::addr::{align_down, align_up, PhysAddr, VirtAddr};

/// Makes a function const only when `feature = "const_fn"` is enabled.
///
/// This is needed for const functions with bounds on their generic parameters,
/// such as those in `Page` and `PhysFrame` and many more.
macro_rules! const_fn {
    (
        $(#[$attr:meta])*
        $sv:vis fn $($fn:tt)*
    ) => {
        $(#[$attr])*
        #[cfg(feature = "const_fn")]
        $sv const fn $($fn)*

        $(#[$attr])*
        #[cfg(not(feature = "const_fn"))]
        $sv fn $($fn)*
    };
    (
        $(#[$attr:meta])*
        $sv:vis unsafe fn $($fn:tt)*
    ) => {
        $(#[$attr])*
        #[cfg(feature = "const_fn")]
        $sv const unsafe fn $($fn)*

        $(#[$attr])*
        #[cfg(not(feature = "const_fn"))]
        $sv unsafe fn $($fn)*
    };
}

#[cfg(all(feature = "instructions", feature = "external_asm"))]
pub(crate) mod asm;

pub mod addr;
pub mod instructions;
pub mod registers;
pub mod structures;

/// Represents a protection ring level.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum PrivilegeLevel {
    /// Privilege-level 0 (most privilege): This level is used by critical system-software
    /// components that require direct access to, and control over, all processor and system
    /// resources. This can include BIOS, memory-management functions, and interrupt handlers.
    Ring0 = 0,

    /// Privilege-level 1 (moderate privilege): This level is used by less-critical system-
    /// software services that can access and control a limited scope of processor and system
    /// resources. Software running at these privilege levels might include some device drivers
    /// and library routines. The actual privileges of this level are defined by the
    /// operating system.
    Ring1 = 1,

    /// Privilege-level 2 (moderate privilege): Like level 1, this level is used by
    /// less-critical system-software services that can access and control a limited scope of
    /// processor and system resources. The actual privileges of this level are defined by the
    /// operating system.
    Ring2 = 2,

    /// Privilege-level 3 (least privilege): This level is used by application software.
    /// Software running at privilege-level 3 is normally prevented from directly accessing
    /// most processor and system resources. Instead, applications request access to the
    /// protected processor and system resources by calling more-privileged service routines
    /// to perform the accesses.
    Ring3 = 3,
}

impl PrivilegeLevel {
    /// Creates a `PrivilegeLevel` from a numeric value. The value must be in the range 0..4.
    ///
    /// This function panics if the passed value is >3.
    #[inline]
    pub fn from_u16(value: u16) -> PrivilegeLevel {
        match value {
            0 => PrivilegeLevel::Ring0,
            1 => PrivilegeLevel::Ring1,
            2 => PrivilegeLevel::Ring2,
            3 => PrivilegeLevel::Ring3,
            i => panic!("{} is not a valid privilege level", i),
        }
    }
}
<|endoftext|>