<commit_before>/*!
 * SMTP commands library
 *
 * RFC 5321 : http://tools.ietf.org/html/rfc5321#section-4.1
 */

use std::fmt;
use common::CRLF;

/*
 * HELO <SP> <domain> <CRLF>
 * MAIL <SP> FROM:<reverse-path> <CRLF>
 * RCPT <SP> TO:<forward-path> <CRLF>
 * DATA <CRLF>
 * RSET <CRLF>
 * SEND <SP> FROM:<reverse-path> <CRLF>
 * SOML <SP> FROM:<reverse-path> <CRLF>
 * SAML <SP> FROM:<reverse-path> <CRLF>
 * VRFY <SP> <string> <CRLF>
 * EXPN <SP> <string> <CRLF>
 * HELP [<SP> <string>] <CRLF>
 * NOOP <CRLF>
 * QUIT <CRLF>
 * TURN <CRLF>
 */

/// List of SMTP commands
#[deriving(Eq,Clone)]
pub enum Command {
    Hello,
    Ehello,
    Mail,
    Recipient,
    Data,
    Reset,
    SendMail,
    SendOrMail,
    SendAndMail,
    Verify,
    Expand,
    Help,
    Noop,
    Quit,
    /// Deprecated in RFC 5321
    Turn,
}

impl Command {
    /// Tell if the command accetps an string argument.
    pub fn takes_argument(&self) -> bool{
        match *self {
            Ehello        => true,
            Hello         => true,
            Mail          => true,
            Recipient     => true,
            Data          => false,
            Reset         => false,
            SendMail      => true,
            SendOrMail    => true,
            SendAndMail   => true,
            Verify        => true,
            Expand        => true,
            Help          => true,
            Noop          => false,
            Quit          => false,
            Turn          => false,
        }
    }

    /// Tell if an argument is needed by the command.
    pub fn needs_argument(&self) -> bool {
        match *self {
            Ehello        => true,
            Hello         => true,
            Mail          => true,
            Recipient     => true,
            Data          => false,
            Reset         => false,
            SendMail      => true,
            SendOrMail    => true,
            SendAndMail   => true,
            Verify        => true,
            Expand        => true,
            Help          => false,
            Noop          => false,
            Quit          => false,
            Turn          => false,
        }
    }
}

impl ToStr for Command {
    /// Get the name of a command.
    fn to_str(&self) -> ~str {
        match *self {
            Hello           => ~"HELO",
            Ehello          => ~"EHLO",
            Mail            => ~"MAIL",
            Recipient       => ~"RCPT",
            Data            => ~"DATA",
            Reset           => ~"RSET",
            SendMail        => ~"SEND",
            SendOrMail      => ~"SOML",
            SendAndMail     => ~"SAML",
            Verify          => ~"VRFY",
            Expand          => ~"EXPN",
            Help            => ~"HELP",
            Noop            => ~"NOOP",
            Quit            => ~"QUIT",
            Turn            => ~"TURN",
        }
    }
}

impl FromStr for Command {
    /// Get the Command from its name.
    fn from_str(command: &str) -> Option<Command> {
        if !command.is_ascii() {
            return None;
        }
        match command {
            "HELO" => Some(Hello),
            "EHLO" => Some(Ehello),
            "MAIL" => Some(Mail),
            "RCPT" => Some(Recipient),
            "DATA" => Some(Data),
            "RSET" => Some(Reset),
            "SEND" => Some(SendMail),
            "SOML" => Some(SendOrMail),
            "SAML" => Some(SendAndMail),
            "VRFY" => Some(Verify),
            "EXPN" => Some(Expand),
            "HELP" => Some(Help),
            "NOOP" => Some(Noop),
            "QUIT" => Some(Quit),
            "TURN" => Some(Turn),
            _      => None,
        }
    }
}

impl fmt::Show for Command {
    /// Format SMTP command display
    fn fmt(s: &Command, f: &mut fmt::Formatter) {
        f.buf.write(match *s {
            Ehello        => "EHLO".as_bytes(),
            Hello         => "HELO".as_bytes(),
            Mail          => "MAIL FROM:".as_bytes(),
            Recipient     => "RCPT TO:".as_bytes(),
            Data          => "DATA".as_bytes(),
            Reset         => "RSET".as_bytes(),
            SendMail      => "SEND TO:".as_bytes(),
            SendOrMail    => "SOML TO:".as_bytes(),
            SendAndMail   => "SAML TO:".as_bytes(),
            Verify        => "VRFY".as_bytes(),
            Expand        => "EXPN".as_bytes(),
            Help          => "HELP".as_bytes(),
            Noop          => "NOOP".as_bytes(),
            Quit          => "QUIT".as_bytes(),
            Turn          => "TURN".as_bytes()
        })
    }
}

/// Structure for a complete SMTP command, containing an optionnal string argument.
pub struct SmtpCommand {
    command: Command,
    argument: Option<~str>
}

impl SmtpCommand {
    /// Return a new structure from the name of the command and an optionnal argument.
    pub fn new(command_str: ~str, argument: Option<~str>) -> SmtpCommand {
        let command = match from_str::<Command>(command_str) {
            Some(x) => x,
            None    => fail!("Unrecognized SMTP command")
        };

        match (command.takes_argument(), command.needs_argument(), argument.clone()) {
            (true, true, None)      => fail!("Wrong SMTP syntax : argument needed"),
            (false, false, Some(x)) => fail!("Wrong SMTP syntax : {:s} not accepted", x),
            _                       => SmtpCommand {command: command, argument: argument}
        }
    }

    /// Return the formatted command, ready to be used in an SMTP session.
    pub fn get_formatted_command(&self) -> ~str {
        match (self.command.takes_argument(), self.command.needs_argument(), self.argument.clone()) {
            (true, _, Some(argument)) => format!("{} {}{}", self.command, argument, CRLF),
            (_, false, None)   => format!("{}{}", self.command, CRLF),
            _                  => fail!("Wrong SMTP syntax")
        }
    }
}

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

    #[test]
    fn test_command_parameters() {
        assert!((super::Help).takes_argument() == true);
        assert!((super::Reset).takes_argument() == false);
        assert!((super::Hello).needs_argument() == true);
    }

    #[test]
    fn test_get_simple_command() {
        assert!(SmtpCommand::new(~"TURN", None).get_formatted_command() == format!("TURN{}", ::common::CRLF));
    }

    #[test]
    fn test_get_argument_command() {
        assert!(SmtpCommand::new(~"EHLO", Some(~"example.example")).get_formatted_command() == format!("EHLO example.example{}", ::common::CRLF));
    }
}<commit_msg>Make compilation work with yersterday's rust version<commit_after>/*!
 * SMTP commands library
 *
 * RFC 5321 : http://tools.ietf.org/html/rfc5321#section-4.1
 */

use std::fmt;
use common::CRLF;

/*
 * HELO <SP> <domain> <CRLF>
 * MAIL <SP> FROM:<reverse-path> <CRLF>
 * RCPT <SP> TO:<forward-path> <CRLF>
 * DATA <CRLF>
 * RSET <CRLF>
 * SEND <SP> FROM:<reverse-path> <CRLF>
 * SOML <SP> FROM:<reverse-path> <CRLF>
 * SAML <SP> FROM:<reverse-path> <CRLF>
 * VRFY <SP> <string> <CRLF>
 * EXPN <SP> <string> <CRLF>
 * HELP [<SP> <string>] <CRLF>
 * NOOP <CRLF>
 * QUIT <CRLF>
 * TURN <CRLF>
 */

/// List of SMTP commands
#[deriving(Eq,Clone)]
pub enum Command {
    Hello,
    Ehello,
    Mail,
    Recipient,
    Data,
    Reset,
    SendMail,
    SendOrMail,
    SendAndMail,
    Verify,
    Expand,
    Help,
    Noop,
    Quit,
    /// Deprecated in RFC 5321
    Turn,
}

impl Command {
    /// Tell if the command accetps an string argument.
    pub fn takes_argument(&self) -> bool{
        match *self {
            Ehello        => true,
            Hello         => true,
            Mail          => true,
            Recipient     => true,
            Data          => false,
            Reset         => false,
            SendMail      => true,
            SendOrMail    => true,
            SendAndMail   => true,
            Verify        => true,
            Expand        => true,
            Help          => true,
            Noop          => false,
            Quit          => false,
            Turn          => false,
        }
    }

    /// Tell if an argument is needed by the command.
    pub fn needs_argument(&self) -> bool {
        match *self {
            Ehello        => true,
            Hello         => true,
            Mail          => true,
            Recipient     => true,
            Data          => false,
            Reset         => false,
            SendMail      => true,
            SendOrMail    => true,
            SendAndMail   => true,
            Verify        => true,
            Expand        => true,
            Help          => false,
            Noop          => false,
            Quit          => false,
            Turn          => false,
        }
    }
}

impl ToStr for Command {
    /// Get the name of a command.
    fn to_str(&self) -> ~str {
        match *self {
            Hello           => ~"HELO",
            Ehello          => ~"EHLO",
            Mail            => ~"MAIL",
            Recipient       => ~"RCPT",
            Data            => ~"DATA",
            Reset           => ~"RSET",
            SendMail        => ~"SEND",
            SendOrMail      => ~"SOML",
            SendAndMail     => ~"SAML",
            Verify          => ~"VRFY",
            Expand          => ~"EXPN",
            Help            => ~"HELP",
            Noop            => ~"NOOP",
            Quit            => ~"QUIT",
            Turn            => ~"TURN",
        }
    }
}

impl FromStr for Command {
    /// Get the Command from its name.
    fn from_str(command: &str) -> Option<Command> {
        if !command.is_ascii() {
            return None;
        }
        match command {
            "HELO" => Some(Hello),
            "EHLO" => Some(Ehello),
            "MAIL" => Some(Mail),
            "RCPT" => Some(Recipient),
            "DATA" => Some(Data),
            "RSET" => Some(Reset),
            "SEND" => Some(SendMail),
            "SOML" => Some(SendOrMail),
            "SAML" => Some(SendAndMail),
            "VRFY" => Some(Verify),
            "EXPN" => Some(Expand),
            "HELP" => Some(Help),
            "NOOP" => Some(Noop),
            "QUIT" => Some(Quit),
            "TURN" => Some(Turn),
            _      => None,
        }
    }
}

impl fmt::Default for Command {
    /// Format SMTP command display
    fn fmt(s: &Command, f: &mut fmt::Formatter) {
        f.buf.write(match *s {
            Ehello        => "EHLO".as_bytes(),
            Hello         => "HELO".as_bytes(),
            Mail          => "MAIL FROM:".as_bytes(),
            Recipient     => "RCPT TO:".as_bytes(),
            Data          => "DATA".as_bytes(),
            Reset         => "RSET".as_bytes(),
            SendMail      => "SEND TO:".as_bytes(),
            SendOrMail    => "SOML TO:".as_bytes(),
            SendAndMail   => "SAML TO:".as_bytes(),
            Verify        => "VRFY".as_bytes(),
            Expand        => "EXPN".as_bytes(),
            Help          => "HELP".as_bytes(),
            Noop          => "NOOP".as_bytes(),
            Quit          => "QUIT".as_bytes(),
            Turn          => "TURN".as_bytes()
        })
    }
}

/// Structure for a complete SMTP command, containing an optionnal string argument.
pub struct SmtpCommand {
    command: Command,
    argument: Option<~str>
}

impl SmtpCommand {
    /// Return a new structure from the name of the command and an optionnal argument.
    pub fn new(command_str: ~str, argument: Option<~str>) -> SmtpCommand {
        let command = match from_str::<Command>(command_str) {
            Some(x) => x,
            None    => fail!("Unrecognized SMTP command")
        };

        match (command.takes_argument(), command.needs_argument(), argument.clone()) {
            (true, true, None)      => fail!("Wrong SMTP syntax : argument needed"),
            (false, false, Some(x)) => fail!("Wrong SMTP syntax : {:s} not accepted", x),
            _                       => SmtpCommand {command: command, argument: argument}
        }
    }

    /// Return the formatted command, ready to be used in an SMTP session.
    pub fn get_formatted_command(&self) -> ~str {
        match (self.command.takes_argument(), self.command.needs_argument(), self.argument.clone()) {
            (true, _, Some(argument)) => format!("{} {}{}", self.command, argument, CRLF),
            (_, false, None)   => format!("{}{}", self.command, CRLF),
            _                  => fail!("Wrong SMTP syntax")
        }
    }
}

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

    #[test]
    fn test_command_parameters() {
        assert!((super::Help).takes_argument() == true);
        assert!((super::Reset).takes_argument() == false);
        assert!((super::Hello).needs_argument() == true);
    }

    #[test]
    fn test_get_simple_command() {
        assert!(SmtpCommand::new(~"TURN", None).get_formatted_command() == format!("TURN{}", ::common::CRLF));
    }

    #[test]
    fn test_get_argument_command() {
        assert!(SmtpCommand::new(~"EHLO", Some(~"example.example")).get_formatted_command() == format!("EHLO example.example{}", ::common::CRLF));
    }
}
<|endoftext|>


<commit_before>#![crate_name = "uptime"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

#![allow(non_camel_case_types)]
#![feature(macro_rules, globs)]

extern crate getopts;
extern crate libc;
extern crate "time" as rtime;

use std::mem::transmute;
use std::io::{print, File};
use std::ptr::null;
use std::str::from_str;
use libc::{time_t, c_double, c_int, c_char};
use utmpx::*;

#[path = "../common/util.rs"] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

#[cfg(unix)]
extern {
    fn getloadavg(loadavg: *mut c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *const c_utmp;
    fn setutxent();
    fn endutxent();

    #[cfg(any(target_os = "macos", target_os = "linux"))]
    fn utmpxname(file: *const c_char) -> c_int;
}

#[cfg(windows)]
extern {
    fn GetTickCount() -> libc::uint32_t;
}

#[cfg(target_os = "freebsd")]
unsafe extern fn utmpxname(_file: *const c_char) -> c_int {
    0
}

pub fn uumain(args: Vec<String>) -> int {
    let program = args[0].clone();
    let opts = [
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f)
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return 0;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0} [OPTION]", program);
        println!("");
        print(getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", &opts).as_slice());
        return 0;
    }

    print_time();
    let (boot_time, user_count) = process_utmpx();
    let upsecs = get_uptime(boot_time) / 100;
    print_uptime(upsecs);
    print_nusers(user_count);
    print_loadavg();

    0
}

fn print_loadavg() {
    let mut avg: [c_double, ..3] = [0.0, ..3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_mut_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ")
        for n in range(0, loads) {
            print!("{:.2}{}", avg[n as uint], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

#[cfg(unix)]
fn process_utmpx() -> (Option<time_t>, uint) {
    DEFAULT_FILE.with_c_str(|filename| {
        unsafe {
            utmpxname(filename);
        }
    });

    let mut nusers = 0;
    let mut boot_time = None;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            match (*line).ut_type {
                USER_PROCESS => nusers += 1,
                BOOT_TIME => {
                    let t = (*line).ut_tv;
                    if t.tv_sec > 0 {
                        boot_time = Some(t.tv_sec);
                    }
                },
                _ => continue
            }
        }

        endutxent();
    }

    (boot_time, nusers)
}

#[cfg(windows)]
fn process_utmpx() -> (Option<time_t>, uint) {
    (None, 0) // TODO: change 0 to number of users
}

fn print_nusers(nusers: uint) {
    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = rtime::now();

    print!(" {:02}:{:02}:{:02} ", local_time.tm_hour,
           local_time.tm_min, local_time.tm_sec);
}

#[cfg(unix)]
fn get_uptime(boot_time: Option<time_t>) -> i64 {
    let proc_uptime = File::open(&Path::new("/proc/uptime"))
                            .read_to_string();

    let uptime_text = match proc_uptime {
        Ok(s) => s,
        _ => return match boot_time {
                Some(t) => {
                    let now = rtime::get_time().sec;
                    ((now - t) * 100) as i64 // Return in ms
                },
                _ => -1
             }
    };

    match uptime_text.as_slice().words().next() {
        Some(s) => match from_str(s.replace(".", "").as_slice()) {
                    Some(n) => n,
                    None => -1
                   },
        None => -1
    }
}

#[cfg(windows)]
fn get_uptime(boot_time: Option<time_t>) -> i64 {
    unsafe { GetTickCount() as i64 }
}

fn print_uptime(upsecs: i64) {
    let updays = upsecs / 86400;
    let uphours = (upsecs - (updays * 86400)) / 3600;
    let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1} day, {:2}:{:02},  ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1} days, {:2}:{:02},  ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2}:{:02},  ", uphours, upmins);
    }
}
<commit_msg>fix 32-bit kernel uptime error<commit_after>#![crate_name = "uptime"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

#![allow(non_camel_case_types)]
#![feature(macro_rules, globs)]

extern crate getopts;
extern crate libc;
extern crate "time" as rtime;

use std::mem::transmute;
use std::io::{print, File};
use std::ptr::null;
use std::str::from_str;
use libc::{time_t, c_double, c_int, c_char};
use utmpx::*;

#[path = "../common/util.rs"] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

#[cfg(unix)]
extern {
    fn getloadavg(loadavg: *mut c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *const c_utmp;
    fn setutxent();
    fn endutxent();

    #[cfg(any(target_os = "macos", target_os = "linux"))]
    fn utmpxname(file: *const c_char) -> c_int;
}

#[cfg(windows)]
extern {
    fn GetTickCount() -> libc::uint32_t;
}

#[cfg(target_os = "freebsd")]
unsafe extern fn utmpxname(_file: *const c_char) -> c_int {
    0
}

pub fn uumain(args: Vec<String>) -> int {
    let program = args[0].clone();
    let opts = [
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f)
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return 0;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0} [OPTION]", program);
        println!("");
        print(getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", &opts).as_slice());
        return 0;
    }

    print_time();
    let (boot_time, user_count) = process_utmpx();
    let upsecs = get_uptime(boot_time) / 100;
    print_uptime(upsecs);
    print_nusers(user_count);
    print_loadavg();

    0
}

fn print_loadavg() {
    let mut avg: [c_double, ..3] = [0.0, ..3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_mut_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ")
        for n in range(0, loads) {
            print!("{:.2}{}", avg[n as uint], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

#[cfg(unix)]
fn process_utmpx() -> (Option<time_t>, uint) {
    DEFAULT_FILE.with_c_str(|filename| {
        unsafe {
            utmpxname(filename);
        }
    });

    let mut nusers = 0;
    let mut boot_time = None;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            match (*line).ut_type {
                USER_PROCESS => nusers += 1,
                BOOT_TIME => {
                    let t = (*line).ut_tv;
                    if t.tv_sec > 0 {
                        boot_time = Some(t.tv_sec);
                    }
                },
                _ => continue
            }
        }

        endutxent();
    }

    (boot_time, nusers)
}

#[cfg(windows)]
fn process_utmpx() -> (Option<time_t>, uint) {
    (None, 0) // TODO: change 0 to number of users
}

fn print_nusers(nusers: uint) {
    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = rtime::now();

    print!(" {:02}:{:02}:{:02} ", local_time.tm_hour,
           local_time.tm_min, local_time.tm_sec);
}

#[cfg(unix)]
fn get_uptime(boot_time: Option<time_t>) -> i64 {
    let proc_uptime = File::open(&Path::new("/proc/uptime"))
                            .read_to_string();

    let uptime_text = match proc_uptime {
        Ok(s) => s,
        _ => return match boot_time {
                Some(t) => {
                    let now = rtime::get_time().sec;
                    let time = t.to_i64().unwrap();
                    ((now - time) * 100) as i64 // Return in ms
                },
                _ => -1
             }
    };

    match uptime_text.as_slice().words().next() {
        Some(s) => match from_str(s.replace(".", "").as_slice()) {
                    Some(n) => n,
                    None => -1
                   },
        None => -1
    }
}

#[cfg(windows)]
fn get_uptime(boot_time: Option<time_t>) -> i64 {
    unsafe { GetTickCount() as i64 }
}

fn print_uptime(upsecs: i64) {
    let updays = upsecs / 86400;
    let uphours = (upsecs - (updays * 86400)) / 3600;
    let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1} day, {:2}:{:02},  ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1} days, {:2}:{:02},  ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2}:{:02},  ", uphours, upmins);
    }
}
<|endoftext|>


<commit_before><commit_msg>[parser] add dataset writer<commit_after>use crate::dataset::*;
use crate::error::{Error, Result};
use dicom_core::{DataElementHeader, Length, VR};
use dicom_encoding::encode::{Encode, EncodeTo};
use dicom_encoding::text::{SpecificCharacterSet, TextCodec};
use dicom_encoding::TransferSyntax;
use std::io::Write;

/// A token representing a sequence or item start.
#[derive(Debug)]
struct SeqToken {
    /// Whether it is the start of a sequence or the start of an item.
    typ: SeqTokenType,
    /// The length of the value, as indicated by the starting element,
    /// can be unknown.
    len: Length,
}

/// A stateful device for printing a DICOM data set in sequential order.
/// This is analogous to the `DatasetReader` type for converting data
/// set tokens to bytes.
#[derive(Debug)]
pub struct DataSetWriter<W, E, T> {
    to: W,
    encoder: E,
    text: T,
    seq_tokens: Vec<SeqToken>,
}

impl<W> DataSetWriter<W, Box<dyn EncodeTo<W>>, Box<dyn TextCodec>>
where
    W: Write,
{
    pub fn with_ts_cs(to: W, ts: TransferSyntax, cs: SpecificCharacterSet) -> Result<Self> {
        let encoder = ts
            .encoder_for()
            .ok_or_else(|| Error::UnsupportedTransferSyntax)?;
        let text = cs.codec().ok_or_else(|| Error::UnsupportedCharacterSet)?;
        Ok(DataSetWriter::new(to, encoder, text))
    }
}

impl<W, E, T> DataSetWriter<W, E, T> {
    pub fn new(to: W, encoder: E, text: T) -> Self {
        DataSetWriter {
            to,
            encoder,
            text,
            seq_tokens: Vec::new(),
        }
    }
}

impl<W, E, T> DataSetWriter<W, E, T>
where
    W: Write,
    E: Encode,
    T: TextCodec,
{
    /// Feed the given sequence of tokens which are part of the same data set.
    pub fn write_sequence<I>(&mut self, tokens: I) -> Result<()>
    where
        I: IntoIterator<Item = DataToken>,
    {
        for token in tokens {
            self.write(token)?;
        }

        Ok(())
    }

    /// Feed the given data set token for writing the data set.
    #[inline]
    pub fn write(&mut self, token: DataToken) -> Result<()> {
        // TODO adjust the logic of sequence printing:
        // explicit length sequences or items should not print
        // the respective delimiter

        match token {
            DataToken::SequenceStart { tag: _, len } => {
                self.seq_tokens.push(SeqToken {
                    typ: SeqTokenType::Sequence,
                    len,
                });
                self.write_stateless(token)?;
                Ok(())
            }
            DataToken::ItemStart { len } => {
                self.seq_tokens.push(SeqToken {
                    typ: SeqTokenType::Item,
                    len,
                });
                self.write_stateless(token)?;
                Ok(())
            }
            DataToken::ItemEnd => {
                // only write if it's an unknown length item
                if let Some(seq_start) = self.seq_tokens.pop() {
                    if seq_start.typ == SeqTokenType::Item && seq_start.len.is_undefined() {
                        self.write_stateless(token)?;
                    }
                }
                Ok(())
            }
            DataToken::SequenceEnd => {
                // only write if it's an unknown length sequence
                if let Some(seq_start) = self.seq_tokens.pop() {
                    if seq_start.typ == SeqTokenType::Sequence && seq_start.len.is_undefined() {
                        self.write_stateless(token)?;
                    }
                }
                Ok(())
            }
            _ => self.write_stateless(token),
        }
    }

    fn write_stateless(&mut self, token: DataToken) -> Result<()> {
        use DataToken::*;
        match token {
            ElementHeader(header) => {
                self.encoder.encode_element_header(&mut self.to, header)?;
            }
            SequenceStart { tag, len } => {
                self.encoder.encode_element_header(
                    &mut self.to,
                    DataElementHeader::new(tag, VR::SQ, len),
                )?;
            }
            SequenceEnd => {
                self.encoder.encode_sequence_delimiter(&mut self.to)?;
            }
            ItemStart { len } => {
                self.encoder.encode_item_header(&mut self.to, len.0)?;
            }
            ItemEnd => {
                self.encoder.encode_item_delimiter(&mut self.to)?;
            }
            PrimitiveValue(value) => {
                // TODO handle strings properly
                self.encoder.encode_primitive(&mut self.to, &value)?;
            }
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::super::DataToken;
    use super::DataSetWriter;
    use crate::printer::Printer;
    use dicom_core::header::{DataElementHeader, Length};
    use dicom_core::value::PrimitiveValue;
    use dicom_encoding::text::DefaultCharacterSetCodec;
    use dicom_encoding::transfer_syntax::explicit_le::ExplicitVRLittleEndianEncoder;

    fn validate_dataset_writer<I>(tokens: I, ground_truth: &[u8])
    where
        I: IntoIterator<Item = DataToken>,
    {
        let mut raw_out: Vec<u8> = vec![];
        let encoder = ExplicitVRLittleEndianEncoder::default();
        let text = DefaultCharacterSetCodec::default();
        let mut dset_writer = DataSetWriter::new(&mut raw_out, encoder, text);

        //let mut iter = Iterator::zip(dset_writer.by_ref(), ground_truth);
    }
}
<|endoftext|>


<commit_before>use regex::Regex;
use regex::Captures;
use rustc_demangle::demangle;

pub fn remove_assembler_directives(block: &str) -> String {
    lazy_static! {
        static ref ASM_DIR_REGEX: Regex = Regex::new(r"(?m)^\s*\..*$").expect("Failed to create ASM_DIR_REGEX");
    }

    let mut filtered_asm = String::new();
    for line in block.lines() {
        if !ASM_DIR_REGEX.is_match(line) {
            filtered_asm.push_str(line);
            filtered_asm.push('\n');
        }
    }

    filtered_asm
}

pub fn demangle_asm(block: &str) -> String {
    lazy_static! {
        static ref DEMANGLE_REGEX: Regex = Regex::new(r"_[a-zA-Z0-9._$]*").expect("Failed to create DEMANGLE_REGEX");
    }

    DEMANGLE_REGEX.replace_all(block, |caps: &Captures| {
        format!("{:#}", demangle(caps.get(0)
                                     .expect("Failed to find symbols to demangle")
                                     .as_str()))
    }).to_string()
}

#[cfg(test)]
mod test {
    #[test]
    fn directives_pass_through() {
        assert_eq!(
            super::remove_assembler_directives("core::fmt::Arguments::new_v1:\n push rbp\n mov rbp, rsp"),
            "core::fmt::Arguments::new_v1:\n push rbp\n mov rbp, rsp\n");
    }

    #[test]
    fn one_directive_removed() {
        assert_eq!(
            super::remove_assembler_directives("  .filesystem1 \"<println macros>\"\n  movq%rsp, %rbp\n"),
            "  movq%rsp, %rbp\n");
    }

    #[test]
    fn many_directives_removed() {
        assert_eq!(
            super::remove_assembler_directives(" .cfi_def_cfa_register %rbp\n subq$80, %rsp\n .Ltmp2:"),
            " subq$80, %rsp\n");
    }

    #[test]
    fn demangle_pass_through() {
        assert_eq!(
            super::demangle_asm("push rbp\n mov rbp, rsp"),
            "push rbp\n mov rbp, rsp");
    }

    #[test]
    fn demangles() {
        assert_eq!(
            super::demangle_asm("_ZN4core3fmt9Arguments6new_v117h3c6f806acbe1ddabE"),
            "core::fmt::Arguments::new_v1");
        }

    #[test]
    fn many_demangles() {
        assert_eq!(
            super::demangle_asm(".section.text._ZN4core3fmt9Arguments6new_v117h3c6f806acbe1ddabE,\"ax\",@progbits\n .p2align4, 0x90\n .type_ZN4core3fmt9Arguments6new_v117h3c6f806acbe1ddabE,@function"),
            ".section.text.core::fmt::Arguments::new_v1,\"ax\",@progbits\n .p2align4, 0x90\n .typecore::fmt::Arguments::new_v1,@function");
        }

}
<commit_msg>Fixed labels being removed from asm<commit_after>use regex::Regex;
use regex::Captures;
use rustc_demangle::demangle;

pub fn remove_assembler_directives(block: &str) -> String {
    lazy_static! {
        static ref ASM_DIR_REGEX: Regex = Regex::new(r"(?m)^\s*\..*[^:]$").expect("Failed to create ASM_DIR_REGEX");
    }

    let mut filtered_asm = String::new();
    for line in block.lines() {
        if !ASM_DIR_REGEX.is_match(line) {
            filtered_asm.push_str(line);
            filtered_asm.push('\n');
        }
    }

    filtered_asm
}

pub fn demangle_asm(block: &str) -> String {
    lazy_static! {
        static ref DEMANGLE_REGEX: Regex = Regex::new(r"_[a-zA-Z0-9._$]*").expect("Failed to create DEMANGLE_REGEX");
    }

    DEMANGLE_REGEX.replace_all(block, |caps: &Captures| {
        format!("{:#}", demangle(caps.get(0)
                                     .expect("Failed to find symbols to demangle")
                                     .as_str()))
    }).to_string()
}

#[cfg(test)]
mod test {
    #[test]
    fn directives_pass_through() {
        assert_eq!(
            super::remove_assembler_directives("core::fmt::Arguments::new_v1:\n push rbp\n mov rbp, rsp"),
            "core::fmt::Arguments::new_v1:\n push rbp\n mov rbp, rsp\n");
    }

    #[test]
    fn one_directive_removed() {
        assert_eq!(
            super::remove_assembler_directives("  .filesystem1 \"<println macros>\"\n  movq%rsp, %rbp\n"),
            "  movq%rsp, %rbp\n");
    }

    #[test]
    fn many_directives_removed() {
        assert_eq!(
            super::remove_assembler_directives(" .cfi_def_cfa_register %rbp\n subq$80, %rsp\n .text\n"),
            " subq$80, %rsp\n");
    }

    #[test]
    fn labels_not_removed() {
        assert_eq!(
            super::remove_assembler_directives(
      ".type core::fmt::Arguments::new_v1,@function\n core::fmt::Arguments::new_v1:\n .Lfunc_begin0:\n"),
             " core::fmt::Arguments::new_v1:\n .Lfunc_begin0:\n");
    }

    #[test]
    fn demangle_pass_through() {
        assert_eq!(
            super::demangle_asm("push rbp\n mov rbp, rsp"),
            "push rbp\n mov rbp, rsp");
    }

    #[test]
    fn demangles() {
        assert_eq!(
            super::demangle_asm("_ZN4core3fmt9Arguments6new_v117h3c6f806acbe1ddabE"),
            "core::fmt::Arguments::new_v1");
        }

    #[test]
    fn many_demangles() {
        assert_eq!(
            super::demangle_asm(".section.text._ZN4core3fmt9Arguments6new_v117h3c6f806acbe1ddabE,\"ax\",@progbits\n .p2align4, 0x90\n .type_ZN4core3fmt9Arguments6new_v117h3c6f806acbe1ddabE,@function"),
            ".section.text.core::fmt::Arguments::new_v1,\"ax\",@progbits\n .p2align4, 0x90\n .typecore::fmt::Arguments::new_v1,@function");
        }

}
<|endoftext|>


<commit_before><commit_msg>short result<commit_after><|endoftext|>


<commit_before><commit_msg>rollup merge of #23921: aturon/issue-17746<commit_after>// Copyright 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.

// Regression test for #17746

fn main() {}

struct A;

impl A {
    fn b(&mut self) {
        self.a()
    }
}

trait Foo {
    fn dummy(&self) {}
}
trait Bar {
    fn a(&self);
}

impl Foo for A {}
impl<T> Bar for T where T: Foo {
    fn a(&self) {}
}
<|endoftext|>


<commit_before><commit_msg>Test case for borrowk ICE #25579<commit_after>// Copyright 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.

enum Sexpression {
  Num(()),
  Cons(&'static mut Sexpression)
}

fn causes_ice(mut l: &mut Sexpression)
{
    loop { match l {
        &mut Sexpression::Num(ref mut n) => {},
        &mut Sexpression::Cons(ref mut expr) => {
            l = &mut **expr;
        }
    }}
}

fn main() {
}
<|endoftext|>


<commit_before><commit_msg>Rollup merge of #55963 - stepancheg:mpsc-take-2, r=alexcrichton<commit_after>// Copyright 2017 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.

// compile-flags:--test
// ignore-emscripten

use std::sync::mpsc::channel;
use std::sync::mpsc::TryRecvError;
use std::sync::mpsc::RecvError;
use std::sync::mpsc::RecvTimeoutError;
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;

use std::thread;
use std::time::Duration;

/// Simple thread synchronization utility
struct Barrier {
    // Not using mutex/condvar for precision
    shared: Arc<AtomicUsize>,
    count: usize,
}

impl Barrier {
    fn new(count: usize) -> Vec<Barrier> {
        let shared = Arc::new(AtomicUsize::new(0));
        (0..count).map(|_| Barrier { shared: shared.clone(), count: count }).collect()
    }

    fn new2() -> (Barrier, Barrier) {
        let mut v = Barrier::new(2);
        (v.pop().unwrap(), v.pop().unwrap())
    }

    /// Returns when `count` threads enter `wait`
    fn wait(self) {
        self.shared.fetch_add(1, Ordering::SeqCst);
        while self.shared.load(Ordering::SeqCst) != self.count {
        }
    }
}

fn shared_close_sender_does_not_lose_messages_iter() {
    let (tb, rb) = Barrier::new2();

    let (tx, rx) = channel();
    let _ = tx.clone(); // convert to shared

    thread::spawn(move || {
        tb.wait();
        thread::sleep(Duration::from_micros(1));
        tx.send(17).expect("send");
        drop(tx);
    });

    let i = rx.into_iter();
    rb.wait();
    // Make sure it doesn't return disconnected before returning an element
    assert_eq!(vec![17], i.collect::<Vec<_>>());
}

#[test]
fn shared_close_sender_does_not_lose_messages() {
    for _ in 0..10000 {
        shared_close_sender_does_not_lose_messages_iter();
    }
}

// https://github.com/rust-lang/rust/issues/39364
fn concurrent_recv_timeout_and_upgrade_iter() {
    // 1 us
    let sleep = Duration::new(0, 1_000);

    let (a, b) = Barrier::new2();
    let (tx, rx) = channel();
    let th = thread::spawn(move || {
        a.wait();
        loop {
            match rx.recv_timeout(sleep) {
                Ok(_) => {
                    break;
                },
                Err(_) => {},
            }
        }
    });
    b.wait();
    thread::sleep(sleep);
    tx.clone().send(()).expect("send");
    th.join().unwrap();
}

#[test]
fn concurrent_recv_timeout_and_upgrade() {
    // FIXME: fix and enable
    if true { return }

    // at the moment of writing this test fails like this:
    // thread '<unnamed>' panicked at 'assertion failed: `(left == right)`
    //  left: `4561387584`,
    // right: `0`', libstd/sync/mpsc/shared.rs:253:13

    for _ in 0..10000 {
        concurrent_recv_timeout_and_upgrade_iter();
    }
}

fn concurrent_writes_iter() {
    const THREADS: usize = 4;
    const PER_THR: usize = 100;

    let mut bs = Barrier::new(THREADS + 1);
    let (tx, rx) = channel();

    let mut threads = Vec::new();
    for j in 0..THREADS {
        let tx = tx.clone();
        let b = bs.pop().unwrap();
        threads.push(thread::spawn(move || {
            b.wait();
            for i in 0..PER_THR {
                tx.send(j * 1000 + i).expect("send");
            }
        }));
    }

    let b = bs.pop().unwrap();
    b.wait();

    let mut v: Vec<_> = rx.iter().take(THREADS * PER_THR).collect();
    v.sort();

    for j in 0..THREADS {
        for i in 0..PER_THR {
            assert_eq!(j * 1000 + i, v[j * PER_THR + i]);
        }
    }

    for t in threads {
        t.join().unwrap();
    }

    let one_us = Duration::new(0, 1000);

    assert_eq!(TryRecvError::Empty, rx.try_recv().unwrap_err());
    assert_eq!(RecvTimeoutError::Timeout, rx.recv_timeout(one_us).unwrap_err());

    drop(tx);

    assert_eq!(RecvError, rx.recv().unwrap_err());
    assert_eq!(RecvTimeoutError::Disconnected, rx.recv_timeout(one_us).unwrap_err());
    assert_eq!(TryRecvError::Disconnected, rx.try_recv().unwrap_err());
}

#[test]
fn concurrent_writes() {
    for _ in 0..100 {
        concurrent_writes_iter();
    }
}
<|endoftext|>


<commit_before>use alloc::boxed::Box;

use arch::memory;

use collections::slice;
use collections::string::ToString;
use collections::vec::Vec;
use collections::vec_deque::VecDeque;

use core::ptr;

use common::debug;

use drivers::pci::config::PciConfig;
use drivers::io::{Io, Pio};

use network::common::*;
use network::scheme::*;

use fs::{KScheme, Resource, Url};

use syscall::Result;

use sync::Intex;

const RTL8139_TSR_OWN: u32 = 1 << 13;

const RTL8139_CR_RST: u8 = 1 << 4;
const RTL8139_CR_RE: u8 = 1 << 3;
const RTL8139_CR_TE: u8 = 1 << 2;
const RTL8139_CR_BUFE: u8 = 1 << 0;

const RTL8139_ISR_SERR: u16 = 1 << 15;
const RTL8139_ISR_TIMEOUT: u16 = 1 << 14;
const RTL8139_ISR_LENCHG: u16 = 1 << 13;
const RTL8139_ISR_FOVW: u16 = 1 << 6;
const RTL8139_ISR_PUN_LINKCHG: u16 = 1 << 5;
const RTL8139_ISR_RXOVW: u16 = 1 << 4;
const RTL8139_ISR_TER: u16 = 1 << 3;
const RTL8139_ISR_TOK: u16 = 1 << 2;
const RTL8139_ISR_RER: u16 = 1 << 1;
const RTL8139_ISR_ROK: u16 = 1 << 0;

const RTL8139_TCR_IFG: u32 = 0b11 << 24;

const RTL8139_RCR_WRAP: u32 = 1 << 7;
const RTL8139_RCR_AR: u32 = 1 << 4;
const RTL8139_RCR_AB: u32 = 1 << 3;
const RTL8139_RCR_AM: u32 = 1 << 2;
const RTL8139_RCR_APM: u32 = 1 << 1;

#[repr(packed)]
struct Txd {
    pub address_port: Pio<u32>,
    pub status_port: Pio<u32>,
    pub buffer: usize,
}

pub struct Rtl8139Port {
    pub idr: [Pio<u8>; 6],
    pub rbstart: Pio<u32>,
    pub cr: Pio<u8>,
    pub capr: Pio<u16>,
    pub cbr: Pio<u16>,
    pub imr: Pio<u16>,
    pub isr: Pio<u16>,
    pub tcr: Pio<u32>,
    pub rcr: Pio<u32>,
    pub config1: Pio<u8>,
}

impl Rtl8139Port {
    pub fn new(base: u16) -> Self {
        return Rtl8139Port {
            idr: [Pio::<u8>::new(base + 0x00),
                  Pio::<u8>::new(base + 0x01),
                  Pio::<u8>::new(base + 0x02),
                  Pio::<u8>::new(base + 0x03),
                  Pio::<u8>::new(base + 0x04),
                  Pio::<u8>::new(base + 0x05)],
            rbstart: Pio::<u32>::new(base + 0x30),
            cr: Pio::<u8>::new(base + 0x37),
            capr: Pio::<u16>::new(base + 0x38),
            cbr: Pio::<u16>::new(base + 0x3A),
            imr: Pio::<u16>::new(base + 0x3C),
            isr: Pio::<u16>::new(base + 0x3E),
            tcr: Pio::<u32>::new(base + 0x40),
            rcr: Pio::<u32>::new(base + 0x44),
            config1: Pio::<u8>::new(base + 0x52),
        };
    }
}

pub struct Rtl8139 {
    pci: PciConfig,
    base: usize,
    memory_mapped: bool,
    irq: u8,
    resources: Intex<Vec<*mut NetworkResource>>,
    inbound: VecDeque<Vec<u8>>,
    outbound: VecDeque<Vec<u8>>,
    txds: Vec<Txd>,
    txd_i: usize,
    port: Rtl8139Port,
}

impl Rtl8139 {
    pub fn new(mut pci: PciConfig) -> Box<Self> {
        let pci_id = unsafe { pci.read(0x00) };
        let revision = (unsafe { pci.read(0x08) } & 0xFF) as u8;
        if pci_id == 0x813910EC && revision < 0x20 {
            debug::d("Not an 8139C+ compatible chip")
        }

        let base = unsafe { pci.read(0x10) as usize };
        let irq = unsafe { pci.read(0x3C) as u8 & 0xF };

        let mut module = box Rtl8139 {
            pci: pci,
            base: base & 0xFFFFFFF0,
            memory_mapped: base & 1 == 0,
            irq: irq,
            resources: Intex::new(Vec::new()),
            inbound: VecDeque::new(),
            outbound: VecDeque::new(),
            txds: Vec::new(),
            txd_i: 0,
            port: Rtl8139Port::new((base & 0xFFFFFFF0) as u16),
        };

        unsafe { module.init() };

        module
    }

    unsafe fn init(&mut self) {
        debug::d("RTL8139 on: ");
        debug::dh(self.base);
        if self.memory_mapped {
            debug::d(" memory mapped");
        } else {
            debug::d(" port mapped");
        }
        debug::d(" IRQ: ");
        debug::dbh(self.irq);

        self.pci.flag(4, 4, true); // Bus mastering

        let base = self.base as u16;

        self.port.config1.write(0);
        self.port.cr.write(RTL8139_CR_RST);
        while self.port.cr.read() & RTL8139_CR_RST != 0 {}

        debug::d(" MAC: ");
        MAC_ADDR = MacAddr {
            bytes: [self.port.idr[0].read(),
                    self.port.idr[1].read(),
                    self.port.idr[2].read(),
                    self.port.idr[3].read(),
                    self.port.idr[4].read(),
                    self.port.idr[5].read()],
        };
        debug::d(&MAC_ADDR.to_string());

        let receive_buffer = memory::alloc(10240);
        self.port.rbstart.write(receive_buffer as u32);

        for i in 0..4 {
            self.txds.push(Txd {
                address_port: Pio::<u32>::new(base + 0x20 + (i as u16) * 4),
                status_port: Pio::<u32>::new(base + 0x10 + (i as u16) * 4),
                buffer: memory::alloc(4096),
            });
        }

        self.port.imr.write(RTL8139_ISR_TOK | RTL8139_ISR_ROK);
        debug::d(" IMR: ");
        debug::dh(self.port.imr.read() as usize);

        self.port.cr.write(RTL8139_CR_RE | RTL8139_CR_TE);
        debug::d(" CMD: ");
        debug::dbh(self.port.cr.read());

        self.port.rcr.write(RTL8139_RCR_WRAP | RTL8139_RCR_AR | RTL8139_RCR_AB | RTL8139_RCR_AM |
                            RTL8139_RCR_APM);
        debug::d(" RCR: ");
        debug::dh(self.port.rcr.read() as usize);

        self.port.tcr.writef(RTL8139_TCR_IFG, true);
        debug::d(" TCR: ");
        debug::dh(self.port.tcr.read() as usize);

        debug::dl();
    }

    unsafe fn receive_inbound(&mut self) {
        let receive_buffer = self.port.rbstart.read() as usize;
        let mut capr = (self.port.capr.read() + 16) as usize;
        let cbr = self.port.cbr.read() as usize;

        while capr != cbr {
            let frame_addr = receive_buffer + capr + 4;
            let frame_status = ptr::read((receive_buffer + capr) as *const u16) as usize;
            let frame_len = ptr::read((receive_buffer + capr + 2) as *const u16) as usize;

            debug::d("Recv ");
            debug::dh(capr as usize);
            debug::d(" ");
            debug::dh(frame_status);
            debug::d(" ");
            debug::dh(frame_addr);
            debug::d(" ");
            debug::dh(frame_len);
            debug::dl();

            self.inbound.push_back(Vec::from(slice::from_raw_parts(frame_addr as *const u8, frame_len - 4)));

            capr = capr + frame_len + 4;
            capr = (capr + 3) & (0xFFFFFFFF - 3);
            if capr >= 8192 {
                capr -= 8192
            }

            self.port.capr.write((capr as u16) - 16);
        }
    }

    unsafe fn send_outbound(&mut self) {
        while let Some(bytes) = self.outbound.pop_front() {
            if let Some(ref mut txd) = self.txds.get_mut(self.txd_i) {
                if bytes.len() < 4096 {
                    while !txd.status_port.readf(RTL8139_TSR_OWN) {}

                    debug::d("Send ");
                    debug::dh(self.txd_i as usize);
                    debug::d(" ");
                    debug::dh(txd.status_port.read() as usize);
                    debug::d(" ");
                    debug::dh(txd.buffer);
                    debug::d(" ");
                    debug::dh(bytes.len() & 0xFFF);
                    debug::dl();

                    ::memcpy(txd.buffer as *mut u8, bytes.as_ptr(), bytes.len());

                    txd.address_port.write(txd.buffer as u32);
                    txd.status_port.write(bytes.len() as u32 & 0xFFF);

                    self.txd_i = (self.txd_i + 1) % 4;
                } else {
                    debug::dl();
                    debug::d("RTL8139: Frame too long for transmit: ");
                    debug::dd(bytes.len());
                    debug::dl();
                }
            } else {
                debug::d("RTL8139: TXD Overflow!\n");
                self.txd_i = 0;
            }
        }
    }
}

impl KScheme for Rtl8139 {
    fn scheme(&self) -> &str {
        "network"
    }

    fn open(&mut self, _: &Url, _: usize) -> Result<Box<Resource>> {
        Ok(NetworkResource::new(self))
    }

    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            let isr = self.port.isr.read();
            self.port.isr.write(isr);

            // dh(isr as usize);
            // dl();

            self.sync();
        }
    }

    fn on_poll(&mut self) {
        self.sync();
    }
}

impl NetworkScheme for Rtl8139 {
    fn add(&mut self, resource: *mut NetworkResource) {
        self.resources.lock().push(resource);
    }

    fn remove(&mut self, resource: *mut NetworkResource) {
        let mut resources = self.resources.lock();

        let mut i = 0;
        while i < resources.len() {
            let mut remove = false;

            match resources.get(i) {
                Some(ptr) => if *ptr == resource {
                    remove = true;
                } else {
                    i += 1;
                },
                None => break,
            }

            if remove {
                resources.remove(i);
            }
        }
    }

    fn sync(&mut self) {
        unsafe {
            {
                let resources = self.resources.lock();

                for resource in resources.iter() {
                    while let Some(bytes) = (**resource).outbound.lock().pop_front() {
                        self.outbound.push_back(bytes);
                    }
                }
            }

            self.send_outbound();

            self.receive_inbound();

            {
                let resources = self.resources.lock();

                while let Some(bytes) = self.inbound.pop_front() {
                    for resource in resources.iter() {
                        (**resource).inbound.lock().push_back(bytes.clone());
                    }
                }
            }
        }
    }
}
<commit_msg>Newline in rtl8139 driver<commit_after>use alloc::boxed::Box;

use arch::memory;

use collections::slice;
use collections::string::ToString;
use collections::vec::Vec;
use collections::vec_deque::VecDeque;

use core::ptr;

use common::debug;

use drivers::pci::config::PciConfig;
use drivers::io::{Io, Pio};

use network::common::*;
use network::scheme::*;

use fs::{KScheme, Resource, Url};

use syscall::Result;

use sync::Intex;

const RTL8139_TSR_OWN: u32 = 1 << 13;

const RTL8139_CR_RST: u8 = 1 << 4;
const RTL8139_CR_RE: u8 = 1 << 3;
const RTL8139_CR_TE: u8 = 1 << 2;
const RTL8139_CR_BUFE: u8 = 1 << 0;

const RTL8139_ISR_SERR: u16 = 1 << 15;
const RTL8139_ISR_TIMEOUT: u16 = 1 << 14;
const RTL8139_ISR_LENCHG: u16 = 1 << 13;
const RTL8139_ISR_FOVW: u16 = 1 << 6;
const RTL8139_ISR_PUN_LINKCHG: u16 = 1 << 5;
const RTL8139_ISR_RXOVW: u16 = 1 << 4;
const RTL8139_ISR_TER: u16 = 1 << 3;
const RTL8139_ISR_TOK: u16 = 1 << 2;
const RTL8139_ISR_RER: u16 = 1 << 1;
const RTL8139_ISR_ROK: u16 = 1 << 0;

const RTL8139_TCR_IFG: u32 = 0b11 << 24;

const RTL8139_RCR_WRAP: u32 = 1 << 7;
const RTL8139_RCR_AR: u32 = 1 << 4;
const RTL8139_RCR_AB: u32 = 1 << 3;
const RTL8139_RCR_AM: u32 = 1 << 2;
const RTL8139_RCR_APM: u32 = 1 << 1;

#[repr(packed)]
struct Txd {
    pub address_port: Pio<u32>,
    pub status_port: Pio<u32>,
    pub buffer: usize,
}

pub struct Rtl8139Port {
    pub idr: [Pio<u8>; 6],
    pub rbstart: Pio<u32>,
    pub cr: Pio<u8>,
    pub capr: Pio<u16>,
    pub cbr: Pio<u16>,
    pub imr: Pio<u16>,
    pub isr: Pio<u16>,
    pub tcr: Pio<u32>,
    pub rcr: Pio<u32>,
    pub config1: Pio<u8>,
}

impl Rtl8139Port {
    pub fn new(base: u16) -> Self {
        return Rtl8139Port {
            idr: [Pio::<u8>::new(base + 0x00),
                  Pio::<u8>::new(base + 0x01),
                  Pio::<u8>::new(base + 0x02),
                  Pio::<u8>::new(base + 0x03),
                  Pio::<u8>::new(base + 0x04),
                  Pio::<u8>::new(base + 0x05)],
            rbstart: Pio::<u32>::new(base + 0x30),
            cr: Pio::<u8>::new(base + 0x37),
            capr: Pio::<u16>::new(base + 0x38),
            cbr: Pio::<u16>::new(base + 0x3A),
            imr: Pio::<u16>::new(base + 0x3C),
            isr: Pio::<u16>::new(base + 0x3E),
            tcr: Pio::<u32>::new(base + 0x40),
            rcr: Pio::<u32>::new(base + 0x44),
            config1: Pio::<u8>::new(base + 0x52),
        };
    }
}

pub struct Rtl8139 {
    pci: PciConfig,
    base: usize,
    memory_mapped: bool,
    irq: u8,
    resources: Intex<Vec<*mut NetworkResource>>,
    inbound: VecDeque<Vec<u8>>,
    outbound: VecDeque<Vec<u8>>,
    txds: Vec<Txd>,
    txd_i: usize,
    port: Rtl8139Port,
}

impl Rtl8139 {
    pub fn new(mut pci: PciConfig) -> Box<Self> {
        let pci_id = unsafe { pci.read(0x00) };
        let revision = (unsafe { pci.read(0x08) } & 0xFF) as u8;
        if pci_id == 0x813910EC && revision < 0x20 {
            debugln!("Not an 8139C+ compatible chip")
        }

        let base = unsafe { pci.read(0x10) as usize };
        let irq = unsafe { pci.read(0x3C) as u8 & 0xF };

        let mut module = box Rtl8139 {
            pci: pci,
            base: base & 0xFFFFFFF0,
            memory_mapped: base & 1 == 0,
            irq: irq,
            resources: Intex::new(Vec::new()),
            inbound: VecDeque::new(),
            outbound: VecDeque::new(),
            txds: Vec::new(),
            txd_i: 0,
            port: Rtl8139Port::new((base & 0xFFFFFFF0) as u16),
        };

        unsafe { module.init() };

        module
    }

    unsafe fn init(&mut self) {
        debug::d("RTL8139 on: ");
        debug::dh(self.base);
        if self.memory_mapped {
            debug::d(" memory mapped");
        } else {
            debug::d(" port mapped");
        }
        debug::d(" IRQ: ");
        debug::dbh(self.irq);

        self.pci.flag(4, 4, true); // Bus mastering

        let base = self.base as u16;

        self.port.config1.write(0);
        self.port.cr.write(RTL8139_CR_RST);
        while self.port.cr.read() & RTL8139_CR_RST != 0 {}

        debug::d(" MAC: ");
        MAC_ADDR = MacAddr {
            bytes: [self.port.idr[0].read(),
                    self.port.idr[1].read(),
                    self.port.idr[2].read(),
                    self.port.idr[3].read(),
                    self.port.idr[4].read(),
                    self.port.idr[5].read()],
        };
        debug::d(&MAC_ADDR.to_string());

        let receive_buffer = memory::alloc(10240);
        self.port.rbstart.write(receive_buffer as u32);

        for i in 0..4 {
            self.txds.push(Txd {
                address_port: Pio::<u32>::new(base + 0x20 + (i as u16) * 4),
                status_port: Pio::<u32>::new(base + 0x10 + (i as u16) * 4),
                buffer: memory::alloc(4096),
            });
        }

        self.port.imr.write(RTL8139_ISR_TOK | RTL8139_ISR_ROK);
        debug::d(" IMR: ");
        debug::dh(self.port.imr.read() as usize);

        self.port.cr.write(RTL8139_CR_RE | RTL8139_CR_TE);
        debug::d(" CMD: ");
        debug::dbh(self.port.cr.read());

        self.port.rcr.write(RTL8139_RCR_WRAP | RTL8139_RCR_AR | RTL8139_RCR_AB | RTL8139_RCR_AM |
                            RTL8139_RCR_APM);
        debug::d(" RCR: ");
        debug::dh(self.port.rcr.read() as usize);

        self.port.tcr.writef(RTL8139_TCR_IFG, true);
        debug::d(" TCR: ");
        debug::dh(self.port.tcr.read() as usize);

        debug::dl();
    }

    unsafe fn receive_inbound(&mut self) {
        let receive_buffer = self.port.rbstart.read() as usize;
        let mut capr = (self.port.capr.read() + 16) as usize;
        let cbr = self.port.cbr.read() as usize;

        while capr != cbr {
            let frame_addr = receive_buffer + capr + 4;
            let frame_status = ptr::read((receive_buffer + capr) as *const u16) as usize;
            let frame_len = ptr::read((receive_buffer + capr + 2) as *const u16) as usize;

            debug::d("Recv ");
            debug::dh(capr as usize);
            debug::d(" ");
            debug::dh(frame_status);
            debug::d(" ");
            debug::dh(frame_addr);
            debug::d(" ");
            debug::dh(frame_len);
            debug::dl();

            self.inbound.push_back(Vec::from(slice::from_raw_parts(frame_addr as *const u8, frame_len - 4)));

            capr = capr + frame_len + 4;
            capr = (capr + 3) & (0xFFFFFFFF - 3);
            if capr >= 8192 {
                capr -= 8192
            }

            self.port.capr.write((capr as u16) - 16);
        }
    }

    unsafe fn send_outbound(&mut self) {
        while let Some(bytes) = self.outbound.pop_front() {
            if let Some(ref mut txd) = self.txds.get_mut(self.txd_i) {
                if bytes.len() < 4096 {
                    while !txd.status_port.readf(RTL8139_TSR_OWN) {}

                    debug::d("Send ");
                    debug::dh(self.txd_i as usize);
                    debug::d(" ");
                    debug::dh(txd.status_port.read() as usize);
                    debug::d(" ");
                    debug::dh(txd.buffer);
                    debug::d(" ");
                    debug::dh(bytes.len() & 0xFFF);
                    debug::dl();

                    ::memcpy(txd.buffer as *mut u8, bytes.as_ptr(), bytes.len());

                    txd.address_port.write(txd.buffer as u32);
                    txd.status_port.write(bytes.len() as u32 & 0xFFF);

                    self.txd_i = (self.txd_i + 1) % 4;
                } else {
                    debug::dl();
                    debug::d("RTL8139: Frame too long for transmit: ");
                    debug::dd(bytes.len());
                    debug::dl();
                }
            } else {
                debug::d("RTL8139: TXD Overflow!\n");
                self.txd_i = 0;
            }
        }
    }
}

impl KScheme for Rtl8139 {
    fn scheme(&self) -> &str {
        "network"
    }

    fn open(&mut self, _: &Url, _: usize) -> Result<Box<Resource>> {
        Ok(NetworkResource::new(self))
    }

    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            let isr = self.port.isr.read();
            self.port.isr.write(isr);

            // dh(isr as usize);
            // dl();

            self.sync();
        }
    }

    fn on_poll(&mut self) {
        self.sync();
    }
}

impl NetworkScheme for Rtl8139 {
    fn add(&mut self, resource: *mut NetworkResource) {
        self.resources.lock().push(resource);
    }

    fn remove(&mut self, resource: *mut NetworkResource) {
        let mut resources = self.resources.lock();

        let mut i = 0;
        while i < resources.len() {
            let mut remove = false;

            match resources.get(i) {
                Some(ptr) => if *ptr == resource {
                    remove = true;
                } else {
                    i += 1;
                },
                None => break,
            }

            if remove {
                resources.remove(i);
            }
        }
    }

    fn sync(&mut self) {
        unsafe {
            {
                let resources = self.resources.lock();

                for resource in resources.iter() {
                    while let Some(bytes) = (**resource).outbound.lock().pop_front() {
                        self.outbound.push_back(bytes);
                    }
                }
            }

            self.send_outbound();

            self.receive_inbound();

            {
                let resources = self.resources.lock();

                while let Some(bytes) = self.inbound.pop_front() {
                    for resource in resources.iter() {
                        (**resource).inbound.lock().push_back(bytes.clone());
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix copy error<commit_after><|endoftext|>


<commit_before><commit_msg>Remove DXGIGetDebugInterface, there is no .lib for this, it has to be loaded dynamically.<commit_after><|endoftext|>


<commit_before><commit_msg>Reorder config overrides (cli / file)<commit_after><|endoftext|>


<commit_before>// Copyright 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.

//! Panic support in the standard library

#![unstable(feature = "std_panic", reason = "awaiting feedback",
            issue = "27719")]

use any::Any;
use boxed::Box;
use cell::UnsafeCell;
use ops::{Deref, DerefMut};
use ptr::{Unique, Shared};
use rc::Rc;
use sync::{Arc, Mutex, RwLock};
use sys_common::unwind;
use thread::Result;

pub use panicking::{take_handler, set_handler, PanicInfo, Location};

/// A marker trait which represents "panic safe" types in Rust.
///
/// This trait is implemented by default for many types and behaves similarly in
/// terms of inference of implementation to the `Send` and `Sync` traits. The
/// purpose of this trait is to encode what types are safe to cross a `recover`
/// boundary with no fear of panic safety.
///
/// ## What is panic safety?
///
/// In Rust a function can "return" early if it either panics or calls a
/// function which transitively panics. This sort of control flow is not always
/// anticipated, and has the possibility of causing subtle bugs through a
/// combination of two cricial components:
///
/// 1. A data structure is in a temporarily invalid state when the thread
///    panics.
/// 2. This broken invariant is then later observed.
///
/// Typically in Rust, it is difficult to perform step (2) because catching a
/// panic involves either spawning a thread (which in turns makes it difficult
/// to later witness broken invariants) or using the `recover` function in this
/// module. Additionally, even if an invariant is witnessed, it typically isn't a
/// problem in Rust because there's no uninitialized values (like in C or C++).
///
/// It is possible, however, for **logical** invariants to be broken in Rust,
/// which can end up causing behavioral bugs. Another key aspect of panic safety
/// in Rust is that, in the absence of `unsafe` code, a panic cannot lead to
/// memory unsafety.
///
/// That was a bit of a whirlwind tour of panic safety, but for more information
/// about panic safety and how it applies to Rust, see an [associated RFC][rfc].
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// ## What is `RecoverSafe`?
///
/// Now that we've got an idea of what panic safety is in Rust, it's also
/// important to understand what this trait represents. As mentioned above, one
/// way to witness broken invariants is through the `recover` function in this
/// module as it allows catching a panic and then re-using the environment of
/// the closure.
///
/// Simply put, a type `T` implements `RecoverSafe` if it cannot easily allow
/// witnessing a broken invariant through the use of `recover` (catching a
/// panic). This trait is a marker trait, so it is automatically implemented for
/// many types, and it is also structurally composed (e.g. a struct is recover
/// safe if all of its components are recover safe).
///
/// Note, however, that this is not an unsafe trait, so there is not a succinct
/// contract that this trait is providing. Instead it is intended as more of a
/// "speed bump" to alert users of `recover` that broken invariants may be
/// witnessed and may need to be accounted for.
///
/// ## Who implements `RecoverSafe`?
///
/// Types such as `&mut T` and `&RefCell<T>` are examples which are **not**
/// recover safe. The general idea is that any mutable state which can be shared
/// across `recover` is not recover safe by default. This is because it is very
/// easy to witness a broken invariant outside of `recover` as the data is
/// simply accessed as usual.
///
/// Types like `&Mutex<T>`, however, are recover safe because they implement
/// poisoning by default. They still allow witnessing a broken invariant, but
/// they already provide their own "speed bumps" to do so.
///
/// ## When should `RecoverSafe` be used?
///
/// Is not intended that most types or functions need to worry about this trait.
/// It is only used as a bound on the `recover` function and as mentioned above,
/// the lack of `unsafe` means it is mostly an advisory. The `AssertRecoverSafe`
/// wrapper struct in this module can be used to force this trait to be
/// implemented for any closed over variables passed to the `recover` function
/// (more on this below).
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
#[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
                            across a recover boundary"]
pub trait RecoverSafe {}

/// A marker trait representing types where a shared reference is considered
/// recover safe.
///
/// This trait is namely not implemented by `UnsafeCell`, the root of all
/// interior mutability.
///
/// This is a "helper marker trait" used to provide impl blocks for the
/// `RecoverSafe` trait, for more information see that documentation.
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
#[rustc_on_unimplemented = "the type {Self} contains interior mutability \
                            and a reference may not be safely transferrable \
                            across a recover boundary"]
pub trait RefRecoverSafe {}

/// A simple wrapper around a type to assert that it is panic safe.
///
/// When using `recover` it may be the case that some of the closed over
/// variables are not panic safe. For example if `&mut T` is captured the
/// compiler will generate a warning indicating that it is not panic safe. It
/// may not be the case, however, that this is actually a problem due to the
/// specific usage of `recover` if panic safety is specifically taken into
/// account. This wrapper struct is useful for a quick and lightweight
/// annotation that a variable is indeed panic safe.
///
/// # Examples
///
/// ```
/// #![feature(recover, std_panic)]
///
/// use std::panic::{self, AssertRecoverSafe};
///
/// let mut variable = 4;
///
/// // This code will not compile because the closure captures `&mut variable`
/// // which is not considered panic safe by default.
///
/// // panic::recover(|| {
/// //     variable += 3;
/// // });
///
/// // This, however, will compile due to the `AssertRecoverSafe` wrapper
/// let result = {
///     let mut wrapper = AssertRecoverSafe::new(&mut variable);
///     panic::recover(move || {
///         **wrapper += 3;
///     })
/// };
/// // ...
/// ```
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
pub struct AssertRecoverSafe<T>(T);

// Implementations of the `RecoverSafe` trait:
//
// * By default everything is recover safe
// * pointers T contains mutability of some form are not recover safe
// * Unique, an owning pointer, lifts an implementation
// * Types like Mutex/RwLock which are explicilty poisoned are recover safe
// * Our custom AssertRecoverSafe wrapper is indeed recover safe
impl RecoverSafe for .. {}
impl<'a, T: ?Sized> !RecoverSafe for &'a mut T {}
impl<'a, T: RefRecoverSafe + ?Sized> RecoverSafe for &'a T {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *const T {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *mut T {}
impl<T: RecoverSafe> RecoverSafe for Unique<T> {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Shared<T> {}
impl<T: ?Sized> RecoverSafe for Mutex<T> {}
impl<T: ?Sized> RecoverSafe for RwLock<T> {}
impl<T> RecoverSafe for AssertRecoverSafe<T> {}

// not covered via the Shared impl above b/c the inner contents use
// Cell/AtomicUsize, but the usage here is recover safe so we can lift the
// impl up one level to Arc/Rc itself
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Rc<T> {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Arc<T> {}

// Pretty simple implementations for the `RefRecoverSafe` marker trait,
// basically just saying that this is a marker trait and `UnsafeCell` is the
// only thing which doesn't implement it (which then transitively applies to
// everything else).
impl RefRecoverSafe for .. {}
impl<T: ?Sized> !RefRecoverSafe for UnsafeCell<T> {}
impl<T> RefRecoverSafe for AssertRecoverSafe<T> {}

impl<T> AssertRecoverSafe<T> {
    /// Creates a new `AssertRecoverSafe` wrapper around the provided type.
    #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
    pub fn new(t: T) -> AssertRecoverSafe<T> {
        AssertRecoverSafe(t)
    }
}

impl<T> Deref for AssertRecoverSafe<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> DerefMut for AssertRecoverSafe<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

/// Invokes a closure, capturing the cause of panic if one occurs.
///
/// This function will return `Ok` with the closure's result if the closure
/// does not panic, and will return `Err(cause)` if the closure panics. The
/// `cause` returned is the object with which panic was originally invoked.
///
/// It is currently undefined behavior to unwind from Rust code into foreign
/// code, so this function is particularly useful when Rust is called from
/// another language (normally C). This can run arbitrary Rust code, capturing a
/// panic and allowing a graceful handling of the error.
///
/// It is **not** recommended to use this function for a general try/catch
/// mechanism. The `Result` type is more appropriate to use for functions that
/// can fail on a regular basis.
///
/// The closure provided is required to adhere to the `RecoverSafe` to ensure
/// that all captured variables are safe to cross this recover boundary. The
/// purpose of this bound is to encode the concept of [exception safety][rfc] in
/// the type system. Most usage of this function should not need to worry about
/// this bound as programs are naturally panic safe without `unsafe` code. If it
/// becomes a problem the associated `AssertRecoverSafe` wrapper type in this
/// module can be used to quickly assert that the usage here is indeed exception
/// safe.
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// # Examples
///
/// ```
/// #![feature(recover, std_panic)]
///
/// use std::panic;
///
/// let result = panic::recover(|| {
///     println!("hello!");
/// });
/// assert!(result.is_ok());
///
/// let result = panic::recover(|| {
///     panic!("oh no!");
/// });
/// assert!(result.is_err());
/// ```
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
pub fn recover<F: FnOnce() -> R + RecoverSafe, R>(f: F) -> Result<R> {
    let mut result = None;
    unsafe {
        let result = &mut result;
        try!(unwind::try(move || *result = Some(f())))
    }
    Ok(result.unwrap())
}

/// Triggers a panic without invoking the panic handler.
///
/// This is designed to be used in conjunction with `recover` to, for example,
/// carry a panic across a layer of C code.
///
/// # Examples
///
/// ```should_panic
/// #![feature(std_panic, recover, panic_propagate)]
///
/// use std::panic;
///
/// let result = panic::recover(|| {
///     panic!("oh no!");
/// });
///
/// if let Err(err) = result {
///     panic::propagate(err);
/// }
/// ```
#[unstable(feature = "panic_propagate", reason = "awaiting feedback", issue = "30752")]
pub fn propagate(payload: Box<Any + Send>) -> ! {
    unwind::rust_panic(payload)
}
<commit_msg>Add into_inner to AssertRecoverSafe<commit_after>// Copyright 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.

//! Panic support in the standard library

#![unstable(feature = "std_panic", reason = "awaiting feedback",
            issue = "27719")]

use any::Any;
use boxed::Box;
use cell::UnsafeCell;
use ops::{Deref, DerefMut};
use ptr::{Unique, Shared};
use rc::Rc;
use sync::{Arc, Mutex, RwLock};
use sys_common::unwind;
use thread::Result;

pub use panicking::{take_handler, set_handler, PanicInfo, Location};

/// A marker trait which represents "panic safe" types in Rust.
///
/// This trait is implemented by default for many types and behaves similarly in
/// terms of inference of implementation to the `Send` and `Sync` traits. The
/// purpose of this trait is to encode what types are safe to cross a `recover`
/// boundary with no fear of panic safety.
///
/// ## What is panic safety?
///
/// In Rust a function can "return" early if it either panics or calls a
/// function which transitively panics. This sort of control flow is not always
/// anticipated, and has the possibility of causing subtle bugs through a
/// combination of two cricial components:
///
/// 1. A data structure is in a temporarily invalid state when the thread
///    panics.
/// 2. This broken invariant is then later observed.
///
/// Typically in Rust, it is difficult to perform step (2) because catching a
/// panic involves either spawning a thread (which in turns makes it difficult
/// to later witness broken invariants) or using the `recover` function in this
/// module. Additionally, even if an invariant is witnessed, it typically isn't a
/// problem in Rust because there's no uninitialized values (like in C or C++).
///
/// It is possible, however, for **logical** invariants to be broken in Rust,
/// which can end up causing behavioral bugs. Another key aspect of panic safety
/// in Rust is that, in the absence of `unsafe` code, a panic cannot lead to
/// memory unsafety.
///
/// That was a bit of a whirlwind tour of panic safety, but for more information
/// about panic safety and how it applies to Rust, see an [associated RFC][rfc].
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// ## What is `RecoverSafe`?
///
/// Now that we've got an idea of what panic safety is in Rust, it's also
/// important to understand what this trait represents. As mentioned above, one
/// way to witness broken invariants is through the `recover` function in this
/// module as it allows catching a panic and then re-using the environment of
/// the closure.
///
/// Simply put, a type `T` implements `RecoverSafe` if it cannot easily allow
/// witnessing a broken invariant through the use of `recover` (catching a
/// panic). This trait is a marker trait, so it is automatically implemented for
/// many types, and it is also structurally composed (e.g. a struct is recover
/// safe if all of its components are recover safe).
///
/// Note, however, that this is not an unsafe trait, so there is not a succinct
/// contract that this trait is providing. Instead it is intended as more of a
/// "speed bump" to alert users of `recover` that broken invariants may be
/// witnessed and may need to be accounted for.
///
/// ## Who implements `RecoverSafe`?
///
/// Types such as `&mut T` and `&RefCell<T>` are examples which are **not**
/// recover safe. The general idea is that any mutable state which can be shared
/// across `recover` is not recover safe by default. This is because it is very
/// easy to witness a broken invariant outside of `recover` as the data is
/// simply accessed as usual.
///
/// Types like `&Mutex<T>`, however, are recover safe because they implement
/// poisoning by default. They still allow witnessing a broken invariant, but
/// they already provide their own "speed bumps" to do so.
///
/// ## When should `RecoverSafe` be used?
///
/// Is not intended that most types or functions need to worry about this trait.
/// It is only used as a bound on the `recover` function and as mentioned above,
/// the lack of `unsafe` means it is mostly an advisory. The `AssertRecoverSafe`
/// wrapper struct in this module can be used to force this trait to be
/// implemented for any closed over variables passed to the `recover` function
/// (more on this below).
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
#[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
                            across a recover boundary"]
pub trait RecoverSafe {}

/// A marker trait representing types where a shared reference is considered
/// recover safe.
///
/// This trait is namely not implemented by `UnsafeCell`, the root of all
/// interior mutability.
///
/// This is a "helper marker trait" used to provide impl blocks for the
/// `RecoverSafe` trait, for more information see that documentation.
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
#[rustc_on_unimplemented = "the type {Self} contains interior mutability \
                            and a reference may not be safely transferrable \
                            across a recover boundary"]
pub trait RefRecoverSafe {}

/// A simple wrapper around a type to assert that it is panic safe.
///
/// When using `recover` it may be the case that some of the closed over
/// variables are not panic safe. For example if `&mut T` is captured the
/// compiler will generate a warning indicating that it is not panic safe. It
/// may not be the case, however, that this is actually a problem due to the
/// specific usage of `recover` if panic safety is specifically taken into
/// account. This wrapper struct is useful for a quick and lightweight
/// annotation that a variable is indeed panic safe.
///
/// # Examples
///
/// ```
/// #![feature(recover, std_panic)]
///
/// use std::panic::{self, AssertRecoverSafe};
///
/// let mut variable = 4;
///
/// // This code will not compile because the closure captures `&mut variable`
/// // which is not considered panic safe by default.
///
/// // panic::recover(|| {
/// //     variable += 3;
/// // });
///
/// // This, however, will compile due to the `AssertRecoverSafe` wrapper
/// let result = {
///     let mut wrapper = AssertRecoverSafe::new(&mut variable);
///     panic::recover(move || {
///         **wrapper += 3;
///     })
/// };
/// // ...
/// ```
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
pub struct AssertRecoverSafe<T>(T);

// Implementations of the `RecoverSafe` trait:
//
// * By default everything is recover safe
// * pointers T contains mutability of some form are not recover safe
// * Unique, an owning pointer, lifts an implementation
// * Types like Mutex/RwLock which are explicilty poisoned are recover safe
// * Our custom AssertRecoverSafe wrapper is indeed recover safe
impl RecoverSafe for .. {}
impl<'a, T: ?Sized> !RecoverSafe for &'a mut T {}
impl<'a, T: RefRecoverSafe + ?Sized> RecoverSafe for &'a T {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *const T {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *mut T {}
impl<T: RecoverSafe> RecoverSafe for Unique<T> {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Shared<T> {}
impl<T: ?Sized> RecoverSafe for Mutex<T> {}
impl<T: ?Sized> RecoverSafe for RwLock<T> {}
impl<T> RecoverSafe for AssertRecoverSafe<T> {}

// not covered via the Shared impl above b/c the inner contents use
// Cell/AtomicUsize, but the usage here is recover safe so we can lift the
// impl up one level to Arc/Rc itself
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Rc<T> {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Arc<T> {}

// Pretty simple implementations for the `RefRecoverSafe` marker trait,
// basically just saying that this is a marker trait and `UnsafeCell` is the
// only thing which doesn't implement it (which then transitively applies to
// everything else).
impl RefRecoverSafe for .. {}
impl<T: ?Sized> !RefRecoverSafe for UnsafeCell<T> {}
impl<T> RefRecoverSafe for AssertRecoverSafe<T> {}

impl<T> AssertRecoverSafe<T> {
    /// Creates a new `AssertRecoverSafe` wrapper around the provided type.
    #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
    pub fn new(t: T) -> AssertRecoverSafe<T> {
        AssertRecoverSafe(t)
    }

    /// Consumes the `AssertRecoverSafe`, returning the wrapped value.
    #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
    pub fn into_inner(self) -> T {
        self.0
    }
}

impl<T> Deref for AssertRecoverSafe<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> DerefMut for AssertRecoverSafe<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

/// Invokes a closure, capturing the cause of panic if one occurs.
///
/// This function will return `Ok` with the closure's result if the closure
/// does not panic, and will return `Err(cause)` if the closure panics. The
/// `cause` returned is the object with which panic was originally invoked.
///
/// It is currently undefined behavior to unwind from Rust code into foreign
/// code, so this function is particularly useful when Rust is called from
/// another language (normally C). This can run arbitrary Rust code, capturing a
/// panic and allowing a graceful handling of the error.
///
/// It is **not** recommended to use this function for a general try/catch
/// mechanism. The `Result` type is more appropriate to use for functions that
/// can fail on a regular basis.
///
/// The closure provided is required to adhere to the `RecoverSafe` to ensure
/// that all captured variables are safe to cross this recover boundary. The
/// purpose of this bound is to encode the concept of [exception safety][rfc] in
/// the type system. Most usage of this function should not need to worry about
/// this bound as programs are naturally panic safe without `unsafe` code. If it
/// becomes a problem the associated `AssertRecoverSafe` wrapper type in this
/// module can be used to quickly assert that the usage here is indeed exception
/// safe.
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// # Examples
///
/// ```
/// #![feature(recover, std_panic)]
///
/// use std::panic;
///
/// let result = panic::recover(|| {
///     println!("hello!");
/// });
/// assert!(result.is_ok());
///
/// let result = panic::recover(|| {
///     panic!("oh no!");
/// });
/// assert!(result.is_err());
/// ```
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
pub fn recover<F: FnOnce() -> R + RecoverSafe, R>(f: F) -> Result<R> {
    let mut result = None;
    unsafe {
        let result = &mut result;
        try!(unwind::try(move || *result = Some(f())))
    }
    Ok(result.unwrap())
}

/// Triggers a panic without invoking the panic handler.
///
/// This is designed to be used in conjunction with `recover` to, for example,
/// carry a panic across a layer of C code.
///
/// # Examples
///
/// ```should_panic
/// #![feature(std_panic, recover, panic_propagate)]
///
/// use std::panic;
///
/// let result = panic::recover(|| {
///     panic!("oh no!");
/// });
///
/// if let Err(err) = result {
///     panic::propagate(err);
/// }
/// ```
#[unstable(feature = "panic_propagate", reason = "awaiting feedback", issue = "30752")]
pub fn propagate(payload: Box<Any + Send>) -> ! {
    unwind::rust_panic(payload)
}
<|endoftext|>


<commit_before><commit_msg>Remove unnecessary let binding<commit_after><|endoftext|>


<commit_before><commit_msg>Rollup merge of #36087 - apasel422:issue-28324, r=alexcrichton<commit_after>// Copyright 2016 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.

extern {
    static error_message_count: u32;
}

pub static BAZ: u32 = *&error_message_count;
//~^ ERROR cannot refer to other statics by value

fn main() {}
<|endoftext|>


<commit_before><commit_msg>Update cryptoutil to use wrapping arithmetic functions<commit_after><|endoftext|>


<commit_before><commit_msg>Rollup merge of #76961 - bugadani:test-34634, r=Mark-Simulacrum<commit_after>// Test that `wrapping_div` only checks divisor once.
// This test checks that there is only a single compare agains -1 and -1 is not present as a
// switch case (the second check present until rustc 1.12).
// This test also verifies that a single panic call is generated (for the division by zero case).

// compile-flags: -O
#![crate_type = "lib"]

// CHECK-LABEL: @f
#[no_mangle]
pub fn f(x: i32, y: i32) -> i32 {
    // CHECK-COUNT-1: icmp eq i32 %y, -1
    // CHECK-COUNT-1: panic
    // CHECK-NOT: i32 -1, label
    x.wrapping_div(y)
}
<|endoftext|>


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

// Issue #5783
// Nondeterministic behavior when referencing a closure more than once

fn main() {
    let a: &fn(int) -> @fn(int) -> int = |x:int| |y:int| -> int x + y;
    let b = a(2);
    assert!(a(2)(3) == 5);
    assert!(b(6) == 8);
}
<|endoftext|>


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

struct A<'a> {
    a: &'a [~str],
    b: Option<&'a [~str]>,
}

pub fn main() {
    let b = &[~"foo"];
    let a = A {
        a: &[~"test"],
        b: Some(b),
    };
    assert_eq!(a.b.get_ref()[0].as_slice(), "foo");
}
<|endoftext|>


<commit_before><commit_msg>feat(json_schema): less rigid date-parsing<commit_after><|endoftext|>