<commit_before>#![allow(dead_code)]
use std::io::Error as IoError;
use std::ffi::CString;
use std::ptr::null;
use std::path::Path;
use libc::{c_ulong, c_int};

use super::itertools::{NextValue, NextStr, words};
use super::utils::cpath;

// sys/mount.h
static MS_RDONLY: c_ulong = 1;                /* Mount read-only.  */
static MS_NOSUID: c_ulong = 2;                /* Ignore suid and sgid bits.  */
static MS_NODEV: c_ulong = 4;                 /* Disallow access to device special files.  */
static MS_NOEXEC: c_ulong = 8;                /* Disallow program execution.  */
static MS_SYNCHRONOUS: c_ulong = 16;          /* Writes are synced at once.  */
static MS_REMOUNT: c_ulong = 32;              /* Alter flags of a mounted FS.  */
static MS_MANDLOCK: c_ulong = 64;             /* Allow mandatory locks on an FS.  */
static MS_DIRSYNC: c_ulong = 128;             /* Directory modifications are synchronous.  */
static MS_NOATIME: c_ulong = 1024;            /* Do not update access times.  */
static MS_NODIRATIME: c_ulong = 2048;         /* Do not update directory access times.  */
static MS_BIND: c_ulong = 4096;               /* Bind directory at different place.  */
static MS_MOVE: c_ulong = 8192;
static MS_REC: c_ulong = 16384;
static MS_SILENT: c_ulong = 32768;
static MS_POSIXACL: c_ulong = 1 << 16;        /* VFS does not apply the umask.  */
static MS_UNBINDABLE: c_ulong = 1 << 17;      /* Change to unbindable.  */
static MS_PRIVATE: c_ulong = 1 << 18;         /* Change to private.  */
static MS_SLAVE: c_ulong = 1 << 19;           /* Change to slave.  */
static MS_SHARED: c_ulong = 1 << 20;          /* Change to shared.  */
static MS_RELATIME: c_ulong = 1 << 21;        /* Update atime relative to mtime/ctime.  */
static MS_KERNMOUNT: c_ulong = 1 << 22;       /* This is a kern_mount call.  */
static MS_I_VERSION: c_ulong =  1 << 23;      /* Update inode I_version field.  */
static MS_STRICTATIME: c_ulong = 1 << 24;     /* Always perform atime updates.  */
static MS_ACTIVE: c_ulong = 1 << 30;
static MS_NOUSER: c_ulong = 1 << 31;

static MNT_FORCE: c_int = 1;           /* Force unmounting.  */
static MNT_DETACH: c_int = 2;          /* Just detach from the tree.  */
static MNT_EXPIRE: c_int = 4;          /* Mark for expiry.  */
static UMOUNT_NOFOLLOW: c_int = 8;     /* Don't follow symlink on umount.  */

extern {
    fn mount(source: *const i8, target: *const i8,
        filesystemtype: *const i8, flags: c_ulong,
        data: *const i8) -> c_int;
    fn umount(target: *const i8) -> c_int;
    fn umount2(target: *const i8, flags: c_int) -> c_int;
}

pub struct MountRecord<'a> {
    pub mount_id: usize,
    pub parent_id: usize,
    _device: &'a str,  // TODO(tailhook) parse if ever need
    pub relative_root: &'a str,
    pub mount_point: &'a str,
    pub mount_options: &'a str,
    pub tag_shared: Option<usize>,
    pub tag_master: Option<usize>,
    pub tag_propagate_from: Option<usize>,
    pub tag_unbindable: Option<()>,
    pub fstype: &'a str,
    pub mount_source: &'a str,
    pub super_options: &'a str,
}

impl<'a> MountRecord<'a> {
    pub fn from_str<'x>(line: &'x str) -> Result<MountRecord<'x>, ()> {
        let mut parts = words(line);
        let mount_id = try!(parts.next_value());
        let parent_id = try!(parts.next_value());
        let device = try!(parts.next_str());
        let relative_root = try!(parts.next_str());
        let mount_point = try!(parts.next_str());
        let mount_options = try!(parts.next_str());
        let mut tag_shared = None;
        let mut tag_master = None;
        let mut tag_propagate_from = None;
        let mut tag_unbindable = None;

        for name in &mut parts {
            if name == "-" { break; }
            let mut pair = name.splitn(2, ':');
            let key = pair.next();
            match key {
                Some("shared") => {
                    tag_shared = Some(try!(pair.next_value()));
                }
                Some("master") => {
                    tag_master = Some(try!(pair.next_value()));
                }
                Some("propagate_from") => {
                    tag_propagate_from = Some(try!(pair.next_value()));
                }
                Some("unbindable") => tag_unbindable = Some(()),
                _ => {}
            }
        }

        let fstype = try!(parts.next_str());
        let mount_source = try!(parts.next_str());
        let super_options = try!(parts.next_str());

        return Ok(MountRecord {
            mount_id: mount_id,
            parent_id: parent_id,
            _device: device,
            relative_root: relative_root,
            mount_point: mount_point,
            mount_options: mount_options,
            tag_shared: tag_shared,
            tag_master: tag_master,
            tag_propagate_from: tag_propagate_from,
            tag_unbindable: tag_unbindable,
            fstype: fstype,
            mount_source: mount_source,
            super_options: super_options,
            });
    }
    pub fn is_private(&self) -> bool {
        return self.tag_shared.is_none()
            && self.tag_master.is_none()
            && self.tag_propagate_from.is_none()
            && self.tag_unbindable.is_none();
    }
}

pub fn mount_ro_recursive(target: &Path) -> Result<(), String> {
    let none = CString::new("none").unwrap();
    debug!("Remount readonly: {:?}", target);
    let c_target = cpath(target);
    let rc = unsafe { mount(
       none.as_ptr(),
       c_target.as_ptr(),
       null(), MS_BIND|MS_REMOUNT|MS_RDONLY, null()) };
    if rc != 0 {
        let err = IoError::last_os_error();
        return Err(format!("Remount readonly {}: {}", target.display(), err));
    }
    return Ok(());
}

pub fn mount_private(target: &Path) -> Result<(), String> {
    let none = CString::new("none").unwrap();
    let c_target = cpath(target);
    debug!("Making private {:?}", target);
    let rc = unsafe { mount(
        none.as_ptr(),
        c_target.as_ptr(),
        null(), MS_REC|MS_PRIVATE, null()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_os_error();
        return Err(format!("Can't make {} a slave: {}",
            target.display(), err));
    }
}

pub fn bind_mount(source: &Path, target: &Path) -> Result<(), String> {
    let c_source = cpath(source);
    let c_target = cpath(target);
    debug!("Bind mount {} -> {}", source.display(), target.display());
    let rc = unsafe {
        mount(c_source.as_ptr(), c_target.as_ptr(),
        null(), MS_BIND|MS_REC, null()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_os_error();
        return Err(format!("Can't mount bind {} to {}: {}",
            source.display(), target.display(), err));
    }
}

pub fn mount_pseudo(target: &Path, name: &str, options: &str, readonly: bool)
    -> Result<(), String>
{
    let c_name = CString::new(name).unwrap();
    let c_target = cpath(target);
    let c_opts = CString::new(options).unwrap();
    let mut flags = MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_NOATIME;
    if readonly {
        flags |= MS_RDONLY;
    }
    debug!("Pseudofs mount {} {} {}", target.display(), name, options);
    let rc = unsafe { mount(
        c_name.as_ptr(),
        c_target.as_ptr(),
        c_name.as_ptr(),
        flags,
        c_opts.as_ptr()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_os_error();
        return Err(format!("Can't mount pseudofs {} ({}, options: {}): {}",
            target.display(), options, name, err));
    }
}

pub fn mount_tmpfs(target: &Path, options: &str) -> Result<(), String> {
    let c_tmpfs = CString::new("tmpfs").unwrap();
    let c_target = cpath(target);
    let c_opts = CString::new(options).unwrap();
    debug!("Tmpfs mount {} {}", target.display(), options);
    let rc = unsafe { mount(
        c_tmpfs.as_ptr(),
        c_target.as_ptr(),
        c_tmpfs.as_ptr(),
        MS_NOSUID | MS_NODEV | MS_NOATIME,
        c_opts.as_ptr()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_os_error();
        return Err(format!("Can't mount tmpfs {} (options: {}): {}",
            target.display(), options, err));
    }
}

pub fn unmount(target: &Path) -> Result<(), String> {
    let c_target = cpath(target);
    let rc = unsafe { umount2(c_target.as_ptr(), MNT_DETACH) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_os_error();
        return Err(format!("Can't unmount {} : {}", target.display(), err));
    }
}

<commit_msg>Better error messages on bind mount errors<commit_after>#![allow(dead_code)]
use std::io::Error as IoError;
use std::ffi::CString;
use std::ptr::null;
use std::path::Path;
use libc::{c_ulong, c_int};

use super::itertools::{NextValue, NextStr, words};
use super::utils::cpath;

// sys/mount.h
static MS_RDONLY: c_ulong = 1;                /* Mount read-only.  */
static MS_NOSUID: c_ulong = 2;                /* Ignore suid and sgid bits.  */
static MS_NODEV: c_ulong = 4;                 /* Disallow access to device special files.  */
static MS_NOEXEC: c_ulong = 8;                /* Disallow program execution.  */
static MS_SYNCHRONOUS: c_ulong = 16;          /* Writes are synced at once.  */
static MS_REMOUNT: c_ulong = 32;              /* Alter flags of a mounted FS.  */
static MS_MANDLOCK: c_ulong = 64;             /* Allow mandatory locks on an FS.  */
static MS_DIRSYNC: c_ulong = 128;             /* Directory modifications are synchronous.  */
static MS_NOATIME: c_ulong = 1024;            /* Do not update access times.  */
static MS_NODIRATIME: c_ulong = 2048;         /* Do not update directory access times.  */
static MS_BIND: c_ulong = 4096;               /* Bind directory at different place.  */
static MS_MOVE: c_ulong = 8192;
static MS_REC: c_ulong = 16384;
static MS_SILENT: c_ulong = 32768;
static MS_POSIXACL: c_ulong = 1 << 16;        /* VFS does not apply the umask.  */
static MS_UNBINDABLE: c_ulong = 1 << 17;      /* Change to unbindable.  */
static MS_PRIVATE: c_ulong = 1 << 18;         /* Change to private.  */
static MS_SLAVE: c_ulong = 1 << 19;           /* Change to slave.  */
static MS_SHARED: c_ulong = 1 << 20;          /* Change to shared.  */
static MS_RELATIME: c_ulong = 1 << 21;        /* Update atime relative to mtime/ctime.  */
static MS_KERNMOUNT: c_ulong = 1 << 22;       /* This is a kern_mount call.  */
static MS_I_VERSION: c_ulong =  1 << 23;      /* Update inode I_version field.  */
static MS_STRICTATIME: c_ulong = 1 << 24;     /* Always perform atime updates.  */
static MS_ACTIVE: c_ulong = 1 << 30;
static MS_NOUSER: c_ulong = 1 << 31;

static MNT_FORCE: c_int = 1;           /* Force unmounting.  */
static MNT_DETACH: c_int = 2;          /* Just detach from the tree.  */
static MNT_EXPIRE: c_int = 4;          /* Mark for expiry.  */
static UMOUNT_NOFOLLOW: c_int = 8;     /* Don't follow symlink on umount.  */

extern {
    fn mount(source: *const i8, target: *const i8,
        filesystemtype: *const i8, flags: c_ulong,
        data: *const i8) -> c_int;
    fn umount(target: *const i8) -> c_int;
    fn umount2(target: *const i8, flags: c_int) -> c_int;
}

pub struct MountRecord<'a> {
    pub mount_id: usize,
    pub parent_id: usize,
    _device: &'a str,  // TODO(tailhook) parse if ever need
    pub relative_root: &'a str,
    pub mount_point: &'a str,
    pub mount_options: &'a str,
    pub tag_shared: Option<usize>,
    pub tag_master: Option<usize>,
    pub tag_propagate_from: Option<usize>,
    pub tag_unbindable: Option<()>,
    pub fstype: &'a str,
    pub mount_source: &'a str,
    pub super_options: &'a str,
}

impl<'a> MountRecord<'a> {
    pub fn from_str<'x>(line: &'x str) -> Result<MountRecord<'x>, ()> {
        let mut parts = words(line);
        let mount_id = try!(parts.next_value());
        let parent_id = try!(parts.next_value());
        let device = try!(parts.next_str());
        let relative_root = try!(parts.next_str());
        let mount_point = try!(parts.next_str());
        let mount_options = try!(parts.next_str());
        let mut tag_shared = None;
        let mut tag_master = None;
        let mut tag_propagate_from = None;
        let mut tag_unbindable = None;

        for name in &mut parts {
            if name == "-" { break; }
            let mut pair = name.splitn(2, ':');
            let key = pair.next();
            match key {
                Some("shared") => {
                    tag_shared = Some(try!(pair.next_value()));
                }
                Some("master") => {
                    tag_master = Some(try!(pair.next_value()));
                }
                Some("propagate_from") => {
                    tag_propagate_from = Some(try!(pair.next_value()));
                }
                Some("unbindable") => tag_unbindable = Some(()),
                _ => {}
            }
        }

        let fstype = try!(parts.next_str());
        let mount_source = try!(parts.next_str());
        let super_options = try!(parts.next_str());

        return Ok(MountRecord {
            mount_id: mount_id,
            parent_id: parent_id,
            _device: device,
            relative_root: relative_root,
            mount_point: mount_point,
            mount_options: mount_options,
            tag_shared: tag_shared,
            tag_master: tag_master,
            tag_propagate_from: tag_propagate_from,
            tag_unbindable: tag_unbindable,
            fstype: fstype,
            mount_source: mount_source,
            super_options: super_options,
            });
    }
    pub fn is_private(&self) -> bool {
        return self.tag_shared.is_none()
            && self.tag_master.is_none()
            && self.tag_propagate_from.is_none()
            && self.tag_unbindable.is_none();
    }
}

pub fn mount_ro_recursive(target: &Path) -> Result<(), String> {
    let none = CString::new("none").unwrap();
    debug!("Remount readonly: {:?}", target);
    let c_target = cpath(target);
    let rc = unsafe { mount(
       none.as_ptr(),
       c_target.as_ptr(),
       null(), MS_BIND|MS_REMOUNT|MS_RDONLY, null()) };
    if rc != 0 {
        let err = IoError::last_os_error();
        return Err(format!("Remount readonly {}: {}", target.display(), err));
    }
    return Ok(());
}

pub fn mount_private(target: &Path) -> Result<(), String> {
    let none = CString::new("none").unwrap();
    let c_target = cpath(target);
    debug!("Making private {:?}", target);
    let rc = unsafe { mount(
        none.as_ptr(),
        c_target.as_ptr(),
        null(), MS_REC|MS_PRIVATE, null()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_os_error();
        return Err(format!("Can't make {} a slave: {}",
            target.display(), err));
    }
}

pub fn bind_mount(source: &Path, target: &Path) -> Result<(), String> {
    let c_source = cpath(source);
    let c_target = cpath(target);
    debug!("Bind mount {} -> {}", source.display(), target.display());
    let rc = unsafe {
        mount(c_source.as_ptr(), c_target.as_ptr(),
        null(), MS_BIND|MS_REC, null()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_os_error();

        return Err(format!("Can't mount bind {:?} to {:?}: {}.
            Source dir: {}, destination dir: {}",
            source, target, err,
            if source.exists() { "exists" } else { "missing" },
            if target.exists() { "exists" } else { "missing" }));
    }
}

pub fn mount_pseudo(target: &Path, name: &str, options: &str, readonly: bool)
    -> Result<(), String>
{
    let c_name = CString::new(name).unwrap();
    let c_target = cpath(target);
    let c_opts = CString::new(options).unwrap();
    let mut flags = MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_NOATIME;
    if readonly {
        flags |= MS_RDONLY;
    }
    debug!("Pseudofs mount {} {} {}", target.display(), name, options);
    let rc = unsafe { mount(
        c_name.as_ptr(),
        c_target.as_ptr(),
        c_name.as_ptr(),
        flags,
        c_opts.as_ptr()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_os_error();
        return Err(format!("Can't mount pseudofs {} ({}, options: {}): {}",
            target.display(), options, name, err));
    }
}

pub fn mount_tmpfs(target: &Path, options: &str) -> Result<(), String> {
    let c_tmpfs = CString::new("tmpfs").unwrap();
    let c_target = cpath(target);
    let c_opts = CString::new(options).unwrap();
    debug!("Tmpfs mount {} {}", target.display(), options);
    let rc = unsafe { mount(
        c_tmpfs.as_ptr(),
        c_target.as_ptr(),
        c_tmpfs.as_ptr(),
        MS_NOSUID | MS_NODEV | MS_NOATIME,
        c_opts.as_ptr()) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_os_error();
        return Err(format!("Can't mount tmpfs {} (options: {}): {}",
            target.display(), options, err));
    }
}

pub fn unmount(target: &Path) -> Result<(), String> {
    let c_target = cpath(target);
    let rc = unsafe { umount2(c_target.as_ptr(), MNT_DETACH) };
    if rc == 0 {
        return Ok(());
    } else {
        let err = IoError::last_os_error();
        return Err(format!("Can't unmount {} : {}", target.display(), err));
    }
}

<|endoftext|>


<commit_before>pub enum Player {
    White,
    Black,
}

#[derive(PartialEq, Debug)]
pub enum Piece {
    Rook,
    Knight,
    Bishop,
    Queen,
    King,
    Pawn,
}

impl Piece {
    fn to_char(&self) -> char {
        match *self {
            Piece::Rook   => 'R',
            Piece::Knight => 'N',
            Piece::Bishop => 'B',
            Piece::Queen  => 'Q',
            Piece::King   => 'K',
            Piece::Pawn   => 'P',
        }
    }

    fn from_char(c: char) -> Option<Piece> {
        match c {
            'R' => Some(Piece::Rook),
            'N' => Some(Piece::Knight),
            'B' => Some(Piece::Bishop),
            'Q' => Some(Piece::Queen),
            'K' => Some(Piece::King),
            'P' => Some(Piece::Pawn),
            _   => None,
        }
    }
}

#[test]
fn test_piece_to_str() {
    assert_eq!('R', Piece::Rook.to_char());
}

#[test]
fn test_piece_from_str() {
    assert_eq!(Some(Piece::Knight), Piece::from_char('N'));
}

#[derive(PartialEq, Debug)]
pub enum Castle {
    Queenside,
    Kingside,
}

impl Castle {
    fn to_str(&self) -> String {
        match *self {
            Castle::Queenside => String::from("O-O-O"),
            Castle::Kingside  => String::from("O-O"),
        }
    }

    fn from_str(s: String) -> Option<Castle> {
        match s.as_ref() {
            "O-O"   => Some(Castle::Kingside),
            "O-O-O" => Some(Castle::Queenside),
            _       => None
        }
    }
}

#[test]
fn test_castle_to_str() {
    assert_eq!(Castle::Queenside.to_str(), "O-O-O");
}

#[test]
fn test_castle_from_str() {
    assert_eq!(Some(Castle::Queenside),
               Castle::from_str(String::from("O-O-O")));
}

struct Move {
    piece: Option<Piece>,
    from_file: Option<char>, // column, 'a' to 'h'
    from_rank: Option<i8>,   // row,     1  to  8
    capture: bool,
    to_file: Option<char>,   // column, 'a' to 'h'
    to_rank: Option<i8>,     // row,     1  to  8
    en_passant: bool,
    check: bool,
    checkmate: bool,
    promotion: Option<Piece>,
    castle: Option<Castle>,
}

impl Move {
    fn new() -> Move {
        Move {
            piece: None,
            from_file: None,
            from_rank: None,
            capture: false,
            to_file: None,
            to_rank: None,
            promotion: None,
            castle: None,
            check: false,
            checkmate: false,
            en_passant: false,
        }
    }

    pub fn from(mov_str: &String) -> Move {
        let mut mov = Move::new();
        if mov_str.contains("x") {
            mov.capture = true;
        }
        if mov_str.contains("=") {
            // Promotion
            // TODO
        }
        mov
    }

    pub fn to_str(&self) -> String {
        let mut ret = String::new();
        match self.piece {
            Some(Piece::Pawn) => (),
            Some(ref p) => ret.push(p.to_char()),
            _ => (),
        }
        if self.from_file.is_some() {
            ret.push(self.from_file.unwrap());
        }
        if self.from_rank.is_some() {
            ret.push(self.from_rank.unwrap().to_string().pop().unwrap());
        }
        if self.capture {
            ret.push('x');
        }
        if self.to_file.is_some() {
            ret.push(self.to_file.unwrap());
        }
        if self.to_rank.is_some() {
            ret.push(self.to_rank.unwrap().to_string().pop().unwrap());
        }
        match self.promotion {
            Some(Piece::Pawn) => (),
            Some(ref p) => {
                ret.push('=');
                ret.push(p.to_char());
            },
            _ => (),
        }
        match self.castle {
            Some(Castle::Kingside)  => ret.push_str("O-O"),
            Some(Castle::Queenside) => ret.push_str("O-O-O"),
            _ => (),
        }
        if self.check {
            ret.push('+');
        }
        if self.checkmate {
            ret.push('#');
        }
        if self.en_passant {
            ret.push_str(" e.p.");
        }
        ret
    }
}

#[test]
fn test_pawn_move() {
    let mut m = Move::new();
    m.to_file = Some('e');
    m.to_rank = Some(4 as i8);
    assert_eq!(m.to_str(), "e4");
    m.piece = Some(Piece::Pawn);
    assert_eq!(m.to_str(), "e4");
}

#[test]
fn test_longest_move() {
    let mut m = Move::new();
    m.from_file = Some('e');
    m.capture = true;
    m.to_file = Some('d');
    m.to_rank = Some(6 as i8);
    m.check = true;
    m.en_passant = true;
    assert_eq!(m.to_str(), "exd6+ e.p.");
}

struct State {
    board: [[char; 8]; 8]
}

impl State {
    pub fn new() -> State {
        State {
            board: [['♜', '♞', '♝', '♛', '♚', '♝', '♞', '♜'],
                    ['♟', '♟', '♟', '♟', '♟', '♟', '♟', '♟'],
                    [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
                    [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
                    [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
                    [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
                    ['♙', '♙', '♙', '♙', '♙', '♙', '♙', '♙'],
                    ['♖', '♘', '♗', '♕', '♔', '♗', '♘', '♖']],
        }
    }

    pub fn make_move(&self, player: Player, mov: Move) {
    }
}
<commit_msg>More board display impl<commit_after>pub enum Player {
    White,
    Black,
}

#[derive(PartialEq, Debug)]
pub enum Piece {
    Rook,
    Knight,
    Bishop,
    Queen,
    King,
    Pawn,
}

impl Piece {
    fn to_char(&self) -> char {
        match *self {
            Piece::Rook   => 'R',
            Piece::Knight => 'N',
            Piece::Bishop => 'B',
            Piece::Queen  => 'Q',
            Piece::King   => 'K',
            Piece::Pawn   => 'P',
        }
    }

    fn from(c: char) -> Option<Piece> {
        match c {
            'R' => Some(Piece::Rook),
            'N' => Some(Piece::Knight),
            'B' => Some(Piece::Bishop),
            'Q' => Some(Piece::Queen),
            'K' => Some(Piece::King),
            'P' => Some(Piece::Pawn),
            _   => None,
        }
    }
}

#[test]
fn test_piece_to_str() {
    assert_eq!('R', Piece::Rook.to_char());
}

#[test]
fn test_piece_from_str() {
    assert_eq!(Some(Piece::Knight), Piece::from('N'));
}

#[derive(PartialEq, Debug)]
pub enum Castle {
    Queenside,
    Kingside,
}

impl Castle {
    fn to_str(&self) -> String {
        match *self {
            Castle::Queenside => String::from("O-O-O"),
            Castle::Kingside  => String::from("O-O"),
        }
    }

    fn from_str(s: String) -> Option<Castle> {
        match s.as_ref() {
            "O-O"   => Some(Castle::Kingside),
            "O-O-O" => Some(Castle::Queenside),
            _       => None
        }
    }
}

#[test]
fn test_castle_to_str() {
    assert_eq!(Castle::Queenside.to_str(), "O-O-O");
}

#[test]
fn test_castle_from_str() {
    assert_eq!(Some(Castle::Queenside),
               Castle::from_str(String::from("O-O-O")));
}

#[derive(PartialEq, Debug)]
struct Move {
    piece: Option<Piece>,
    from_file: Option<char>, // column, 'a' to 'h'
    from_rank: Option<i8>,   // row,     1  to  8
    capture: bool,
    to_file: Option<char>,   // column, 'a' to 'h'
    to_rank: Option<i8>,     // row,     1  to  8
    en_passant: bool,
    check: bool,
    checkmate: bool,
    promotion: Option<Piece>,
    castle: Option<Castle>,
}

impl Move {
    fn new() -> Move {
        Move {
            piece: None,
            from_file: None,
            from_rank: None,
            capture: false,
            to_file: None,
            to_rank: None,
            promotion: None,
            castle: None,
            check: false,
            checkmate: false,
            en_passant: false,
        }
    }

    pub fn from(mov_str: &String) -> Move {
        // WOW, I should really write a regex for this
        let mut mov = Move::new();
        if mov_str.contains("x") {
            mov.capture = true;
        }
        if mov_str.contains("e.p.") {
            mov.en_passant = true;
        }
        if mov_str.contains("+") {
            mov.check = true;
        }
        if mov_str.contains("#") {
            mov.checkmate = true;
        }
        // Piece
        if mov_str.starts_with("R") {
            mov.piece = Some(Piece::Rook);
        } else if mov_str.starts_with("N") {
            mov.piece = Some(Piece::Knight);
        } else if mov_str.starts_with("B") {
            mov.piece = Some(Piece::Bishop);
        } else if mov_str.starts_with("Q") {
            mov.piece = Some(Piece::Queen);
        } else if mov_str.starts_with("K") {
            mov.piece = Some(Piece::King);
        } else if mov_str.contains("O-O-O") {
            // no piece
            mov.castle = Some(Castle::Queenside);
        } else if mov_str.contains("O-O") {
            // no piece
            mov.castle = Some(Castle::Kingside);
        } else {
            mov.piece = Some(Piece::Pawn);
        }
        if mov_str.contains("=") {
            // Promotion
            mov.promotion = Piece::from(mov_str.chars().nth(
                mov_str.find("=").unwrap() + 1).unwrap());
        }
        // Get from/to positions if there
        // TODO
        mov
    }

    pub fn to_str(&self) -> String {
        let mut ret = String::new();
        match self.piece {
            Some(Piece::Pawn) => (),
            Some(ref p) => ret.push(p.to_char()),
            _ => (),
        }
        if self.from_file.is_some() {
            ret.push(self.from_file.unwrap());
        }
        if self.from_rank.is_some() {
            ret.push(self.from_rank.unwrap().to_string().pop().unwrap());
        }
        if self.capture {
            ret.push('x');
        }
        if self.to_file.is_some() {
            ret.push(self.to_file.unwrap());
        }
        if self.to_rank.is_some() {
            ret.push(self.to_rank.unwrap().to_string().pop().unwrap());
        }
        match self.promotion {
            Some(Piece::Pawn) => (),
            Some(ref p) => {
                ret.push('=');
                ret.push(p.to_char());
            },
            _ => (),
        }
        match self.castle {
            Some(Castle::Kingside)  => ret.push_str("O-O"),
            Some(Castle::Queenside) => ret.push_str("O-O-O"),
            _ => (),
        }
        if self.check {
            ret.push('+');
        }
        if self.checkmate {
            ret.push('#');
        }
        if self.en_passant {
            ret.push_str(" e.p.");
        }
        ret
    }
}

#[test]
fn test_pawn_move_to_str() {
    let mut m = Move::new();
    m.to_file = Some('e');
    m.to_rank = Some(4 as i8);
    assert_eq!(m.to_str(), "e4");
    m.piece = Some(Piece::Pawn);
    assert_eq!(m.to_str(), "e4");
}

#[test]
fn test_longest_move_to_str() {
    // https://www.chess.com/blog/kurtgodden/think-you-know-algebraic-notation
    // according to the above site, the following is the longest legal move
    let mut m = Move::new();
    m.from_file = Some('e');
    m.capture = true;
    m.to_file = Some('d');
    m.to_rank = Some(6 as i8);
    m.check = true;
    m.en_passant = true;
    assert_eq!(m.to_str(), "exd6+ e.p.");
}

#[test]
fn test_castle_move_from_str() {
    let mut m = Move::new();
    m.castle = Some(Castle::Kingside);
    assert_eq!(Move::from(&String::from("O-O")), m);
    m = Move::new();
    m.castle = Some(Castle::Queenside);
    m.check = true;
    assert_eq!(Move::from(&String::from("O-O-O+")), m);
}

#[test]
fn test_promotion_move_from_str() {
    let m = Move::from(&String::from("e8=Q"));
    assert_eq!(m.promotion, Some(Piece::Queen));
}

struct State {
    board: [[char; 8]; 8]
}

impl State {
    pub fn new() -> State {
        State {
            board: [['♜', '♞', '♝', '♛', '♚', '♝', '♞', '♜'],
                    ['♟', '♟', '♟', '♟', '♟', '♟', '♟', '♟'],
                    [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
                    [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
                    [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
                    [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
                    ['♙', '♙', '♙', '♙', '♙', '♙', '♙', '♙'],
                    ['♖', '♘', '♗', '♕', '♔', '♗', '♘', '♖']],
        }
    }

    pub fn make_move(&self, player: Player, mov: Move) {
    }
}
<|endoftext|>


<commit_before>use std::rc::{self, Rc};
use std::sync::{self, Arc};

/// Trait for generalizing downgrading a strong reference to a weak reference.
pub trait Downgrade
where
    Self: Sized,
{
    /// Weak reference type.
    type Weak;

    /// Downgrade to a weak reference.
    fn downgrade(&self) -> Self::Weak;
}

/// Trait for generalizing upgrading a weak reference to a strong reference.
pub trait Upgrade
where
    Self: Sized,
{
    /// Strong reference type.
    type Strong;

    /// Try upgrading a weak reference to a strong reference.
    fn upgrade(&self) -> Option<Self::Strong>;
}

impl<T: Downgrade + crate::ObjectType> Upgrade for crate::WeakRef<T> {
    type Strong = T;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

impl<T> Downgrade for Arc<T> {
    type Weak = sync::Weak<T>;

    fn downgrade(&self) -> Self::Weak {
        Arc::downgrade(self)
    }
}

impl<T> Upgrade for sync::Weak<T> {
    type Strong = Arc<T>;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

impl<T> Downgrade for Rc<T> {
    type Weak = rc::Weak<T>;

    fn downgrade(&self) -> Self::Weak {
        Rc::downgrade(self)
    }
}

impl<T> Upgrade for rc::Weak<T> {
    type Strong = Rc<T>;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_type_before {
    (_) => ();
    (self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    (@weak self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    (@strong self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    ($variable:ident) => (
        compile_error!("You need to specify if this is a weak or a strong clone.");
    );
    (@strong $variable:ident) => (
        let $variable = $variable.clone();
    );
    (@weak $variable:ident) => (
        let $variable = $crate::clone::Downgrade::downgrade(&$variable);
    );
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_type_after {
    (@weak self, $return_value:expr) => {};
    (@strong self, $return_value:expr) => {};
    (@weak $variable:ident , $return_value:expr) => {
        let $variable = match $crate::clone::Upgrade::upgrade(&$variable) {
            Some(val) => val,
            None => return ($return_value)(),
        };
    };
    (@strong $variable:ident , $return_value:expr) => {};
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_return_value {
    () => {
        ()
    };
    ($value:expr) => {
        $value
    };
}

/// Macro for passing variables as strong or weak references into a closure.
///
/// This macro can be useful in combination with closures, e.g. signal handlers, to reduce the
/// boilerplate required for passing strong or weak references into the closure. It will
/// automatically create the new reference and pass it with the same name into the closure.
///
/// If upgrading the weak reference to a strong reference inside the closure is failing, the
/// closure is immediately returning an optional default return value. If none is provided, `()` is
/// returned.
///
/// ### Passing a strong reference
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let closure = clone!(@strong v => move |x| {
///     println!("v: {}, x: {}", v, x);
/// });
///
/// closure(2);
/// ```
///
/// ### Passing a strong and weak reference
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let u = Rc::new(2);
/// let closure = clone!(@strong v, @weak u => move |x| {
///     println!("v: {}, u: {}, x: {}", v, u, x);
/// });
///
/// closure(3);
/// ```
///
/// ### Providing a default return value if upgrading a weak reference fails
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let closure = clone!(@weak v => @default-return false, move |x| {
///     println!("v: {}, x: {}", v, x);
///     true
/// });
///
/// // Drop value so that the weak reference can't be upgraded.
/// drop(v);
///
/// assert_eq!(closure(2), false);
/// ```
///
/// ### Errors
///
/// Here is a list of errors you might encounter:
///
/// **Missing `@weak` or `@strong`**:
///
/// ```compile_fail
/// # use glib::clone;
/// # use std::rc::Rc;
/// let v = Rc::new(1);
///
/// let closure = clone!(v => move |x| {
///     println!("v: {}, x: {}", v, x);
/// });
/// ```
///
/// **Passing `self` as an argument**:
///
/// ```compile_fail
/// # use glib::clone;
/// # use std::rc::Rc;
/// struct Foo;
///
/// impl Foo {
///     fn foo(&self) {
///         let v = Rc::new(1);
///
///         let closure = clone!(self => move |x| {
///             println!("v: {}, x: {}", v, x);
///         });
///     }
/// }
/// ```
#[macro_export]
macro_rules! clone {
    ($($(@ $strength:ident)? $variables:ident),+ => $(@default-return $return_value:expr,)? move || $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move || {
                let return_value = || $crate::to_return_value!($($return_value)?);
                $( $crate::to_type_after!($(@ $strength)? $variables, return_value );)*
                $body
            }
        }
    );
    ($($(@ $strength:ident)? $variables:ident),+ => $(@default-return $return_value:expr ,)? move | $($pattern:pat),* | $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move |$($pattern),*| {
                let return_value = || $crate::to_return_value!($($return_value)?);
                $( $crate::to_type_after!($(@ $strength)? $variables, return_value );)*
                $body
            }
        }
    );
}
<commit_msg>Add @default-panic syntax as well<commit_after>use std::rc::{self, Rc};
use std::sync::{self, Arc};

/// Trait for generalizing downgrading a strong reference to a weak reference.
pub trait Downgrade
where
    Self: Sized,
{
    /// Weak reference type.
    type Weak;

    /// Downgrade to a weak reference.
    fn downgrade(&self) -> Self::Weak;
}

/// Trait for generalizing upgrading a weak reference to a strong reference.
pub trait Upgrade
where
    Self: Sized,
{
    /// Strong reference type.
    type Strong;

    /// Try upgrading a weak reference to a strong reference.
    fn upgrade(&self) -> Option<Self::Strong>;
}

impl<T: Downgrade + crate::ObjectType> Upgrade for crate::WeakRef<T> {
    type Strong = T;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

impl<T> Downgrade for Arc<T> {
    type Weak = sync::Weak<T>;

    fn downgrade(&self) -> Self::Weak {
        Arc::downgrade(self)
    }
}

impl<T> Upgrade for sync::Weak<T> {
    type Strong = Arc<T>;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

impl<T> Downgrade for Rc<T> {
    type Weak = rc::Weak<T>;

    fn downgrade(&self) -> Self::Weak {
        Rc::downgrade(self)
    }
}

impl<T> Upgrade for rc::Weak<T> {
    type Strong = Rc<T>;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_type_before {
    (_) => ();
    (self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    (@weak self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    (@strong self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    ($variable:ident) => (
        compile_error!("You need to specify if this is a weak or a strong clone.");
    );
    (@strong $variable:ident) => (
        let $variable = $variable.clone();
    );
    (@weak $variable:ident) => (
        let $variable = $crate::clone::Downgrade::downgrade(&$variable);
    );
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_type_after {
    (@weak self, $return_value:expr) => {};
    (@strong self, $return_value:expr) => {};
    (@weak $variable:ident , $return_value:expr) => {
        let $variable = match $crate::clone::Upgrade::upgrade(&$variable) {
            Some(val) => val,
            None => return ($return_value)(),
        };
    };
    (@strong $variable:ident , $return_value:expr) => {};
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_return_value {
    () => {
        ()
    };
    ($value:expr) => {
        $value
    };
}

/// Macro for passing variables as strong or weak references into a closure.
///
/// This macro can be useful in combination with closures, e.g. signal handlers, to reduce the
/// boilerplate required for passing strong or weak references into the closure. It will
/// automatically create the new reference and pass it with the same name into the closure.
///
/// If upgrading the weak reference to a strong reference inside the closure is failing, the
/// closure is immediately returning an optional default return value. If none is provided, `()` is
/// returned.
///
/// ### Passing a strong reference
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let closure = clone!(@strong v => move |x| {
///     println!("v: {}, x: {}", v, x);
/// });
///
/// closure(2);
/// ```
///
/// ### Passing a strong and weak reference
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let u = Rc::new(2);
/// let closure = clone!(@strong v, @weak u => move |x| {
///     println!("v: {}, u: {}, x: {}", v, u, x);
/// });
///
/// closure(3);
/// ```
///
/// ### Providing a default return value if upgrading a weak reference fails
///
/// You can do it in two different ways:
///
/// Either by providing the value yourself using `@default-return`:
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let closure = clone!(@weak v => @default-return false, move |x| {
///     println!("v: {}, x: {}", v, x);
///     true
/// });
///
/// // Drop value so that the weak reference can't be upgraded.
/// drop(v);
///
/// assert_eq!(closure(2), false);
/// ```
///
/// Or by using `@default-panic` (if the value fails to get upgraded, it'll panic):
///
/// ```run_fail
/// # use glib::clone;
/// # use std::rc::Rc;
/// # let v = Rc::new(1);
/// let closure = clone!(@weak v => @default-panic, move |x| {
///     println!("v: {}, x: {}", v, x);
///     true
/// });
/// # drop(v);
/// # assert_eq!(closure(2), false);
/// ```
///
/// ### Errors
///
/// Here is a list of errors you might encounter:
///
/// **Missing `@weak` or `@strong`**:
///
/// ```compile_fail
/// # use glib::clone;
/// # use std::rc::Rc;
/// let v = Rc::new(1);
///
/// let closure = clone!(v => move |x| {
///     println!("v: {}, x: {}", v, x);
/// });
/// ```
///
/// **Passing `self` as an argument**:
///
/// ```compile_fail
/// # use glib::clone;
/// # use std::rc::Rc;
/// struct Foo;
///
/// impl Foo {
///     fn foo(&self) {
///         let v = Rc::new(1);
///
///         let closure = clone!(self => move |x| {
///             println!("v: {}, x: {}", v, x);
///         });
///     }
/// }
/// ```
#[macro_export]
macro_rules! clone {
    ($($(@ $strength:ident)? $variables:ident),+ => $(@default-panic,)? move || $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move || {
                let return_value = || $crate::to_return_value!(panic!("Failed to upgrade weak reference"));
                $( $crate::to_type_after!($(@ $strength)? $variables, return_value );)*
                $body
            }
        }
    );
    ($($(@ $strength:ident)? $variables:ident),+ => $(@default-return $return_value:expr,)? move || $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move || {
                let return_value = || $crate::to_return_value!($($return_value)?);
                $( $crate::to_type_after!($(@ $strength)? $variables, return_value );)*
                $body
            }
        }
    );
    ($($(@ $strength:ident)? $variables:ident),+ => $(@default-panic,)? move | $($pattern:pat),* | $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move |$($pattern),*| {
                let return_value = || $crate::to_return_value!(panic!("Failed to upgrade weak reference"));
                $( $crate::to_type_after!($(@ $strength)? $variables, return_value );)*
                $body
            }
        }
    );
    ($($(@ $strength:ident)? $variables:ident),+ => $(@default-return $return_value:expr,)? move | $($pattern:pat),* | $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move |$($pattern),*| {
                let return_value = || $crate::to_return_value!($($return_value)?);
                $( $crate::to_type_after!($(@ $strength)? $variables, return_value );)*
                $body
            }
        }
    );
}
<|endoftext|>


<commit_before>use handlebars_iron::{Template, HandlebarsEngine};

use serde_json::builder::ObjectBuilder;
use serde_json::value::Value;
use serde_json::de;

use iron::prelude::*;
use iron::status;
use router::Router;

use std::fs::File;

use helpers::value_to_json;

pub fn make_simple_content(title: String, content: String) -> Value {
	return ObjectBuilder::new()
		.insert("title".to_string(), title)
		.insert("content".to_string(), content)
		.unwrap();
}

fn listPages() ->  {

}

pub fn handle() -> Chain {
	// Make the layout
	let mut router = Router::new();

	router.get("/", |_: &mut Request| {
		let mut resp = Response::new();
		resp.set_mut(Template::new("simple_content", value_to_json(de::from_reader(File::open("content/index.json").unwrap()).unwrap()))).set_mut(status::Ok);
    	return Ok(resp);
	});
	router.get("/about/", |_: &mut Request| {
		let mut resp = Response::new();
		resp.set_mut(Template::new("simple_content", value_to_json(de::from_reader(File::open("content/about.json").unwrap()).unwrap()))).set_mut(status::Ok);
		return Ok(resp);
	});

	let mut chain = Chain::new(router);
	chain.link_after(HandlebarsEngine::new("templates/", ".hbs"));
	return chain;
}
<commit_msg>Fix the build.<commit_after>use handlebars_iron::{Template, HandlebarsEngine};

use serde_json::builder::ObjectBuilder;
use serde_json::value::Value;
use serde_json::de;

use iron::prelude::*;
use iron::status;
use router::Router;

use std::fs::File;

use helpers::value_to_json;

pub fn make_simple_content(title: String, content: String) -> Value {
	return ObjectBuilder::new()
		.insert("title".to_string(), title)
		.insert("content".to_string(), content)
		.unwrap();
}

pub fn handle() -> Chain {
	// Make the layout
	let mut router = Router::new();

	router.get("/", |_: &mut Request| {
		let mut resp = Response::new();
		resp.set_mut(Template::new("simple_content", value_to_json(de::from_reader(File::open("content/index.json").unwrap()).unwrap()))).set_mut(status::Ok);
    	return Ok(resp);
	});
	router.get("/about/", |_: &mut Request| {
		let mut resp = Response::new();
		resp.set_mut(Template::new("simple_content", value_to_json(de::from_reader(File::open("content/about.json").unwrap()).unwrap()))).set_mut(status::Ok);
		return Ok(resp);
	});

	let mut chain = Chain::new(router);
	chain.link_after(HandlebarsEngine::new("templates/", ".hbs"));
	return chain;
}
<|endoftext|>


<commit_before><commit_msg>Remove empty file.<commit_after><|endoftext|>


<commit_before>//! Server discovery endpoints.

use std::{collections::BTreeMap, time::SystemTime};

use ruma_identifiers::{ServerKeyId, ServerNameBox};
use serde::{Deserialize, Serialize};

pub mod discover_homeserver;
pub mod get_remote_server_keys;
pub mod get_remote_server_keys_batch;
pub mod get_server_keys;
pub mod get_server_version;

/// Public key of the homeserver for verifying digital signatures.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct VerifyKey {
    /// The Unpadded Base64 encoded key.
    pub key: String,
}

impl VerifyKey {
    /// Creates a new `VerifyKey` from the given key.
    pub fn new(key: String) -> Self {
        Self { key }
    }
}

/// A key the server used to use, but stopped using.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct OldVerifyKey {
    /// Timestamp when this key expired.
    #[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
    pub expired_ts: SystemTime,
    /// The Unpadded Base64 encoded key.
    pub key: String,
}

impl OldVerifyKey {
    /// Creates a new `OldVerifyKey` with the given expiry time and key.
    pub fn new(expired_ts: SystemTime, key: String) -> Self {
        Self { expired_ts, key }
    }
}

// Spec is wrong, all fields are required (see https://github.com/matrix-org/matrix-doc/issues/2508)
/// Queried server key, signed by the notary server.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct ServerKey {
    /// DNS name of the homeserver.
    pub server_name: ServerNameBox,
    /// Public keys of the homeserver for verifying digital signatures.
    pub verify_keys: BTreeMap<ServerKeyId, VerifyKey>,
    /// Public keys that the homeserver used to use and when it stopped using them.
    pub old_verify_keys: BTreeMap<ServerKeyId, OldVerifyKey>,
    /// Digital signatures of this object signed using the verify_keys. Map of
    /// server name to keys by key ID
    pub signatures: BTreeMap<ServerNameBox, BTreeMap<ServerKeyId, String>>,
    /// Timestamp when the keys should be refreshed. This field MUST be ignored in room
    /// versions 1, 2, 3, and 4.
    #[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
    pub valid_until_ts: SystemTime,
}

impl ServerKey {
    /// Creates a new `ServerKey` with the given server name and validity timestamp.
    ///
    /// All other fields will be empty.
    pub fn new(server_name: ServerNameBox, valid_until_ts: SystemTime) -> Self {
        Self {
            server_name,
            verify_keys: BTreeMap::new(),
            old_verify_keys: BTreeMap::new(),
            signatures: BTreeMap::new(),
            valid_until_ts,
        }
    }
}
<commit_msg>Fix small code style inconsistency<commit_after>//! Server discovery endpoints.

use std::{collections::BTreeMap, time::SystemTime};

use ruma_identifiers::{ServerKeyId, ServerNameBox};
use serde::{Deserialize, Serialize};

pub mod discover_homeserver;
pub mod get_remote_server_keys;
pub mod get_remote_server_keys_batch;
pub mod get_server_keys;
pub mod get_server_version;

/// Public key of the homeserver for verifying digital signatures.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct VerifyKey {
    /// The Unpadded Base64 encoded key.
    pub key: String,
}

impl VerifyKey {
    /// Creates a new `VerifyKey` from the given key.
    pub fn new(key: String) -> Self {
        Self { key }
    }
}

/// A key the server used to use, but stopped using.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct OldVerifyKey {
    /// Timestamp when this key expired.
    #[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
    pub expired_ts: SystemTime,

    /// The Unpadded Base64 encoded key.
    pub key: String,
}

impl OldVerifyKey {
    /// Creates a new `OldVerifyKey` with the given expiry time and key.
    pub fn new(expired_ts: SystemTime, key: String) -> Self {
        Self { expired_ts, key }
    }
}

// Spec is wrong, all fields are required (see https://github.com/matrix-org/matrix-doc/issues/2508)
/// Queried server key, signed by the notary server.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct ServerKey {
    /// DNS name of the homeserver.
    pub server_name: ServerNameBox,

    /// Public keys of the homeserver for verifying digital signatures.
    pub verify_keys: BTreeMap<ServerKeyId, VerifyKey>,

    /// Public keys that the homeserver used to use and when it stopped using them.
    pub old_verify_keys: BTreeMap<ServerKeyId, OldVerifyKey>,

    /// Digital signatures of this object signed using the verify_keys. Map of
    /// server name to keys by key ID
    pub signatures: BTreeMap<ServerNameBox, BTreeMap<ServerKeyId, String>>,

    /// Timestamp when the keys should be refreshed. This field MUST be ignored in room
    /// versions 1, 2, 3, and 4.
    #[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
    pub valid_until_ts: SystemTime,
}

impl ServerKey {
    /// Creates a new `ServerKey` with the given server name and validity timestamp.
    ///
    /// All other fields will be empty.
    pub fn new(server_name: ServerNameBox, valid_until_ts: SystemTime) -> Self {
        Self {
            server_name,
            verify_keys: BTreeMap::new(),
            old_verify_keys: BTreeMap::new(),
            signatures: BTreeMap::new(),
            valid_until_ts,
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::fs::File;
use std::io;
use std::io::BufReader;
use std::io::BufWriter;
use std::io::Read;
use std::io::Write;
use std::io::Seek;
use std::path::Path;
use std::process::Command;

extern crate tools;
use tools::find_source_file;
use tools::file_format::analysis::{read_analysis, read_source, read_jumps};
use tools::format::format_file_data;
use tools::config;
use tools::languages;
use languages::FormatAs;

use tools::output::{PanelItem, PanelSection};

fn format_documentation(input_fname: &str, output_fname: &str) {
    let _ = Command::new("pandoc")
        .arg("--css")
        .arg("/static/css/pandoc.css")
        .arg("-o")
        .arg(output_fname)
        .arg("-w")
        .arg("html")
        .arg(input_fname)
        .status();
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let (base_args, fname_args) = args.split_at(3);

    let cfg = config::load(&base_args[1], false);
    println!("Config file read");

    let tree_name = &base_args[2];
    let tree_config = cfg.trees.get(tree_name).unwrap();

    let jumps_fname = format!("{}/jumps", tree_config.paths.index_path);
    //let jumps : std::collections::HashMap<String, tools::analysis::Jump> = std::collections::HashMap::new();
    let jumps = read_jumps(&jumps_fname);
    println!("Jumps read");

    let (blame_commit, head_oid) = match &tree_config.git {
        &Some(ref git) => {
            let head_oid = git.repo.refname_to_id("HEAD").unwrap();
            let blame_commit = if let Some(ref blame_repo) = git.blame_repo {
                let blame_oid = blame_repo.refname_to_id("HEAD").unwrap();
                Some(blame_repo.find_commit(blame_oid).unwrap())
            } else {
                None
            };
            (blame_commit, Some(head_oid))
        },
        &None => (None, None),
    };

    for path in fname_args {
        println!("File {}", path);

        let output_fname = format!("{}/file/{}", tree_config.paths.index_path, path);
        let source_fname = find_source_file(path, &tree_config.paths.files_path, &tree_config.paths.objdir_path);

        let format = languages::select_formatting(path);
        match format {
            FormatAs::FormatDoc(_) => {
                let _ = format_documentation(&source_fname, &output_fname);
                continue;
            },
            _ => {},
        };

        let output_file = File::create(output_fname).unwrap();
        let mut writer = BufWriter::new(output_file);

        let source_file = match File::open(source_fname.clone()) {
            Ok(f) => f,
            Err(_) => {
                println!("Unable to open file");
                continue;
            },
        };

        let p = Path::new(&source_fname);
        let metadata = fs::symlink_metadata(p).unwrap();
        if metadata.file_type().is_symlink() {
            let dest = fs::read_link(p).unwrap();
            write!(writer, "Symlink to {}", dest.to_str().unwrap()).unwrap();
            continue;
        }

        let mut reader = BufReader::new(&source_file);

        match format {
            FormatAs::Binary => {
                let _ = io::copy(&mut reader, &mut writer);
                continue;
            },
            _ => {},
        };

        let analysis_fname = format!("{}/analysis/{}", tree_config.paths.index_path, path);
        let analysis = read_analysis(&analysis_fname, &read_source);

        let mut input = String::new();
        match reader.read_to_string(&mut input) {
            Ok(_) => {},
            Err(_) => {
                let mut bytes = Vec::new();
                reader.seek(std::io::SeekFrom::Start(0)).unwrap();
                match reader.read_to_end(&mut bytes) {
                    Ok(_) => {
                        input.push_str(&bytes.iter().map(|c| *c as char).collect::<String>());
                    },
                    Err(e) => {
                        println!("Unable to read file: {:?}", e);
                        continue;
                    }
                }
            }
        }

        let panel = if path.contains("__GENERATED__") {
            vec![]
        } else if let Some(oid) = head_oid {
            vec![PanelSection {
                name: "Revision control".to_owned(),
                items: vec![PanelItem {
                    title: "Permalink".to_owned(),
                    link: format!("/{}/rev/{}/{}", tree_name, oid, path),
                    update_link_lineno: true,
                }, PanelItem {
                    title: "Log".to_owned(),
                    link: format!("{}/log/tip/{}", config::get_hg_root(tree_config), path),
                    update_link_lineno: false,
                 }, PanelItem {
                    title: "Raw".to_owned(),
                    link: format!("{}/raw-file/tip/{}", config::get_hg_root(tree_config), path),
                    update_link_lineno: false,
                }, PanelItem {
                    title: "Blame".to_owned(),
                    link: "javascript:alert('Hover over the gray bar on the left to see blame information.')".to_owned(),
                    update_link_lineno: false,
                }],
            }]
        } else {
            vec![]
        };

        format_file_data(&cfg,
                         tree_name,
                         &panel,
                         &None,
                         &blame_commit,
                         path,
                         input,
                         &jumps,
                         &analysis,
                         &mut writer).unwrap();
    }
}
<commit_msg>Bug 1282151 - Show changeset bar even for tip revision<commit_after>use std::env;
use std::fs;
use std::fs::File;
use std::io;
use std::io::BufReader;
use std::io::BufWriter;
use std::io::Read;
use std::io::Write;
use std::io::Seek;
use std::path::Path;
use std::process::Command;

extern crate tools;
use tools::find_source_file;
use tools::file_format::analysis::{read_analysis, read_source, read_jumps};
use tools::format::format_file_data;
use tools::config;
use tools::languages;
use languages::FormatAs;

use tools::output::{PanelItem, PanelSection};

fn format_documentation(input_fname: &str, output_fname: &str) {
    let _ = Command::new("pandoc")
        .arg("--css")
        .arg("/static/css/pandoc.css")
        .arg("-o")
        .arg(output_fname)
        .arg("-w")
        .arg("html")
        .arg(input_fname)
        .status();
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let (base_args, fname_args) = args.split_at(3);

    let cfg = config::load(&base_args[1], false);
    println!("Config file read");

    let tree_name = &base_args[2];
    let tree_config = cfg.trees.get(tree_name).unwrap();

    let jumps_fname = format!("{}/jumps", tree_config.paths.index_path);
    //let jumps : std::collections::HashMap<String, tools::analysis::Jump> = std::collections::HashMap::new();
    let jumps = read_jumps(&jumps_fname);
    println!("Jumps read");

    let (blame_commit, head_oid) = match &tree_config.git {
        &Some(ref git) => {
            let head_oid = git.repo.refname_to_id("HEAD").unwrap();
            let blame_commit = if let Some(ref blame_repo) = git.blame_repo {
                let blame_oid = blame_repo.refname_to_id("HEAD").unwrap();
                Some(blame_repo.find_commit(blame_oid).unwrap())
            } else {
                None
            };
            (blame_commit, Some(head_oid))
        },
        &None => (None, None),
    };

    for path in fname_args {
        println!("File {}", path);

        let output_fname = format!("{}/file/{}", tree_config.paths.index_path, path);
        let source_fname = find_source_file(path, &tree_config.paths.files_path, &tree_config.paths.objdir_path);

        let format = languages::select_formatting(path);
        match format {
            FormatAs::FormatDoc(_) => {
                let _ = format_documentation(&source_fname, &output_fname);
                continue;
            },
            _ => {},
        };

        let output_file = File::create(output_fname).unwrap();
        let mut writer = BufWriter::new(output_file);

        let source_file = match File::open(source_fname.clone()) {
            Ok(f) => f,
            Err(_) => {
                println!("Unable to open file");
                continue;
            },
        };

        let p = Path::new(&source_fname);
        let metadata = fs::symlink_metadata(p).unwrap();
        if metadata.file_type().is_symlink() {
            let dest = fs::read_link(p).unwrap();
            write!(writer, "Symlink to {}", dest.to_str().unwrap()).unwrap();
            continue;
        }

        let mut reader = BufReader::new(&source_file);

        match format {
            FormatAs::Binary => {
                let _ = io::copy(&mut reader, &mut writer);
                continue;
            },
            _ => {},
        };

        let analysis_fname = format!("{}/analysis/{}", tree_config.paths.index_path, path);
        let analysis = read_analysis(&analysis_fname, &read_source);

        let mut input = String::new();
        match reader.read_to_string(&mut input) {
            Ok(_) => {},
            Err(_) => {
                let mut bytes = Vec::new();
                reader.seek(std::io::SeekFrom::Start(0)).unwrap();
                match reader.read_to_end(&mut bytes) {
                    Ok(_) => {
                        input.push_str(&bytes.iter().map(|c| *c as char).collect::<String>());
                    },
                    Err(e) => {
                        println!("Unable to read file: {:?}", e);
                        continue;
                    }
                }
            }
        }

        let panel = if path.contains("__GENERATED__") {
            vec![]
        } else if let Some(oid) = head_oid {
            vec![PanelSection {
                name: "Revision control".to_owned(),
                items: vec![PanelItem {
                    title: "Permalink".to_owned(),
                    link: format!("/{}/rev/{}/{}", tree_name, oid, path),
                    update_link_lineno: true,
                }, PanelItem {
                    title: "Log".to_owned(),
                    link: format!("{}/log/tip/{}", config::get_hg_root(tree_config), path),
                    update_link_lineno: false,
                 }, PanelItem {
                    title: "Raw".to_owned(),
                    link: format!("{}/raw-file/tip/{}", config::get_hg_root(tree_config), path),
                    update_link_lineno: false,
                }, PanelItem {
                    title: "Blame".to_owned(),
                    link: "javascript:alert('Hover over the gray bar on the left to see blame information.')".to_owned(),
                    update_link_lineno: false,
                }],
            }]
        } else {
            vec![]
        };

        let head_commit = head_oid
            .and_then(|oid| tree_config.git.as_ref().unwrap().repo.find_commit(oid).ok());

        format_file_data(&cfg,
                         tree_name,
                         &panel,
                         &head_commit,
                         &blame_commit,
                         path,
                         input,
                         &jumps,
                         &analysis,
                         &mut writer).unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate crypto;
extern crate rand;

use self::crypto::aes_gcm::AesGcm;
use self::crypto::aead::AeadEncryptor;
use self::crypto::aead::AeadDecryptor;
use self::crypto::aes::KeySize::KeySize256;
use self::rand::{Rng, OsRng};

const TAG_LENGTH: usize = 16;
const KEY_LENGTH: usize = 32;
const IV_LENGTH: usize = 12;

pub struct EncryptionResult {
  pub key: Box<[u8]>,
  pub iv: Box<[u8]>,
  pub ciphertext: Vec<u8>,
  pub tag: Box<[u8]>
}

pub struct DecryptionResult {
    pub plaintext: Vec<u8>
}

pub fn encrypt(auth_data: &[u8], plaintext: &[u8]) -> EncryptionResult {

	let plaintext_len: usize = plaintext.len();

	let mut key: [u8; KEY_LENGTH] = [0; KEY_LENGTH];
	let mut iv: [u8; IV_LENGTH] = [0; IV_LENGTH];
	let mut rng = OsRng::new().ok().unwrap();
	rng.fill_bytes(&mut key);
	rng.fill_bytes(&mut iv);

	let mut cipher = AesGcm::new(KeySize256, &key, &iv, &auth_data);

 	let mut ciphertext: Vec<u8> = Vec::with_capacity(plaintext_len);
	unsafe { ciphertext.set_len(plaintext_len); }
	let mut tag: [u8; TAG_LENGTH] = [0; TAG_LENGTH];

	cipher.encrypt(plaintext, &mut ciphertext, &mut tag);

	EncryptionResult { key: Box::new(key), iv: Box::new(iv), ciphertext: ciphertext, tag: Box::new(tag) }
}

pub fn decrypt(auth_data: &[u8], key: &[u8], iv: &[u8], ciphertext: &[u8], tag: &[u8]) -> DecryptionResult {
    let ciphertext_len: usize = ciphertext.len();
    let mut decipher = AesGcm::new(KeySize256, key, iv, auth_data);
    let mut plaintext: Vec<u8> = Vec::with_capacity(ciphertext_len);
    unsafe { plaintext.set_len(ciphertext_len); }
    decipher.decrypt(ciphertext, &mut plaintext, tag);

    DecryptionResult { plaintext: plaintext }
}
<commit_msg>Remove tabs.<commit_after>extern crate crypto;
extern crate rand;

use self::crypto::aes_gcm::AesGcm;
use self::crypto::aead::AeadEncryptor;
use self::crypto::aead::AeadDecryptor;
use self::crypto::aes::KeySize::KeySize256;
use self::rand::{Rng, OsRng};

const TAG_LENGTH: usize = 16;
const KEY_LENGTH: usize = 32;
const IV_LENGTH: usize = 12;

pub struct EncryptionResult {
    pub key: Box<[u8]>,
    pub iv: Box<[u8]>,
    pub ciphertext: Vec<u8>,
    pub tag: Box<[u8]>
}

pub struct DecryptionResult {
    pub plaintext: Vec<u8>
}

pub fn encrypt(auth_data: &[u8], plaintext: &[u8]) -> EncryptionResult {

    let plaintext_len: usize = plaintext.len();

    let mut key: [u8; KEY_LENGTH] = [0; KEY_LENGTH];
    let mut iv: [u8; IV_LENGTH] = [0; IV_LENGTH];
    let mut rng = OsRng::new().ok().unwrap();
    rng.fill_bytes(&mut key);
    rng.fill_bytes(&mut iv);

    let mut cipher = AesGcm::new(KeySize256, &key, &iv, &auth_data);

    let mut ciphertext: Vec<u8> = Vec::with_capacity(plaintext_len);
    unsafe { ciphertext.set_len(plaintext_len); }
    let mut tag: [u8; TAG_LENGTH] = [0; TAG_LENGTH];

    cipher.encrypt(plaintext, &mut ciphertext, &mut tag);

    EncryptionResult { key: Box::new(key), iv: Box::new(iv), ciphertext: ciphertext, tag: Box::new(tag) }
}

pub fn decrypt(auth_data: &[u8], key: &[u8], iv: &[u8], ciphertext: &[u8], tag: &[u8]) -> DecryptionResult {
    let ciphertext_len: usize = ciphertext.len();
    let mut decipher = AesGcm::new(KeySize256, key, iv, auth_data);
    let mut plaintext: Vec<u8> = Vec::with_capacity(ciphertext_len);
    unsafe { plaintext.set_len(ciphertext_len); }
    decipher.decrypt(ciphertext, &mut plaintext, tag);

    DecryptionResult { plaintext: plaintext }
}
<|endoftext|>


<commit_before>//! `cpuid` intrinsics
#![allow(clippy::module_name_repetitions)]

#[cfg(test)]
use stdarch_test::assert_instr;

/// Result of the `cpuid` instruction.
#[allow(clippy::missing_inline_in_public_items)]
// ^^ the derived impl of Debug for CpuidResult is not #[inline] and that's OK.
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let eax;
    let ebx;
    let ecx;
    let edx;

    #[cfg(target_arch = "x86")]
    {
        asm!(
            "cpuid",
            inlateout("eax") leaf => eax,
            lateout("ebx") ebx,
            inlateout("ecx") sub_leaf => ecx,
            lateout("edx") edx,
            options(nostack, preserves_flags),
        );
    }
    #[cfg(target_arch = "x86_64")]
    {
        // x86-64 uses `rbx` as the base register, so preserve it.
        // This works around a bug in LLVM with ASAN enabled:
        // https://bugs.llvm.org/show_bug.cgi?id=17907
        asm!(
            "mov rsi, rbx",
            "cpuid",
            "xchg rsi, rbx",
            inlateout("eax") leaf => eax,
            lateout("esi") ebx,
            inlateout("ecx") sub_leaf => ecx,
            lateout("edx") edx,
            options(nostack, preserves_flags),
        );
    }
    CpuidResult { eax, ebx, ecx, edx }
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline]
pub fn has_cpuid() -> bool {
    #[cfg(target_env = "sgx")]
    {
        false
    }
    #[cfg(all(not(target_env = "sgx"), target_arch = "x86_64"))]
    {
        true
    }
    #[cfg(all(not(target_env = "sgx"), target_arch = "x86"))]
    {
        // Optimization for i586 and i686 Rust targets which SSE enabled
        // and support cpuid:
        #[cfg(target_feature = "sse")]
        {
            true
        }

        // If SSE is not enabled, detect whether cpuid is available:
        #[cfg(not(target_feature = "sse"))]
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether
            // the 21st bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let result: u32;
            asm!(
                // Read eflags and save a copy of it
                "pushfd",
                "pop {result}",
                "mov {saved_flags}, {result}",
                // Flip 21st bit of the flags
                "xor {result}, 0x200000",
                // Load the modified flags and read them back.
                // Bit 21 can only be modified if cpuid is available.
                "push {result}",
                "popfd",
                "pushfd",
                "pop {result}",
                // Use xor to find out whether bit 21 has changed
                "xor {result}, {saved_flags}",
                result = out(reg) result,
                saved_flags = out(reg) _,
                options(nomem),
            );
            // There is a race between popfd (A) and pushfd (B)
            // where other bits beyond 21st may have been modified due to
            // interrupts, a debugger stepping through the asm, etc.
            //
            // Therefore, explicitly check whether the 21st bit
            // was modified or not.
            //
            // If the result is zero, the cpuid bit was not modified.
            // If the result is `0x200000` (non-zero), then the cpuid
            // was correctly modified and the CPU supports the cpuid
            // instruction:
            (result & 0x200000) != 0
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

#[cfg(test)]
mod tests {
    use crate::core_arch::x86::*;

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());
    }
}
<commit_msg>Avoid using ebx as an asm! operand (#1121)<commit_after>//! `cpuid` intrinsics
#![allow(clippy::module_name_repetitions)]

#[cfg(test)]
use stdarch_test::assert_instr;

/// Result of the `cpuid` instruction.
#[allow(clippy::missing_inline_in_public_items)]
// ^^ the derived impl of Debug for CpuidResult is not #[inline] and that's OK.
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let eax;
    let ebx;
    let ecx;
    let edx;

    // LLVM sometimes reserves `ebx` for its internal use, we so we need to use
    // a scratch register for it instead.
    #[cfg(target_arch = "x86")]
    {
        asm!(
            "mov {0}, ebx",
            "cpuid",
            "xchg {0}, ebx",
            lateout(reg) ebx,
            inlateout("eax") leaf => eax,
            inlateout("ecx") sub_leaf => ecx,
            lateout("edx") edx,
            options(nostack, preserves_flags),
        );
    }
    #[cfg(target_arch = "x86_64")]
    {
        asm!(
            "mov {0:r}, rbx",
            "cpuid",
            "xchg {0:r}, rbx",
            lateout(reg) ebx,
            inlateout("eax") leaf => eax,
            inlateout("ecx") sub_leaf => ecx,
            lateout("edx") edx,
            options(nostack, preserves_flags),
        );
    }
    CpuidResult { eax, ebx, ecx, edx }
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline]
pub fn has_cpuid() -> bool {
    #[cfg(target_env = "sgx")]
    {
        false
    }
    #[cfg(all(not(target_env = "sgx"), target_arch = "x86_64"))]
    {
        true
    }
    #[cfg(all(not(target_env = "sgx"), target_arch = "x86"))]
    {
        // Optimization for i586 and i686 Rust targets which SSE enabled
        // and support cpuid:
        #[cfg(target_feature = "sse")]
        {
            true
        }

        // If SSE is not enabled, detect whether cpuid is available:
        #[cfg(not(target_feature = "sse"))]
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether
            // the 21st bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let result: u32;
            asm!(
                // Read eflags and save a copy of it
                "pushfd",
                "pop {result}",
                "mov {saved_flags}, {result}",
                // Flip 21st bit of the flags
                "xor {result}, 0x200000",
                // Load the modified flags and read them back.
                // Bit 21 can only be modified if cpuid is available.
                "push {result}",
                "popfd",
                "pushfd",
                "pop {result}",
                // Use xor to find out whether bit 21 has changed
                "xor {result}, {saved_flags}",
                result = out(reg) result,
                saved_flags = out(reg) _,
                options(nomem),
            );
            // There is a race between popfd (A) and pushfd (B)
            // where other bits beyond 21st may have been modified due to
            // interrupts, a debugger stepping through the asm, etc.
            //
            // Therefore, explicitly check whether the 21st bit
            // was modified or not.
            //
            // If the result is zero, the cpuid bit was not modified.
            // If the result is `0x200000` (non-zero), then the cpuid
            // was correctly modified and the CPU supports the cpuid
            // instruction:
            (result & 0x200000) != 0
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

#[cfg(test)]
mod tests {
    use crate::core_arch::x86::*;

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());
    }
}
<|endoftext|>


<commit_before>use std::{error, fmt};

/// The SCRAM mechanism error cases.
#[derive(Debug, PartialEq)]
pub enum Error {
    /// A message wasn't formatted as required. `Kind` contains further information.
    ///
    /// RFC5803 section 7 describes the format of the exchanged messages.
    Protocol(Kind),
    /// The server required a mandatory extension to be present that this client doesn't support.
    UnsupportedExtension,
    /// The server couldn't be validated. This usually means that the server didn't posess a stored
    /// key to verify the credentials.
    InvalidServer,
    /// The server rejected the authentication request. `String` contains a message from the server.
    Authentication(String),
    /// The username supplied was not valid
    InvalidUser(String),
}

/// The kinds of protocol errors.
#[derive(Debug, PartialEq)]
pub enum Kind {
    /// The server responded with a nonce that doesn't start with our nonce.
    InvalidNonce,
    /// The content of the field `Field` is invalid.
    InvalidField(Field),
    /// The field `Field` was expected but not found.
    ExpectedField(Field),
}

/// The fields used in the exchanged messages.
#[derive(Debug, PartialEq)]
pub enum Field {
    /// Nonce
    Nonce,
    /// Salt
    Salt,
    /// Iterations
    Iterations,
    /// Verify or Error
    VerifyOrError,
    /// Channel Binding
    ChannelBinding,
    /// Authtorization ID
    Authzid,
    /// Authcid
    Authcid,
    /// GS2Header
    GS2Header,
    /// Client Proof
    Proof,
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;
        use self::Kind::*;
        match *self {
            Protocol(InvalidNonce) => write!(fmt, "Invalid nonce"),
            Protocol(InvalidField(ref field)) => write!(fmt, "Invalid field {:?}", field),
            Protocol(ExpectedField(ref field)) => write!(fmt, "Expected field {:?}", field),
            UnsupportedExtension => write!(fmt, "Unsupported extension"),
            InvalidServer => write!(fmt, "Server failed validation"),
            InvalidUser(ref username) => write!(fmt, "Invalid user: '{}'", username),
            Authentication(ref msg) => write!(fmt, "authentication error {}", msg),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        use self::Error::*;
        use self::Kind::*;
        match *self {
            Protocol(InvalidNonce) => "Invalid nonce",
            Protocol(InvalidField(_)) => "Invalid field",
            Protocol(ExpectedField(_)) => "Expected field",
            UnsupportedExtension => "Unsupported extension",
            InvalidServer => "Server failed validation",
            InvalidUser(_) => "Invalid user",
            Authentication(_) => "Unspecified error",
        }
    }
}
<commit_msg>Fix typo in documentation<commit_after>use std::{error, fmt};

/// The SCRAM mechanism error cases.
#[derive(Debug, PartialEq)]
pub enum Error {
    /// A message wasn't formatted as required. `Kind` contains further information.
    ///
    /// RFC5803 section 7 describes the format of the exchanged messages.
    Protocol(Kind),
    /// The server required a mandatory extension to be present that this client doesn't support.
    UnsupportedExtension,
    /// The server couldn't be validated. This usually means that the server didn't posess a stored
    /// key to verify the credentials.
    InvalidServer,
    /// The server rejected the authentication request. `String` contains a message from the server.
    Authentication(String),
    /// The username supplied was not valid
    InvalidUser(String),
}

/// The kinds of protocol errors.
#[derive(Debug, PartialEq)]
pub enum Kind {
    /// The server responded with a nonce that doesn't start with our nonce.
    InvalidNonce,
    /// The content of the field `Field` is invalid.
    InvalidField(Field),
    /// The field `Field` was expected but not found.
    ExpectedField(Field),
}

/// The fields used in the exchanged messages.
#[derive(Debug, PartialEq)]
pub enum Field {
    /// Nonce
    Nonce,
    /// Salt
    Salt,
    /// Iterations
    Iterations,
    /// Verify or Error
    VerifyOrError,
    /// Channel Binding
    ChannelBinding,
    /// Authorization ID
    Authzid,
    /// Authcid
    Authcid,
    /// GS2Header
    GS2Header,
    /// Client Proof
    Proof,
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;
        use self::Kind::*;
        match *self {
            Protocol(InvalidNonce) => write!(fmt, "Invalid nonce"),
            Protocol(InvalidField(ref field)) => write!(fmt, "Invalid field {:?}", field),
            Protocol(ExpectedField(ref field)) => write!(fmt, "Expected field {:?}", field),
            UnsupportedExtension => write!(fmt, "Unsupported extension"),
            InvalidServer => write!(fmt, "Server failed validation"),
            InvalidUser(ref username) => write!(fmt, "Invalid user: '{}'", username),
            Authentication(ref msg) => write!(fmt, "authentication error {}", msg),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        use self::Error::*;
        use self::Kind::*;
        match *self {
            Protocol(InvalidNonce) => "Invalid nonce",
            Protocol(InvalidField(_)) => "Invalid field",
            Protocol(ExpectedField(_)) => "Expected field",
            UnsupportedExtension => "Unsupported extension",
            InvalidServer => "Server failed validation",
            InvalidUser(_) => "Invalid user",
            Authentication(_) => "Unspecified error",
        }
    }
}
<|endoftext|>


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

use std::fmt;

use syntax;

/// An error that occurred during parsing or compiling a regular expression.
#[derive(Debug)]
pub enum Error {
    /// A syntax error.
    Syntax(syntax::Error),
    /// The compiled program exceeded the set size limit.
    /// The argument is the size limit imposed.
    CompiledTooBig(usize),
    /// **DEPRECATED:** Will be removed on next major version bump.
    ///
    /// This error is no longer used. (A `RegexSet` can now contain zero or
    /// more regular expressions.)
    InvalidSet,
    /// Hints that destructuring should not be exhaustive.
    ///
    /// This enum may grow additional variants, so this makes sure clients
    /// don't count on exhaustive matching. (Otherwise, adding a new variant
    /// could break existing code.)
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Syntax(ref err) => err.description(),
            Error::CompiledTooBig(_) => "compiled program too big",
            Error::InvalidSet => {
                "sets must contain 2 or more regular expressions"
            }
            Error::__Nonexhaustive => unreachable!(),
        }
    }

    fn cause(&self) -> Option<&::std::error::Error> {
        match *self {
            Error::Syntax(ref err) => Some(err),
            _ => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Syntax(ref err) => err.fmt(f),
            Error::CompiledTooBig(limit) => {
                write!(f, "Compiled regex exceeds size limit of {} bytes.",
                       limit)
            }
            Error::InvalidSet => {
                write!(f, "Sets must contain 2 or more regular expressions.")
            }
            Error::__Nonexhaustive => unreachable!(),
        }
    }
}

impl From<syntax::Error> for Error {
    fn from(err: syntax::Error) -> Error {
        Error::Syntax(err)
    }
}
<commit_msg>Update the Error type.<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;

use syntax;

/// An error that occurred during parsing or compiling a regular expression.
#[derive(Debug)]
pub enum Error {
    /// A syntax error.
    Syntax(String),
    /// The compiled program exceeded the set size limit.
    /// The argument is the size limit imposed.
    CompiledTooBig(usize),
    /// Hints that destructuring should not be exhaustive.
    ///
    /// This enum may grow additional variants, so this makes sure clients
    /// don't count on exhaustive matching. (Otherwise, adding a new variant
    /// could break existing code.)
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Syntax(ref err) => err,
            Error::CompiledTooBig(_) => "compiled program too big",
            Error::__Nonexhaustive => unreachable!(),
        }
    }

    fn cause(&self) -> Option<&::std::error::Error> {
        None
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Syntax(ref err) => err.fmt(f),
            Error::CompiledTooBig(limit) => {
                write!(f, "Compiled regex exceeds size limit of {} bytes.",
                       limit)
            }
            Error::__Nonexhaustive => unreachable!(),
        }
    }
}

impl From<syntax::Error> for Error {
    fn from(err: syntax::Error) -> Error {
        Error::Syntax(err.to_string())
    }
}
<|endoftext|>


<commit_before>//! Provides a general partitioning function that implements C++'s
//! [std::partition](http://en.cppreference.com/w/cpp/algorithm/partition)
use std::mem;

/// Re-orders elements in the range yielded by `it` based on `pred`. All elements
/// that the predicate returns true for will be placed before all elements
/// that the predicate returned false for. Also returns the index of the
/// first element in the false group
pub fn partition<'a, T: 'a, I, F>(mut it: I, pred: F) -> usize
        where I: DoubleEndedIterator<Item = &'a mut T>,
        F: Fn(&T) -> bool {
    let mut split_idx = 0;
    loop {
        let mut front = None;
        let mut back = None;
        while let Some(f) = it.next() {
            split_idx += 1;
            if !pred(f) {
                front = Some(f);
                break;
            }
        }
        while let Some(b) = it.next_back() {
            if pred(b) {
                back = Some(b);
                break;
            }
        }
        match (front, back) {
            (Some(f), Some(b)) => mem::swap(f, b),
            _ => break,
        }
    }
    split_idx
}

#[test]
fn test_partition() {
    // This test just partitions the odd and even numbers
    let mut vals = vec![1u32, 2, 3, 4, 5, 6];
    let idx = partition(vals.iter_mut(), |x| *x % 2 == 0);
    println!("Partition idx = {}", idx);
    // The first 3 items should be even the next 3 should be odd
    println!("Partitioned: {:?}", vals);
    assert_eq!(idx, 3);
    assert!(vals.iter().take(3).fold(true, |f, x| *x % 2 == 0 && f));
    assert!(vals.iter().skip(3).fold(true, |f, x| *x % 2 != 0 && f));
}

<commit_msg>Caught bug in partition that was causing bad splits in rare cases<commit_after>//! Provides a general partitioning function that implements C++'s
//! [std::partition](http://en.cppreference.com/w/cpp/algorithm/partition)
use std::mem;

/// Re-orders elements in the range yielded by `it` based on `pred`. All elements
/// that the predicate returns true for will be placed before all elements
/// that the predicate returned false for. Also returns the index of the
/// first element in the false group
pub fn partition<'a, T: 'a, I, F>(mut it: I, pred: F) -> usize
        where I: DoubleEndedIterator<Item = &'a mut T>,
        F: Fn(&T) -> bool {
    let mut split_idx = 0;
    loop {
        let mut front = None;
        let mut back = None;
        while let Some(f) = it.next() {
            if !pred(f) {
                front = Some(f);
                break;
            } else {
                split_idx += 1;
            }
        }
        while let Some(b) = it.next_back() {
            if pred(b) {
                back = Some(b);
                break;
            }
        }
        match (front, back) {
            (Some(f), Some(b)) => {
                mem::swap(f, b);
                split_idx += 1;
            },
            _ => break,
        }
    }
    split_idx
}

#[test]
fn test_partition() {
    // This test just partitions the odd and even numbers
    let mut vals = vec![1u32, 2, 3, 4, 5, 6];
    let idx = partition(vals.iter_mut(), |x| *x % 2 == 0);
    println!("Partition idx = {}", idx);
    // The first 3 items should be even the next 3 should be odd
    println!("Partitioned: {:?}", vals);
    assert_eq!(idx, 3);
    assert!(vals.iter().take(3).fold(true, |f, x| *x % 2 == 0 && f));
    assert!(vals.iter().skip(3).fold(true, |f, x| *x % 2 != 0 && f));
}

<|endoftext|>


<commit_before>//! Abstraction of spatial partitioning schemes

use std::vec::IntoIter;

/// A type describing a partition of some space
pub trait Partition<T>: Sized {
    // TODO: uncomment the following, as soon as this bug is fixed.
    // link: https://github.com/rust-lang/rust/issues/20551

    // The type of subsequent partitions
    // type Subpartition: Partition<T> = Self;

    /// The type of iterator used for subdivision
    type Iter: Iterator<Item=Self>;

    /// Subdivide into smaller partitions
    fn subdivide(&self) -> Self::Iter;

    /// Does the partition contain an element?
    fn contains(&self, elem: &T) -> bool;

    /// Totality proposition
    ///
    /// A partition is required to be total, i.e. any element contained in the
    /// partition will be contained in exactly one of its subdivided partitions.
    /// At the same time, an element not contained in the partition can not be
    /// contained by any subdivided partition.
    fn prop_is_total(&self, elem: &T) -> bool {
        if self.contains(elem) {
            self.subdivide().filter(|sub| sub.contains(elem)).count() == 1
        }
        else {
            self.subdivide().all(|sub| !sub.contains(elem))
        }
    }
}

/// A half-open interval [a, b) between two f64
#[derive(Copy)]
pub struct Interval {
    start: f64,
    end: f64
}

impl Interval {
    /// Create a new interval given lower and upper bound
    ///
    /// This constructor dynamically asserts that `start < end`.
    pub fn new(start: f64, end: f64) -> Interval {
        assert!(start < end);
        Interval { start: start, end: end }
    }
}

impl Partition<f64> for Interval {
    type Iter = IntoIter<Interval>;

    fn subdivide(&self) -> IntoIter<Interval> {
        let mid = (self.start + self.end) / 2.0;
        vec![
            Interval::new(self.start, mid),
            Interval::new(mid, self.end)
        ].into_iter()
    }

    fn contains(&self, elem: &f64) -> bool {
        (self.start <= *elem) && (*elem < self.end)
    }
}

#[cfg(test)]
mod test {
    use super::{Interval, Partition};
    use quickcheck::{quickcheck, TestResult};

    #[test]
    fn interval_total() {
        fn interval_total((a, b): (f64, f64), c: f64) -> TestResult {
            if b < a { TestResult::discard() }
            else { TestResult::from_bool({
                Interval::new(a, b).prop_is_total(&c)
            })}
        }
        quickcheck(interval_total as fn((f64, f64), f64) -> TestResult);
    }
}
<commit_msg>Make interval more generic<commit_after>//! Abstraction of spatial partitioning schemes

use std::vec::IntoIter;

/// A type describing a partition of some space
pub trait Partition<T>: Sized {
    // TODO: uncomment the following, as soon as this bug is fixed.
    // link: https://github.com/rust-lang/rust/issues/20551

    // The type of subsequent partitions
    // type Subpartition: Partition<T> = Self;

    /// The type of iterator used for subdivision
    type Iter: Iterator<Item=Self>;

    /// Subdivide into smaller partitions
    fn subdivide(&self) -> Self::Iter;

    /// Does the partition contain an element?
    fn contains(&self, elem: &T) -> bool;

    /// Totality proposition
    ///
    /// A partition is required to be total, i.e. any element contained in the
    /// partition will be contained in exactly one of its subdivided partitions.
    /// At the same time, an element not contained in the partition can not be
    /// contained by any subdivided partition.
    fn prop_is_total(&self, elem: &T) -> bool {
        if self.contains(elem) {
            self.subdivide().filter(|sub| sub.contains(elem)).count() == 1
        }
        else {
            self.subdivide().all(|sub| !sub.contains(elem))
        }
    }
}

/// The notion of a mid point between two inputs
trait Mid {
    /// Return the mid between this point and another
    fn mid(self, other: Self) -> Self;
}

impl Mid for f64 {
    fn mid(self, other: f64) -> f64 { (self + other) / 2.0 }
}

impl Mid for f32 {
    fn mid(self, other: f32) -> f32 { (self + other) / 2.0 }
}

/// A half-open interval [a, b) between two points a and b
#[derive(Copy)]
pub struct Interval<T> {
    start: T,
    end: T,
}

impl<T: PartialOrd> Interval<T> {
    /// Create a new interval given lower and upper bound
    ///
    /// This constructor dynamically asserts that `start < end`.
    pub fn new(start: T, end: T) -> Interval<T> {
        assert!(start < end);
        Interval { start: start, end: end }
    }
}

impl<T: Mid + PartialOrd + Copy> Partition<T> for Interval<T> {
    type Iter = IntoIter<Interval<T>>;

    fn subdivide(&self) -> IntoIter<Interval<T>> {
        let mid = self.start.mid(self.end);
        vec![
            Interval { start: self.start, end: mid },
            Interval { start: mid, end: self.end },
        ].into_iter()
    }

    fn contains(&self, elem: &T) -> bool {
        (self.start <= *elem) && (*elem < self.end)
    }
}

#[cfg(test)]
mod test {
    use super::{Interval, Partition};
    use quickcheck::{quickcheck, TestResult};

    #[test]
    fn interval_total_f64() {
        fn interval_total_f64((a, b): (f64, f64), c: f64) -> TestResult {
            if b < a { TestResult::discard() }
            else { TestResult::from_bool({
                Interval::new(a, b).prop_is_total(&c)
            })}
        }
        quickcheck(interval_total_f64 as fn((f64, f64), f64) -> TestResult);
    }
}
<|endoftext|>