<commit_before>use rand::Rng;
use rand::distributions::{Sample, IndependentSample};
use statistics::*;
use distribution::{Univariate, Continuous, Distribution};
use result::Result;
use error::StatsError;

/// Implements the [Inverse Gamma](https://en.wikipedia.org/wiki/Inverse-gamma_distribution) distribution
///
/// # Examples
///
/// ```
/// ```
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct InverseGamma {
    shape: f64,
    rate: f64,
}

impl InverseGamma {
    /// Constructs a new inverse gamma distribution with a shape (α)
    /// of `shape` and a rate (β) of `rate`
    ///
    /// # Errors
    ///
    /// Returns an error if `shape` or `rate` are `NaN`.
    /// Also returns an error if `shape <= 0.0` or `rate <= 0.0`
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::InverseGamma;
    ///
    /// let mut result = InverseGamma::new(3.0, 1.0);
    /// assert!(result.is_ok());
    ///
    /// result = InverseGamma::new(0.0, 0.0);
    /// assert!(result.is_err());
    /// ```
    pub fn new(shape: f64, rate: f64) -> Result<InverseGamma> {
        let is_nan = shape.is_nan() || rate.is_nan();
        match (shape, rate, is_nan) {
            (_, _, true) => Err(StatsError::BadParams),
            (_, _, false) if shape <= 0.0 || rate <= 0.0 => Err(StatsError::BadParams),
            (_, _, false) => {
                Ok(InverseGamma {
                    shape: shape,
                    rate: rate,
                })
            }
        }
    }

    /// Returns the shape (α) of the inverse gamma distribution
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::InverseGamma;
    ///
    /// let n = InverseGamma::new(3.0, 1.0).unwrap();
    /// assert_eq!(n.shape(), 3.0);
    /// ```
    pub fn shape(&self) -> f64 {
        self.shape
    }

    /// Returns the rate (β) of the inverse gamma distribution
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::InverseGamma;
    ///
    /// let n = InverseGamma::new(3.0, 1.0);
    /// assert_eq!(n.rate(), 1.0);
    /// ```
    pub fn rate(&self) -> f64 {
        self.rate
    }
}

impl Sample<f64> for InverseGamma {
    /// Generate a random sample from an inverse gamma
    /// distribution using `r` as the source of randomness.
    /// Refer [here](#method.sample-1) for implementation details
    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl IndependentSample<f64> for InverseGamma {
    /// Generate a random independent sample from an inverse gamma
    /// distribution using `r` as the source of randomness.
    /// Refer [here](#method.sample-1) for implementation details
    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl Distribution<f64> for InverseGamma {
    /// Generate a random sample from an inverse gamma distribution
    /// using `r` as the source of randomness.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate rand;
    /// # extern crate statrs;
    /// use rand::StdRng;
    /// use statrs::distribution::{InverseGamma, Distribution};
    ///
    /// # fn main() {
    /// let mut r = rand::StdRng::new().unwrap();
    /// let n = InverseGamma::new(3.0, 1.0).unwrap();
    /// print!("{}", n.sample::<StdRng>(&mut r));
    /// # }
    /// ```
    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
        1.0 / super::gamma::sample_unchecked(r, self.shape, self.rate)
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)]
#[cfg(test)]
mod test {
    use std::f64;
    use statistics::*;
    use distribution::{Univariate, Continuous, InverseGamma};

    fn try_create(shape: f64, rate: f64) -> InverseGamma {
        let n = InverseGamma::new(shape, rate);
        assert!(n.is_ok());
        n.unwrap()
    }

    fn create_case(shape: f64, rate: f64) {
        let n = try_create(shape, rate);
        assert_eq!(shape, n.shape());
        assert_eq!(rate, n.rate());
    }

    fn bad_create_case(shape: f64, rate: f64) {
        let n = InverseGamma::new(shape, rate);
        assert!(n.is_err());
    }

    #[test]
    fn test_create() {
        create_case(0.1, 0.1);
        create_case(1.0, 1.0);
    }

    #[test]
    fn test_bad_create() {
        bad_create_case(0.0, 1.0);
        bad_create_case(-1.0, 1.0);
        bad_create_case(-100.0, 1.0);
        bad_create_case(f64::NEG_INFINITY, 1.0);
        bad_create_case(f64::NAN, 1.0);
        bad_create_case(1.0, 0.0);
        bad_create_case(1.0, -1.0);
        bad_create_case(1.0, -100.0);
        bad_create_case(1.0, f64::NEG_INFINITY);
        bad_create_case(1.0, f64::NAN);
    }
}<commit_msg>wip: fix doc example bug<commit_after>use rand::Rng;
use rand::distributions::{Sample, IndependentSample};
use statistics::*;
use distribution::{Univariate, Continuous, Distribution};
use result::Result;
use error::StatsError;

/// Implements the [Inverse Gamma](https://en.wikipedia.org/wiki/Inverse-gamma_distribution) distribution
///
/// # Examples
///
/// ```
/// ```
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct InverseGamma {
    shape: f64,
    rate: f64,
}

impl InverseGamma {
    /// Constructs a new inverse gamma distribution with a shape (α)
    /// of `shape` and a rate (β) of `rate`
    ///
    /// # Errors
    ///
    /// Returns an error if `shape` or `rate` are `NaN`.
    /// Also returns an error if `shape <= 0.0` or `rate <= 0.0`
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::InverseGamma;
    ///
    /// let mut result = InverseGamma::new(3.0, 1.0);
    /// assert!(result.is_ok());
    ///
    /// result = InverseGamma::new(0.0, 0.0);
    /// assert!(result.is_err());
    /// ```
    pub fn new(shape: f64, rate: f64) -> Result<InverseGamma> {
        let is_nan = shape.is_nan() || rate.is_nan();
        match (shape, rate, is_nan) {
            (_, _, true) => Err(StatsError::BadParams),
            (_, _, false) if shape <= 0.0 || rate <= 0.0 => Err(StatsError::BadParams),
            (_, _, false) => {
                Ok(InverseGamma {
                    shape: shape,
                    rate: rate,
                })
            }
        }
    }

    /// Returns the shape (α) of the inverse gamma distribution
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::InverseGamma;
    ///
    /// let n = InverseGamma::new(3.0, 1.0).unwrap();
    /// assert_eq!(n.shape(), 3.0);
    /// ```
    pub fn shape(&self) -> f64 {
        self.shape
    }

    /// Returns the rate (β) of the inverse gamma distribution
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::InverseGamma;
    ///
    /// let n = InverseGamma::new(3.0, 1.0).unwrap();
    /// assert_eq!(n.rate(), 1.0);
    /// ```
    pub fn rate(&self) -> f64 {
        self.rate
    }
}

impl Sample<f64> for InverseGamma {
    /// Generate a random sample from an inverse gamma
    /// distribution using `r` as the source of randomness.
    /// Refer [here](#method.sample-1) for implementation details
    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl IndependentSample<f64> for InverseGamma {
    /// Generate a random independent sample from an inverse gamma
    /// distribution using `r` as the source of randomness.
    /// Refer [here](#method.sample-1) for implementation details
    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl Distribution<f64> for InverseGamma {
    /// Generate a random sample from an inverse gamma distribution
    /// using `r` as the source of randomness.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate rand;
    /// # extern crate statrs;
    /// use rand::StdRng;
    /// use statrs::distribution::{InverseGamma, Distribution};
    ///
    /// # fn main() {
    /// let mut r = rand::StdRng::new().unwrap();
    /// let n = InverseGamma::new(3.0, 1.0).unwrap();
    /// print!("{}", n.sample::<StdRng>(&mut r));
    /// # }
    /// ```
    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
        1.0 / super::gamma::sample_unchecked(r, self.shape, self.rate)
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)]
#[cfg(test)]
mod test {
    use std::f64;
    use statistics::*;
    use distribution::{Univariate, Continuous, InverseGamma};

    fn try_create(shape: f64, rate: f64) -> InverseGamma {
        let n = InverseGamma::new(shape, rate);
        assert!(n.is_ok());
        n.unwrap()
    }

    fn create_case(shape: f64, rate: f64) {
        let n = try_create(shape, rate);
        assert_eq!(shape, n.shape());
        assert_eq!(rate, n.rate());
    }

    fn bad_create_case(shape: f64, rate: f64) {
        let n = InverseGamma::new(shape, rate);
        assert!(n.is_err());
    }

    #[test]
    fn test_create() {
        create_case(0.1, 0.1);
        create_case(1.0, 1.0);
    }

    #[test]
    fn test_bad_create() {
        bad_create_case(0.0, 1.0);
        bad_create_case(-1.0, 1.0);
        bad_create_case(-100.0, 1.0);
        bad_create_case(f64::NEG_INFINITY, 1.0);
        bad_create_case(f64::NAN, 1.0);
        bad_create_case(1.0, 0.0);
        bad_create_case(1.0, -1.0);
        bad_create_case(1.0, -100.0);
        bad_create_case(1.0, f64::NEG_INFINITY);
        bad_create_case(1.0, f64::NAN);
    }
}<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::path::Path;
use std::path::PathBuf;

use devicemapper::DM;
use uuid::Uuid;

use engine::Engine;
use engine::EngineError;
use engine::EngineResult;
use engine::ErrorEnum;
use engine::Pool;
use engine::Redundancy;
use engine::RenameAction;

use super::pool::StratPool;

use super::super::engine::{HasName, HasUuid, PoolUuid};
use super::super::structures::Table;

#[derive(Debug)]
pub enum DevOwnership {
    Ours(Uuid),
    Unowned,
    Theirs,
}

#[derive(Debug)]
pub struct StratEngine {
    pools: Table<StratPool>,
}

impl StratEngine {
    pub fn new() -> StratEngine {
        StratEngine { pools: Table::new() }
    }
}

impl Engine for StratEngine {
    fn configure_simulator(&mut self, _denominator: u32) -> EngineResult<()> {
        Ok(()) // we're not the simulator and not configurable, so just say ok
    }

    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   redundancy: Option<u16>,
                   force: bool)
                   -> EngineResult<(PoolUuid, Vec<PathBuf>)> {

        let redundancy = calculate_redundancy!(redundancy);

        if self.pools.contains_name(name) {
            return Err(EngineError::Engine(ErrorEnum::AlreadyExists, name.into()));
        }

        let dm = try!(DM::new());
        let pool = try!(StratPool::new(name, &dm, blockdev_paths, redundancy, force));
        let bdev_paths = pool.block_devs.iter().map(|p| p.1.devnode.clone()).collect();

        let uuid = pool.uuid().clone();
        self.pools.insert(pool);
        Ok((uuid, bdev_paths))
    }

    /// Destroy a pool, if the pool does not exist, return Ok.
    fn destroy_pool(&mut self, uuid: &PoolUuid) -> EngineResult<bool> {
        destroy_pool!{self; uuid}
    }

    fn rename_pool(&mut self, uuid: &PoolUuid, new_name: &str) -> EngineResult<RenameAction> {
        rename_pool!{self; uuid; new_name}
    }

    fn get_pool(&mut self, uuid: &PoolUuid) -> Option<&mut Pool> {
        get_pool!(self; uuid)
    }
}
<commit_msg>Derive equality for DevOwnership<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::path::Path;
use std::path::PathBuf;

use devicemapper::DM;
use uuid::Uuid;

use engine::Engine;
use engine::EngineError;
use engine::EngineResult;
use engine::ErrorEnum;
use engine::Pool;
use engine::Redundancy;
use engine::RenameAction;

use super::pool::StratPool;

use super::super::engine::{HasName, HasUuid, PoolUuid};
use super::super::structures::Table;

#[derive(Debug, PartialEq, Eq)]
pub enum DevOwnership {
    Ours(Uuid),
    Unowned,
    Theirs,
}

#[derive(Debug)]
pub struct StratEngine {
    pools: Table<StratPool>,
}

impl StratEngine {
    pub fn new() -> StratEngine {
        StratEngine { pools: Table::new() }
    }
}

impl Engine for StratEngine {
    fn configure_simulator(&mut self, _denominator: u32) -> EngineResult<()> {
        Ok(()) // we're not the simulator and not configurable, so just say ok
    }

    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   redundancy: Option<u16>,
                   force: bool)
                   -> EngineResult<(PoolUuid, Vec<PathBuf>)> {

        let redundancy = calculate_redundancy!(redundancy);

        if self.pools.contains_name(name) {
            return Err(EngineError::Engine(ErrorEnum::AlreadyExists, name.into()));
        }

        let dm = try!(DM::new());
        let pool = try!(StratPool::new(name, &dm, blockdev_paths, redundancy, force));
        let bdev_paths = pool.block_devs.iter().map(|p| p.1.devnode.clone()).collect();

        let uuid = pool.uuid().clone();
        self.pools.insert(pool);
        Ok((uuid, bdev_paths))
    }

    /// Destroy a pool, if the pool does not exist, return Ok.
    fn destroy_pool(&mut self, uuid: &PoolUuid) -> EngineResult<bool> {
        destroy_pool!{self; uuid}
    }

    fn rename_pool(&mut self, uuid: &PoolUuid, new_name: &str) -> EngineResult<RenameAction> {
        rename_pool!{self; uuid; new_name}
    }

    fn get_pool(&mut self, uuid: &PoolUuid) -> Option<&mut Pool> {
        get_pool!(self; uuid)
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate libnewsboat;

use libc::c_char;
use std::ffi::{CStr, CString};
use std::ptr;

use libnewsboat::{utils, logger, human_panic};

#[no_mangle]
pub extern "C" fn rs_replace_all(
    input: *const c_char,
    from: *const c_char,
    to: *const c_char)
    -> *mut c_char
{
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy().into_owned();

    let rs_from = unsafe { CStr::from_ptr(from) };
    let rs_from = rs_from.to_str()
        .expect("rs_from contained invalid UTF-8");

    let rs_to = unsafe { CStr::from_ptr(to) };
    let rs_to = rs_to.to_str()
        .expect("rs_to contained invalid UTF-8");

    let result = utils::replace_all(rs_input, rs_from, rs_to);
    // Panic here can't happen because:
    // 1. panic can only happen if `result` contains null bytes;
    // 2. `result` contains what `input` contained, plus maybe what `to` contains (if there were
    //    replacements);
    // 3. neither `input` nor `to` could contain null bytes because they're null-terminated
    //    strings we got from C.
    let result = CString::new(result).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_consolidate_whitespace( input: *const c_char) -> *mut c_char {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy().into_owned();

    let result = utils::consolidate_whitespace(rs_input);
    // Panic here can't happen because:
    // 1. panic can only happen if `result` contains null bytes;
    // 2. `result` contains what `input` contained, and input is a
    // null-terminated string from C.
    let result = CString::new(result).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_resolve_tilde( path: *const c_char) -> *mut c_char {

    let rs_path = unsafe { CStr::from_ptr(path) };
    let rs_path = rs_path.to_string_lossy().into_owned();

    let result = utils::resolve_tilde(rs_path);

    let result = CString::new(result).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_to_u(in_str: *const c_char, default_value: u32) -> u32
{
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy().into_owned();

    utils::to_u( rs_str, default_value)
}

#[no_mangle]
pub extern "C" fn rs_absolute_url(base_url: *const c_char, link: *const c_char) -> *mut c_char {
    let rs_base_url = unsafe { CStr::from_ptr(base_url) };
    let rs_base_url = rs_base_url.to_string_lossy();
    let rs_link = unsafe { CStr::from_ptr(link) };
    let rs_link = rs_link.to_string_lossy();

    let ret = utils::absolute_url(&rs_base_url, &rs_link);
    CString::new(ret).unwrap().into_raw()
}

#[no_mangle]
pub extern "C" fn rs_is_special_url(in_str: *const c_char) -> bool {
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy();
    utils::is_special_url(&rs_str)
}

#[no_mangle]
pub extern "C" fn rs_is_http_url(in_str: *const c_char) -> bool {
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy();
    utils::is_http_url(&rs_str)
}

#[no_mangle]
pub extern "C" fn rs_is_query_url(in_str: *const c_char) -> bool {
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy();
    utils::is_query_url(&rs_str)
}

#[no_mangle]
pub extern "C" fn rs_is_filter_url(in_str: *const c_char) -> bool {
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy();
    utils::is_filter_url(&rs_str)
}

#[no_mangle]
pub extern "C" fn rs_is_exec_url(in_str: *const c_char) -> bool {
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy();
    utils::is_exec_url(&rs_str)
}

#[no_mangle]
pub extern "C" fn rs_censor_url(url: *const c_char) -> *mut c_char {
    let rs_url = unsafe { CStr::from_ptr(url) };
    let rs_url = rs_url.to_string_lossy();
    CString::new(utils::censor_url(&rs_url)).unwrap().into_raw()
}

#[no_mangle]
pub extern "C" fn rs_trim_end(input: *const c_char) -> *mut c_char {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy().into_owned();

    let result = utils::trim_end(rs_input);

    let result = CString::new(result).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_trim(input: *const c_char) -> *mut c_char {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy().into_owned();

    let result = utils::trim(rs_input);

    let result = CString::new(result).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_get_random_value(rs_max: u32 ) -> u32 {
    utils::get_random_value(rs_max)
}

#[no_mangle]
pub extern "C" fn rs_unescape_url(input: *const c_char) -> *mut c_char {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy().into_owned();

    let result = utils::unescape_url(rs_input);
    // Panic here can't happen because:
    // 1. It would have already occured within unescape_url
    // 2. panic can only happen if `result` contains null bytes;
    // 3. `result` contains what `input` contained, and input is a
    // null-terminated string from C.
    if result.is_some(){
            let result = CString::new(result.unwrap()).unwrap();
            return result.into_raw()
    }
    return ptr::null_mut()
}

#[no_mangle]
pub extern "C" fn rs_cstring_free(string: *mut c_char) {
    unsafe {
        if string.is_null() { return }
        CString::from_raw(string);
    };
}

#[no_mangle]
pub extern "C" fn rs_get_default_browser() -> *mut c_char {
    let browser = utils::get_default_browser();
    // Panic here can't happen because:
    //1. panic can only happen if `result` contains null bytes;
    //2. std::env::var returns an error if the variable contains invalid Unicode,
    // In that case get_default_browser will return "lynx", which obviously doesn't contain null bytes.
    let result = CString::new(browser).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_is_valid_color(input: *const c_char) -> bool {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy();
    utils::is_valid_color(&rs_input)
}

#[no_mangle]
pub extern "C" fn rs_is_valid_attribute(attribute: *const c_char) -> bool {
    let rs_attribute = unsafe { CStr::from_ptr(attribute) };
    let rs_attribute = rs_attribute.to_string_lossy();
    utils::is_valid_attribute(&rs_attribute)
}

#[no_mangle]
pub extern "C" fn rs_is_valid_podcast_type(mimetype: *const c_char) -> bool {
    let rs_mimetype = unsafe { CStr::from_ptr(mimetype) };
    let rs_mimetype = rs_mimetype.to_string_lossy();
    utils::is_valid_podcast_type(&rs_mimetype)
}

#[no_mangle]
pub extern "C" fn rs_log(level: logger::Level, message: *const c_char) {
    let message = unsafe { CStr::from_ptr(message) };
    logger::get_instance().log_raw(level, message.to_bytes());
}

#[no_mangle]
pub extern "C" fn rs_set_loglevel(level: logger::Level) {
    logger::get_instance().set_loglevel(level);
}

#[no_mangle]
pub extern "C" fn rs_set_logfile(logfile: *const c_char) {
    let logfile = unsafe { CStr::from_ptr(logfile) };
    let logfile = logfile.to_str().expect("logfile path contained invalid UTF-8");
    logger::get_instance().set_logfile(logfile);
}

#[no_mangle]
pub extern "C" fn rs_set_user_error_logfile(user_error_logfile: *const c_char) {
    let user_error_logfile = unsafe { CStr::from_ptr(user_error_logfile) };
    let user_error_logfile = user_error_logfile.to_str().expect("user_error_logfile path contained invalid UTF-8");
    logger::get_instance().set_user_error_logfile(user_error_logfile);
}

#[no_mangle]
pub extern "C" fn rs_get_loglevel() -> u64 {
    logger::get_instance().get_loglevel() as u64
}

#[no_mangle]
pub extern "C" fn rs_setup_human_panic() {
    human_panic::setup();
}

#[no_mangle]
pub extern "C" fn rs_get_command_output(input: *const c_char) -> *mut c_char {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy();
    let output = utils::get_command_output(&rs_input);
    // String::from_utf8_lossy() will replace invalid unicode (including null bytes) with U+FFFD,
    // so this shouldn't be able to panic
    let result = CString::new(output).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_run_command(command: *const c_char, param: *const c_char) {
    let command = unsafe { CStr::from_ptr(command) };
    let command = command.to_str()
        .expect("command contained invalid UTF-8");

    let param = unsafe { CStr::from_ptr(param) };
    let param = param.to_str()
        .expect("param contained invalid UTF-8");

    utils::run_command(command, param);
}

#[no_mangle]
pub extern "C" fn rs_run_program(argv: *mut *mut c_char, input: *const c_char) -> *mut c_char {
    let argv = unsafe {
        let mut result: Vec<&str> = Vec::new();
        let mut cur_ptr = argv;

        let mut offset: usize = 0;
        while !(*cur_ptr).is_null() {
            let arg = CStr::from_ptr(*cur_ptr);
            let arg = arg.to_str()
                .expect(&format!("argument at offset {} contained invalid UTF-8", offset));

            result.push(arg);

            offset += 1;
            cur_ptr = cur_ptr.add(1);
        }

        result
    };

    let input = unsafe { CStr::from_ptr(input) };
    let input = input.to_str()
        .expect("input contained invalid UTF-8");

    let output = utils::run_program(&argv, input);

    // String::from_utf8_lossy() will replace invalid unicode (including null bytes) with U+FFFD,
    // so this shouldn't be able to panic
    let result = CString::new(output).unwrap();
    result.into_raw()
}
<commit_msg>Make it compile with Rust 1.25<commit_after>extern crate libc;
extern crate libnewsboat;

use libc::c_char;
use std::ffi::{CStr, CString};
use std::ptr;

use libnewsboat::{utils, logger, human_panic};

#[no_mangle]
pub extern "C" fn rs_replace_all(
    input: *const c_char,
    from: *const c_char,
    to: *const c_char)
    -> *mut c_char
{
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy().into_owned();

    let rs_from = unsafe { CStr::from_ptr(from) };
    let rs_from = rs_from.to_str()
        .expect("rs_from contained invalid UTF-8");

    let rs_to = unsafe { CStr::from_ptr(to) };
    let rs_to = rs_to.to_str()
        .expect("rs_to contained invalid UTF-8");

    let result = utils::replace_all(rs_input, rs_from, rs_to);
    // Panic here can't happen because:
    // 1. panic can only happen if `result` contains null bytes;
    // 2. `result` contains what `input` contained, plus maybe what `to` contains (if there were
    //    replacements);
    // 3. neither `input` nor `to` could contain null bytes because they're null-terminated
    //    strings we got from C.
    let result = CString::new(result).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_consolidate_whitespace( input: *const c_char) -> *mut c_char {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy().into_owned();

    let result = utils::consolidate_whitespace(rs_input);
    // Panic here can't happen because:
    // 1. panic can only happen if `result` contains null bytes;
    // 2. `result` contains what `input` contained, and input is a
    // null-terminated string from C.
    let result = CString::new(result).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_resolve_tilde( path: *const c_char) -> *mut c_char {

    let rs_path = unsafe { CStr::from_ptr(path) };
    let rs_path = rs_path.to_string_lossy().into_owned();

    let result = utils::resolve_tilde(rs_path);

    let result = CString::new(result).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_to_u(in_str: *const c_char, default_value: u32) -> u32
{
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy().into_owned();

    utils::to_u( rs_str, default_value)
}

#[no_mangle]
pub extern "C" fn rs_absolute_url(base_url: *const c_char, link: *const c_char) -> *mut c_char {
    let rs_base_url = unsafe { CStr::from_ptr(base_url) };
    let rs_base_url = rs_base_url.to_string_lossy();
    let rs_link = unsafe { CStr::from_ptr(link) };
    let rs_link = rs_link.to_string_lossy();

    let ret = utils::absolute_url(&rs_base_url, &rs_link);
    CString::new(ret).unwrap().into_raw()
}

#[no_mangle]
pub extern "C" fn rs_is_special_url(in_str: *const c_char) -> bool {
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy();
    utils::is_special_url(&rs_str)
}

#[no_mangle]
pub extern "C" fn rs_is_http_url(in_str: *const c_char) -> bool {
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy();
    utils::is_http_url(&rs_str)
}

#[no_mangle]
pub extern "C" fn rs_is_query_url(in_str: *const c_char) -> bool {
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy();
    utils::is_query_url(&rs_str)
}

#[no_mangle]
pub extern "C" fn rs_is_filter_url(in_str: *const c_char) -> bool {
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy();
    utils::is_filter_url(&rs_str)
}

#[no_mangle]
pub extern "C" fn rs_is_exec_url(in_str: *const c_char) -> bool {
    let rs_str = unsafe { CStr::from_ptr(in_str) };
    let rs_str = rs_str.to_string_lossy();
    utils::is_exec_url(&rs_str)
}

#[no_mangle]
pub extern "C" fn rs_censor_url(url: *const c_char) -> *mut c_char {
    let rs_url = unsafe { CStr::from_ptr(url) };
    let rs_url = rs_url.to_string_lossy();
    CString::new(utils::censor_url(&rs_url)).unwrap().into_raw()
}

#[no_mangle]
pub extern "C" fn rs_trim_end(input: *const c_char) -> *mut c_char {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy().into_owned();

    let result = utils::trim_end(rs_input);

    let result = CString::new(result).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_trim(input: *const c_char) -> *mut c_char {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy().into_owned();

    let result = utils::trim(rs_input);

    let result = CString::new(result).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_get_random_value(rs_max: u32 ) -> u32 {
    utils::get_random_value(rs_max)
}

#[no_mangle]
pub extern "C" fn rs_unescape_url(input: *const c_char) -> *mut c_char {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy().into_owned();

    let result = utils::unescape_url(rs_input);
    // Panic here can't happen because:
    // 1. It would have already occured within unescape_url
    // 2. panic can only happen if `result` contains null bytes;
    // 3. `result` contains what `input` contained, and input is a
    // null-terminated string from C.
    if result.is_some(){
            let result = CString::new(result.unwrap()).unwrap();
            return result.into_raw()
    }
    return ptr::null_mut()
}

#[no_mangle]
pub extern "C" fn rs_cstring_free(string: *mut c_char) {
    unsafe {
        if string.is_null() { return }
        CString::from_raw(string);
    };
}

#[no_mangle]
pub extern "C" fn rs_get_default_browser() -> *mut c_char {
    let browser = utils::get_default_browser();
    // Panic here can't happen because:
    //1. panic can only happen if `result` contains null bytes;
    //2. std::env::var returns an error if the variable contains invalid Unicode,
    // In that case get_default_browser will return "lynx", which obviously doesn't contain null bytes.
    let result = CString::new(browser).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_is_valid_color(input: *const c_char) -> bool {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy();
    utils::is_valid_color(&rs_input)
}

#[no_mangle]
pub extern "C" fn rs_is_valid_attribute(attribute: *const c_char) -> bool {
    let rs_attribute = unsafe { CStr::from_ptr(attribute) };
    let rs_attribute = rs_attribute.to_string_lossy();
    utils::is_valid_attribute(&rs_attribute)
}

#[no_mangle]
pub extern "C" fn rs_is_valid_podcast_type(mimetype: *const c_char) -> bool {
    let rs_mimetype = unsafe { CStr::from_ptr(mimetype) };
    let rs_mimetype = rs_mimetype.to_string_lossy();
    utils::is_valid_podcast_type(&rs_mimetype)
}

#[no_mangle]
pub extern "C" fn rs_log(level: logger::Level, message: *const c_char) {
    let message = unsafe { CStr::from_ptr(message) };
    logger::get_instance().log_raw(level, message.to_bytes());
}

#[no_mangle]
pub extern "C" fn rs_set_loglevel(level: logger::Level) {
    logger::get_instance().set_loglevel(level);
}

#[no_mangle]
pub extern "C" fn rs_set_logfile(logfile: *const c_char) {
    let logfile = unsafe { CStr::from_ptr(logfile) };
    let logfile = logfile.to_str().expect("logfile path contained invalid UTF-8");
    logger::get_instance().set_logfile(logfile);
}

#[no_mangle]
pub extern "C" fn rs_set_user_error_logfile(user_error_logfile: *const c_char) {
    let user_error_logfile = unsafe { CStr::from_ptr(user_error_logfile) };
    let user_error_logfile = user_error_logfile.to_str().expect("user_error_logfile path contained invalid UTF-8");
    logger::get_instance().set_user_error_logfile(user_error_logfile);
}

#[no_mangle]
pub extern "C" fn rs_get_loglevel() -> u64 {
    logger::get_instance().get_loglevel() as u64
}

#[no_mangle]
pub extern "C" fn rs_setup_human_panic() {
    human_panic::setup();
}

#[no_mangle]
pub extern "C" fn rs_get_command_output(input: *const c_char) -> *mut c_char {
    let rs_input = unsafe { CStr::from_ptr(input) };
    let rs_input = rs_input.to_string_lossy();
    let output = utils::get_command_output(&rs_input);
    // String::from_utf8_lossy() will replace invalid unicode (including null bytes) with U+FFFD,
    // so this shouldn't be able to panic
    let result = CString::new(output).unwrap();
    result.into_raw()
}

#[no_mangle]
pub extern "C" fn rs_run_command(command: *const c_char, param: *const c_char) {
    let command = unsafe { CStr::from_ptr(command) };
    let command = command.to_str()
        .expect("command contained invalid UTF-8");

    let param = unsafe { CStr::from_ptr(param) };
    let param = param.to_str()
        .expect("param contained invalid UTF-8");

    utils::run_command(command, param);
}

#[no_mangle]
pub extern "C" fn rs_run_program(argv: *mut *mut c_char, input: *const c_char) -> *mut c_char {
    let argv = unsafe {
        let mut result: Vec<&str> = Vec::new();
        let mut cur_ptr = argv;

        let mut offset: usize = 0;
        while !(*cur_ptr).is_null() {
            let arg = CStr::from_ptr(*cur_ptr);
            let arg = arg.to_str()
                .expect(&format!("argument at offset {} contained invalid UTF-8", offset));

            result.push(arg);

            offset += 1;
            cur_ptr = cur_ptr.offset(1isize);
        }

        result
    };

    let input = unsafe { CStr::from_ptr(input) };
    let input = input.to_str()
        .expect("input contained invalid UTF-8");

    let output = utils::run_program(&argv, input);

    // String::from_utf8_lossy() will replace invalid unicode (including null bytes) with U+FFFD,
    // so this shouldn't be able to panic
    let result = CString::new(output).unwrap();
    result.into_raw()
}
<|endoftext|>


<commit_before>use crate::intrinsics;
use crate::iter::{
    DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedRandomAccess,
};
use crate::ops::Try;

/// An iterator that yields `None` forever after the underlying iterator
/// yields `None` once.
///
/// This `struct` is created by the [`fuse`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`fuse`]: trait.Iterator.html#method.fuse
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Fuse<I> {
    // NOTE: for `I: FusedIterator`, this is always assumed `Some`!
    iter: Option<I>,
}
impl<I> Fuse<I> {
    pub(in crate::iter) fn new(iter: I) -> Fuse<I> {
        Fuse { iter: Some(iter) }
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Fuse<I> where I: Iterator {}

/// Fuse the iterator if the expression is `None`.
macro_rules! fuse {
    ($self:ident . iter . $($call:tt)+) => {
        match $self.iter {
            Some(ref mut iter) => match iter.$($call)+ {
                None => {
                    $self.iter = None;
                    None
                }
                item => item,
            },
            None => None,
        }
    };
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> Iterator for Fuse<I>
where
    I: Iterator,
{
    type Item = <I as Iterator>::Item;

    #[inline]
    default fn next(&mut self) -> Option<<I as Iterator>::Item> {
        fuse!(self.iter.next())
    }

    #[inline]
    default fn nth(&mut self, n: usize) -> Option<I::Item> {
        fuse!(self.iter.nth(n))
    }

    #[inline]
    default fn last(self) -> Option<I::Item> {
        match self.iter {
            Some(iter) => iter.last(),
            None => None,
        }
    }

    #[inline]
    default fn count(self) -> usize {
        match self.iter {
            Some(iter) => iter.count(),
            None => 0,
        }
    }

    #[inline]
    default fn size_hint(&self) -> (usize, Option<usize>) {
        match self.iter {
            Some(ref iter) => iter.size_hint(),
            None => (0, Some(0)),
        }
    }

    #[inline]
    default fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_fold(acc, fold)?;
            self.iter = None;
        }
        Try::from_ok(acc)
    }

    #[inline]
    default fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(iter) = self.iter {
            acc = iter.fold(acc, fold);
        }
        acc
    }

    #[inline]
    default fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        fuse!(self.iter.find(predicate))
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
    I: DoubleEndedIterator,
{
    #[inline]
    default fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
        fuse!(self.iter.next_back())
    }

    #[inline]
    default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
        fuse!(self.iter.nth_back(n))
    }

    #[inline]
    default fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_rfold(acc, fold)?;
            self.iter = None;
        }
        Try::from_ok(acc)
    }

    #[inline]
    default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(iter) = self.iter {
            acc = iter.rfold(acc, fold);
        }
        acc
    }

    #[inline]
    default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        fuse!(self.iter.rfind(predicate))
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
    I: ExactSizeIterator,
{
    default fn len(&self) -> usize {
        match self.iter {
            Some(ref iter) => iter.len(),
            None => 0,
        }
    }

    default fn is_empty(&self) -> bool {
        match self.iter {
            Some(ref iter) => iter.is_empty(),
            None => true,
        }
    }
}

// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`.
// Implementing this as a directly-expanded macro helps codegen performance.
macro_rules! unchecked {
    ($self:ident) => {
        match $self {
            Fuse { iter: Some(iter) } => iter,
            // SAFETY: the specialized iterator never sets `None`
            Fuse { iter: None } => unsafe { intrinsics::unreachable() },
        }
    };
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> Iterator for Fuse<I>
where
    I: FusedIterator,
{
    #[inline]
    fn next(&mut self) -> Option<<I as Iterator>::Item> {
        unchecked!(self).next()
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<I::Item> {
        unchecked!(self).nth(n)
    }

    #[inline]
    fn last(self) -> Option<I::Item> {
        unchecked!(self).last()
    }

    #[inline]
    fn count(self) -> usize {
        unchecked!(self).count()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        unchecked!(self).size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        unchecked!(self).try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        unchecked!(self).fold(init, fold)
    }

    #[inline]
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        unchecked!(self).find(predicate)
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
    I: DoubleEndedIterator + FusedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
        unchecked!(self).next_back()
    }

    #[inline]
    fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
        unchecked!(self).nth_back(n)
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        unchecked!(self).try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        unchecked!(self).rfold(init, fold)
    }

    #[inline]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        unchecked!(self).rfind(predicate)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
    I: ExactSizeIterator + FusedIterator,
{
    fn len(&self) -> usize {
        unchecked!(self).len()
    }

    fn is_empty(&self) -> bool {
        unchecked!(self).is_empty()
    }
}

unsafe impl<I> TrustedRandomAccess for Fuse<I>
where
    I: TrustedRandomAccess,
{
    unsafe fn get_unchecked(&mut self, i: usize) -> I::Item {
        match self.iter {
            Some(ref mut iter) => iter.get_unchecked(i),
            // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
            None => intrinsics::unreachable(),
        }
    }

    fn may_have_side_effect() -> bool {
        I::may_have_side_effect()
    }
}
<commit_msg>Rollup merge of #70910 - rakshith-ravi:master, r=cuviper<commit_after>use crate::intrinsics;
use crate::iter::{
    DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedRandomAccess,
};
use crate::ops::Try;

/// An iterator that yields `None` forever after the underlying iterator
/// yields `None` once.
///
/// This `struct` is created by the [`fuse`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`fuse`]: trait.Iterator.html#method.fuse
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Fuse<I> {
    // NOTE: for `I: FusedIterator`, this is always assumed `Some`!
    iter: Option<I>,
}
impl<I> Fuse<I> {
    pub(in crate::iter) fn new(iter: I) -> Fuse<I> {
        Fuse { iter: Some(iter) }
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Fuse<I> where I: Iterator {}

/// Fuse the iterator if the expression is `None`.
macro_rules! fuse {
    ($self:ident . iter . $($call:tt)+) => {
        match $self.iter {
            Some(ref mut iter) => match iter.$($call)+ {
                None => {
                    $self.iter = None;
                    None
                }
                item => item,
            },
            None => None,
        }
    };
}

// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`.
// Implementing this as a directly-expanded macro helps codegen performance.
macro_rules! unchecked {
    ($self:ident) => {
        match $self {
            Fuse { iter: Some(iter) } => iter,
            // SAFETY: the specialized iterator never sets `None`
            Fuse { iter: None } => unsafe { intrinsics::unreachable() },
        }
    };
}

// Any implementation here is made internal to avoid exposing default fns outside this trait
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> Iterator for Fuse<I>
where
    I: Iterator,
{
    type Item = <I as Iterator>::Item;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        FuseImpl::next(self)
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<I::Item> {
        FuseImpl::nth(self, n)
    }

    #[inline]
    fn last(self) -> Option<Self::Item> {
        FuseImpl::last(self)
    }

    #[inline]
    fn count(self) -> usize {
        FuseImpl::count(self)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        FuseImpl::size_hint(self)
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        FuseImpl::try_fold(self, acc, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        FuseImpl::fold(self, acc, fold)
    }

    #[inline]
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        FuseImpl::find(self, predicate)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
    I: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
        FuseImpl::next_back(self)
    }

    #[inline]
    fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
        FuseImpl::nth_back(self, n)
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        FuseImpl::try_rfold(self, acc, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        FuseImpl::rfold(self, acc, fold)
    }

    #[inline]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        FuseImpl::rfind(self, predicate)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
    I: ExactSizeIterator,
{
    fn len(&self) -> usize {
        FuseImpl::len(self)
    }

    fn is_empty(&self) -> bool {
        FuseImpl::is_empty(self)
    }
}

unsafe impl<I> TrustedRandomAccess for Fuse<I>
where
    I: TrustedRandomAccess,
{
    unsafe fn get_unchecked(&mut self, i: usize) -> I::Item {
        match self.iter {
            Some(ref mut iter) => iter.get_unchecked(i),
            // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
            None => intrinsics::unreachable(),
        }
    }

    fn may_have_side_effect() -> bool {
        I::may_have_side_effect()
    }
}

// Fuse specialization trait
#[doc(hidden)]
trait FuseImpl<I> {
    type Item;

    // Functions specific to any normal Iterators
    fn next(&mut self) -> Option<Self::Item>;
    fn nth(&mut self, n: usize) -> Option<Self::Item>;
    fn last(self) -> Option<Self::Item>;
    fn count(self) -> usize;
    fn size_hint(&self) -> (usize, Option<usize>);
    fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>;
    fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc;
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool;

    // Functions specific to DoubleEndedIterators
    fn next_back(&mut self) -> Option<Self::Item>
    where
        I: DoubleEndedIterator;
    fn nth_back(&mut self, n: usize) -> Option<Self::Item>
    where
        I: DoubleEndedIterator;
    fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
        I: DoubleEndedIterator;
    fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
        I: DoubleEndedIterator;
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
        I: DoubleEndedIterator;

    // Functions specific to ExactSizeIterator
    fn len(&self) -> usize
    where
        I: ExactSizeIterator;
    fn is_empty(&self) -> bool
    where
        I: ExactSizeIterator;
}

// General Fuse impl
#[doc(hidden)]
impl<I> FuseImpl<I> for Fuse<I>
where
    I: Iterator,
{
    type Item = <I as Iterator>::Item;

    #[inline]
    default fn next(&mut self) -> Option<<I as Iterator>::Item> {
        fuse!(self.iter.next())
    }

    #[inline]
    default fn nth(&mut self, n: usize) -> Option<I::Item> {
        fuse!(self.iter.nth(n))
    }

    #[inline]
    default fn last(self) -> Option<I::Item> {
        match self.iter {
            Some(iter) => iter.last(),
            None => None,
        }
    }

    #[inline]
    default fn count(self) -> usize {
        match self.iter {
            Some(iter) => iter.count(),
            None => 0,
        }
    }

    #[inline]
    default fn size_hint(&self) -> (usize, Option<usize>) {
        match self.iter {
            Some(ref iter) => iter.size_hint(),
            None => (0, Some(0)),
        }
    }

    #[inline]
    default fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_fold(acc, fold)?;
            self.iter = None;
        }
        Try::from_ok(acc)
    }

    #[inline]
    default fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(iter) = self.iter {
            acc = iter.fold(acc, fold);
        }
        acc
    }

    #[inline]
    default fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        fuse!(self.iter.find(predicate))
    }

    #[inline]
    default fn next_back(&mut self) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        fuse!(self.iter.next_back())
    }

    #[inline]
    default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        fuse!(self.iter.nth_back(n))
    }

    #[inline]
    default fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
        I: DoubleEndedIterator,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_rfold(acc, fold)?;
            self.iter = None;
        }
        Try::from_ok(acc)
    }

    #[inline]
    default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
        I: DoubleEndedIterator,
    {
        if let Some(iter) = self.iter {
            acc = iter.rfold(acc, fold);
        }
        acc
    }

    #[inline]
    default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
        I: DoubleEndedIterator,
    {
        fuse!(self.iter.rfind(predicate))
    }

    #[inline]
    default fn len(&self) -> usize
    where
        I: ExactSizeIterator,
    {
        match self.iter {
            Some(ref iter) => iter.len(),
            None => 0,
        }
    }

    #[inline]
    default fn is_empty(&self) -> bool
    where
        I: ExactSizeIterator,
    {
        match self.iter {
            Some(ref iter) => iter.is_empty(),
            None => true,
        }
    }
}

#[doc(hidden)]
impl<I> FuseImpl<I> for Fuse<I>
where
    I: FusedIterator,
{
    #[inline]
    fn next(&mut self) -> Option<<I as Iterator>::Item> {
        unchecked!(self).next()
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<I::Item> {
        unchecked!(self).nth(n)
    }

    #[inline]
    fn last(self) -> Option<I::Item> {
        unchecked!(self).last()
    }

    #[inline]
    fn count(self) -> usize {
        unchecked!(self).count()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        unchecked!(self).size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        unchecked!(self).try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        unchecked!(self).fold(init, fold)
    }

    #[inline]
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        unchecked!(self).find(predicate)
    }

    #[inline]
    fn next_back(&mut self) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        unchecked!(self).next_back()
    }

    #[inline]
    fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        unchecked!(self).nth_back(n)
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
        I: DoubleEndedIterator,
    {
        unchecked!(self).try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
        I: DoubleEndedIterator,
    {
        unchecked!(self).rfold(init, fold)
    }

    #[inline]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
        I: DoubleEndedIterator,
    {
        unchecked!(self).rfind(predicate)
    }

    #[inline]
    fn len(&self) -> usize
    where
        I: ExactSizeIterator,
    {
        unchecked!(self).len()
    }

    #[inline]
    fn is_empty(&self) -> bool
    where
        I: ExactSizeIterator,
    {
        unchecked!(self).is_empty()
    }
}
<|endoftext|>


<commit_before>use super::*;

use crate::json::JsonEmitter;
use rustc_span::source_map::{FilePathMapping, SourceMap};

use crate::emitter::{ColorConfig, HumanReadableErrorType};
use crate::Handler;
use rustc_serialize::json::decode;
use rustc_span::{BytePos, Span};

use std::str;

#[derive(RustcDecodable, Debug, PartialEq, Eq)]
struct TestData {
    spans: Vec<SpanTestData>,
}

#[derive(RustcDecodable, Debug, PartialEq, Eq)]
struct SpanTestData {
    pub byte_start: u32,
    pub byte_end: u32,
    pub line_start: u32,
    pub column_start: u32,
    pub line_end: u32,
    pub column_end: u32,
}

struct Shared<T> {
    data: Arc<Mutex<T>>,
}

impl<T: Write> Write for Shared<T> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.data.lock().unwrap().write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.data.lock().unwrap().flush()
    }
}

fn with_default_globals(f: impl FnOnce()) {
    let globals = rustc_span::Globals::new(rustc_span::edition::DEFAULT_EDITION);
    rustc_span::GLOBALS.set(&globals, || rustc_span::GLOBALS.set(&globals, f))
}

/// Test the span yields correct positions in JSON.
fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
    let expected_output = TestData { spans: vec![expected_output] };

    with_default_globals(|| {
        let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
        sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());

        let output = Arc::new(Mutex::new(Vec::new()));
        let je = JsonEmitter::new(
            Box::new(Shared { data: output.clone() }),
            None,
            sm,
            true,
            HumanReadableErrorType::Short(ColorConfig::Never),
            false,
        );

        let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
        let handler = Handler::with_emitter(true, None, Box::new(je));
        handler.span_err(span, "foo");

        let bytes = output.lock().unwrap();
        let actual_output = str::from_utf8(&bytes).unwrap();
        let actual_output: TestData = decode(actual_output).unwrap();

        assert_eq!(expected_output, actual_output)
    })
}

#[test]
fn empty() {
    test_positions(
        " ",
        (0, 1),
        SpanTestData {
            byte_start: 0,
            byte_end: 1,
            line_start: 1,
            column_start: 1,
            line_end: 1,
            column_end: 2,
        },
    )
}

#[test]
fn bom() {
    test_positions(
        "\u{feff} ",
        (0, 1),
        SpanTestData {
            byte_start: 3,
            byte_end: 4,
            line_start: 1,
            column_start: 1,
            line_end: 1,
            column_end: 2,
        },
    )
}

#[test]
fn lf_newlines() {
    test_positions(
        "\nmod foo;\nmod bar;\n",
        (5, 12),
        SpanTestData {
            byte_start: 5,
            byte_end: 12,
            line_start: 2,
            column_start: 5,
            line_end: 3,
            column_end: 3,
        },
    )
}

#[test]
fn crlf_newlines() {
    test_positions(
        "\r\nmod foo;\r\nmod bar;\r\n",
        (5, 12),
        SpanTestData {
            byte_start: 6,
            byte_end: 14,
            line_start: 2,
            column_start: 5,
            line_end: 3,
            column_end: 3,
        },
    )
}

#[test]
fn crlf_newlines_with_bom() {
    test_positions(
        "\u{feff}\r\nmod foo;\r\nmod bar;\r\n",
        (5, 12),
        SpanTestData {
            byte_start: 9,
            byte_end: 17,
            line_start: 2,
            column_start: 5,
            line_end: 3,
            column_end: 3,
        },
    )
}

#[test]
fn span_before_crlf() {
    test_positions(
        "foo\r\nbar",
        (2, 3),
        SpanTestData {
            byte_start: 2,
            byte_end: 3,
            line_start: 1,
            column_start: 3,
            line_end: 1,
            column_end: 4,
        },
    )
}

#[test]
fn span_on_crlf() {
    test_positions(
        "foo\r\nbar",
        (3, 4),
        SpanTestData {
            byte_start: 3,
            byte_end: 5,
            line_start: 1,
            column_start: 4,
            line_end: 2,
            column_end: 1,
        },
    )
}

#[test]
fn span_after_crlf() {
    test_positions(
        "foo\r\nbar",
        (4, 5),
        SpanTestData {
            byte_start: 5,
            byte_end: 6,
            line_start: 2,
            column_start: 1,
            line_end: 2,
            column_end: 2,
        },
    )
}
<commit_msg>Fix librustc_errors unit tests.<commit_after>use super::*;

use crate::json::JsonEmitter;
use rustc_span::source_map::{FilePathMapping, SourceMap};

use crate::emitter::{ColorConfig, HumanReadableErrorType};
use crate::Handler;
use rustc_serialize::json::decode;
use rustc_span::{BytePos, Span};

use std::str;

#[derive(RustcDecodable, Debug, PartialEq, Eq)]
struct TestData {
    spans: Vec<SpanTestData>,
}

#[derive(RustcDecodable, Debug, PartialEq, Eq)]
struct SpanTestData {
    pub byte_start: u32,
    pub byte_end: u32,
    pub line_start: u32,
    pub column_start: u32,
    pub line_end: u32,
    pub column_end: u32,
}

struct Shared<T> {
    data: Arc<Mutex<T>>,
}

impl<T: Write> Write for Shared<T> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.data.lock().unwrap().write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.data.lock().unwrap().flush()
    }
}

fn with_default_globals(f: impl FnOnce()) {
    let globals = rustc_span::Globals::new(rustc_span::edition::DEFAULT_EDITION);
    rustc_span::GLOBALS.set(&globals, || rustc_span::GLOBALS.set(&globals, f))
}

/// Test the span yields correct positions in JSON.
fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
    let expected_output = TestData { spans: vec![expected_output] };

    with_default_globals(|| {
        let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
        sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());

        let output = Arc::new(Mutex::new(Vec::new()));
        let je = JsonEmitter::new(
            Box::new(Shared { data: output.clone() }),
            None,
            sm,
            true,
            HumanReadableErrorType::Short(ColorConfig::Never),
            None,
            false,
        );

        let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
        let handler = Handler::with_emitter(true, None, Box::new(je));
        handler.span_err(span, "foo");

        let bytes = output.lock().unwrap();
        let actual_output = str::from_utf8(&bytes).unwrap();
        let actual_output: TestData = decode(actual_output).unwrap();

        assert_eq!(expected_output, actual_output)
    })
}

#[test]
fn empty() {
    test_positions(
        " ",
        (0, 1),
        SpanTestData {
            byte_start: 0,
            byte_end: 1,
            line_start: 1,
            column_start: 1,
            line_end: 1,
            column_end: 2,
        },
    )
}

#[test]
fn bom() {
    test_positions(
        "\u{feff} ",
        (0, 1),
        SpanTestData {
            byte_start: 3,
            byte_end: 4,
            line_start: 1,
            column_start: 1,
            line_end: 1,
            column_end: 2,
        },
    )
}

#[test]
fn lf_newlines() {
    test_positions(
        "\nmod foo;\nmod bar;\n",
        (5, 12),
        SpanTestData {
            byte_start: 5,
            byte_end: 12,
            line_start: 2,
            column_start: 5,
            line_end: 3,
            column_end: 3,
        },
    )
}

#[test]
fn crlf_newlines() {
    test_positions(
        "\r\nmod foo;\r\nmod bar;\r\n",
        (5, 12),
        SpanTestData {
            byte_start: 6,
            byte_end: 14,
            line_start: 2,
            column_start: 5,
            line_end: 3,
            column_end: 3,
        },
    )
}

#[test]
fn crlf_newlines_with_bom() {
    test_positions(
        "\u{feff}\r\nmod foo;\r\nmod bar;\r\n",
        (5, 12),
        SpanTestData {
            byte_start: 9,
            byte_end: 17,
            line_start: 2,
            column_start: 5,
            line_end: 3,
            column_end: 3,
        },
    )
}

#[test]
fn span_before_crlf() {
    test_positions(
        "foo\r\nbar",
        (2, 3),
        SpanTestData {
            byte_start: 2,
            byte_end: 3,
            line_start: 1,
            column_start: 3,
            line_end: 1,
            column_end: 4,
        },
    )
}

#[test]
fn span_on_crlf() {
    test_positions(
        "foo\r\nbar",
        (3, 4),
        SpanTestData {
            byte_start: 3,
            byte_end: 5,
            line_start: 1,
            column_start: 4,
            line_end: 2,
            column_end: 1,
        },
    )
}

#[test]
fn span_after_crlf() {
    test_positions(
        "foo\r\nbar",
        (4, 5),
        SpanTestData {
            byte_start: 5,
            byte_end: 6,
            line_start: 2,
            column_start: 1,
            line_end: 2,
            column_end: 2,
        },
    )
}
<|endoftext|>


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

//! Windows-specific primitives

#[stable(feature = "raw_ext", since = "1.1.0")]

use os::raw::c_void;

#[stable(feature = "raw_ext", since = "1.1.0")] pub type HANDLE = *mut c_void;
#[cfg(target_pointer_width = "32")]
#[stable(feature = "raw_ext", since = "1.1.0")] pub type SOCKET = u32;
#[cfg(target_pointer_width = "64")]
#[stable(feature = "raw_ext", since = "1.1.0")] pub type SOCKET = u64;
<commit_msg>Rollup merge of #27069 - Eljay:fix-raw-attr-typo, r=alexcrichton<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.

//! Windows-specific primitives

#![stable(feature = "raw_ext", since = "1.1.0")]

use os::raw::c_void;

#[stable(feature = "raw_ext", since = "1.1.0")] pub type HANDLE = *mut c_void;
#[cfg(target_pointer_width = "32")]
#[stable(feature = "raw_ext", since = "1.1.0")] pub type SOCKET = u32;
#[cfg(target_pointer_width = "64")]
#[stable(feature = "raw_ext", since = "1.1.0")] pub type SOCKET = u64;
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Our current on-disk metadata format uses a JSON-based structure. We
// are using serde-rs, which allows us to implement serialization (to
// JSON) and deserialization (from JSON) by deriving Serialize and
// Deserialize traits.  But, our in-memory structs are too complex for
// serde to handle, and in any case it's best to not tie our real
// structs to what will be saved on disk. Therefore we have *Save
// structs. These contain simple, serde-friendly data types, and we
// can convert to or from them when saving our current state, or
// restoring state from saved metadata.

use std::collections::HashMap;
use std::path::PathBuf;

use devicemapper::Sectors;

use engine::EngineResult;

/// Implements saving struct data to a serializable form. The form should be
/// sufficient, in conjunction with the environment, to reconstruct the
/// saved struct in all its essentials.
pub trait Recordable<T> {
    fn record(&self) -> EngineResult<T>;
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PoolSave {
    pub name: String,
    pub block_devs: HashMap<String, BlockDevSave>,
    pub flex_devs: FlexDevsSave,
    pub thinpool_dev: ThinPoolDevSave,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct BlockDevSave {
    pub devnode: PathBuf,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct FilesystemSave {
    pub name: String,
    pub uuid: String,
    pub thin_id: u32,
    pub size: Sectors,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct FlexDevsSave {
    pub meta_dev: Vec<(String, Sectors, Sectors)>,
    pub thin_meta_dev: Vec<(String, Sectors, Sectors)>,
    pub thin_data_dev: Vec<(String, Sectors, Sectors)>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ThinPoolDevSave {
    pub data_block_size: u64,
}
<commit_msg>Use relative path for EngineResult import<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Our current on-disk metadata format uses a JSON-based structure. We
// are using serde-rs, which allows us to implement serialization (to
// JSON) and deserialization (from JSON) by deriving Serialize and
// Deserialize traits.  But, our in-memory structs are too complex for
// serde to handle, and in any case it's best to not tie our real
// structs to what will be saved on disk. Therefore we have *Save
// structs. These contain simple, serde-friendly data types, and we
// can convert to or from them when saving our current state, or
// restoring state from saved metadata.

use std::collections::HashMap;
use std::path::PathBuf;

use devicemapper::Sectors;

use super::super::errors::EngineResult;

/// Implements saving struct data to a serializable form. The form should be
/// sufficient, in conjunction with the environment, to reconstruct the
/// saved struct in all its essentials.
pub trait Recordable<T> {
    fn record(&self) -> EngineResult<T>;
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PoolSave {
    pub name: String,
    pub block_devs: HashMap<String, BlockDevSave>,
    pub flex_devs: FlexDevsSave,
    pub thinpool_dev: ThinPoolDevSave,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct BlockDevSave {
    pub devnode: PathBuf,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct FilesystemSave {
    pub name: String,
    pub uuid: String,
    pub thin_id: u32,
    pub size: Sectors,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct FlexDevsSave {
    pub meta_dev: Vec<(String, Sectors, Sectors)>,
    pub thin_meta_dev: Vec<(String, Sectors, Sectors)>,
    pub thin_data_dev: Vec<(String, Sectors, Sectors)>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ThinPoolDevSave {
    pub data_block_size: u64,
}
<|endoftext|>


<commit_before>//! Intrinsics and other functions that the miri engine executes without
//! looking at their MIR.  Intrinsics/functions supported here are shared by CTFE
//! and miri.

use syntax::symbol::Symbol;
use rustc::ty;
use rustc::ty::layout::{LayoutOf, Primitive, Size};
use rustc::mir::BinOp;
use rustc::mir::interpret::{
    EvalResult, EvalErrorKind, Scalar,
};

use super::{
    Machine, PlaceTy, OpTy, EvalContext,
};

fn numeric_intrinsic<'tcx, Tag>(
    name: &str,
    bits: u128,
    kind: Primitive,
) -> EvalResult<'tcx, Scalar<Tag>> {
    let size = match kind {
        Primitive::Int(integer, _) => integer.size(),
        _ => bug!("invalid `{}` argument: {:?}", name, bits),
    };
    let extra = 128 - size.bits() as u128;
    let bits_out = match name {
        "ctpop" => bits.count_ones() as u128,
        "ctlz" => bits.leading_zeros() as u128 - extra,
        "cttz" => (bits << extra).trailing_zeros() as u128 - extra,
        "bswap" => (bits << extra).swap_bytes(),
        "bitreverse" => (bits << extra).reverse_bits(),
        _ => bug!("not a numeric intrinsic: {}", name),
    };
    Ok(Scalar::from_uint(bits_out, size))
}

impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
    /// Returns whether emulation happened.
    pub fn emulate_intrinsic(
        &mut self,
        instance: ty::Instance<'tcx>,
        args: &[OpTy<'tcx, M::PointerTag>],
        dest: PlaceTy<'tcx, M::PointerTag>,
    ) -> EvalResult<'tcx, bool> {
        let substs = instance.substs;

        let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
        match intrinsic_name {
            "min_align_of" => {
                let elem_ty = substs.type_at(0);
                let elem_align = self.layout_of(elem_ty)?.align.abi.bytes();
                let align_val = Scalar::from_uint(elem_align, dest.layout.size);
                self.write_scalar(align_val, dest)?;
            }

            "needs_drop" => {
                let ty = substs.type_at(0);
                let ty_needs_drop = ty.needs_drop(self.tcx.tcx, self.param_env);
                let val = Scalar::from_bool(ty_needs_drop);
                self.write_scalar(val, dest)?;
            }

            "size_of" => {
                let ty = substs.type_at(0);
                let size = self.layout_of(ty)?.size.bytes() as u128;
                let size_val = Scalar::from_uint(size, dest.layout.size);
                self.write_scalar(size_val, dest)?;
            }

            "type_id" => {
                let ty = substs.type_at(0);
                let type_id = self.tcx.type_id_hash(ty) as u128;
                let id_val = Scalar::from_uint(type_id, dest.layout.size);
                self.write_scalar(id_val, dest)?;
            }
            | "ctpop"
            | "cttz"
            | "cttz_nonzero"
            | "ctlz"
            | "ctlz_nonzero"
            | "bswap"
            | "bitreverse" => {
                let ty = substs.type_at(0);
                let layout_of = self.layout_of(ty)?;
                let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?;
                let kind = match layout_of.abi {
                    ty::layout::Abi::Scalar(ref scalar) => scalar.value,
                    _ => Err(::rustc::mir::interpret::EvalErrorKind::TypeNotPrimitive(ty))?,
                };
                let out_val = if intrinsic_name.ends_with("_nonzero") {
                    if bits == 0 {
                        return err!(Intrinsic(format!("{} called on 0", intrinsic_name)));
                    }
                    numeric_intrinsic(intrinsic_name.trim_end_matches("_nonzero"), bits, kind)?
                } else {
                    numeric_intrinsic(intrinsic_name, bits, kind)?
                };
                self.write_scalar(out_val, dest)?;
            }
            | "overflowing_add"
            | "overflowing_sub"
            | "overflowing_mul"
            | "add_with_overflow"
            | "sub_with_overflow"
            | "mul_with_overflow" => {
                let lhs = self.read_immediate(args[0])?;
                let rhs = self.read_immediate(args[1])?;
                let (bin_op, ignore_overflow) = match intrinsic_name {
                    "overflowing_add" => (BinOp::Add, true),
                    "overflowing_sub" => (BinOp::Sub, true),
                    "overflowing_mul" => (BinOp::Mul, true),
                    "add_with_overflow" => (BinOp::Add, false),
                    "sub_with_overflow" => (BinOp::Sub, false),
                    "mul_with_overflow" => (BinOp::Mul, false),
                    _ => bug!("Already checked for int ops")
                };
                if ignore_overflow {
                    self.binop_ignore_overflow(bin_op, lhs, rhs, dest)?;
                } else {
                    self.binop_with_overflow(bin_op, lhs, rhs, dest)?;
                }
            }
            "saturating_add" => {
                let l = self.read_immediate(args[0])?;
                let r = self.read_immediate(args[1])?;
                let (val, overflowed) = self.binary_op_imm(BinOp::Add, l, r)?;
                if overflowed {
                    let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
                    let num_bits = l.layout.size.bits();
                    let val = if l.layout.abi.is_signed() {
                        // For signed addition the saturated value depends on the
                        // sign of either term
                        if first_term & (1 << (num_bits-1)) == 0 {  // signed term is positive
                            Scalar::from_uint((1u128 << (num_bits - 1)) - 1, Size::from_bits(num_bits))
                        } else {  // signed term is negative
                            Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
                        }
                    } else {
                        if num_bits == 128 {
                            Scalar::from_uint(u128::max_value(), Size::from_bits(128))
                        } else {
                            Scalar::from_uint(u128::max_value() & ((1 << num_bits) - 1),
                                Size::from_bits(num_bits))
                        }
                    };
                    self.write_scalar(val, dest)?;
                } else {
                    self.write_scalar(val, dest)?;
                }
            }
            "saturating_sub" => {
                let l = self.read_immediate(args[0])?;
                let r = self.read_immediate(args[1])?;
                let (val, overflowed) = self.binary_op_imm(BinOp::Sub, l, r)?;
                if overflowed {
                    let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
                    let num_bits = l.layout.size.bits();
                    let val = if first_term & (1 << (num_bits-1)) == 0 {  // first term is positive
                        // so overflow is positive
                        Scalar::from_uint((1u128 << (num_bits - 1)) - 1, Size::from_bits(num_bits))
                    } else {
                        // if first term negative, overflow must be negative
                        Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
                    };
                    self.write_scalar(val, dest)?;
                } else {
                    self.write_scalar(val, dest)?;
                }
            }
            "unchecked_shl" | "unchecked_shr" => {
                let l = self.read_immediate(args[0])?;
                let r = self.read_immediate(args[1])?;
                let bin_op = match intrinsic_name {
                    "unchecked_shl" => BinOp::Shl,
                    "unchecked_shr" => BinOp::Shr,
                    _ => bug!("Already checked for int ops")
                };
                let (val, overflowed) = self.binary_op_imm(bin_op, l, r)?;
                if overflowed {
                    let layout = self.layout_of(substs.type_at(0))?;
                    let r_val =  r.to_scalar()?.to_bits(layout.size)?;
                    return err!(Intrinsic(
                        format!("Overflowing shift by {} in {}", r_val, intrinsic_name),
                    ));
                }
                self.write_scalar(val, dest)?;
            }
            "rotate_left" | "rotate_right" => {
                // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
                // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
                let layout = self.layout_of(substs.type_at(0))?;
                let val_bits = self.read_scalar(args[0])?.to_bits(layout.size)?;
                let raw_shift_bits = self.read_scalar(args[1])?.to_bits(layout.size)?;
                let width_bits = layout.size.bits() as u128;
                let shift_bits = raw_shift_bits % width_bits;
                let inv_shift_bits = (width_bits - raw_shift_bits) % width_bits;
                let result_bits = if intrinsic_name == "rotate_left" {
                    (val_bits << shift_bits) | (val_bits >> inv_shift_bits)
                } else {
                    (val_bits >> shift_bits) | (val_bits << inv_shift_bits)
                };
                let truncated_bits = self.truncate(result_bits, layout);
                let result = Scalar::from_uint(truncated_bits, layout.size);
                self.write_scalar(result, dest)?;
            }
            "transmute" => {
                self.copy_op_transmute(args[0], dest)?;
            }

            _ => return Ok(false),
        }

        Ok(true)
    }

    /// "Intercept" a function call because we have something special to do for it.
    /// Returns whether an intercept happened.
    pub fn hook_fn(
        &mut self,
        instance: ty::Instance<'tcx>,
        args: &[OpTy<'tcx, M::PointerTag>],
        dest: Option<PlaceTy<'tcx, M::PointerTag>>,
    ) -> EvalResult<'tcx, bool> {
        let def_id = instance.def_id();
        // Some fn calls are actually BinOp intrinsics
        if let Some((op, oflo)) = self.tcx.is_binop_lang_item(def_id) {
            let dest = dest.expect("128 lowerings can't diverge");
            let l = self.read_immediate(args[0])?;
            let r = self.read_immediate(args[1])?;
            if oflo {
                self.binop_with_overflow(op, l, r, dest)?;
            } else {
                self.binop_ignore_overflow(op, l, r, dest)?;
            }
            return Ok(true);
        } else if Some(def_id) == self.tcx.lang_items().panic_fn() {
            assert!(args.len() == 1);
            // &(&'static str, &'static str, u32, u32)
            let place = self.deref_operand(args[0])?;
            let (msg, file, line, col) = (
                self.mplace_field(place, 0)?,
                self.mplace_field(place, 1)?,
                self.mplace_field(place, 2)?,
                self.mplace_field(place, 3)?,
            );

            let msg_place = self.deref_operand(msg.into())?;
            let msg = Symbol::intern(self.read_str(msg_place)?);
            let file_place = self.deref_operand(file.into())?;
            let file = Symbol::intern(self.read_str(file_place)?);
            let line = self.read_scalar(line.into())?.to_u32()?;
            let col = self.read_scalar(col.into())?.to_u32()?;
            return Err(EvalErrorKind::Panic { msg, file, line, col }.into());
        } else if Some(def_id) == self.tcx.lang_items().begin_panic_fn() {
            assert!(args.len() == 2);
            // &'static str, &(&'static str, u32, u32)
            let msg = args[0];
            let place = self.deref_operand(args[1])?;
            let (file, line, col) = (
                self.mplace_field(place, 0)?,
                self.mplace_field(place, 1)?,
                self.mplace_field(place, 2)?,
            );

            let msg_place = self.deref_operand(msg.into())?;
            let msg = Symbol::intern(self.read_str(msg_place)?);
            let file_place = self.deref_operand(file.into())?;
            let file = Symbol::intern(self.read_str(file_place)?);
            let line = self.read_scalar(line.into())?.to_u32()?;
            let col = self.read_scalar(col.into())?.to_u32()?;
            return Err(EvalErrorKind::Panic { msg, file, line, col }.into());
        } else {
            return Ok(false);
        }
    }
}
<commit_msg>tidy line length split<commit_after>//! Intrinsics and other functions that the miri engine executes without
//! looking at their MIR.  Intrinsics/functions supported here are shared by CTFE
//! and miri.

use syntax::symbol::Symbol;
use rustc::ty;
use rustc::ty::layout::{LayoutOf, Primitive, Size};
use rustc::mir::BinOp;
use rustc::mir::interpret::{
    EvalResult, EvalErrorKind, Scalar,
};

use super::{
    Machine, PlaceTy, OpTy, EvalContext,
};

fn numeric_intrinsic<'tcx, Tag>(
    name: &str,
    bits: u128,
    kind: Primitive,
) -> EvalResult<'tcx, Scalar<Tag>> {
    let size = match kind {
        Primitive::Int(integer, _) => integer.size(),
        _ => bug!("invalid `{}` argument: {:?}", name, bits),
    };
    let extra = 128 - size.bits() as u128;
    let bits_out = match name {
        "ctpop" => bits.count_ones() as u128,
        "ctlz" => bits.leading_zeros() as u128 - extra,
        "cttz" => (bits << extra).trailing_zeros() as u128 - extra,
        "bswap" => (bits << extra).swap_bytes(),
        "bitreverse" => (bits << extra).reverse_bits(),
        _ => bug!("not a numeric intrinsic: {}", name),
    };
    Ok(Scalar::from_uint(bits_out, size))
}

impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
    /// Returns whether emulation happened.
    pub fn emulate_intrinsic(
        &mut self,
        instance: ty::Instance<'tcx>,
        args: &[OpTy<'tcx, M::PointerTag>],
        dest: PlaceTy<'tcx, M::PointerTag>,
    ) -> EvalResult<'tcx, bool> {
        let substs = instance.substs;

        let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
        match intrinsic_name {
            "min_align_of" => {
                let elem_ty = substs.type_at(0);
                let elem_align = self.layout_of(elem_ty)?.align.abi.bytes();
                let align_val = Scalar::from_uint(elem_align, dest.layout.size);
                self.write_scalar(align_val, dest)?;
            }

            "needs_drop" => {
                let ty = substs.type_at(0);
                let ty_needs_drop = ty.needs_drop(self.tcx.tcx, self.param_env);
                let val = Scalar::from_bool(ty_needs_drop);
                self.write_scalar(val, dest)?;
            }

            "size_of" => {
                let ty = substs.type_at(0);
                let size = self.layout_of(ty)?.size.bytes() as u128;
                let size_val = Scalar::from_uint(size, dest.layout.size);
                self.write_scalar(size_val, dest)?;
            }

            "type_id" => {
                let ty = substs.type_at(0);
                let type_id = self.tcx.type_id_hash(ty) as u128;
                let id_val = Scalar::from_uint(type_id, dest.layout.size);
                self.write_scalar(id_val, dest)?;
            }
            | "ctpop"
            | "cttz"
            | "cttz_nonzero"
            | "ctlz"
            | "ctlz_nonzero"
            | "bswap"
            | "bitreverse" => {
                let ty = substs.type_at(0);
                let layout_of = self.layout_of(ty)?;
                let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?;
                let kind = match layout_of.abi {
                    ty::layout::Abi::Scalar(ref scalar) => scalar.value,
                    _ => Err(::rustc::mir::interpret::EvalErrorKind::TypeNotPrimitive(ty))?,
                };
                let out_val = if intrinsic_name.ends_with("_nonzero") {
                    if bits == 0 {
                        return err!(Intrinsic(format!("{} called on 0", intrinsic_name)));
                    }
                    numeric_intrinsic(intrinsic_name.trim_end_matches("_nonzero"), bits, kind)?
                } else {
                    numeric_intrinsic(intrinsic_name, bits, kind)?
                };
                self.write_scalar(out_val, dest)?;
            }
            | "overflowing_add"
            | "overflowing_sub"
            | "overflowing_mul"
            | "add_with_overflow"
            | "sub_with_overflow"
            | "mul_with_overflow" => {
                let lhs = self.read_immediate(args[0])?;
                let rhs = self.read_immediate(args[1])?;
                let (bin_op, ignore_overflow) = match intrinsic_name {
                    "overflowing_add" => (BinOp::Add, true),
                    "overflowing_sub" => (BinOp::Sub, true),
                    "overflowing_mul" => (BinOp::Mul, true),
                    "add_with_overflow" => (BinOp::Add, false),
                    "sub_with_overflow" => (BinOp::Sub, false),
                    "mul_with_overflow" => (BinOp::Mul, false),
                    _ => bug!("Already checked for int ops")
                };
                if ignore_overflow {
                    self.binop_ignore_overflow(bin_op, lhs, rhs, dest)?;
                } else {
                    self.binop_with_overflow(bin_op, lhs, rhs, dest)?;
                }
            }
            "saturating_add" => {
                let l = self.read_immediate(args[0])?;
                let r = self.read_immediate(args[1])?;
                let (val, overflowed) = self.binary_op_imm(BinOp::Add, l, r)?;
                if overflowed {
                    let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
                    let num_bits = l.layout.size.bits();
                    let val = if l.layout.abi.is_signed() {
                        // For signed addition the saturated value depends on the
                        // sign of either term
                        if first_term & (1 << (num_bits-1)) == 0 {  // signed term is positive
                            Scalar::from_uint((1u128 << (num_bits - 1)) - 1,
                                Size::from_bits(num_bits))
                        } else {  // signed term is negative
                            Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
                        }
                    } else {
                        if num_bits == 128 {
                            Scalar::from_uint(u128::max_value(), Size::from_bits(128))
                        } else {
                            Scalar::from_uint(u128::max_value() & ((1 << num_bits) - 1),
                                Size::from_bits(num_bits))
                        }
                    };
                    self.write_scalar(val, dest)?;
                } else {
                    self.write_scalar(val, dest)?;
                }
            }
            "saturating_sub" => {
                let l = self.read_immediate(args[0])?;
                let r = self.read_immediate(args[1])?;
                let (val, overflowed) = self.binary_op_imm(BinOp::Sub, l, r)?;
                if overflowed {
                    let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
                    let num_bits = l.layout.size.bits();
                    let val = if first_term & (1 << (num_bits-1)) == 0 {  // first term is positive
                        // so overflow is positive
                        Scalar::from_uint((1u128 << (num_bits - 1)) - 1, Size::from_bits(num_bits))
                    } else {
                        // if first term negative, overflow must be negative
                        Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
                    };
                    self.write_scalar(val, dest)?;
                } else {
                    self.write_scalar(val, dest)?;
                }
            }
            "unchecked_shl" | "unchecked_shr" => {
                let l = self.read_immediate(args[0])?;
                let r = self.read_immediate(args[1])?;
                let bin_op = match intrinsic_name {
                    "unchecked_shl" => BinOp::Shl,
                    "unchecked_shr" => BinOp::Shr,
                    _ => bug!("Already checked for int ops")
                };
                let (val, overflowed) = self.binary_op_imm(bin_op, l, r)?;
                if overflowed {
                    let layout = self.layout_of(substs.type_at(0))?;
                    let r_val =  r.to_scalar()?.to_bits(layout.size)?;
                    return err!(Intrinsic(
                        format!("Overflowing shift by {} in {}", r_val, intrinsic_name),
                    ));
                }
                self.write_scalar(val, dest)?;
            }
            "rotate_left" | "rotate_right" => {
                // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
                // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
                let layout = self.layout_of(substs.type_at(0))?;
                let val_bits = self.read_scalar(args[0])?.to_bits(layout.size)?;
                let raw_shift_bits = self.read_scalar(args[1])?.to_bits(layout.size)?;
                let width_bits = layout.size.bits() as u128;
                let shift_bits = raw_shift_bits % width_bits;
                let inv_shift_bits = (width_bits - raw_shift_bits) % width_bits;
                let result_bits = if intrinsic_name == "rotate_left" {
                    (val_bits << shift_bits) | (val_bits >> inv_shift_bits)
                } else {
                    (val_bits >> shift_bits) | (val_bits << inv_shift_bits)
                };
                let truncated_bits = self.truncate(result_bits, layout);
                let result = Scalar::from_uint(truncated_bits, layout.size);
                self.write_scalar(result, dest)?;
            }
            "transmute" => {
                self.copy_op_transmute(args[0], dest)?;
            }

            _ => return Ok(false),
        }

        Ok(true)
    }

    /// "Intercept" a function call because we have something special to do for it.
    /// Returns whether an intercept happened.
    pub fn hook_fn(
        &mut self,
        instance: ty::Instance<'tcx>,
        args: &[OpTy<'tcx, M::PointerTag>],
        dest: Option<PlaceTy<'tcx, M::PointerTag>>,
    ) -> EvalResult<'tcx, bool> {
        let def_id = instance.def_id();
        // Some fn calls are actually BinOp intrinsics
        if let Some((op, oflo)) = self.tcx.is_binop_lang_item(def_id) {
            let dest = dest.expect("128 lowerings can't diverge");
            let l = self.read_immediate(args[0])?;
            let r = self.read_immediate(args[1])?;
            if oflo {
                self.binop_with_overflow(op, l, r, dest)?;
            } else {
                self.binop_ignore_overflow(op, l, r, dest)?;
            }
            return Ok(true);
        } else if Some(def_id) == self.tcx.lang_items().panic_fn() {
            assert!(args.len() == 1);
            // &(&'static str, &'static str, u32, u32)
            let place = self.deref_operand(args[0])?;
            let (msg, file, line, col) = (
                self.mplace_field(place, 0)?,
                self.mplace_field(place, 1)?,
                self.mplace_field(place, 2)?,
                self.mplace_field(place, 3)?,
            );

            let msg_place = self.deref_operand(msg.into())?;
            let msg = Symbol::intern(self.read_str(msg_place)?);
            let file_place = self.deref_operand(file.into())?;
            let file = Symbol::intern(self.read_str(file_place)?);
            let line = self.read_scalar(line.into())?.to_u32()?;
            let col = self.read_scalar(col.into())?.to_u32()?;
            return Err(EvalErrorKind::Panic { msg, file, line, col }.into());
        } else if Some(def_id) == self.tcx.lang_items().begin_panic_fn() {
            assert!(args.len() == 2);
            // &'static str, &(&'static str, u32, u32)
            let msg = args[0];
            let place = self.deref_operand(args[1])?;
            let (file, line, col) = (
                self.mplace_field(place, 0)?,
                self.mplace_field(place, 1)?,
                self.mplace_field(place, 2)?,
            );

            let msg_place = self.deref_operand(msg.into())?;
            let msg = Symbol::intern(self.read_str(msg_place)?);
            let file_place = self.deref_operand(file.into())?;
            let file = Symbol::intern(self.read_str(file_place)?);
            let line = self.read_scalar(line.into())?.to_u32()?;
            let col = self.read_scalar(col.into())?.to_u32()?;
            return Err(EvalErrorKind::Panic { msg, file, line, col }.into());
        } else {
            return Ok(false);
        }
    }
}
<|endoftext|>