<commit_before>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 Lumol's contributors — BSD license
use toml::{Table, Value};
use error::{Error, Result};

/// Extract the table at the given `key`, from the `config` TOML table
/// interpreted as a `context`.
pub fn table<'a>(key: &str, config: &'a Table, context: &str) -> Result<&'a Table> {
    let table = try!(config.get(key).ok_or(Error::from(
        format!("Missing '{}' key in {}", key, context)
    )));
    return table.as_table().ok_or(Error::from(
        format!("'{}' must be a table in {}", key, context)
    ));
}

/// Extract the string at the given `key`, from the `config` TOML table
/// interpreted as a `context`
pub fn str<'a>(key: &str, config: &'a Table, context: &str) -> Result<&'a str> {
    let string = try!(config.get(key).ok_or(Error::from(
        format!("Missing '{}' key in {}", key, context)
    )));
    return string.as_str().ok_or(Error::from(
        format!("'{}' must be a string in {}", key, context)
    ));
}

/// Extract a number (integer or float) at the given `key`, from the `config`
/// TOML table interpreted as a `context`
pub fn number(key: &str, config: &Table, context: &str) -> Result<f64> {
    let number = try!(config.get(key).ok_or(Error::from(
        format!("Missing '{}' key in {}", key, context)
    )));
    match *number {
        ::toml::Value::Integer(v) => Ok(v as f64),
        ::toml::Value::Float(v) => Ok(v),
        _ => Err(Error::from(
            format!("'{}' must be a number in {}", key, context)
        ))
    }
}

/// Extract a unsigned integer at the given `key`, from the `config`
/// TOML table interpreted as a `context`
pub fn uint(key: &str, config: &Table, context: &str) -> Result<u64> {
    let number = try!(config.get(key).ok_or(Error::from(
        format!("Missing '{}' key in {}", key, context)
    )));
    match *number {
        ::toml::Value::Integer(v) => {
            if v < 0 {
                Err(Error::from(format!(
                    "'{}' must be a positive integer in {}", key, context)))
            } else {
                Ok(v as u64)
            }
        },
        _ => Err(Error::from(
            format!("'{}' must be an usigned integer in {}", key, context)
        ))
    }
}

/// Extract an array at the given `key`, from the `config` TOML table
/// interpreted as a `context`
pub fn slice<'a>(key: &str, config: &'a Table, context: &str) -> Result<&'a [Value]> {
    let array = try!(config.get(key).ok_or(Error::from(
        format!("Missing '{}' key in {}", key, context)
    )));
    return array.as_slice().ok_or(Error::from(
        format!("'{}' must be an array in {}", key, context)
    ))
}

/// Extract the string 'type' key in a TOML table
pub fn typ<'a>(config: &'a Table, context: &str) -> Result<&'a str> {
    let typ = try!(config.get("type").ok_or(Error::from(
        format!("Missing 'type' key in {}", context)
    )));
    return typ.as_str().ok_or(Error::from(
        format!("'type' key must be a string in {}", context)
    ));
}

<commit_msg>Better error message for uint.<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 Lumol's contributors — BSD license
use toml::{Table, Value};
use error::{Error, Result};

/// Extract the table at the given `key`, from the `config` TOML table
/// interpreted as a `context`.
pub fn table<'a>(key: &str, config: &'a Table, context: &str) -> Result<&'a Table> {
    let table = try!(config.get(key).ok_or(Error::from(
        format!("Missing '{}' key in {}", key, context)
    )));
    return table.as_table().ok_or(Error::from(
        format!("'{}' must be a table in {}", key, context)
    ));
}

/// Extract the string at the given `key`, from the `config` TOML table
/// interpreted as a `context`
pub fn str<'a>(key: &str, config: &'a Table, context: &str) -> Result<&'a str> {
    let string = try!(config.get(key).ok_or(Error::from(
        format!("Missing '{}' key in {}", key, context)
    )));
    return string.as_str().ok_or(Error::from(
        format!("'{}' must be a string in {}", key, context)
    ));
}

/// Extract a number (integer or float) at the given `key`, from the `config`
/// TOML table interpreted as a `context`
pub fn number(key: &str, config: &Table, context: &str) -> Result<f64> {
    let number = try!(config.get(key).ok_or(Error::from(
        format!("Missing '{}' key in {}", key, context)
    )));
    match *number {
        ::toml::Value::Integer(v) => Ok(v as f64),
        ::toml::Value::Float(v) => Ok(v),
        _ => Err(Error::from(
            format!("'{}' must be a number in {}", key, context)
        ))
    }
}

/// Extract a unsigned integer at the given `key`, from the `config`
/// TOML table interpreted as a `context`
pub fn uint(key: &str, config: &Table, context: &str) -> Result<u64> {
    let number = try!(config.get(key).ok_or(Error::from(
        format!("Missing '{}' key in {}", key, context)
    )));
    match *number {
        ::toml::Value::Integer(v) => {
            if v < 0 {
                Err(Error::from(format!(
                    "'{}' must be a positive integer in {}", key, context)))
            } else {
                Ok(v as u64)
            }
        },
        _ => Err(Error::from(
            format!("'{}' must be a positive integer in {}", key, context)
        ))
    }
}

/// Extract an array at the given `key`, from the `config` TOML table
/// interpreted as a `context`
pub fn slice<'a>(key: &str, config: &'a Table, context: &str) -> Result<&'a [Value]> {
    let array = try!(config.get(key).ok_or(Error::from(
        format!("Missing '{}' key in {}", key, context)
    )));
    return array.as_slice().ok_or(Error::from(
        format!("'{}' must be an array in {}", key, context)
    ))
}

/// Extract the string 'type' key in a TOML table
pub fn typ<'a>(config: &'a Table, context: &str) -> Result<&'a str> {
    let typ = try!(config.get("type").ok_or(Error::from(
        format!("Missing 'type' key in {}", context)
    )));
    return typ.as_str().ok_or(Error::from(
        format!("'type' key must be a string in {}", context)
    ));
}

<|endoftext|>


<commit_before>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::result::Result;
use std::collections::HashMap;

use clap::{App, ArgMatches};

use storage::backend::{StorageBackend, StorageBackendError};

pub mod bm;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
    caused_by: Option<Box<Error>>,
}

impl ModuleError {
    pub fn new(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
            caused_by: None,
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        unimplemented!()
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub struct CommandEnv<'a> {
    pub rt:         &'a Runtime<'a>,
    pub bk:         &'a StorageBackend,
    pub matches:    &'a ArgMatches<'a, 'a>,
}

pub type ModuleResult = Result<(), ModuleError>;
pub type CommandResult  = ModuleResult;
pub type CommandMap<'a> = HashMap<&'a str, fn(&Module, CommandEnv) -> CommandResult>;

pub trait Module {

    fn callnames(&self) -> &'static [&'static str];
    fn name(&self) -> &'static str;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

    fn get_commands(&self, rt: &Runtime) -> CommandMap;

}

<commit_msg>Implement StorageBackendError::cause()<commit_after>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::result::Result;
use std::collections::HashMap;

use clap::{App, ArgMatches};

use storage::backend::{StorageBackend, StorageBackendError};

pub mod bm;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
    caused_by: Option<Box<Error>>,
}

impl ModuleError {
    pub fn new(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
            caused_by: None,
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        self.caused_by.as_ref().map(|e| &**e)
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub struct CommandEnv<'a> {
    pub rt:         &'a Runtime<'a>,
    pub bk:         &'a StorageBackend,
    pub matches:    &'a ArgMatches<'a, 'a>,
}

pub type ModuleResult = Result<(), ModuleError>;
pub type CommandResult  = ModuleResult;
pub type CommandMap<'a> = HashMap<&'a str, fn(&Module, CommandEnv) -> CommandResult>;

pub trait Module {

    fn callnames(&self) -> &'static [&'static str];
    fn name(&self) -> &'static str;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

    fn get_commands(&self, rt: &Runtime) -> CommandMap;

}

<|endoftext|>


<commit_before>use {Style, Sign, Float};
use ramp::Int;

use std::i64;
use std::ops::{Mul, MulAssign, Div, DivAssign};

impl<'a> Mul<&'a Float> for Float {
    type Output = Float;

    fn mul(mut self, other: &'a Float) -> Float {
        self.debug_assert_valid();
        other.debug_assert_valid();
        assert_eq!(self.prec, other.prec);
        let prec = self.prec;

        match (self.style, other.style) {
            (Style::NaN, _) | (_, Style::NaN) => Float::nan(prec),
            // 0.0 * inf, inf * 0.0 are NaN
            (Style::Infinity, Style::Zero) | (Style::Zero, Style::Infinity) => {
                Float::nan(prec)
            }
            (Style::Infinity, _) | (_, Style::Infinity) => {
                Float::inf(prec, self.sign ^ other.sign)
            }
            (Style::Zero, _) | (_, Style::Zero) => {
                // FIXME (#3): need to get the right sign
                Float::zero(prec, Sign::Pos)
            }
            (Style::Normal, Style::Normal) => {
                if self.exp > 0 && other.exp > i64::MAX - self.exp {
                    // overflow
                    return Float::inf(prec, self.sign ^ other.sign)
                } else if self.exp < 0 && other.exp < i64::MIN - self.exp {
                    // FIXME (#1): handle underflow
                    unimplemented!()
                }

                self.exp += other.exp;
                self.signif *= &other.signif;
                self.sign = self.sign ^ other.sign;

                let bits = self.signif.bit_length();
                let shift = bits - prec;

                let ulp_bit = self.signif.bit(shift);
                let half_ulp_bit = self.signif.bit(shift - 1);
                let has_trailing_ones = self.signif.trailing_zeros() < shift - 1;

                self.signif >>= shift as usize;
                self.exp += shift as i64 - (prec - 1) as i64;

                let round = half_ulp_bit && (ulp_bit || has_trailing_ones);

                if round {
                    self.add_ulp(prec);
                }
                self
            }
        }
    }
}

impl Mul<Float> for Float {
    type Output = Float;

    fn mul(self, other: Float) -> Float {
        // FIXME (#6): this could/should decide to use the Normal one
        // with the largest backing storage as the by-value arg
        // (i.e. reuse the biggest allocation)
        self * &other
    }
}

impl<'a> Mul<Float> for &'a Float {
    type Output = Float;

    fn mul(self, other: Float) -> Float {
        other * self
    }
}

impl<'a> Mul<&'a Float> for &'a Float {
    type Output = Float;

    fn mul(self, other: &'a Float) -> Float {
        // FIXME: this could clone and reserve enough space for the
        // intermediate multiplication, to avoid needing to realloc
        self.clone() * other
    }
}

impl MulAssign<Float> for Float {
    fn mul_assign(&mut self, other: Float) {
        self.modify(|x| x * other)
    }
}

impl<'a> MulAssign<&'a Float> for Float {
    fn mul_assign(&mut self, other: &'a Float) {
        self.modify(|x| x * other)
    }
}

impl<'a> Div<&'a Float> for Float {
    type Output = Float;

    fn div(mut self, other: &'a Float) -> Float {
        self.debug_assert_valid();
        other.debug_assert_valid();
        assert_eq!(self.prec, other.prec);
        let prec = self.prec;

        match (self.style, other.style) {
            (Style::NaN, _) | (_, Style::NaN) => Float::nan(prec),
            // 0.0 / 0.0 is NaN
            (Style::Zero, Style::Zero) => Float::nan(prec),
            // 0.0 / x == 0.0
            (Style::Zero, _) => Float::zero(prec, self.sign),
            // x / 0.0 == inf
            (_, Style::Zero) => Float::inf(prec, other.sign),
            (Style::Infinity, Style::Infinity) => {
                Float::nan(prec)
            }
            // x / inf == 0.0
            (_, Style::Infinity) => Float::zero(prec, other.sign),
            // inf / x == inf (x != 0)
            (Style::Infinity, _) => {
                self.sign = self.sign ^ other.sign;
                self
            }
            (Style::Normal, Style::Normal) => {
                if self.exp > 0 && -other.exp > i64::MAX - self.exp {
                    // overflow
                    return Float::inf(prec, self.sign ^ other.sign)
                } else if self.exp < 0 && -other.exp < i64::MIN - self.exp {
                    // FIXME (#1): handle underflow
                    unimplemented!()
                }

                let sign = self.sign ^ other.sign;

                let mut n = self.signif;
                let m = &other.signif;
                let c = if n < *m { 0 } else { 1 };
                let exp = self.exp + -other.exp - 1 + c;

                if c == 0 {
                    n <<= 1;
                }

                let mut q = Int::from(1);
                let mut r = n - m;

                for _ in 0..prec {
                    let t = (r << 1) - m;
                    if t < 0 {
                        q <<= 1;
                        r = t + m;
                    } else {
                        q <<= 1;
                        q += 1;
                        r = t;
                    }
                }
                let round = q.bit(0);
                let signif = (q >> 1) + (round as i32);

                Float {
                    prec: prec,
                    sign: sign,
                    exp: exp,
                    signif: signif,
                    style: Style::Normal,
                }
            }
        }
    }
}

impl Div<Float> for Float {
    type Output = Float;

    fn div(self, other: Float) -> Float {
        self / &other
    }
}
impl<'a> Div<Float> for &'a Float {
    type Output = Float;

    fn div(self, other: Float) -> Float {
        self.clone() / &other
    }
}
impl<'a> Div<&'a Float> for &'a Float {
    type Output = Float;

    fn div(self, other: &'a Float) -> Float {
        self.clone() / other
    }
}

impl DivAssign<Float> for Float {
    fn div_assign(&mut self, other: Float) {
        self.modify(|x| x / other)
    }
}
impl<'a> DivAssign<&'a Float> for Float {
    fn div_assign(&mut self, other: &'a Float) {
        self.modify(|x| x / other)
    }
}
<commit_msg>Massively(asymptotically?) optimise division.<commit_after>use {Style, Sign, Float};
use std::i64;
use std::ops::{Mul, MulAssign, Div, DivAssign};

use ramp::ll::limb::Limb;

impl<'a> Mul<&'a Float> for Float {
    type Output = Float;

    fn mul(mut self, other: &'a Float) -> Float {
        self.debug_assert_valid();
        other.debug_assert_valid();
        assert_eq!(self.prec, other.prec);
        let prec = self.prec;

        match (self.style, other.style) {
            (Style::NaN, _) | (_, Style::NaN) => Float::nan(prec),
            // 0.0 * inf, inf * 0.0 are NaN
            (Style::Infinity, Style::Zero) | (Style::Zero, Style::Infinity) => {
                Float::nan(prec)
            }
            (Style::Infinity, _) | (_, Style::Infinity) => {
                Float::inf(prec, self.sign ^ other.sign)
            }
            (Style::Zero, _) | (_, Style::Zero) => {
                // FIXME (#3): need to get the right sign
                Float::zero(prec, Sign::Pos)
            }
            (Style::Normal, Style::Normal) => {
                if self.exp > 0 && other.exp > i64::MAX - self.exp {
                    // overflow
                    return Float::inf(prec, self.sign ^ other.sign)
                } else if self.exp < 0 && other.exp < i64::MIN - self.exp {
                    // FIXME (#1): handle underflow
                    unimplemented!()
                }

                self.exp += other.exp;
                self.signif *= &other.signif;
                self.sign = self.sign ^ other.sign;

                let bits = self.signif.bit_length();
                let shift = bits - prec;

                let ulp_bit = self.signif.bit(shift);
                let half_ulp_bit = self.signif.bit(shift - 1);
                let has_trailing_ones = self.signif.trailing_zeros() < shift - 1;

                self.signif >>= shift as usize;
                self.exp += shift as i64 - (prec - 1) as i64;

                let round = half_ulp_bit && (ulp_bit || has_trailing_ones);

                if round {
                    self.add_ulp(prec);
                }
                self
            }
        }
    }
}

impl Mul<Float> for Float {
    type Output = Float;

    fn mul(self, other: Float) -> Float {
        // FIXME (#6): this could/should decide to use the Normal one
        // with the largest backing storage as the by-value arg
        // (i.e. reuse the biggest allocation)
        self * &other
    }
}

impl<'a> Mul<Float> for &'a Float {
    type Output = Float;

    fn mul(self, other: Float) -> Float {
        other * self
    }
}

impl<'a> Mul<&'a Float> for &'a Float {
    type Output = Float;

    fn mul(self, other: &'a Float) -> Float {
        // FIXME: this could clone and reserve enough space for the
        // intermediate multiplication, to avoid needing to realloc
        self.clone() * other
    }
}

impl MulAssign<Float> for Float {
    fn mul_assign(&mut self, other: Float) {
        self.modify(|x| x * other)
    }
}

impl<'a> MulAssign<&'a Float> for Float {
    fn mul_assign(&mut self, other: &'a Float) {
        self.modify(|x| x * other)
    }
}

impl<'a> Div<&'a Float> for Float {
    type Output = Float;

    fn div(mut self, other: &'a Float) -> Float {
        self.debug_assert_valid();
        other.debug_assert_valid();
        assert_eq!(self.prec, other.prec);
        let prec = self.prec;

        match (self.style, other.style) {
            (Style::NaN, _) | (_, Style::NaN) => Float::nan(prec),
            // 0.0 / 0.0 is NaN
            (Style::Zero, Style::Zero) => Float::nan(prec),
            // 0.0 / x == 0.0
            (Style::Zero, _) => Float::zero(prec, self.sign),
            // x / 0.0 == inf
            (_, Style::Zero) => Float::inf(prec, other.sign),
            (Style::Infinity, Style::Infinity) => {
                Float::nan(prec)
            }
            // x / inf == 0.0
            (_, Style::Infinity) => Float::zero(prec, other.sign),
            // inf / x == inf (x != 0)
            (Style::Infinity, _) => {
                self.sign = self.sign ^ other.sign;
                self
            }
            (Style::Normal, Style::Normal) => {
                if self.exp > 0 && -other.exp > i64::MAX - self.exp {
                    // overflow
                    return Float::inf(prec, self.sign ^ other.sign)
                } else if self.exp < 0 && -other.exp < i64::MIN - self.exp {
                    // FIXME (#1): handle underflow
                    unimplemented!()
                }

                let exp = self.exp - other.exp - (self.signif < other.signif) as i64;
                let sign = self.sign ^ other.sign;

                // we compute (m1 * 2**x) / m2 for some x >= p + 1, to
                // ensure we get the full significand, and the
                // rounding bit, and can use the remainder to check
                // for sticky bits.

                // round-up so that we're shifting by whole limbs,
                // ensuring there's no need for sub-limb shifts.
                let shift = (prec as usize  + 1 + Limb::BITS - 1) / Limb::BITS * Limb::BITS;

                self.signif <<= shift;

                let (mut q, r) = self.signif.divmod(&other.signif);

                let bits = q.bit_length();
                assert!(bits >= prec + 1);
                let unshift = bits - prec;

                let ulp_bit = q.bit(unshift);
                let half_ulp_bit = q.bit(unshift - 1);
                let has_trailing_ones = r != 0 || q.trailing_zeros() < unshift - 1;

                q >>= unshift as usize;

                let mut ret = Float {
                    prec: prec,
                    sign: sign,
                    exp: exp,
                    signif: q,
                    style: Style::Normal,
                };

                if half_ulp_bit && (ulp_bit || has_trailing_ones) {
                    ret.add_ulp(prec);
                }

                ret
            }
        }
    }
}

impl Div<Float> for Float {
    type Output = Float;

    fn div(self, other: Float) -> Float {
        self / &other
    }
}
impl<'a> Div<Float> for &'a Float {
    type Output = Float;

    fn div(self, other: Float) -> Float {
        self.clone() / &other
    }
}
impl<'a> Div<&'a Float> for &'a Float {
    type Output = Float;

    fn div(self, other: &'a Float) -> Float {
        self.clone() / other
    }
}

impl DivAssign<Float> for Float {
    fn div_assign(&mut self, other: Float) {
        self.modify(|x| x / other)
    }
}
impl<'a> DivAssign<&'a Float> for Float {
    fn div_assign(&mut self, other: &'a Float) {
        self.modify(|x| x / other)
    }
}
<|endoftext|>


<commit_before>/// Used for immutable dereferencing operations, like `*v`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
///
/// Implementing `Deref` for smart pointers makes accessing the data behind them
/// convenient, which is why they implement `Deref`. On the other hand, the
/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
/// accommodate smart pointers. Because of this, **`Deref` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
///
/// * In immutable contexts, `*x` on non-pointer types is equivalent to
///   `*Deref::deref(&x)`.
/// * Values of type `&T` are coerced to values of type `&U`
/// * `T` implicitly implements all the (immutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`DerefMut`]: trait.DerefMut.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is accessible by dereferencing the
/// struct.
///
/// ```
/// use std::ops::Deref;
///
/// struct DerefExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// let x = DerefExample { value: 'a' };
/// assert_eq!('a', *x);
/// ```
#[lang = "deref"]
#[doc(alias = "*")]
#[doc(alias = "&*")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Deref {
    /// The resulting type after dereferencing.
    #[stable(feature = "rust1", since = "1.0.0")]
    type Target: ?Sized;

    /// Dereferences the value.
    #[must_use]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref(&self) -> &Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for &T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for &mut T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

/// Used for mutable dereferencing operations, like in `*v = 1;`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
///
/// Implementing `DerefMut` for smart pointers makes mutating the data behind
/// them convenient, which is why they implement `DerefMut`. On the other hand,
/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
/// accommodate smart pointers. Because of this, **`DerefMut` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `DerefMut` is invoked
/// implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
/// then:
///
/// * In mutable contexts, `*x` on non-pointer types is equivalent to
///   `*Deref::deref(&x)`.
/// * Values of type `&mut T` are coerced to values of type `&mut U`
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`Deref`]: trait.Deref.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is modifiable by dereferencing the
/// struct.
///
/// ```
/// use std::ops::{Deref, DerefMut};
///
/// struct DerefMutExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefMutExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// impl<T> DerefMut for DerefMutExample<T> {
///     fn deref_mut(&mut self) -> &mut T {
///         &mut self.value
///     }
/// }
///
/// let mut x = DerefMutExample { value: 'a' };
/// *x = 'b';
/// assert_eq!('b', *x);
/// ```
#[lang = "deref_mut"]
#[doc(alias = "*")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DerefMut: Deref {
    /// Mutably dereferences the value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref_mut(&mut self) -> &mut Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for &mut T {
    fn deref_mut(&mut self) -> &mut T { *self }
}

/// Indicates that a struct can be used as a method receiver, without the
/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
/// `Rc<T>`, `&T`, and `Pin<P>`.
#[cfg_attr(not(stage0), lang = "receiver")]
#[unstable(feature = "receiver_trait", issue = "0")]
#[doc(hidden)]
pub trait Receiver {
    // Empty.
}

#[unstable(feature = "receiver_trait", issue = "0")]
impl<T: ?Sized> Receiver for &T {}

#[unstable(feature = "receiver_trait", issue = "0")]
impl<T: ?Sized> Receiver for &mut T {}
<commit_msg>Auto merge of #57826 - danielhenrymantilla:master, r=Centril<commit_after>/// Used for immutable dereferencing operations, like `*v`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
///
/// Implementing `Deref` for smart pointers makes accessing the data behind them
/// convenient, which is why they implement `Deref`. On the other hand, the
/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
/// accommodate smart pointers. Because of this, **`Deref` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
///
/// * In immutable contexts, `*x` on non-pointer types is equivalent to
///   `*Deref::deref(&x)`.
/// * Values of type `&T` are coerced to values of type `&U`
/// * `T` implicitly implements all the (immutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`DerefMut`]: trait.DerefMut.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is accessible by dereferencing the
/// struct.
///
/// ```
/// use std::ops::Deref;
///
/// struct DerefExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// let x = DerefExample { value: 'a' };
/// assert_eq!('a', *x);
/// ```
#[lang = "deref"]
#[doc(alias = "*")]
#[doc(alias = "&*")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Deref {
    /// The resulting type after dereferencing.
    #[stable(feature = "rust1", since = "1.0.0")]
    type Target: ?Sized;

    /// Dereferences the value.
    #[must_use]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref(&self) -> &Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for &T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for &mut T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

/// Used for mutable dereferencing operations, like in `*v = 1;`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
///
/// Implementing `DerefMut` for smart pointers makes mutating the data behind
/// them convenient, which is why they implement `DerefMut`. On the other hand,
/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
/// accommodate smart pointers. Because of this, **`DerefMut` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `DerefMut` is invoked
/// implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
/// then:
///
/// * In mutable contexts, `*x` on non-pointer types is equivalent to
///   `*DerefMut::deref_mut(&mut x)`.
/// * Values of type `&mut T` are coerced to values of type `&mut U`
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`Deref`]: trait.Deref.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is modifiable by dereferencing the
/// struct.
///
/// ```
/// use std::ops::{Deref, DerefMut};
///
/// struct DerefMutExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefMutExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// impl<T> DerefMut for DerefMutExample<T> {
///     fn deref_mut(&mut self) -> &mut T {
///         &mut self.value
///     }
/// }
///
/// let mut x = DerefMutExample { value: 'a' };
/// *x = 'b';
/// assert_eq!('b', *x);
/// ```
#[lang = "deref_mut"]
#[doc(alias = "*")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DerefMut: Deref {
    /// Mutably dereferences the value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref_mut(&mut self) -> &mut Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for &mut T {
    fn deref_mut(&mut self) -> &mut T { *self }
}

/// Indicates that a struct can be used as a method receiver, without the
/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
/// `Rc<T>`, `&T`, and `Pin<P>`.
#[cfg_attr(not(stage0), lang = "receiver")]
#[unstable(feature = "receiver_trait", issue = "0")]
#[doc(hidden)]
pub trait Receiver {
    // Empty.
}

#[unstable(feature = "receiver_trait", issue = "0")]
impl<T: ?Sized> Receiver for &T {}

#[unstable(feature = "receiver_trait", issue = "0")]
impl<T: ?Sized> Receiver for &mut T {}
<|endoftext|>


<commit_before>use bindings::*;
use function::Function;
use value::Value;
use types::*;
use util::NativeRef;
/// A type that can be compiled into a LibJIT representation
pub trait Compilable {
	/// Get a JIT representation of this value
	fn compile(&self, func:&Function) -> Value;
}
#[cfg(test)]
fn test_compile<T:Compilable+Default>(kind:TypeKind) {
	with_empty_func(|_, func| {
		let pval:T = Default::default();
		let val = pval.compile(func);
		assert!(val.get_type().get_kind().contains(kind));
	})
}
impl Compilable for () {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_void_ptr, 0))
		}
	}
}
#[test]
fn test_compile_unit() {
	test_compile::<()>(Void)
}
impl Compilable for f64 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_float64_constant(func.as_ptr(), jit_type_float64, *self) )
		}
	}
}
#[test]
fn test_compile_f64() {
	test_compile::<f64>(Float64)
}
impl Compilable for f32 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_float32_constant(func.as_ptr(), jit_type_float32, *self) )
		}
	}
}
#[test]
fn test_compile_f32() {
	test_compile::<f32>(Float32)
}
impl Compilable for int {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_long_constant(func.as_ptr(), jit_type_nint, *self as i64) )
		}
	}
}
#[test]
fn test_compile_int() {
	test_compile::<int>(NInt)
}
impl Compilable for uint {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_nuint, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_uint() {
	test_compile::<uint>(NUInt)
}
impl Compilable for i32 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_int, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_i32() {
	test_compile::<i32>(Int)
}
impl Compilable for u32 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_uint, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_u32() {
	test_compile::<u32>(UInt)
}
impl Compilable for i16 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_short, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_i16() {
	test_compile::<i16>(Short)
}
impl Compilable for u16 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_ushort, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_u16() {
	test_compile::<u16>(UShort)
}
impl Compilable for i8 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_sbyte, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_i8() {
	test_compile::<i8>(SByte)
}
impl Compilable for u8 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_ubyte, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_u8() {
	test_compile::<u8>(UByte)
}
impl Compilable for bool {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_sys_bool, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_bool() {
	test_compile::<bool>(SysBool)
}
impl Compilable for char {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_sys_char, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_char() {
	test_compile::<char>(SysChar)
}
impl<'t> Compilable for &'t str {
	fn compile(&self, func:&Function) -> Value {
		let cstring_t = Types::get_cstring();
		let strlen_i = (self.len() as i32).compile(func);
		let bufptr = func.create_value(&cstring_t);
		func.insn_store(&bufptr, &func.insn_alloca(&strlen_i));
		for i in range(0, self.len()) {
			let char_i = self.char_at(i).compile(func);
			func.insn_store_relative(&bufptr, i as int, &char_i);
		}
		let null_term = '\0'.compile(func);
		func.insn_store_relative(&bufptr, self.len() as int, &null_term);
		bufptr
	}
}
impl Compilable for String {
	fn compile(&self, func:&Function) -> Value {
		self.as_slice().compile(func)
	}
}<commit_msg>Fix tests<commit_after>use bindings::*;
use function::Function;
use value::Value;
use types::*;
use util::NativeRef;
use std::default::Default;
/// A type that can be compiled into a LibJIT representation
pub trait Compilable {
	/// Get a JIT representation of this value
	fn compile(&self, func:&Function) -> Value;
}
#[cfg(test)]
fn test_compile<T:Compilable+Default>(kind:TypeKind) {
	::with_empty_func(|_, func| {
		let pval:T = Default::default();
		let val = pval.compile(func);
		assert!(val.get_type().get_kind().contains(kind));
	})
}
impl Compilable for () {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_void_ptr, 0))
		}
	}
}
#[test]
fn test_compile_unit() {
	test_compile::<()>(Void)
}
impl Compilable for f64 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_float64_constant(func.as_ptr(), jit_type_float64, *self) )
		}
	}
}
#[test]
fn test_compile_f64() {
	test_compile::<f64>(Float64)
}
impl Compilable for f32 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_float32_constant(func.as_ptr(), jit_type_float32, *self) )
		}
	}
}
#[test]
fn test_compile_f32() {
	test_compile::<f32>(Float32)
}
impl Compilable for int {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_long_constant(func.as_ptr(), jit_type_nint, *self as i64) )
		}
	}
}
#[test]
fn test_compile_int() {
	test_compile::<int>(NInt)
}
impl Compilable for uint {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_nuint, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_uint() {
	test_compile::<uint>(NUInt)
}
impl Compilable for i32 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_int, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_i32() {
	test_compile::<i32>(Int)
}
impl Compilable for u32 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_uint, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_u32() {
	test_compile::<u32>(UInt)
}
impl Compilable for i16 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_short, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_i16() {
	test_compile::<i16>(Short)
}
impl Compilable for u16 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_ushort, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_u16() {
	test_compile::<u16>(UShort)
}
impl Compilable for i8 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_sbyte, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_i8() {
	test_compile::<i8>(SByte)
}
impl Compilable for u8 {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_ubyte, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_u8() {
	test_compile::<u8>(UByte)
}
impl Compilable for bool {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_sys_bool, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_bool() {
	test_compile::<bool>(SysBool)
}
impl Compilable for char {
	fn compile(&self, func:&Function) -> Value {
		unsafe {
			NativeRef::from_ptr(jit_value_create_nint_constant(func.as_ptr(), jit_type_sys_char, *self as jit_nint) )
		}
	}
}
#[test]
fn test_compile_char() {
	test_compile::<char>(SysChar)
}
impl<'t> Compilable for &'t str {
	fn compile(&self, func:&Function) -> Value {
		let cstring_t = Types::get_cstring();
		let strlen_i = (self.len() as i32).compile(func);
		let bufptr = func.create_value(&cstring_t);
		func.insn_store(&bufptr, &func.insn_alloca(&strlen_i));
		for i in range(0, self.len()) {
			let char_i = self.char_at(i).compile(func);
			func.insn_store_relative(&bufptr, i as int, &char_i);
		}
		let null_term = '\0'.compile(func);
		func.insn_store_relative(&bufptr, self.len() as int, &null_term);
		bufptr
	}
}
impl Compilable for String {
	fn compile(&self, func:&Function) -> Value {
		self.as_slice().compile(func)
	}
}<|endoftext|>


<commit_before>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! GPermission — An object representing the permission to perform a certain action

use glib_container::GlibContainer;
use ffi;

pub struct Permission {
    pointer: *mut ffi::GPermission
}

impl Permission {
    pub fn get_allowed(&self) -> bool {
        match unsafe { ffi::g_permission_get_allowed(self.pointer) } {
            0 => false,
            _ => true
        }
    }

    pub fn get_can_acquire(&self) -> bool {
        match unsafe { ffi::g_permission_get_can_acquire(self.pointer) } {
            0 => false,
            _ => true
        }
    }

    pub fn get_can_release(&self) -> bool {
        match unsafe { ffi::g_permission_get_can_release(self.pointer) } {
            0 => false,
            _ => true
        }
    }

    pub fn impl_update(&self, allowed: bool, can_acquire: bool, can_release: bool) {
        unsafe { ffi::g_permission_impl_update(self.pointer,
            if allowed == true { 1 } else { 0 },
            if can_acquire == true { 1 } else { 0 },
            if can_release == true { 1 } else { 0 }) }
    }
}

/*impl Drop for Permission {
    fn drop(&mut self) {
        self.release();
    }
}*/

impl GlibContainer<*mut ffi::GPermission> for Permission {
    fn wrap(pointer: *mut ffi::GPermission) -> Permission {
        Permission {
            pointer: pointer
        }
    }

    fn unwrap(&self) -> *mut ffi::GPermission {
        self.pointer
    }
}<commit_msg>Add documentation<commit_after>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! GPermission — An object representing the permission to perform a certain action

use glib_container::GlibContainer;
use ffi;

pub struct Permission {
    pointer: *mut ffi::GPermission
}

impl Permission {
    /// Gets the value of the 'allowed' property. This property is true if the caller
    /// currently has permission to perform the action that permission represents the
    /// permission to perform.
    pub fn get_allowed(&self) -> bool {
        match unsafe { ffi::g_permission_get_allowed(self.pointer) } {
            0 => false,
            _ => true
        }
    }

    /// Gets the value of the 'can-acquire' property. This property is true if it is
    /// generally possible to acquire the permission by calling g_permission_acquire().
    pub fn get_can_acquire(&self) -> bool {
        match unsafe { ffi::g_permission_get_can_acquire(self.pointer) } {
            0 => false,
            _ => true
        }
    }

    /// Gets the value of the 'can-release' property. This property is true if it is
    /// generally possible to release the permission by calling g_permission_release().
    pub fn get_can_release(&self) -> bool {
        match unsafe { ffi::g_permission_get_can_release(self.pointer) } {
            0 => false,
            _ => true
        }
    }

    /// This function is called by the GPermission implementation to update the properties
    /// of the permission. You should never call this function except from a GPermission
    /// implementation.
    ///
    /// GObject notify signals are generated, as appropriate.
    pub fn impl_update(&self, allowed: bool, can_acquire: bool, can_release: bool) {
        unsafe { ffi::g_permission_impl_update(self.pointer,
            if allowed == true { 1 } else { 0 },
            if can_acquire == true { 1 } else { 0 },
            if can_release == true { 1 } else { 0 }) }
    }
}

/*impl Drop for Permission {
    fn drop(&mut self) {
        self.release();
    }
}*/

impl GlibContainer<*mut ffi::GPermission> for Permission {
    fn wrap(pointer: *mut ffi::GPermission) -> Permission {
        Permission {
            pointer: pointer
        }
    }

    fn unwrap(&self) -> *mut ffi::GPermission {
        self.pointer
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * TODO: automatically add the model() method with a () return type when it is not found?
 * FIXME: Doing model.text.push_str() will not cause a set_text() to be added.
 * TODO: think about conditions and loops (widget-list).
 */

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate quote;
extern crate syn;

mod adder;
mod gen;
mod parser;
mod walker;

use std::collections::{HashMap, HashSet};

use adder::{Adder, Property};
use gen::gen;
use parser::Widget::{Gtk, Relm};
use parser::{Widget, parse};
use quote::{Tokens, ToTokens};
use syn::{Delimited, FunctionRetTy, Ident, ImplItem, Mac, MethodSig, TokenTree, parse_expr, parse_item};
use syn::FnArg::Captured;
use syn::fold::Folder;
use syn::ImplItemKind::{Const, Macro, Method, Type};
use syn::ItemKind::Impl;
use syn::Ty;
use syn::visit::Visitor;
use walker::ModelVariableVisitor;

type PropertyModelMap = HashMap<Ident, HashSet<Property>>;

#[derive(Debug)]
struct State {
    model_type: Option<ImplItem>,
    msg_type: Option<ImplItem>,
    properties_model_map: Option<PropertyModelMap>,
    root_method: Option<ImplItem>,
    root_type: Option<ImplItem>,
    root_widget: Option<Ident>,
    root_widget_expr: Option<Tokens>,
    root_widget_type: Option<Ident>,
    update_method: Option<ImplItem>,
    view_macro: Option<Mac>,
    widget_model_type: Option<Ty>,
    widget_msg_type: Option<Ty>,
    widgets: HashMap<Ident, Ident>, // Map widget ident to widget type.
}

struct View {
    container_impl: Tokens,
    item: ImplItem,
    properties_model_map: PropertyModelMap,
    relm_widgets: HashMap<Ident, Ident>,
    widget: Widget,
}

impl State {
    fn new() -> Self {
        State {
            root_method: None,
            root_type: None,
            model_type: None,
            msg_type: None,
            properties_model_map: None,
            root_widget: None,
            root_widget_expr: None,
            root_widget_type: None,
            update_method: None,
            view_macro: None,
            widget_model_type: None,
            widget_msg_type: None,
            widgets: HashMap::new(),
        }
    }
}

pub fn gen_widget(input: Tokens) -> Tokens {
    let source = input.to_string();
    let mut ast = parse_item(&source).expect("parse_item() in gen_widget()");
    if let Impl(unsafety, polarity, generics, path, typ, items) = ast.node {
        let name = get_name(&typ);
        let mut new_items = vec![];
        let mut state = State::new();
        for item in items {
            let i = item.clone();
            match item.node {
                Const(_, _) => panic!("Unexpected const item"),
                Macro(mac) => state.view_macro = Some(mac),
                Method(sig, _) => {
                    match item.ident.to_string().as_ref() {
                        "root" => state.root_method = Some(i),
                        "model" => {
                            state.widget_model_type = Some(get_return_type(sig));
                            new_items.push(i);
                        },
                        "init_view" | "subscriptions" | "update_command" => new_items.push(i),
                        "update" => {
                            state.widget_msg_type = Some(get_second_param_type(&sig));
                            state.update_method = Some(i)
                        },
                        method_name => panic!("Unexpected method {}", method_name),
                    }
                },
                Type(_) => {
                    match item.ident.to_string().as_ref() {
                        "Root" => state.root_type = Some(i),
                        "Model" => state.model_type = Some(i),
                        "Msg" => state.msg_type = Some(i),
                        _ => panic!("Unexpected type item {:?}", item.ident),
                    }
                },
            }
        }
        let view = get_view(&name, &mut state);
        if let Some(on_add) = gen_set_child_prop_calls(&view.widget) {
            new_items.push(on_add);
        }
        state.properties_model_map = Some(view.properties_model_map);
        new_items.push(view.item);
        state.widgets.insert(state.root_widget.clone().expect("root widget"),
            state.root_widget_type.clone().expect("root widget type"));
        new_items.push(get_msg_type(state.msg_type, state.widget_msg_type));
        new_items.push(get_model_type(state.model_type, state.widget_model_type));
        new_items.push(get_root_type(state.root_type, state.root_widget_type));
        new_items.push(get_update(state.update_method.expect("update method"),
            &state.properties_model_map.expect("properties model map")));
        new_items.push(get_root(state.root_method, state.root_widget_expr));
        let item = Impl(unsafety, polarity, generics, path, typ, new_items);
        ast.node = item;
        let widget_struct = create_struct(&name, &state.widgets, &view.relm_widgets);
        let container_impl = view.container_impl;
        quote! {
            #widget_struct
            #ast
            #container_impl
        }
    }
    else {
        panic!("Expected impl");
    }
}

fn add_widgets(widget: &Widget, widgets: &mut HashMap<Ident, Ident>, map: &PropertyModelMap) {
    // Only add widgets that are needed by the update() function.
    let mut to_add = false;
    for values in map.values() {
        for value in values {
            if value.widget_name == widget.name() {
                to_add = true;
            }
        }
    }
    if to_add {
        widgets.insert(widget.name().clone(), widget.typ().clone());
    }
    match *widget {
        Gtk(ref widget) =>  {
            for child in &widget.children {
                add_widgets(child, widgets, map);
            }
        },
        Relm(ref widget) =>  {
            for child in &widget.children {
                add_widgets(child, widgets, map);
            }
        },
    }
}

fn block_to_impl_item(tokens: Tokens) -> ImplItem {
    let implementation = quote! {
        impl Test {
            #tokens
        }
    };
    let implementation = parse_item(implementation.as_str()).expect("parse_ẗem in block_to_impl_item");
    match implementation.node {
        Impl(_, _, _, _, _, items) => items[0].clone(),
        _ => unreachable!(),
    }
}

fn create_struct(name: &Ident, widgets: &HashMap<Ident, Ident>, relm_widgets: &HashMap<Ident, Ident>) -> Tokens {
    let widgets = widgets.iter().filter(|&(ident, _)| !relm_widgets.contains_key(ident));
    let (idents, types): (Vec<_>, Vec<_>) = widgets.unzip();
    let relm_idents = relm_widgets.keys();
    let relm_types = relm_widgets.values();
    quote! {
        #[allow(dead_code)]
        #[derive(Clone)]
        pub struct #name {
            #(#idents: #types,)*
            #(#relm_idents: #relm_types,)*
        }
    }
}

fn get_model_type(model_type: Option<ImplItem>, widget_model_type: Option<Ty>) -> ImplItem {
    model_type.unwrap_or_else(|| {
        let widget_model_type = widget_model_type.expect("missing model method");
        block_to_impl_item(quote! {
            type Model = #widget_model_type;
        })
    })
}

fn get_msg_type(msg_type: Option<ImplItem>, widget_msg_type: Option<Ty>) -> ImplItem {
    msg_type.unwrap_or_else(|| {
        let widget_msg_type = widget_msg_type.expect("missing update method");
        block_to_impl_item(quote! {
            type Msg = #widget_msg_type;
        })
    })
}

fn get_name(typ: &Ty) -> Ident {
    if let Ty::Path(_, ref path) = *typ {
        let mut tokens = Tokens::new();
        path.to_tokens(&mut tokens);
        Ident::new(tokens.to_string())
    }
    else {
        panic!("Expected Path")
    }
}

macro_rules! get_map {
    ($widget:expr, $map:expr, $is_relm:expr) => {{
        for (name, value) in &$widget.properties {
            let string = value.parse::<String>().expect("parse::<String>() in get_map!");
            let expr = parse_expr(&string).expect("parse_expr in get_map!");
            let mut visitor = ModelVariableVisitor::new();
            visitor.visit_expr(&expr);
            let model_variables = visitor.idents;
            for var in model_variables {
                let set = $map.entry(var).or_insert_with(HashSet::new);
                set.insert(Property {
                    expr: string.clone(),
                    is_relm_widget: $is_relm,
                    name: name.clone(),
                    widget_name: $widget.name.clone(),
                });
            }
        }
        for child in &$widget.children {
            get_properties_model_map(child, $map);
        }
    }};
}

/*
 * The map maps model variable name to a vector of tuples (widget name, property name).
 */
fn get_properties_model_map(widget: &Widget, map: &mut PropertyModelMap) {
    match *widget {
        Gtk(ref widget) => get_map!(widget, map, false),
        Relm(ref widget) => get_map!(widget, map, true),
    }
}

fn get_return_type(sig: MethodSig) -> Ty {
    if let FunctionRetTy::Ty(ty) = sig.decl.output {
        ty
    }
    else {
        panic!("Unexpected default, expecting Ty");
    }
}

fn get_root(root_method: Option<ImplItem>, root_widget_expr: Option<Tokens>) -> ImplItem {
    root_method.unwrap_or_else(|| {
        let root_widget_expr = root_widget_expr.expect("root widget expr");
        block_to_impl_item(quote! {
            fn root(&self) -> &Self::Root {
                &self.#root_widget_expr
            }
        })
    })
}

fn get_root_type(root_type: Option<ImplItem>, root_widget_type: Option<Ident>) -> ImplItem {
    root_type.unwrap_or_else(|| {
        let root_widget_type = root_widget_type.expect("root widget type");
        block_to_impl_item(quote! {
            type Root = #root_widget_type;
        })
    })
}

fn get_second_param_type(sig: &MethodSig) -> Ty {
    if let Captured(_, ref path) = sig.decl.inputs[1] {
        path.clone()
    }
    else {
        panic!("Unexpected `{:?}`, expecting Captured Ty", sig.decl.inputs[1]);
    }
}

/*
 * TODO: Create a control flow graph for each variable of the model.
 * Add the set_property() calls in every leaf of every graphs.
 */
fn get_update(mut func: ImplItem, map: &PropertyModelMap) -> ImplItem {
    if let Method(_, ref mut block) = func.node {
        let mut adder = Adder::new(map);
        *block = adder.fold_block(block.clone());
    }
    // TODO: consider gtk::main_quit() as return.
    func
}

fn get_view(name: &Ident, state: &mut State) -> View {
    {
        let segments = &state.view_macro.as_ref().expect("view! macro missing").path.segments;
        if segments.len() != 1 || segments[0].ident != "view" {
            panic!("Unexpected macro item")
        }
    }
    impl_view(name, state)
}

fn impl_view(name: &Ident, state: &mut State) -> View {
    let tokens = &state.view_macro.as_ref().expect("view_macro in impl_view()").tts;
    if let TokenTree::Delimited(Delimited { ref tts, .. }) = tokens[0] {
        let mut widget = parse(tts);
        if let Gtk(ref mut widget) = widget {
            widget.relm_name = Some(name.clone());
        }
        let mut properties_model_map = HashMap::new();
        get_properties_model_map(&widget, &mut properties_model_map);
        add_widgets(&widget, &mut state.widgets, &properties_model_map);
        let idents: Vec<_> = state.widgets.keys().collect();
        let (view, relm_widgets, container_impl) = gen(name, &widget, &mut state.root_widget, &mut state.root_widget_expr, &mut state.root_widget_type, &idents);
        let event_type = &state.widget_msg_type;
        let item = block_to_impl_item(quote! {
            #[allow(unused_variables)] // Necessary to avoid warnings in case the parameters are unused.
            fn view(relm: ::relm::RemoteRelm<#event_type>, model: &Self::Model) -> Self {
                #view
            }
        });
        View {
            container_impl: container_impl,
            item: item,
            properties_model_map: properties_model_map,
            relm_widgets: relm_widgets,
            widget: widget,
        }
    }
    else {
        panic!("Expected `{{` but found `{:?}` in view! macro", tokens[0]);
    }
}

fn gen_set_child_prop_calls(widget: &Widget) -> Option<ImplItem> {
    let widget = match *widget {
        Gtk(ref gtk_widget) => gtk_widget,
        Relm(_) => return None,
    };
    let mut tokens = Tokens::new();
    let widget_name = &widget.name;
    for (key, value) in &widget.child_properties {
        let property_func = Ident::new(format!("set_child_{}", key));
        tokens.append(quote! {
            parent.#property_func(&self.#widget_name, #value);
        });
    }
    if !widget.child_properties.is_empty() {
        Some(block_to_impl_item(quote! {
            fn on_add<W: ::gtk::IsA<::gtk::Widget> + ::gtk::IsA<::gtk::Object>>(&self, parent: W) {
                let parent: gtk::Box = ::gtk::Cast::downcast(::gtk::Cast::upcast::<::gtk::Widget>(parent))
                    .expect("the parent of a widget with child properties must be a gtk::Box");
                #tokens
            }
        }))
    }
    else {
        None
    }
}
<commit_msg>Fix spelling mistake<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * TODO: automatically add the model() method with a () return type when it is not found?
 * FIXME: Doing model.text.push_str() will not cause a set_text() to be added.
 * TODO: think about conditions and loops (widget-list).
 */

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate quote;
extern crate syn;

mod adder;
mod gen;
mod parser;
mod walker;

use std::collections::{HashMap, HashSet};

use adder::{Adder, Property};
use gen::gen;
use parser::Widget::{Gtk, Relm};
use parser::{Widget, parse};
use quote::{Tokens, ToTokens};
use syn::{Delimited, FunctionRetTy, Ident, ImplItem, Mac, MethodSig, TokenTree, parse_expr, parse_item};
use syn::FnArg::Captured;
use syn::fold::Folder;
use syn::ImplItemKind::{Const, Macro, Method, Type};
use syn::ItemKind::Impl;
use syn::Ty;
use syn::visit::Visitor;
use walker::ModelVariableVisitor;

type PropertyModelMap = HashMap<Ident, HashSet<Property>>;

#[derive(Debug)]
struct State {
    model_type: Option<ImplItem>,
    msg_type: Option<ImplItem>,
    properties_model_map: Option<PropertyModelMap>,
    root_method: Option<ImplItem>,
    root_type: Option<ImplItem>,
    root_widget: Option<Ident>,
    root_widget_expr: Option<Tokens>,
    root_widget_type: Option<Ident>,
    update_method: Option<ImplItem>,
    view_macro: Option<Mac>,
    widget_model_type: Option<Ty>,
    widget_msg_type: Option<Ty>,
    widgets: HashMap<Ident, Ident>, // Map widget ident to widget type.
}

struct View {
    container_impl: Tokens,
    item: ImplItem,
    properties_model_map: PropertyModelMap,
    relm_widgets: HashMap<Ident, Ident>,
    widget: Widget,
}

impl State {
    fn new() -> Self {
        State {
            root_method: None,
            root_type: None,
            model_type: None,
            msg_type: None,
            properties_model_map: None,
            root_widget: None,
            root_widget_expr: None,
            root_widget_type: None,
            update_method: None,
            view_macro: None,
            widget_model_type: None,
            widget_msg_type: None,
            widgets: HashMap::new(),
        }
    }
}

pub fn gen_widget(input: Tokens) -> Tokens {
    let source = input.to_string();
    let mut ast = parse_item(&source).expect("parse_item() in gen_widget()");
    if let Impl(unsafety, polarity, generics, path, typ, items) = ast.node {
        let name = get_name(&typ);
        let mut new_items = vec![];
        let mut state = State::new();
        for item in items {
            let i = item.clone();
            match item.node {
                Const(_, _) => panic!("Unexpected const item"),
                Macro(mac) => state.view_macro = Some(mac),
                Method(sig, _) => {
                    match item.ident.to_string().as_ref() {
                        "root" => state.root_method = Some(i),
                        "model" => {
                            state.widget_model_type = Some(get_return_type(sig));
                            new_items.push(i);
                        },
                        "init_view" | "subscriptions" | "update_command" => new_items.push(i),
                        "update" => {
                            state.widget_msg_type = Some(get_second_param_type(&sig));
                            state.update_method = Some(i)
                        },
                        method_name => panic!("Unexpected method {}", method_name),
                    }
                },
                Type(_) => {
                    match item.ident.to_string().as_ref() {
                        "Root" => state.root_type = Some(i),
                        "Model" => state.model_type = Some(i),
                        "Msg" => state.msg_type = Some(i),
                        _ => panic!("Unexpected type item {:?}", item.ident),
                    }
                },
            }
        }
        let view = get_view(&name, &mut state);
        if let Some(on_add) = gen_set_child_prop_calls(&view.widget) {
            new_items.push(on_add);
        }
        state.properties_model_map = Some(view.properties_model_map);
        new_items.push(view.item);
        state.widgets.insert(state.root_widget.clone().expect("root widget"),
            state.root_widget_type.clone().expect("root widget type"));
        new_items.push(get_msg_type(state.msg_type, state.widget_msg_type));
        new_items.push(get_model_type(state.model_type, state.widget_model_type));
        new_items.push(get_root_type(state.root_type, state.root_widget_type));
        new_items.push(get_update(state.update_method.expect("update method"),
            &state.properties_model_map.expect("properties model map")));
        new_items.push(get_root(state.root_method, state.root_widget_expr));
        let item = Impl(unsafety, polarity, generics, path, typ, new_items);
        ast.node = item;
        let widget_struct = create_struct(&name, &state.widgets, &view.relm_widgets);
        let container_impl = view.container_impl;
        quote! {
            #widget_struct
            #ast
            #container_impl
        }
    }
    else {
        panic!("Expected impl");
    }
}

fn add_widgets(widget: &Widget, widgets: &mut HashMap<Ident, Ident>, map: &PropertyModelMap) {
    // Only add widgets that are needed by the update() function.
    let mut to_add = false;
    for values in map.values() {
        for value in values {
            if value.widget_name == widget.name() {
                to_add = true;
            }
        }
    }
    if to_add {
        widgets.insert(widget.name().clone(), widget.typ().clone());
    }
    match *widget {
        Gtk(ref widget) =>  {
            for child in &widget.children {
                add_widgets(child, widgets, map);
            }
        },
        Relm(ref widget) =>  {
            for child in &widget.children {
                add_widgets(child, widgets, map);
            }
        },
    }
}

fn block_to_impl_item(tokens: Tokens) -> ImplItem {
    let implementation = quote! {
        impl Test {
            #tokens
        }
    };
    let implementation = parse_item(implementation.as_str()).expect("parse_item in block_to_impl_item");
    match implementation.node {
        Impl(_, _, _, _, _, items) => items[0].clone(),
        _ => unreachable!(),
    }
}

fn create_struct(name: &Ident, widgets: &HashMap<Ident, Ident>, relm_widgets: &HashMap<Ident, Ident>) -> Tokens {
    let widgets = widgets.iter().filter(|&(ident, _)| !relm_widgets.contains_key(ident));
    let (idents, types): (Vec<_>, Vec<_>) = widgets.unzip();
    let relm_idents = relm_widgets.keys();
    let relm_types = relm_widgets.values();
    quote! {
        #[allow(dead_code)]
        #[derive(Clone)]
        pub struct #name {
            #(#idents: #types,)*
            #(#relm_idents: #relm_types,)*
        }
    }
}

fn get_model_type(model_type: Option<ImplItem>, widget_model_type: Option<Ty>) -> ImplItem {
    model_type.unwrap_or_else(|| {
        let widget_model_type = widget_model_type.expect("missing model method");
        block_to_impl_item(quote! {
            type Model = #widget_model_type;
        })
    })
}

fn get_msg_type(msg_type: Option<ImplItem>, widget_msg_type: Option<Ty>) -> ImplItem {
    msg_type.unwrap_or_else(|| {
        let widget_msg_type = widget_msg_type.expect("missing update method");
        block_to_impl_item(quote! {
            type Msg = #widget_msg_type;
        })
    })
}

fn get_name(typ: &Ty) -> Ident {
    if let Ty::Path(_, ref path) = *typ {
        let mut tokens = Tokens::new();
        path.to_tokens(&mut tokens);
        Ident::new(tokens.to_string())
    }
    else {
        panic!("Expected Path")
    }
}

macro_rules! get_map {
    ($widget:expr, $map:expr, $is_relm:expr) => {{
        for (name, value) in &$widget.properties {
            let string = value.parse::<String>().expect("parse::<String>() in get_map!");
            let expr = parse_expr(&string).expect("parse_expr in get_map!");
            let mut visitor = ModelVariableVisitor::new();
            visitor.visit_expr(&expr);
            let model_variables = visitor.idents;
            for var in model_variables {
                let set = $map.entry(var).or_insert_with(HashSet::new);
                set.insert(Property {
                    expr: string.clone(),
                    is_relm_widget: $is_relm,
                    name: name.clone(),
                    widget_name: $widget.name.clone(),
                });
            }
        }
        for child in &$widget.children {
            get_properties_model_map(child, $map);
        }
    }};
}

/*
 * The map maps model variable name to a vector of tuples (widget name, property name).
 */
fn get_properties_model_map(widget: &Widget, map: &mut PropertyModelMap) {
    match *widget {
        Gtk(ref widget) => get_map!(widget, map, false),
        Relm(ref widget) => get_map!(widget, map, true),
    }
}

fn get_return_type(sig: MethodSig) -> Ty {
    if let FunctionRetTy::Ty(ty) = sig.decl.output {
        ty
    }
    else {
        panic!("Unexpected default, expecting Ty");
    }
}

fn get_root(root_method: Option<ImplItem>, root_widget_expr: Option<Tokens>) -> ImplItem {
    root_method.unwrap_or_else(|| {
        let root_widget_expr = root_widget_expr.expect("root widget expr");
        block_to_impl_item(quote! {
            fn root(&self) -> &Self::Root {
                &self.#root_widget_expr
            }
        })
    })
}

fn get_root_type(root_type: Option<ImplItem>, root_widget_type: Option<Ident>) -> ImplItem {
    root_type.unwrap_or_else(|| {
        let root_widget_type = root_widget_type.expect("root widget type");
        block_to_impl_item(quote! {
            type Root = #root_widget_type;
        })
    })
}

fn get_second_param_type(sig: &MethodSig) -> Ty {
    if let Captured(_, ref path) = sig.decl.inputs[1] {
        path.clone()
    }
    else {
        panic!("Unexpected `{:?}`, expecting Captured Ty", sig.decl.inputs[1]);
    }
}

/*
 * TODO: Create a control flow graph for each variable of the model.
 * Add the set_property() calls in every leaf of every graphs.
 */
fn get_update(mut func: ImplItem, map: &PropertyModelMap) -> ImplItem {
    if let Method(_, ref mut block) = func.node {
        let mut adder = Adder::new(map);
        *block = adder.fold_block(block.clone());
    }
    // TODO: consider gtk::main_quit() as return.
    func
}

fn get_view(name: &Ident, state: &mut State) -> View {
    {
        let segments = &state.view_macro.as_ref().expect("view! macro missing").path.segments;
        if segments.len() != 1 || segments[0].ident != "view" {
            panic!("Unexpected macro item")
        }
    }
    impl_view(name, state)
}

fn impl_view(name: &Ident, state: &mut State) -> View {
    let tokens = &state.view_macro.as_ref().expect("view_macro in impl_view()").tts;
    if let TokenTree::Delimited(Delimited { ref tts, .. }) = tokens[0] {
        let mut widget = parse(tts);
        if let Gtk(ref mut widget) = widget {
            widget.relm_name = Some(name.clone());
        }
        let mut properties_model_map = HashMap::new();
        get_properties_model_map(&widget, &mut properties_model_map);
        add_widgets(&widget, &mut state.widgets, &properties_model_map);
        let idents: Vec<_> = state.widgets.keys().collect();
        let (view, relm_widgets, container_impl) = gen(name, &widget, &mut state.root_widget, &mut state.root_widget_expr, &mut state.root_widget_type, &idents);
        let event_type = &state.widget_msg_type;
        let item = block_to_impl_item(quote! {
            #[allow(unused_variables)] // Necessary to avoid warnings in case the parameters are unused.
            fn view(relm: ::relm::RemoteRelm<#event_type>, model: &Self::Model) -> Self {
                #view
            }
        });
        View {
            container_impl: container_impl,
            item: item,
            properties_model_map: properties_model_map,
            relm_widgets: relm_widgets,
            widget: widget,
        }
    }
    else {
        panic!("Expected `{{` but found `{:?}` in view! macro", tokens[0]);
    }
}

fn gen_set_child_prop_calls(widget: &Widget) -> Option<ImplItem> {
    let widget = match *widget {
        Gtk(ref gtk_widget) => gtk_widget,
        Relm(_) => return None,
    };
    let mut tokens = Tokens::new();
    let widget_name = &widget.name;
    for (key, value) in &widget.child_properties {
        let property_func = Ident::new(format!("set_child_{}", key));
        tokens.append(quote! {
            parent.#property_func(&self.#widget_name, #value);
        });
    }
    if !widget.child_properties.is_empty() {
        Some(block_to_impl_item(quote! {
            fn on_add<W: ::gtk::IsA<::gtk::Widget> + ::gtk::IsA<::gtk::Object>>(&self, parent: W) {
                let parent: gtk::Box = ::gtk::Cast::downcast(::gtk::Cast::upcast::<::gtk::Widget>(parent))
                    .expect("the parent of a widget with child properties must be a gtk::Box");
                #tokens
            }
        }))
    }
    else {
        None
    }
}
<|endoftext|>


<commit_before>use spin::Once;
use x86_64::structures::tss::TaskStateSegment;
use x86_64::structures::gdt::SegmentSelector;
use x86_64::instructions::segmentation::set_cs;
use x86_64::instructions::tables::load_tss;
use x86_64::PrivilegeLevel;
use x86_64::VirtualAddress;

use core::ptr;
use core::mem;
use core::fmt;

use keyboard;
use pic;
use time;

#[macro_use]
mod macros;
mod gdt;
pub mod idt;

use memory::MemoryController;

#[repr(C,packed)]
struct ExceptionStackFrame {
    instruction_pointer: u64,
    code_segment: u64,
    cpu_flags: u64,
    stack_pointer: u64,
    stack_segment: u64
}
impl fmt::Display for ExceptionStackFrame {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ip = self.instruction_pointer;
        let cs = self.code_segment;
        let fl = self.cpu_flags;
        let sp = self.stack_pointer;
        let ss = self.stack_segment;

        write!(f, "ExceptionStackFrame {{\n  rip: {:#x},\n  cs: {:#x},\n  flags: {:#x},\n  rsp: {:#x},\n  ss: {:#x}\n}}", ip, cs, fl, sp, ss)
    }
}

/// Breakpoint handler
extern "C" fn exception_bp(stack_frame: *const ExceptionStackFrame) {
    unsafe {
        rforce_unlock!();
        rprintln!("Breakpoint at {:#x}\n{}", (*stack_frame).instruction_pointer, *stack_frame);
        bochs_magic_bp!();
    }
}

/// Invalid Opcode handler (instruction undefined)
extern "C" fn exception_ud(stack_frame: *const ExceptionStackFrame) {
    unsafe {
        rforce_unlock!();
        rprintln!("Exception: invalid opcode at {:#x}\n{}", (*stack_frame).instruction_pointer, *stack_frame);
    }
    loop {}
}

/// Double Fault handler
#[allow(unused_variables)]
extern "C" fn exception_df(stack_frame: *const ExceptionStackFrame, error_code: u64) {
    // error code is always zero
    unsafe {
        bochs_magic_bp!();
        panic_indicator!(0x4f664f64);   // "df"
        rforce_unlock!();
        rprintln!("Exception: Double Fault\n{}", *stack_frame);
        rprintln!("exception stack frame at {:#p}", stack_frame);
    }
    loop {}
}

/// General Protection Fault handler
extern "C" fn exception_gpf(stack_frame: *const ExceptionStackFrame, error_code: u64) {
    unsafe {
        rforce_unlock!();
        rprintln!("Exception: General Protection Fault with error code {:#x}\n{}", error_code, *stack_frame);
    }
    loop {}
}

/// Page Fault error codes
bitflags! {
    flags PageFaultErrorCode: u64 {
        const PROTECTION_VIOLATION  = 1 << 0,
        const CAUSED_BY_WRITE       = 1 << 1,
        const USER_MODE             = 1 << 2,
        const MALFORMED_TABLE       = 1 << 3,
        const INSTRUCTION_FETCH     = 1 << 4,
    }
}

/// Page Fault handler
extern "C" fn exception_pf(stack_frame: *const ExceptionStackFrame, error_code: u64) {
    unsafe {
        bochs_magic_bp!();
        rforce_unlock!();
        rprintln!("Exception: Page Fault with error code {:?} ({:?}) at {:#x}\n{}", error_code, PageFaultErrorCode::from_bits(error_code).unwrap(), register!(cr2), *stack_frame);
    }
    loop {}
}

#[derive(Debug)]
#[allow(dead_code)]
enum SegmentNotPresentTable {
    GDT,
    IDT,
    LDT
}

/// Segment Not Present handler
extern "C" fn exception_snp(stack_frame: *const ExceptionStackFrame, error_code: u64) {
    unsafe {
        rforce_unlock!();
        rprintln!("Exception: Segment Not Present with error code {:#x} (e={:b},t={:?},i={:#x})\n{}",
            error_code,
            error_code & 0b1,
            match (error_code & 0b110) >> 1 {
                0b00 => SegmentNotPresentTable::GDT,
                0b01 => SegmentNotPresentTable::IDT,
                0b10 => SegmentNotPresentTable::LDT,
                0b11 => SegmentNotPresentTable::IDT,
                _ => {unreachable!();}
            },
            (error_code & 0xFFFF) >> 4, // FIXME: 3 ?
            *stack_frame
        );
    }
    loop {}
}

/// PIT timer ticked
extern "C" fn exception_irq0() {
    unsafe {
        time::SYSCLOCK.force_unlock();
        time::SYSCLOCK.lock().tick();
        pic::PICS.lock().notify_eoi(0x20);
    }
}

/// First ps/2 device, keyboard, sent data
pub extern "C" fn exception_irq1() {
    unsafe {
        rforce_unlock!();
        let mut kbd = keyboard::KEYBOARD.lock();
        if kbd.is_enabled() {
            kbd.notify();
        }
        pic::PICS.lock().notify_eoi(0x21);
    }
}

/// System calls
#[naked]
pub extern "C" fn syscall() -> ! {
    use super::syscall::{SyscallResult, call};

    unsafe {
        syscall_save_scratch_registers!();
        let routine: u64;
        let arg0: u64;
        let arg1: u64;
        let arg2: u64;
        let arg3: u64;

        asm!("" :
            "={rax}"(routine),
            "={rdi}"(arg0),
            "={rsi}"(arg1),
            "={rdx}"(arg2),
            "={rcx}"(arg3)
            :::
            "intel"
        );

        let result = call(routine, (arg0, arg1, arg2, arg3));

        register!(rax, result.success);
        register!(rdx, result.result);

        syscall_restore_scratch_registers!();
        asm!("iretq" :::: "intel", "volatile");
        ::core::intrinsics::unreachable();
    }
}

#[derive(Clone,Copy)]
struct HandlerInfo {
    function_ptr: *const fn(),
    privilege_level: PrivilegeLevel,
    tss_selector: u8
}
impl HandlerInfo {
    pub const fn new(f: *const fn(), pl: PrivilegeLevel, tss_s: u8) -> HandlerInfo {
        HandlerInfo { function_ptr: f, privilege_level: pl, tss_selector: tss_s }
    }
}

static TSS: Once<TaskStateSegment> = Once::new();
static GDT: Once<gdt::Gdt> = Once::new();

pub fn init(memory_controller: &mut MemoryController) {
    let mut handlers: [Option<HandlerInfo>; idt::ENTRY_COUNT] = [None; idt::ENTRY_COUNT];

    // Initialize TSS
    let double_fault_stack = memory_controller.alloc_stack(1).expect("could not allocate double fault stack");

    let mut code_selector   = SegmentSelector::new(0, PrivilegeLevel::Ring0);
    let mut tss_selector    = SegmentSelector::new(1, PrivilegeLevel::Ring0);

    let tss = TSS.call_once(|| {
        let mut tss = TaskStateSegment::new();
        tss.interrupt_stack_table[gdt::DOUBLE_FAULT_IST_INDEX] = VirtualAddress(double_fault_stack.top);
        tss
    });

    let gdt = GDT.call_once(|| {
        let mut gdt = gdt::Gdt::new();
        code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment());
        tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss));
        gdt
    });

    unsafe {
        // load GDT
        gdt.load();
        // reload code segment register
        set_cs(code_selector);
        // load TSS
        load_tss(tss_selector);
    }

    // Bind exception handlers
    handlers[0x00] = Some(HandlerInfo::new(simple_exception!("Divide-by-zero Error"), PrivilegeLevel::Ring0, 0));
    handlers[0x03] = Some(HandlerInfo::new(exception_handler!(exception_bp), PrivilegeLevel::Ring0, 0));
    handlers[0x06] = Some(HandlerInfo::new(exception_handler!(exception_ud), PrivilegeLevel::Ring0, 0));
    handlers[0x08] = Some(HandlerInfo::new(exception_handler_with_error_code!(exception_df), PrivilegeLevel::Ring0, 5));
    handlers[0x0b] = Some(HandlerInfo::new(exception_handler_with_error_code!(exception_snp), PrivilegeLevel::Ring0, 0));
    handlers[0x0d] = Some(HandlerInfo::new(exception_handler_with_error_code!(exception_gpf), PrivilegeLevel::Ring0, 0));
    handlers[0x0e] = Some(HandlerInfo::new(exception_handler_with_error_code!(exception_pf), PrivilegeLevel::Ring0, 0));
    handlers[0x20] = Some(HandlerInfo::new(irq_handler!(exception_irq0), PrivilegeLevel::Ring0, 0));
    handlers[0x21] = Some(HandlerInfo::new(irq_handler!(exception_irq1), PrivilegeLevel::Ring0, 0));
    handlers[0xd7] = Some(HandlerInfo::new(syscall as *const fn(), PrivilegeLevel::Ring0, 0));

    for index in 0..=(idt::ENTRY_COUNT-1) {
        let descriptor = match handlers[index] {
            None        => {idt::Descriptor::new(false, 0, PrivilegeLevel::Ring0, 0)},
            Some(info)  => {idt::Descriptor::new(true, info.function_ptr as u64, info.privilege_level, info.tss_selector)}
        };
        unsafe {
            ptr::write_volatile((idt::ADDRESS + index * mem::size_of::<idt::Descriptor>()) as *mut _, descriptor);
        }
    }

    unsafe {
        idt::Reference::new().write();
    }

    rprintln!("Enabling interrupt handler...");

    unsafe {
        asm!("lidt [$0]" :: "r"(idt::R_ADDRESS) : "memory" : "volatile", "intel");
        asm!("sti" :::: "volatile", "intel");
    }

    rprintln!("Enabled.");
}
<commit_msg>Handle ATA interrupts<commit_after>use spin::Once;
use x86_64::structures::tss::TaskStateSegment;
use x86_64::structures::gdt::SegmentSelector;
use x86_64::instructions::segmentation::set_cs;
use x86_64::instructions::tables::load_tss;
use x86_64::PrivilegeLevel;
use x86_64::VirtualAddress;

use core::ptr;
use core::mem;
use core::fmt;

use keyboard;
use pic;
use time;

#[macro_use]
mod macros;
mod gdt;
pub mod idt;

use memory::MemoryController;

#[repr(C,packed)]
struct ExceptionStackFrame {
    instruction_pointer: u64,
    code_segment: u64,
    cpu_flags: u64,
    stack_pointer: u64,
    stack_segment: u64
}
impl fmt::Display for ExceptionStackFrame {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ip = self.instruction_pointer;
        let cs = self.code_segment;
        let fl = self.cpu_flags;
        let sp = self.stack_pointer;
        let ss = self.stack_segment;

        write!(f, "ExceptionStackFrame {{\n  rip: {:#x},\n  cs: {:#x},\n  flags: {:#x},\n  rsp: {:#x},\n  ss: {:#x}\n}}", ip, cs, fl, sp, ss)
    }
}

/// Breakpoint handler
extern "C" fn exception_bp(stack_frame: *const ExceptionStackFrame) {
    unsafe {
        rforce_unlock!();
        rprintln!("Breakpoint at {:#x}\n{}", (*stack_frame).instruction_pointer, *stack_frame);
        bochs_magic_bp!();
    }
}

/// Invalid Opcode handler (instruction undefined)
extern "C" fn exception_ud(stack_frame: *const ExceptionStackFrame) {
    unsafe {
        rforce_unlock!();
        rprintln!("Exception: invalid opcode at {:#x}\n{}", (*stack_frame).instruction_pointer, *stack_frame);
    }
    loop {}
}

/// Double Fault handler
#[allow(unused_variables)]
extern "C" fn exception_df(stack_frame: *const ExceptionStackFrame, error_code: u64) {
    // error code is always zero
    unsafe {
        bochs_magic_bp!();
        panic_indicator!(0x4f664f64);   // "df"
        rforce_unlock!();
        rprintln!("Exception: Double Fault\n{}", *stack_frame);
        rprintln!("exception stack frame at {:#p}", stack_frame);
    }
    loop {}
}

/// General Protection Fault handler
extern "C" fn exception_gpf(stack_frame: *const ExceptionStackFrame, error_code: u64) {
    unsafe {
        rforce_unlock!();
        rprintln!("Exception: General Protection Fault with error code {:#x}\n{}", error_code, *stack_frame);
    }
    loop {}
}

/// Page Fault error codes
bitflags! {
    flags PageFaultErrorCode: u64 {
        const PROTECTION_VIOLATION  = 1 << 0,
        const CAUSED_BY_WRITE       = 1 << 1,
        const USER_MODE             = 1 << 2,
        const MALFORMED_TABLE       = 1 << 3,
        const INSTRUCTION_FETCH     = 1 << 4,
    }
}

/// Page Fault handler
extern "C" fn exception_pf(stack_frame: *const ExceptionStackFrame, error_code: u64) {
    unsafe {
        bochs_magic_bp!();
        rforce_unlock!();
        rprintln!("Exception: Page Fault with error code {:?} ({:?}) at {:#x}\n{}", error_code, PageFaultErrorCode::from_bits(error_code).unwrap(), register!(cr2), *stack_frame);
    }
    loop {}
}

#[derive(Debug)]
#[allow(dead_code)]
enum SegmentNotPresentTable {
    GDT,
    IDT,
    LDT
}

/// Segment Not Present handler
extern "C" fn exception_snp(stack_frame: *const ExceptionStackFrame, error_code: u64) {
    unsafe {
        rforce_unlock!();
        rprintln!("Exception: Segment Not Present with error code {:#x} (e={:b},t={:?},i={:#x})\n{}",
            error_code,
            error_code & 0b1,
            match (error_code & 0b110) >> 1 {
                0b00 => SegmentNotPresentTable::GDT,
                0b01 => SegmentNotPresentTable::IDT,
                0b10 => SegmentNotPresentTable::LDT,
                0b11 => SegmentNotPresentTable::IDT,
                _ => {unreachable!();}
            },
            (error_code & 0xFFFF) >> 4, // FIXME: 3 ?
            *stack_frame
        );
    }
    loop {}
}

/// PIT timer ticked
extern "C" fn exception_irq0() {
    unsafe {
        time::SYSCLOCK.force_unlock();
        time::SYSCLOCK.lock().tick();
        pic::PICS.lock().notify_eoi(0x20);
    }
}

/// First ps/2 device, keyboard, sent data
pub extern "C" fn exception_irq1() {
    unsafe {
        // rforce_unlock!();
        // let mut kbd = keyboard::KEYBOARD.lock();
        // if kbd.is_enabled() {
        //     kbd.notify();
        // }
        pic::PICS.lock().notify_eoi(0x21);
    }
}

/// First ATA device is ready for data transfer
pub extern "C" fn exception_irq14() {
    // Since we are polling the drive, just ignore the IRQ
    unsafe {
        pic::PICS.lock().notify_eoi(0x2e);
    }
}

/// System calls
#[naked]
pub extern "C" fn syscall() -> ! {
    use super::syscall::{SyscallResult, call};

    unsafe {
        syscall_save_scratch_registers!();
        let routine: u64;
        let arg0: u64;
        let arg1: u64;
        let arg2: u64;
        let arg3: u64;

        asm!("" :
            "={rax}"(routine),
            "={rdi}"(arg0),
            "={rsi}"(arg1),
            "={rdx}"(arg2),
            "={rcx}"(arg3)
            :::
            "intel"
        );

        let result = call(routine, (arg0, arg1, arg2, arg3));

        register!(rax, result.success);
        register!(rdx, result.result);

        syscall_restore_scratch_registers!();
        asm!("iretq" :::: "intel", "volatile");
        ::core::intrinsics::unreachable();
    }
}

#[derive(Clone,Copy)]
struct HandlerInfo {
    function_ptr: *const fn(),
    privilege_level: PrivilegeLevel,
    tss_selector: u8
}
impl HandlerInfo {
    pub const fn new(f: *const fn(), pl: PrivilegeLevel, tss_s: u8) -> HandlerInfo {
        HandlerInfo { function_ptr: f, privilege_level: pl, tss_selector: tss_s }
    }
}

static TSS: Once<TaskStateSegment> = Once::new();
static GDT: Once<gdt::Gdt> = Once::new();

pub fn init(memory_controller: &mut MemoryController) {
    let mut handlers: [Option<HandlerInfo>; idt::ENTRY_COUNT] = [None; idt::ENTRY_COUNT];

    // Initialize TSS
    let double_fault_stack = memory_controller.alloc_stack(1).expect("could not allocate double fault stack");

    let mut code_selector   = SegmentSelector::new(0, PrivilegeLevel::Ring0);
    let mut tss_selector    = SegmentSelector::new(1, PrivilegeLevel::Ring0);

    let tss = TSS.call_once(|| {
        let mut tss = TaskStateSegment::new();
        tss.interrupt_stack_table[gdt::DOUBLE_FAULT_IST_INDEX] = VirtualAddress(double_fault_stack.top);
        tss
    });

    let gdt = GDT.call_once(|| {
        let mut gdt = gdt::Gdt::new();
        code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment());
        tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss));
        gdt
    });

    unsafe {
        // load GDT
        gdt.load();
        // reload code segment register
        set_cs(code_selector);
        // load TSS
        load_tss(tss_selector);
    }

    // Bind exception handlers
    handlers[0x00] = Some(HandlerInfo::new(simple_exception!("Divide-by-zero Error"), PrivilegeLevel::Ring0, 0));
    handlers[0x03] = Some(HandlerInfo::new(exception_handler!(exception_bp), PrivilegeLevel::Ring0, 0));
    handlers[0x06] = Some(HandlerInfo::new(exception_handler!(exception_ud), PrivilegeLevel::Ring0, 0));
    handlers[0x08] = Some(HandlerInfo::new(exception_handler_with_error_code!(exception_df), PrivilegeLevel::Ring0, 5));
    handlers[0x0b] = Some(HandlerInfo::new(exception_handler_with_error_code!(exception_snp), PrivilegeLevel::Ring0, 0));
    handlers[0x0d] = Some(HandlerInfo::new(exception_handler_with_error_code!(exception_gpf), PrivilegeLevel::Ring0, 0));
    handlers[0x0e] = Some(HandlerInfo::new(exception_handler_with_error_code!(exception_pf), PrivilegeLevel::Ring0, 0));
    handlers[0x20] = Some(HandlerInfo::new(irq_handler!(exception_irq0), PrivilegeLevel::Ring0, 0));
    handlers[0x21] = Some(HandlerInfo::new(irq_handler!(exception_irq1), PrivilegeLevel::Ring0, 0));
    handlers[0x2e] = Some(HandlerInfo::new(irq_handler!(exception_irq14), PrivilegeLevel::Ring0, 0));
    handlers[0xd7] = Some(HandlerInfo::new(syscall as *const fn(), PrivilegeLevel::Ring0, 0));

    for index in 0..=(idt::ENTRY_COUNT-1) {
        let descriptor = match handlers[index] {
            None        => {idt::Descriptor::new(false, 0, PrivilegeLevel::Ring0, 0)},
            Some(info)  => {idt::Descriptor::new(true, info.function_ptr as u64, info.privilege_level, info.tss_selector)}
        };
        unsafe {
            ptr::write_volatile((idt::ADDRESS + index * mem::size_of::<idt::Descriptor>()) as *mut _, descriptor);
        }
    }

    unsafe {
        idt::Reference::new().write();
    }

    rprintln!("Enabling interrupt handler...");

    unsafe {
        asm!("lidt [$0]" :: "r"(idt::R_ADDRESS) : "memory" : "volatile", "intel");
        asm!("sti" :::: "volatile", "intel");
    }

    rprintln!("Enabled.");
}
<|endoftext|>