<commit_before>
//! Immediate operands for Cretonne instructions
//!
//! This module defines the types of immediate operands that can appear on Cretonne instructions.
//! Each type here should have a corresponding definition in the `cretonne.immediates` Python
//! module in the meta language.

use std::fmt::{self, Display, Formatter};
use std::mem;

// Include code generated by `meta/gen_instr.py`. This file contains:
//
// - The `pub enum Opcode` definition with all known opcodes,
// - The private `fn opcode_name(Opcode) -> &'static str` function, and
// - The hash table `const OPCODE_HASH_TABLE: [Opcode; N]`.
//
include!(concat!(env!("OUT_DIR"), "/opcodes.rs"));

impl Display for Opcode {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", opcode_name(*self))
    }
}

// A primitive hash function for matching opcodes.
// Must match `meta/constant_hash.py`.
fn simple_hash(s: &str) -> u32 {
    let mut h: u32 = 5381;
    for c in s.chars() {
        h = (h ^ c as u32).wrapping_add(h.rotate_right(6));
    }
    h
}

impl Opcode {
    /// Parse an Opcode name from a string.
    pub fn from_str(s: &str) -> Option<Opcode> {
        let tlen = OPCODE_HASH_TABLE.len();
        assert!(tlen.is_power_of_two());
        let mut idx = simple_hash(s) as usize;
        let mut step: usize = 0;
        loop {
            idx = idx % tlen;
            let entry = OPCODE_HASH_TABLE[idx];

            if entry == Opcode::NotAnOpcode {
                return None;
            }

            if *opcode_name(entry) == *s {
                return Some(entry);
            }

            // Quadratic probing.
            step += 1;
            // When `tlen` is a power of two, it can be proven that idx will visit all entries.
            // This means that this loop will always terminate if the hash table has even one
            // unused entry.
            assert!(step < tlen);
            idx += step;
        }
    }
}

/// 64-bit immediate integer operand.
///
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Imm64(i64);

impl Display for Imm64 {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let x = self.0;
        if -10_000 < x && x < 10_000 {
            // Use decimal for small numbers.
            write!(f, "{}", x)
        } else {
            // Hexadecimal with a multiple of 4 digits and group separators:
            //
            //   0xfff0
            //   0x0001_ffff
            //   0xffff_ffff_fff8_4400
            //
            let mut pos = (64 - x.leading_zeros() - 1) & 0xf0;
            try!(write!(f, "0x{:04x}", (x >> pos) & 0xffff));
            while pos > 0 {
                pos -= 16;
                try!(write!(f, "_{:04x}", (x >> pos) & 0xffff));
            }
            Ok(())
        }
    }
}

/// An IEEE binary32 immediate floating point value.
///
/// All bit patterns are allowed.
#[derive(Copy, Clone, Debug)]
pub struct Ieee32(f32);

/// An IEEE binary64 immediate floating point value.
///
/// All bit patterns are allowed.
#[derive(Copy, Clone, Debug)]
pub struct Ieee64(f64);

// Format a floating point number in a way that is reasonably human-readable, and that can be
// converted back to binary without any rounding issues. The hexadecimal formatting of normal and
// subnormal numbers is compatible with C99 and the printf "%a" format specifier. The NaN and Inf
// formats are not supported by C99.
//
// The encoding parameters are:
//
// w - exponent field width in bits
// t - trailing significand field width in bits
//
fn format_float(bits: u64, w: u8, t: u8, f: &mut Formatter) -> fmt::Result {
    assert!(w > 0 && w <= 16, "Invalid exponent range");
    assert!(1 + w + t <= 64, "Too large IEEE format for u64");

    let max_e_bits = (1u64 << w) - 1;
    let t_bits = bits & ((1u64 << t) - 1); // Trailing significand.
    let e_bits = (bits >> t) & max_e_bits; // Biased exponent.
    let sign_bit = (bits >> w + t) & 1;

    let bias: i32 = (1 << (w - 1)) - 1;
    let e = e_bits as i32 - bias; // Unbiased exponent.
    let emin = 1 - bias; // Minimum exponent.

    // How many hexadecimal digits are needed for the trailing significand?
    let digits = (t + 3) / 4;
    // Trailing significand left-aligned in `digits` hexadecimal digits.
    let left_t_bits = t_bits << (4 * digits - t);

    // All formats share the leading sign.
    if sign_bit != 0 {
        try!(write!(f, "-"));
    }

    if e_bits == 0 {
        if t_bits == 0 {
            // Zero.
            write!(f, "0.0")
        } else {
            // Subnormal.
            write!(f, "0x0.{0:01$x}p{2}", left_t_bits, digits as usize, emin)
        }
    } else if e_bits == max_e_bits {
        if t_bits == 0 {
            // Infinity.
            write!(f, "Inf")
        } else {
            // NaN.
            let payload = t_bits & ((1 << (t - 1)) - 1);
            if t_bits & (1 << (t - 1)) != 0 {
                // Quiet NaN.
                if payload != 0 {
                    write!(f, "NaN:0x{:x}", payload)
                } else {
                    write!(f, "NaN")
                }
            } else {
                // Signaling NaN.
                write!(f, "sNaN:0x{:x}", payload)
            }
        }
    } else {
        // Normal number.
        write!(f, "0x1.{0:01$x}p{2}", left_t_bits, digits as usize, e)
    }
}

impl Ieee32 {
    pub fn new(x: f32) -> Ieee32 {
        Ieee32(x)
    }

    /// Construct Ieee32 immediate from raw bits.
    pub fn new_from_bits(x: u32) -> Ieee32 {
        Ieee32(unsafe { mem::transmute(x) })
    }
}

impl Display for Ieee32 {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let bits: u32 = unsafe { mem::transmute(self.0) };
        format_float(bits as u64, 8, 23, f)
    }
}

impl Ieee64 {
    pub fn new(x: f64) -> Ieee64 {
        Ieee64(x)
    }

    /// Construct Ieee64 immediate from raw bits.
    pub fn new_from_bits(x: u64) -> Ieee64 {
        Ieee64(unsafe { mem::transmute(x) })
    }
}

impl Display for Ieee64 {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let bits: u64 = unsafe { mem::transmute(self.0) };
        format_float(bits, 11, 52, f)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::{f32, f64};

    #[test]
    fn opcodes() {
        let x = Opcode::Iadd;
        let mut y = Opcode::Isub;

        assert!(x != y);
        y = Opcode::Iadd;
        assert_eq!(x, y);

        assert_eq!(format!("{:?}", Opcode::IaddImm), "IaddImm");
        assert_eq!(format!("{}", Opcode::IaddImm), "iadd_imm");

        // Check the matcher.
        assert_eq!(Opcode::from_str("iadd"), Some(Opcode::Iadd));
        assert_eq!(Opcode::from_str("iadd_imm"), Some(Opcode::IaddImm));
        assert_eq!(Opcode::from_str("iadd\0"), None);
        assert_eq!(Opcode::from_str(""), None);
        assert_eq!(Opcode::from_str("\0"), None);
    }

    #[test]
    fn format_imm64() {
        assert_eq!(format!("{}", Imm64(0)), "0");
        assert_eq!(format!("{}", Imm64(9999)), "9999");
        assert_eq!(format!("{}", Imm64(10000)), "0x2710");
        assert_eq!(format!("{}", Imm64(-9999)), "-9999");
        assert_eq!(format!("{}", Imm64(-10000)), "0xffff_ffff_ffff_d8f0");
        assert_eq!(format!("{}", Imm64(0xffff)), "0xffff");
        assert_eq!(format!("{}", Imm64(0x10000)), "0x0001_0000");
    }

    #[test]
    fn format_ieee32() {
        assert_eq!(format!("{}", Ieee32::new(0.0)), "0.0");
        assert_eq!(format!("{}", Ieee32::new(-0.0)), "-0.0");
        assert_eq!(format!("{}", Ieee32::new(1.0)), "0x1.000000p0");
        assert_eq!(format!("{}", Ieee32::new(1.5)), "0x1.800000p0");
        assert_eq!(format!("{}", Ieee32::new(0.5)), "0x1.000000p-1");
        assert_eq!(format!("{}", Ieee32::new(f32::EPSILON)), "0x1.000000p-23");
        assert_eq!(format!("{}", Ieee32::new(f32::MIN)), "-0x1.fffffep127");
        assert_eq!(format!("{}", Ieee32::new(f32::MAX)), "0x1.fffffep127");
        // Smallest positive normal number.
        assert_eq!(format!("{}", Ieee32::new(f32::MIN_POSITIVE)),
                   "0x1.000000p-126");
        // Subnormals.
        assert_eq!(format!("{}", Ieee32::new(f32::MIN_POSITIVE / 2.0)),
                   "0x0.800000p-126");
        assert_eq!(format!("{}", Ieee32::new(f32::MIN_POSITIVE * f32::EPSILON)),
                   "0x0.000002p-126");
        assert_eq!(format!("{}", Ieee32::new(f32::INFINITY)), "Inf");
        assert_eq!(format!("{}", Ieee32::new(f32::NEG_INFINITY)), "-Inf");
        assert_eq!(format!("{}", Ieee32::new(f32::NAN)), "NaN");
        assert_eq!(format!("{}", Ieee32::new(-f32::NAN)), "-NaN");
        // Construct some qNaNs with payloads.
        assert_eq!(format!("{}", Ieee32::new_from_bits(0x7fc00001)), "NaN:0x1");
        assert_eq!(format!("{}", Ieee32::new_from_bits(0x7ff00001)),
                   "NaN:0x300001");
        // Signaling NaNs.
        assert_eq!(format!("{}", Ieee32::new_from_bits(0x7f800001)), "sNaN:0x1");
        assert_eq!(format!("{}", Ieee32::new_from_bits(0x7fa00001)),
                   "sNaN:0x200001");
    }

    #[test]
    fn format_ieee64() {
        assert_eq!(format!("{}", Ieee64::new(0.0)), "0.0");
        assert_eq!(format!("{}", Ieee64::new(-0.0)), "-0.0");
        assert_eq!(format!("{}", Ieee64::new(1.0)), "0x1.0000000000000p0");
        assert_eq!(format!("{}", Ieee64::new(1.5)), "0x1.8000000000000p0");
        assert_eq!(format!("{}", Ieee64::new(0.5)), "0x1.0000000000000p-1");
        assert_eq!(format!("{}", Ieee64::new(f64::EPSILON)),
                   "0x1.0000000000000p-52");
        assert_eq!(format!("{}", Ieee64::new(f64::MIN)),
                   "-0x1.fffffffffffffp1023");
        assert_eq!(format!("{}", Ieee64::new(f64::MAX)),
                   "0x1.fffffffffffffp1023");
        // Smallest positive normal number.
        assert_eq!(format!("{}", Ieee64::new(f64::MIN_POSITIVE)),
                   "0x1.0000000000000p-1022");
        // Subnormals.
        assert_eq!(format!("{}", Ieee64::new(f64::MIN_POSITIVE / 2.0)),
                   "0x0.8000000000000p-1022");
        assert_eq!(format!("{}", Ieee64::new(f64::MIN_POSITIVE * f64::EPSILON)),
                   "0x0.0000000000001p-1022");
        assert_eq!(format!("{}", Ieee64::new(f64::INFINITY)), "Inf");
        assert_eq!(format!("{}", Ieee64::new(f64::NEG_INFINITY)), "-Inf");
        assert_eq!(format!("{}", Ieee64::new(f64::NAN)), "NaN");
        assert_eq!(format!("{}", Ieee64::new(-f64::NAN)), "-NaN");
        // Construct some qNaNs with payloads.
        assert_eq!(format!("{}", Ieee64::new_from_bits(0x7ff8000000000001)),
                   "NaN:0x1");
        assert_eq!(format!("{}", Ieee64::new_from_bits(0x7ffc000000000001)),
                   "NaN:0x4000000000001");
        // Signaling NaNs.
        assert_eq!(format!("{}", Ieee64::new_from_bits(0x7ff0000000000001)),
                   "sNaN:0x1");
        assert_eq!(format!("{}", Ieee64::new_from_bits(0x7ff4000000000001)),
                   "sNaN:0x4000000000001");
    }
}
<commit_msg>Implement std::str::FromStr for matching opcodes.<commit_after>
//! Immediate operands for Cretonne instructions
//!
//! This module defines the types of immediate operands that can appear on Cretonne instructions.
//! Each type here should have a corresponding definition in the `cretonne.immediates` Python
//! module in the meta language.

use std::fmt::{self, Display, Formatter};
use std::mem;
use std::str::FromStr;

// Include code generated by `meta/gen_instr.py`. This file contains:
//
// - The `pub enum Opcode` definition with all known opcodes,
// - The private `fn opcode_name(Opcode) -> &'static str` function, and
// - The hash table `const OPCODE_HASH_TABLE: [Opcode; N]`.
//
include!(concat!(env!("OUT_DIR"), "/opcodes.rs"));

impl Display for Opcode {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", opcode_name(*self))
    }
}

// A primitive hash function for matching opcodes.
// Must match `meta/constant_hash.py`.
fn simple_hash(s: &str) -> u32 {
    let mut h: u32 = 5381;
    for c in s.chars() {
        h = (h ^ c as u32).wrapping_add(h.rotate_right(6));
    }
    h
}

impl FromStr for Opcode {
    type Err = &'static str;

    /// Parse an Opcode name from a string.
    fn from_str(s: &str) -> Result<Opcode, &'static str> {
        let tlen = OPCODE_HASH_TABLE.len();
        assert!(tlen.is_power_of_two());
        let mut idx = simple_hash(s) as usize;
        let mut step: usize = 0;
        loop {
            idx = idx % tlen;
            let entry = OPCODE_HASH_TABLE[idx];

            if entry == Opcode::NotAnOpcode {
                return Err("Unknown opcode");
            }

            if *opcode_name(entry) == *s {
                return Ok(entry);
            }

            // Quadratic probing.
            step += 1;
            // When `tlen` is a power of two, it can be proven that idx will visit all entries.
            // This means that this loop will always terminate if the hash table has even one
            // unused entry.
            assert!(step < tlen);
            idx += step;
        }
    }
}

/// 64-bit immediate integer operand.
///
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Imm64(i64);

impl Display for Imm64 {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let x = self.0;
        if -10_000 < x && x < 10_000 {
            // Use decimal for small numbers.
            write!(f, "{}", x)
        } else {
            // Hexadecimal with a multiple of 4 digits and group separators:
            //
            //   0xfff0
            //   0x0001_ffff
            //   0xffff_ffff_fff8_4400
            //
            let mut pos = (64 - x.leading_zeros() - 1) & 0xf0;
            try!(write!(f, "0x{:04x}", (x >> pos) & 0xffff));
            while pos > 0 {
                pos -= 16;
                try!(write!(f, "_{:04x}", (x >> pos) & 0xffff));
            }
            Ok(())
        }
    }
}

/// An IEEE binary32 immediate floating point value.
///
/// All bit patterns are allowed.
#[derive(Copy, Clone, Debug)]
pub struct Ieee32(f32);

/// An IEEE binary64 immediate floating point value.
///
/// All bit patterns are allowed.
#[derive(Copy, Clone, Debug)]
pub struct Ieee64(f64);

// Format a floating point number in a way that is reasonably human-readable, and that can be
// converted back to binary without any rounding issues. The hexadecimal formatting of normal and
// subnormal numbers is compatible with C99 and the printf "%a" format specifier. The NaN and Inf
// formats are not supported by C99.
//
// The encoding parameters are:
//
// w - exponent field width in bits
// t - trailing significand field width in bits
//
fn format_float(bits: u64, w: u8, t: u8, f: &mut Formatter) -> fmt::Result {
    assert!(w > 0 && w <= 16, "Invalid exponent range");
    assert!(1 + w + t <= 64, "Too large IEEE format for u64");

    let max_e_bits = (1u64 << w) - 1;
    let t_bits = bits & ((1u64 << t) - 1); // Trailing significand.
    let e_bits = (bits >> t) & max_e_bits; // Biased exponent.
    let sign_bit = (bits >> w + t) & 1;

    let bias: i32 = (1 << (w - 1)) - 1;
    let e = e_bits as i32 - bias; // Unbiased exponent.
    let emin = 1 - bias; // Minimum exponent.

    // How many hexadecimal digits are needed for the trailing significand?
    let digits = (t + 3) / 4;
    // Trailing significand left-aligned in `digits` hexadecimal digits.
    let left_t_bits = t_bits << (4 * digits - t);

    // All formats share the leading sign.
    if sign_bit != 0 {
        try!(write!(f, "-"));
    }

    if e_bits == 0 {
        if t_bits == 0 {
            // Zero.
            write!(f, "0.0")
        } else {
            // Subnormal.
            write!(f, "0x0.{0:01$x}p{2}", left_t_bits, digits as usize, emin)
        }
    } else if e_bits == max_e_bits {
        if t_bits == 0 {
            // Infinity.
            write!(f, "Inf")
        } else {
            // NaN.
            let payload = t_bits & ((1 << (t - 1)) - 1);
            if t_bits & (1 << (t - 1)) != 0 {
                // Quiet NaN.
                if payload != 0 {
                    write!(f, "NaN:0x{:x}", payload)
                } else {
                    write!(f, "NaN")
                }
            } else {
                // Signaling NaN.
                write!(f, "sNaN:0x{:x}", payload)
            }
        }
    } else {
        // Normal number.
        write!(f, "0x1.{0:01$x}p{2}", left_t_bits, digits as usize, e)
    }
}

impl Ieee32 {
    pub fn new(x: f32) -> Ieee32 {
        Ieee32(x)
    }

    /// Construct Ieee32 immediate from raw bits.
    pub fn new_from_bits(x: u32) -> Ieee32 {
        Ieee32(unsafe { mem::transmute(x) })
    }
}

impl Display for Ieee32 {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let bits: u32 = unsafe { mem::transmute(self.0) };
        format_float(bits as u64, 8, 23, f)
    }
}

impl Ieee64 {
    pub fn new(x: f64) -> Ieee64 {
        Ieee64(x)
    }

    /// Construct Ieee64 immediate from raw bits.
    pub fn new_from_bits(x: u64) -> Ieee64 {
        Ieee64(unsafe { mem::transmute(x) })
    }
}

impl Display for Ieee64 {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let bits: u64 = unsafe { mem::transmute(self.0) };
        format_float(bits, 11, 52, f)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::{f32, f64};

    #[test]
    fn opcodes() {
        let x = Opcode::Iadd;
        let mut y = Opcode::Isub;

        assert!(x != y);
        y = Opcode::Iadd;
        assert_eq!(x, y);

        assert_eq!(format!("{:?}", Opcode::IaddImm), "IaddImm");
        assert_eq!(format!("{}", Opcode::IaddImm), "iadd_imm");

        // Check the matcher.
        assert_eq!("iadd".parse::<Opcode>(), Ok(Opcode::Iadd));
        assert_eq!("iadd_imm".parse::<Opcode>(), Ok(Opcode::IaddImm));
        assert_eq!("iadd\0".parse::<Opcode>(), Err("Unknown opcode"));
        assert_eq!("".parse::<Opcode>(), Err("Unknown opcode"));
        assert_eq!("\0".parse::<Opcode>(), Err("Unknown opcode"));
    }

    #[test]
    fn format_imm64() {
        assert_eq!(format!("{}", Imm64(0)), "0");
        assert_eq!(format!("{}", Imm64(9999)), "9999");
        assert_eq!(format!("{}", Imm64(10000)), "0x2710");
        assert_eq!(format!("{}", Imm64(-9999)), "-9999");
        assert_eq!(format!("{}", Imm64(-10000)), "0xffff_ffff_ffff_d8f0");
        assert_eq!(format!("{}", Imm64(0xffff)), "0xffff");
        assert_eq!(format!("{}", Imm64(0x10000)), "0x0001_0000");
    }

    #[test]
    fn format_ieee32() {
        assert_eq!(format!("{}", Ieee32::new(0.0)), "0.0");
        assert_eq!(format!("{}", Ieee32::new(-0.0)), "-0.0");
        assert_eq!(format!("{}", Ieee32::new(1.0)), "0x1.000000p0");
        assert_eq!(format!("{}", Ieee32::new(1.5)), "0x1.800000p0");
        assert_eq!(format!("{}", Ieee32::new(0.5)), "0x1.000000p-1");
        assert_eq!(format!("{}", Ieee32::new(f32::EPSILON)), "0x1.000000p-23");
        assert_eq!(format!("{}", Ieee32::new(f32::MIN)), "-0x1.fffffep127");
        assert_eq!(format!("{}", Ieee32::new(f32::MAX)), "0x1.fffffep127");
        // Smallest positive normal number.
        assert_eq!(format!("{}", Ieee32::new(f32::MIN_POSITIVE)),
                   "0x1.000000p-126");
        // Subnormals.
        assert_eq!(format!("{}", Ieee32::new(f32::MIN_POSITIVE / 2.0)),
                   "0x0.800000p-126");
        assert_eq!(format!("{}", Ieee32::new(f32::MIN_POSITIVE * f32::EPSILON)),
                   "0x0.000002p-126");
        assert_eq!(format!("{}", Ieee32::new(f32::INFINITY)), "Inf");
        assert_eq!(format!("{}", Ieee32::new(f32::NEG_INFINITY)), "-Inf");
        assert_eq!(format!("{}", Ieee32::new(f32::NAN)), "NaN");
        assert_eq!(format!("{}", Ieee32::new(-f32::NAN)), "-NaN");
        // Construct some qNaNs with payloads.
        assert_eq!(format!("{}", Ieee32::new_from_bits(0x7fc00001)), "NaN:0x1");
        assert_eq!(format!("{}", Ieee32::new_from_bits(0x7ff00001)),
                   "NaN:0x300001");
        // Signaling NaNs.
        assert_eq!(format!("{}", Ieee32::new_from_bits(0x7f800001)), "sNaN:0x1");
        assert_eq!(format!("{}", Ieee32::new_from_bits(0x7fa00001)),
                   "sNaN:0x200001");
    }

    #[test]
    fn format_ieee64() {
        assert_eq!(format!("{}", Ieee64::new(0.0)), "0.0");
        assert_eq!(format!("{}", Ieee64::new(-0.0)), "-0.0");
        assert_eq!(format!("{}", Ieee64::new(1.0)), "0x1.0000000000000p0");
        assert_eq!(format!("{}", Ieee64::new(1.5)), "0x1.8000000000000p0");
        assert_eq!(format!("{}", Ieee64::new(0.5)), "0x1.0000000000000p-1");
        assert_eq!(format!("{}", Ieee64::new(f64::EPSILON)),
                   "0x1.0000000000000p-52");
        assert_eq!(format!("{}", Ieee64::new(f64::MIN)),
                   "-0x1.fffffffffffffp1023");
        assert_eq!(format!("{}", Ieee64::new(f64::MAX)),
                   "0x1.fffffffffffffp1023");
        // Smallest positive normal number.
        assert_eq!(format!("{}", Ieee64::new(f64::MIN_POSITIVE)),
                   "0x1.0000000000000p-1022");
        // Subnormals.
        assert_eq!(format!("{}", Ieee64::new(f64::MIN_POSITIVE / 2.0)),
                   "0x0.8000000000000p-1022");
        assert_eq!(format!("{}", Ieee64::new(f64::MIN_POSITIVE * f64::EPSILON)),
                   "0x0.0000000000001p-1022");
        assert_eq!(format!("{}", Ieee64::new(f64::INFINITY)), "Inf");
        assert_eq!(format!("{}", Ieee64::new(f64::NEG_INFINITY)), "-Inf");
        assert_eq!(format!("{}", Ieee64::new(f64::NAN)), "NaN");
        assert_eq!(format!("{}", Ieee64::new(-f64::NAN)), "-NaN");
        // Construct some qNaNs with payloads.
        assert_eq!(format!("{}", Ieee64::new_from_bits(0x7ff8000000000001)),
                   "NaN:0x1");
        assert_eq!(format!("{}", Ieee64::new_from_bits(0x7ffc000000000001)),
                   "NaN:0x4000000000001");
        // Signaling NaNs.
        assert_eq!(format!("{}", Ieee64::new_from_bits(0x7ff0000000000001)),
                   "sNaN:0x1");
        assert_eq!(format!("{}", Ieee64::new_from_bits(0x7ff4000000000001)),
                   "sNaN:0x4000000000001");
    }
}
<|endoftext|>


<commit_before>//! This module contains `HashStable` implementations for various HIR data
//! types in no particular order.

use crate::hir;
use crate::hir::map::DefPathHash;
use crate::hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX};
use crate::ich::{StableHashingContext, NodeIdHashingMode, Fingerprint};
use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
                                           StableHasher, StableHasherResult};
use std::mem;
use syntax::ast;
use syntax::attr;

impl<'a> HashStable<StableHashingContext<'a>> for DefId {
    #[inline]
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.def_path_hash(*self).hash_stable(hcx, hasher);
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>> for DefId {
    type KeyType = DefPathHash;

    #[inline]
    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
        hcx.def_path_hash(*self)
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for LocalDefId {
    #[inline]
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher);
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalDefId {
    type KeyType = DefPathHash;

    #[inline]
    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
        hcx.def_path_hash(self.to_def_id())
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for CrateNum {
    #[inline]
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.def_path_hash(DefId {
            krate: *self,
            index: CRATE_DEF_INDEX
        }).hash_stable(hcx, hasher);
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>> for CrateNum {
    type KeyType = DefPathHash;

    #[inline]
    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
        let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
        def_id.to_stable_hash_key(hcx)
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>>
for hir::ItemLocalId {
    type KeyType = hir::ItemLocalId;

    #[inline]
    fn to_stable_hash_key(&self,
                          _: &StableHashingContext<'a>)
                          -> hir::ItemLocalId {
        *self
    }
}

// The following implementations of HashStable for ItemId, TraitItemId, and
// ImplItemId deserve special attention. Normally we do not hash NodeIds within
// the HIR, since they just signify a HIR nodes own path. But ItemId et al
// are used when another item in the HIR is *referenced* and we certainly
// want to pick up on a reference changing its target, so we hash the NodeIds
// in "DefPath Mode".

impl<'a> HashStable<StableHashingContext<'a>> for hir::ItemId {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::ItemId {
            id
        } = *self;

        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
            id.hash_stable(hcx, hasher);
        })
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItemId {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::TraitItemId {
            hir_id
        } = * self;

        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
            hir_id.hash_stable(hcx, hasher);
        })
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItemId {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::ImplItemId {
            hir_id
        } = * self;

        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
            hir_id.hash_stable(hcx, hasher);
        })
    }
}

impl_stable_hash_for!(struct ast::Label {
    ident
});

impl<'a> HashStable<StableHashingContext<'a>> for hir::Ty {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.while_hashing_hir_bodies(true, |hcx| {
            let hir::Ty {
                hir_id: _,
                ref node,
                ref span,
            } = *self;

            node.hash_stable(hcx, hasher);
            span.hash_stable(hcx, hasher);
        })
    }
}

impl_stable_hash_for_spanned!(hir::FieldPat);

impl_stable_hash_for_spanned!(hir::BinOpKind);

impl_stable_hash_for!(struct hir::Stmt {
    hir_id,
    node,
    span,
});

impl_stable_hash_for_spanned!(ast::Name);

impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.while_hashing_hir_bodies(true, |hcx| {
            let hir::Expr {
                hir_id: _,
                ref span,
                ref node,
                ref attrs
            } = *self;

            span.hash_stable(hcx, hasher);
            node.hash_stable(hcx, hasher);
            attrs.hash_stable(hcx, hasher);
        })
    }
}

impl_stable_hash_for_spanned!(usize);

impl_stable_hash_for_spanned!(ast::Ident);

impl_stable_hash_for!(struct ast::Ident {
    name,
    span,
});

impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::TraitItem {
            hir_id: _,
            ident,
            ref attrs,
            ref generics,
            ref node,
            span
        } = *self;

        hcx.hash_hir_item_like(|hcx| {
            ident.name.hash_stable(hcx, hasher);
            attrs.hash_stable(hcx, hasher);
            generics.hash_stable(hcx, hasher);
            node.hash_stable(hcx, hasher);
            span.hash_stable(hcx, hasher);
        });
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::ImplItem {
            hir_id: _,
            ident,
            ref vis,
            defaultness,
            ref attrs,
            ref generics,
            ref node,
            span
        } = *self;

        hcx.hash_hir_item_like(|hcx| {
            ident.name.hash_stable(hcx, hasher);
            vis.hash_stable(hcx, hasher);
            defaultness.hash_stable(hcx, hasher);
            attrs.hash_stable(hcx, hasher);
            generics.hash_stable(hcx, hasher);
            node.hash_stable(hcx, hasher);
            span.hash_stable(hcx, hasher);
        });
    }
}

impl_stable_hash_for!(enum ::syntax::ast::CrateSugar {
    JustCrate,
    PubCrate,
});

impl<'a> HashStable<StableHashingContext<'a>> for hir::VisibilityKind {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        mem::discriminant(self).hash_stable(hcx, hasher);
        match *self {
            hir::VisibilityKind::Public |
            hir::VisibilityKind::Inherited => {
                // No fields to hash.
            }
            hir::VisibilityKind::Crate(sugar) => {
                sugar.hash_stable(hcx, hasher);
            }
            hir::VisibilityKind::Restricted { ref path, hir_id } => {
                hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
                    hir_id.hash_stable(hcx, hasher);
                });
                path.hash_stable(hcx, hasher);
            }
        }
    }
}

impl_stable_hash_for_spanned!(hir::VisibilityKind);

impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::Mod {
            inner: ref inner_span,
            ref item_ids,
        } = *self;

        inner_span.hash_stable(hcx, hasher);

        // Combining the DefPathHashes directly is faster than feeding them
        // into the hasher. Because we use a commutative combine, we also don't
        // have to sort the array.
        let item_ids_hash = item_ids
            .iter()
            .map(|id| {
                let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx);
                debug_assert_eq!(local_id, hir::ItemLocalId::from_u32(0));
                def_path_hash.0
            }).fold(Fingerprint::ZERO, |a, b| {
                a.combine_commutative(b)
            });

        item_ids.len().hash_stable(hcx, hasher);
        item_ids_hash.hash_stable(hcx, hasher);
    }
}

impl_stable_hash_for_spanned!(hir::VariantKind);

impl<'a> HashStable<StableHashingContext<'a>> for hir::Item {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::Item {
            ident,
            ref attrs,
            hir_id: _,
            ref node,
            ref vis,
            span
        } = *self;

        hcx.hash_hir_item_like(|hcx| {
            ident.name.hash_stable(hcx, hasher);
            attrs.hash_stable(hcx, hasher);
            node.hash_stable(hcx, hasher);
            vis.hash_stable(hcx, hasher);
            span.hash_stable(hcx, hasher);
        });
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::Body {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::Body {
            ref arguments,
            ref value,
            is_generator,
        } = *self;

        hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| {
            arguments.hash_stable(hcx, hasher);
            value.hash_stable(hcx, hasher);
            is_generator.hash_stable(hcx, hasher);
        });
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::BodyId {
    type KeyType = (DefPathHash, hir::ItemLocalId);

    #[inline]
    fn to_stable_hash_key(&self,
                          hcx: &StableHashingContext<'a>)
                          -> (DefPathHash, hir::ItemLocalId) {
        let hir::BodyId { hir_id } = *self;
        hir_id.to_stable_hash_key(hcx)
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::def_id::DefIndex {

    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.local_def_path_hash(*self).hash_stable(hcx, hasher);
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>>
for hir::def_id::DefIndex {
    type KeyType = DefPathHash;

    #[inline]
    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
         hcx.local_def_path_hash(*self)
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for crate::middle::lang_items::LangItem {
    fn hash_stable<W: StableHasherResult>(&self,
                                          _: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        ::std::hash::Hash::hash(self, hasher);
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitCandidate {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
            let &hir::TraitCandidate {
                def_id,
                import_ids,
            } = &self;

            def_id.hash_stable(hcx, hasher);
            // We only use the outermost import NodeId as key
            import_ids.first().hash_stable(hcx, hasher);
        });
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::TraitCandidate {
    type KeyType = (DefPathHash, Option<(DefPathHash, hir::ItemLocalId)>);

    fn to_stable_hash_key(&self,
                          hcx: &StableHashingContext<'a>)
                          -> Self::KeyType {
        let hir::TraitCandidate {
            def_id,
            import_ids,
        } = self;

        let import_ids = import_ids.first().map(|node_id| hcx.node_to_hir_id(*node_id))
                                           .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner),
                                                          hir_id.local_id));
        (hcx.def_path_hash(*def_id), import_ids)
    }
}

impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InlineAttr {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'hir>,
                                          hasher: &mut StableHasher<W>) {
        mem::discriminant(self).hash_stable(hcx, hasher);
    }
}

impl<'hir> HashStable<StableHashingContext<'hir>> for attr::OptimizeAttr {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'hir>,
                                          hasher: &mut StableHasher<W>) {
        mem::discriminant(self).hash_stable(hcx, hasher);
    }
}
<commit_msg>Improved name: first_import_id<commit_after>//! This module contains `HashStable` implementations for various HIR data
//! types in no particular order.

use crate::hir;
use crate::hir::map::DefPathHash;
use crate::hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX};
use crate::ich::{StableHashingContext, NodeIdHashingMode, Fingerprint};
use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
                                           StableHasher, StableHasherResult};
use std::mem;
use syntax::ast;
use syntax::attr;

impl<'a> HashStable<StableHashingContext<'a>> for DefId {
    #[inline]
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.def_path_hash(*self).hash_stable(hcx, hasher);
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>> for DefId {
    type KeyType = DefPathHash;

    #[inline]
    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
        hcx.def_path_hash(*self)
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for LocalDefId {
    #[inline]
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher);
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalDefId {
    type KeyType = DefPathHash;

    #[inline]
    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
        hcx.def_path_hash(self.to_def_id())
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for CrateNum {
    #[inline]
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.def_path_hash(DefId {
            krate: *self,
            index: CRATE_DEF_INDEX
        }).hash_stable(hcx, hasher);
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>> for CrateNum {
    type KeyType = DefPathHash;

    #[inline]
    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
        let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
        def_id.to_stable_hash_key(hcx)
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>>
for hir::ItemLocalId {
    type KeyType = hir::ItemLocalId;

    #[inline]
    fn to_stable_hash_key(&self,
                          _: &StableHashingContext<'a>)
                          -> hir::ItemLocalId {
        *self
    }
}

// The following implementations of HashStable for ItemId, TraitItemId, and
// ImplItemId deserve special attention. Normally we do not hash NodeIds within
// the HIR, since they just signify a HIR nodes own path. But ItemId et al
// are used when another item in the HIR is *referenced* and we certainly
// want to pick up on a reference changing its target, so we hash the NodeIds
// in "DefPath Mode".

impl<'a> HashStable<StableHashingContext<'a>> for hir::ItemId {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::ItemId {
            id
        } = *self;

        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
            id.hash_stable(hcx, hasher);
        })
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItemId {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::TraitItemId {
            hir_id
        } = * self;

        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
            hir_id.hash_stable(hcx, hasher);
        })
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItemId {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::ImplItemId {
            hir_id
        } = * self;

        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
            hir_id.hash_stable(hcx, hasher);
        })
    }
}

impl_stable_hash_for!(struct ast::Label {
    ident
});

impl<'a> HashStable<StableHashingContext<'a>> for hir::Ty {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.while_hashing_hir_bodies(true, |hcx| {
            let hir::Ty {
                hir_id: _,
                ref node,
                ref span,
            } = *self;

            node.hash_stable(hcx, hasher);
            span.hash_stable(hcx, hasher);
        })
    }
}

impl_stable_hash_for_spanned!(hir::FieldPat);

impl_stable_hash_for_spanned!(hir::BinOpKind);

impl_stable_hash_for!(struct hir::Stmt {
    hir_id,
    node,
    span,
});

impl_stable_hash_for_spanned!(ast::Name);

impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.while_hashing_hir_bodies(true, |hcx| {
            let hir::Expr {
                hir_id: _,
                ref span,
                ref node,
                ref attrs
            } = *self;

            span.hash_stable(hcx, hasher);
            node.hash_stable(hcx, hasher);
            attrs.hash_stable(hcx, hasher);
        })
    }
}

impl_stable_hash_for_spanned!(usize);

impl_stable_hash_for_spanned!(ast::Ident);

impl_stable_hash_for!(struct ast::Ident {
    name,
    span,
});

impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::TraitItem {
            hir_id: _,
            ident,
            ref attrs,
            ref generics,
            ref node,
            span
        } = *self;

        hcx.hash_hir_item_like(|hcx| {
            ident.name.hash_stable(hcx, hasher);
            attrs.hash_stable(hcx, hasher);
            generics.hash_stable(hcx, hasher);
            node.hash_stable(hcx, hasher);
            span.hash_stable(hcx, hasher);
        });
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::ImplItem {
            hir_id: _,
            ident,
            ref vis,
            defaultness,
            ref attrs,
            ref generics,
            ref node,
            span
        } = *self;

        hcx.hash_hir_item_like(|hcx| {
            ident.name.hash_stable(hcx, hasher);
            vis.hash_stable(hcx, hasher);
            defaultness.hash_stable(hcx, hasher);
            attrs.hash_stable(hcx, hasher);
            generics.hash_stable(hcx, hasher);
            node.hash_stable(hcx, hasher);
            span.hash_stable(hcx, hasher);
        });
    }
}

impl_stable_hash_for!(enum ::syntax::ast::CrateSugar {
    JustCrate,
    PubCrate,
});

impl<'a> HashStable<StableHashingContext<'a>> for hir::VisibilityKind {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        mem::discriminant(self).hash_stable(hcx, hasher);
        match *self {
            hir::VisibilityKind::Public |
            hir::VisibilityKind::Inherited => {
                // No fields to hash.
            }
            hir::VisibilityKind::Crate(sugar) => {
                sugar.hash_stable(hcx, hasher);
            }
            hir::VisibilityKind::Restricted { ref path, hir_id } => {
                hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
                    hir_id.hash_stable(hcx, hasher);
                });
                path.hash_stable(hcx, hasher);
            }
        }
    }
}

impl_stable_hash_for_spanned!(hir::VisibilityKind);

impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::Mod {
            inner: ref inner_span,
            ref item_ids,
        } = *self;

        inner_span.hash_stable(hcx, hasher);

        // Combining the DefPathHashes directly is faster than feeding them
        // into the hasher. Because we use a commutative combine, we also don't
        // have to sort the array.
        let item_ids_hash = item_ids
            .iter()
            .map(|id| {
                let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx);
                debug_assert_eq!(local_id, hir::ItemLocalId::from_u32(0));
                def_path_hash.0
            }).fold(Fingerprint::ZERO, |a, b| {
                a.combine_commutative(b)
            });

        item_ids.len().hash_stable(hcx, hasher);
        item_ids_hash.hash_stable(hcx, hasher);
    }
}

impl_stable_hash_for_spanned!(hir::VariantKind);

impl<'a> HashStable<StableHashingContext<'a>> for hir::Item {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::Item {
            ident,
            ref attrs,
            hir_id: _,
            ref node,
            ref vis,
            span
        } = *self;

        hcx.hash_hir_item_like(|hcx| {
            ident.name.hash_stable(hcx, hasher);
            attrs.hash_stable(hcx, hasher);
            node.hash_stable(hcx, hasher);
            vis.hash_stable(hcx, hasher);
            span.hash_stable(hcx, hasher);
        });
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::Body {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        let hir::Body {
            ref arguments,
            ref value,
            is_generator,
        } = *self;

        hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| {
            arguments.hash_stable(hcx, hasher);
            value.hash_stable(hcx, hasher);
            is_generator.hash_stable(hcx, hasher);
        });
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::BodyId {
    type KeyType = (DefPathHash, hir::ItemLocalId);

    #[inline]
    fn to_stable_hash_key(&self,
                          hcx: &StableHashingContext<'a>)
                          -> (DefPathHash, hir::ItemLocalId) {
        let hir::BodyId { hir_id } = *self;
        hir_id.to_stable_hash_key(hcx)
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::def_id::DefIndex {

    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.local_def_path_hash(*self).hash_stable(hcx, hasher);
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>>
for hir::def_id::DefIndex {
    type KeyType = DefPathHash;

    #[inline]
    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
         hcx.local_def_path_hash(*self)
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for crate::middle::lang_items::LangItem {
    fn hash_stable<W: StableHasherResult>(&self,
                                          _: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        ::std::hash::Hash::hash(self, hasher);
    }
}

impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitCandidate {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'a>,
                                          hasher: &mut StableHasher<W>) {
        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
            let &hir::TraitCandidate {
                def_id,
                import_ids,
            } = &self;

            def_id.hash_stable(hcx, hasher);
            // We only use the outermost import NodeId as key
            import_ids.first().hash_stable(hcx, hasher);
        });
    }
}

impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::TraitCandidate {
    type KeyType = (DefPathHash, Option<(DefPathHash, hir::ItemLocalId)>);

    fn to_stable_hash_key(&self,
                          hcx: &StableHashingContext<'a>)
                          -> Self::KeyType {
        let hir::TraitCandidate {
            def_id,
            import_ids,
        } = self;

        let first_import_id = import_ids.first().map(|node_id| hcx.node_to_hir_id(*node_id))
                                           .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner),
                                                          hir_id.local_id));
        (hcx.def_path_hash(*def_id), first_import_id)
    }
}

impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InlineAttr {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'hir>,
                                          hasher: &mut StableHasher<W>) {
        mem::discriminant(self).hash_stable(hcx, hasher);
    }
}

impl<'hir> HashStable<StableHashingContext<'hir>> for attr::OptimizeAttr {
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut StableHashingContext<'hir>,
                                          hasher: &mut StableHasher<W>) {
        mem::discriminant(self).hash_stable(hcx, hasher);
    }
}
<|endoftext|>


<commit_before>//! Abstractions for segment registers.

use super::model_specific::Msr;
use crate::{PrivilegeLevel, VirtAddr};
use bit_field::BitField;
use core::fmt;
// imports for intra doc links
#[cfg(doc)]
use crate::registers::control::Cr4Flags;

/// An x86 segment
///
/// Segment registers on x86 are 16-bit [`SegmentSelector`]s, which index into
/// the [`GlobalDescriptorTable`](crate::structures::gdt::GlobalDescriptorTable). The
/// corresponding GDT entry is used to
/// configure the segment itself. Note that most segmentation functionality is
/// disabled in 64-bit mode. See the individual segments for more information.
pub trait Segment {
    /// Returns the current value of the segment register.
    fn get_reg() -> SegmentSelector;
    /// Reload the segment register. Depending on the segment, this may also
    /// reconfigure the corresponding segment.
    ///
    /// ## Safety
    ///
    /// This function is unsafe because the caller must ensure that `sel`
    /// is a valid segment descriptor, and that reconfiguring the segment will
    /// not cause undefined behavior.
    unsafe fn set_reg(sel: SegmentSelector);
}

/// An x86 segment which is actually used in 64-bit mode
///
/// While most segments are unused in 64-bit mode, the FS and GS segments are
/// still partially used. Only the 64-bit segment base address is used, and this
/// address can be set via the GDT, or by using the `FSGSBASE` instructions.
pub trait Segment64: Segment {
    /// MSR containing the segment base. This MSR can be used to set the base
    /// when [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is **not** set.
    const BASE: Msr;
    /// Reads the segment base address
    ///
    /// ## Exceptions
    ///
    /// If [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is not set, this instruction will throw a `#UD`.
    fn read_base() -> VirtAddr;
    /// Writes the segment base address
    ///
    /// ## Exceptions
    ///
    /// If [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is not set, this instruction will throw a `#UD`.
    ///
    /// ## Safety
    ///
    /// The caller must ensure that this write operation has no unsafe side
    /// effects, as the segment base address might be in use.
    unsafe fn write_base(base: VirtAddr);
}

/// Specifies which element to load into a segment from
/// descriptor tables (i.e., is a index to LDT or GDT table
/// with some additional flags).
///
/// See Intel 3a, Section 3.4.2 "Segment Selectors"
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct SegmentSelector(pub u16);

impl SegmentSelector {
    /// Creates a new SegmentSelector
    ///
    /// # Arguments
    ///  * `index`: index in GDT or LDT array (not the offset)
    ///  * `rpl`: the requested privilege level
    #[inline]
    pub const fn new(index: u16, rpl: PrivilegeLevel) -> SegmentSelector {
        SegmentSelector(index << 3 | (rpl as u16))
    }

    /// Returns the GDT index.
    #[inline]
    pub fn index(self) -> u16 {
        self.0 >> 3
    }

    /// Returns the requested privilege level.
    #[inline]
    pub fn rpl(self) -> PrivilegeLevel {
        PrivilegeLevel::from_u16(self.0.get_bits(0..2))
    }

    /// Set the privilege level for this Segment selector.
    #[inline]
    pub fn set_rpl(&mut self, rpl: PrivilegeLevel) {
        self.0.set_bits(0..2, rpl as u16);
    }
}

impl fmt::Debug for SegmentSelector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut s = f.debug_struct("SegmentSelector");
        s.field("index", &self.index());
        s.field("rpl", &self.rpl());
        s.finish()
    }
}

/// Code Segment
///
/// The segment base and limit are unused in 64-bit mode. Only the L (long), D
/// (default operation size), and DPL (descriptor privilege-level) fields of the
/// descriptor are recognized. So changing the segment register can be used to
/// change privilege level or enable/disable long mode.
#[derive(Debug)]
pub struct CS;

/// Stack Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
/// However, in ring 3, the SS register still has to point to a valid
/// [`Descriptor`](crate::structures::gdt::Descriptor) (it cannot be zero). This
/// means a user-mode read/write segment descriptor must be present in the GDT.
///
/// This register is also set by the `syscall`/`sysret` and
/// `sysenter`/`sysexit` instructions (even on 64-bit transitions). This is to
/// maintain symmetry with 32-bit transitions where setting SS actually will
/// actually have an effect.
#[derive(Debug)]
pub struct SS;

/// Data Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
#[derive(Debug)]
pub struct DS;

/// ES Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
#[derive(Debug)]
pub struct ES;

/// FS Segment
///
/// Only base is used in 64-bit mode, see [`Segment64`]. This is often used in
/// user-mode for Thread-Local Storage (TLS).
#[derive(Debug)]
pub struct FS;

/// GS Segment
///
/// Only base is used in 64-bit mode, see [`Segment64`]. In kernel-mode, the GS
/// base often points to a per-cpu kernel data structure.
#[derive(Debug)]
pub struct GS;
<commit_msg>Correct wrong comment. Unlike the comment suggests, more descriptors fields than mentioned in the comment are recognized by the CPU<commit_after>//! Abstractions for segment registers.

use super::model_specific::Msr;
use crate::{PrivilegeLevel, VirtAddr};
use bit_field::BitField;
use core::fmt;
// imports for intra doc links
#[cfg(doc)]
use crate::registers::control::Cr4Flags;

/// An x86 segment
///
/// Segment registers on x86 are 16-bit [`SegmentSelector`]s, which index into
/// the [`GlobalDescriptorTable`](crate::structures::gdt::GlobalDescriptorTable). The
/// corresponding GDT entry is used to
/// configure the segment itself. Note that most segmentation functionality is
/// disabled in 64-bit mode. See the individual segments for more information.
pub trait Segment {
    /// Returns the current value of the segment register.
    fn get_reg() -> SegmentSelector;
    /// Reload the segment register. Depending on the segment, this may also
    /// reconfigure the corresponding segment.
    ///
    /// ## Safety
    ///
    /// This function is unsafe because the caller must ensure that `sel`
    /// is a valid segment descriptor, and that reconfiguring the segment will
    /// not cause undefined behavior.
    unsafe fn set_reg(sel: SegmentSelector);
}

/// An x86 segment which is actually used in 64-bit mode
///
/// While most segments are unused in 64-bit mode, the FS and GS segments are
/// still partially used. Only the 64-bit segment base address is used, and this
/// address can be set via the GDT, or by using the `FSGSBASE` instructions.
pub trait Segment64: Segment {
    /// MSR containing the segment base. This MSR can be used to set the base
    /// when [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is **not** set.
    const BASE: Msr;
    /// Reads the segment base address
    ///
    /// ## Exceptions
    ///
    /// If [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is not set, this instruction will throw a `#UD`.
    fn read_base() -> VirtAddr;
    /// Writes the segment base address
    ///
    /// ## Exceptions
    ///
    /// If [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is not set, this instruction will throw a `#UD`.
    ///
    /// ## Safety
    ///
    /// The caller must ensure that this write operation has no unsafe side
    /// effects, as the segment base address might be in use.
    unsafe fn write_base(base: VirtAddr);
}

/// Specifies which element to load into a segment from
/// descriptor tables (i.e., is a index to LDT or GDT table
/// with some additional flags).
///
/// See Intel 3a, Section 3.4.2 "Segment Selectors"
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct SegmentSelector(pub u16);

impl SegmentSelector {
    /// Creates a new SegmentSelector
    ///
    /// # Arguments
    ///  * `index`: index in GDT or LDT array (not the offset)
    ///  * `rpl`: the requested privilege level
    #[inline]
    pub const fn new(index: u16, rpl: PrivilegeLevel) -> SegmentSelector {
        SegmentSelector(index << 3 | (rpl as u16))
    }

    /// Returns the GDT index.
    #[inline]
    pub fn index(self) -> u16 {
        self.0 >> 3
    }

    /// Returns the requested privilege level.
    #[inline]
    pub fn rpl(self) -> PrivilegeLevel {
        PrivilegeLevel::from_u16(self.0.get_bits(0..2))
    }

    /// Set the privilege level for this Segment selector.
    #[inline]
    pub fn set_rpl(&mut self, rpl: PrivilegeLevel) {
        self.0.set_bits(0..2, rpl as u16);
    }
}

impl fmt::Debug for SegmentSelector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut s = f.debug_struct("SegmentSelector");
        s.field("index", &self.index());
        s.field("rpl", &self.rpl());
        s.finish()
    }
}

/// Code Segment
///
/// Most fields like the segment base and limit are unused in 64-bit mode.
/// Only the LONG_MODE, PRESENT, USER_SEGMENT, EXECUTABLE, DEFAULT_SIZE (default operand size)
/// and DPL_RING_3 (descriptor privilege-level) fields of the
/// descriptor are recognized by the CPU. Some of them (e.g. DEFAULT_SIZE) are required to hold
/// a specific value and can't be changed. Others like the DPL_RING_3 and LONG_MODE
/// can be used to change privilege level or enable/disable long mode.
#[derive(Debug)]
pub struct CS;

/// Stack Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
/// However, in ring 3, the SS register still has to point to a valid
/// [`Descriptor`](crate::structures::gdt::Descriptor) (it cannot be zero). This
/// means a user-mode read/write segment descriptor must be present in the GDT.
///
/// This register is also set by the `syscall`/`sysret` and
/// `sysenter`/`sysexit` instructions (even on 64-bit transitions). This is to
/// maintain symmetry with 32-bit transitions where setting SS actually will
/// actually have an effect.
#[derive(Debug)]
pub struct SS;

/// Data Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
#[derive(Debug)]
pub struct DS;

/// ES Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
#[derive(Debug)]
pub struct ES;

/// FS Segment
///
/// Only base is used in 64-bit mode, see [`Segment64`]. This is often used in
/// user-mode for Thread-Local Storage (TLS).
#[derive(Debug)]
pub struct FS;

/// GS Segment
///
/// Only base is used in 64-bit mode, see [`Segment64`]. In kernel-mode, the GS
/// base often points to a per-cpu kernel data structure.
#[derive(Debug)]
pub struct GS;
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use hyper::method::Method;

use response;
use request::RequestBuilder;
use request::DoRequest;

impl<'t> RequestBuilder<'t, response::Image> {
    pub fn transfer(self, region: &str) -> RequestBuilder<'t, response::Action> {
        // POST: "https://api.digitalocean.com/v2/images/$ID/actions"
        // body:
        //      "type" : "transfer"
        //      "region" : "nyc2"
        RequestBuilder {
            method: Method::Post,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: Some(format!("{{\"type\":\"transfer\",\"region\":{:?}}}", region))
        }
    }
    pub fn convert(self) -> RequestBuilder<'t, response::Action> {
        // POST: "https://api.digitalocean.com/v2/images/7938291/actions"
        // body:
        //      "type" : "convert"
        RequestBuilder {
            method: Method::Post,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: Some(r#"{"type":"convert"}"#.to_owned())
        }
    }
    pub fn actions(mut self) -> RequestBuilder<'t, response::Actions> {
        // GET: https://api.digitalocean.com/v2/images/$SLUG
        self.url.push_str("/actions");
        RequestBuilder {
            url: self.url,
            auth: self.auth,
            method: self.method,
            resp_t: PhantomData,
            body: None
        }
    }
    pub fn action(mut self, id: &str) -> RequestBuilder<'t, response::Action> {
        // GET: https://api.digitalocean.com/v2/images/$IMG_ID/actions/$ID
        self.url.push_str("/actions/");
        self.url.push_str(id);
        RequestBuilder::new(self.auth, self.url)
    }

    pub fn update(self, name: &str) -> RequestBuilder<'t, response::Image> {
        // PUT: https://api.digitalocean.com/v2/images/$ID
        // body:
        //      "name" : "new_name"
        RequestBuilder {
            method: Method::Put,
            url: self.url,
            auth: self.auth,
            resp_t: PhantomData,
            body: Some(format!("{{\"name\":{:?}}}", name))
        }
    }
    pub fn delete(self) -> RequestBuilder<'t, response::HeaderOnly> {
        // DELETE: https://api.digitalocean.com/v2/images/$ID
        RequestBuilder {
            method: Method::Delete,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: None
        }
    }
}

impl<'t> RequestBuilder<'t, response::Images> {
    pub fn applications(mut self) -> RequestBuilder<'t, response::Images> {
        // GET: https://api.digitalocean.com/v2/images?type=applications
        self.url.push_str("?type=applications");
        self
    }
    pub fn distributions(mut self) -> RequestBuilder<'t, response::Images> {
        // GET: https://api.digitalocean.com/v2/images?type=distribtutions
        self.url.push_str("?type=distributions");
        self
    }
    pub fn private(mut self) -> RequestBuilder<'t, response::Images> {
        // GET: https://api.digitalocean.com/v2/images?type=private
        self.url.push_str("?type=private");
        self
    }
    pub fn available(mut self) -> RequestBuilder<'t, response::Images> {
        // GET: https://api.digitalocean.com/v2/images?type=available
        self.url.push_str("?type=available");
        self
    }

}

impl<'t> DoRequest<response::Image> for RequestBuilder<'t, response::Image> {}
<commit_msg>fix: fixes image API<commit_after>use std::marker::PhantomData;

use hyper::method::Method;

use response;
use request::RequestBuilder;
use request::DoRequest;

impl<'t> RequestBuilder<'t, response::Image> {
    pub fn transfer(mut self, region: &str) -> RequestBuilder<'t, response::Action> {
        // POST: "https://api.digitalocean.com/v2/images/$ID/actions"
        // body:
        //      "type" : "transfer"
        //      "region" : "nyc2"
        self.url.push_str("/actions");
        RequestBuilder {
            method: Method::Post,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: Some(format!("{{\"type\":\"transfer\",\"region\":{:?}}}", region))
        }
    }
    pub fn convert(mut self) -> RequestBuilder<'t, response::Action> {
        // POST: "https://api.digitalocean.com/v2/images/$ID/actions"
        // body:
        //      "type" : "convert"
        self.url.push_str("/actions");
        RequestBuilder {
            method: Method::Post,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: Some(r#"{"type":"convert"}"#.to_owned())
        }
    }
    pub fn actions(mut self) -> RequestBuilder<'t, response::Actions> {
        // GET: "https://api.digitalocean.com/v2/images/$ID/actions"
        self.url.push_str("/actions");
        RequestBuilder {
            url: self.url,
            auth: self.auth,
            method: self.method,
            resp_t: PhantomData,
            body: None
        }
    }
    pub fn action(mut self, id: &str) -> RequestBuilder<'t, response::Action> {
        // GET: https://api.digitalocean.com/v2/images/$IMG_ID/actions/$ID
        self.url.push_str("/actions/");
        self.url.push_str(id);
        RequestBuilder::new(self.auth, self.url)
    }

    pub fn update(self, name: &str) -> RequestBuilder<'t, response::Image> {
        // PUT: https://api.digitalocean.com/v2/images/$ID
        // body:
        //      "name" : "new_name"
        RequestBuilder {
            method: Method::Put,
            url: self.url,
            auth: self.auth,
            resp_t: PhantomData,
            body: Some(format!("{{\"name\":{:?}}}", name))
        }
    }
    pub fn delete(self) -> RequestBuilder<'t, response::HeaderOnly> {
        // DELETE: https://api.digitalocean.com/v2/images/$ID
        RequestBuilder {
            method: Method::Delete,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: None
        }
    }
}

impl<'t> RequestBuilder<'t, response::Images> {
    pub fn applications(mut self) -> RequestBuilder<'t, response::Images> {
        // GET: https://api.digitalocean.com/v2/images?type=applications
        self.url.push_str("?type=applications");
        self
    }
    pub fn distributions(mut self) -> RequestBuilder<'t, response::Images> {
        // GET: https://api.digitalocean.com/v2/images?type=distribtutions
        self.url.push_str("?type=distributions");
        self
    }
    pub fn private(mut self) -> RequestBuilder<'t, response::Images> {
        // GET: https://api.digitalocean.com/v2/images?type=private
        self.url.push_str("?type=private");
        self
    }
    pub fn available(mut self) -> RequestBuilder<'t, response::Images> {
        // GET: https://api.digitalocean.com/v2/images?type=available
        self.url.push_str("?type=available");
        self
    }

}

impl<'t> DoRequest<response::Image> for RequestBuilder<'t, response::Image> {}
<|endoftext|>


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

// http://dev.w3.org/csswg/css-syntax/#parsing

use std::ascii::AsciiExt;
use std::str::CowString;
use super::{Token, Parser, Delimiter};

#[deriving(Copy, Eq, PartialEq)]
pub enum Priority {
    Normal,
    Important,
}

pub fn parse_important(input: &mut Parser) -> Result<Priority, ()> {
    match input.next() {
        Ok(Token::Delim('!')) => {
            match try!(input.next()) {
                Token::Ident(ref value) if value.eq_ignore_ascii_case("important") => {
                    Ok(Priority::Important)
                }
                token => input.unexpected(token)
            }
        }
        token => {
            input.push_back_result(token);
            Ok(Priority::Normal)
        }
    }
}

pub enum AtRulePrelude<P, R> {
    WithoutBlock(R),
    WithBlock(P),
    OptionalBlock(P),
}

// FIXME: Use associated types
pub trait DeclarationParser<D> {
    fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<D, ()> {
        let _ = name;
        let _ = input;
        Err(())
    }
}

pub trait AtRuleParser<P, R> {
    fn parse_prelude(&mut self, name: &str, input: &mut Parser)
                     -> Result<AtRulePrelude<P, R>, ()> {
        let _ = name;
        let _ = input;
        Err(())
    }

    fn parse_block(&mut self, prelude: P, input: &mut Parser) -> Result<R, ()> {
        let _ = prelude;
        let _ = input;
        Err(())
    }

    /// An `OptionalBlock` prelude was followed by `;`
    fn rule_without_block(&mut self, prelude: P) -> Result<R, ()> {
        let _ = prelude;
        Err(())
    }
}

pub trait QualifiedRuleParser<P, R> {
    fn parse_prelude(&mut self, input: &mut Parser) -> Result<P, ()> {
        let _ = input;
        Err(())
    }

    fn parse_block(&mut self, prelude: P, input: &mut Parser) -> Result<R, ()> {
        let _ = prelude;
        let _ = input;
        Err(())
    }
}

pub struct DeclarationListParser<'i: 't, 't: 'a, 'a, AP, I, P>
where P: DeclarationParser<I> + AtRuleParser<AP, I> {
    input: &'a mut Parser<'i, 't>,
    parser: P,
}

impl<'i, 't, 'a, AP, I, P> DeclarationListParser<'i, 't, 'a, AP, I, P>
where P: DeclarationParser<I> + AtRuleParser<AP, I> {
    pub fn new(input: &'a mut Parser<'i, 't>, parser: P)
               -> DeclarationListParser<'i, 't, 'a, AP, I, P> {
        DeclarationListParser {
            input: input,
            parser: parser,
        }
    }
}

impl<'i, 't, 'a, AP, I, P> Iterator<Result<I, ()>>
for DeclarationListParser<'i, 't, 'a, AP, I, P>
where P: DeclarationParser<I> + AtRuleParser<AP, I> {
    fn next(&mut self) -> Option<Result<I, ()>> {
        loop {
            match self.input.next() {
                Ok(Token::Semicolon) => {}
                Ok(Token::Ident(name)) => {
                    return Some(parse_declaration(name, self.input, &mut self.parser))
                }
                Ok(Token::AtKeyword(name)) => {
                    return Some(parse_at_rule(name, self.input, &mut self.parser))
                }
                Ok(_) => {
                    return Some(self.input.err_consume_until_after(Delimiter::Semicolon))
                }
                Err(()) => return None,
            }
        }
    }
}

pub struct RuleListParser<'i: 't, 't: 'a, 'a, R, QP, AP, P>
where P: QualifiedRuleParser<QP, R> + AtRuleParser<AP, R> {
    input: &'a mut Parser<'i, 't>,
    parser: P,
    is_stylesheet: bool,
}

impl<'i: 't, 't: 'a, 'a, R, QP, AP, P> RuleListParser<'i, 't, 'a, R, QP, AP, P>
where P: QualifiedRuleParser<QP, R> + AtRuleParser<AP, R> {
    pub fn new_for_stylesheet(input: &'a mut Parser<'i, 't>, parser: P)
                              -> RuleListParser<'i, 't, 'a, R, QP, AP, P> {
        RuleListParser {
            input: input,
            parser: parser,
            is_stylesheet: true,
        }
    }

    pub fn new_for_nested_rule(input: &'a mut Parser<'i, 't>, parser: P)
                               -> RuleListParser<'i, 't, 'a, R, QP, AP, P> {
        RuleListParser {
            input: input,
            parser: parser,
            is_stylesheet: false,
        }
    }
}

impl<'i, 't, 'a, R, QP, AP, P> Iterator<Result<R, ()>>
for RuleListParser<'i, 't, 'a, R, QP, AP, P>
where P: QualifiedRuleParser<QP, R> + AtRuleParser<AP, R> {
    fn next(&mut self) -> Option<Result<R, ()>> {
        loop {
            match self.input.next() {
                Ok(Token::CDO) | Ok(Token::CDC) if self.is_stylesheet => {}
                Ok(Token::AtKeyword(name)) => {
                    return Some(parse_at_rule(name, self.input, &mut self.parser))
                }
                Ok(token) => {
                    self.input.push_back(token);
                    return Some(parse_qualified_rule(self.input, &mut self.parser))
                }
                Err(()) => return None,
            }
        }
    }
}

pub fn parse_one_declaration<D, P>(input: &mut Parser, parser: &mut P)
                                   -> Result<D, ()>
                                   where P: DeclarationParser<D> {
    input.parse_entirely(|input| {
        let name = try!(input.expect_ident());
        try!(input.expect_colon());
        parser.parse_value(name.as_slice(), input)
    })
}

pub fn parse_one_rule<QP, AP, R, P>(input: &mut Parser, parser: &mut P)
                                    -> Result<R, ()>
                                    where P: QualifiedRuleParser<QP, R> + AtRuleParser<AP, R> {
    input.parse_entirely(|input| {
        match try!(input.next()) {
            Token::AtKeyword(name) => {
                parse_at_rule(name, input, parser)
            }
            token => {
                input.push_back(token);
                parse_qualified_rule(input, parser)
            }
        }
    })
}

fn parse_declaration<D, P>(name: CowString, input: &mut Parser, parser: &mut P)
                           -> Result<D, ()>
                           where P: DeclarationParser<D> {
    let result = input.parse_until_before(Delimiter::Semicolon).parse_entirely(|input| {
        try!(input.expect_colon());
        parser.parse_value(name.as_slice(), input)
    });
    match input.next() {
        Ok(Token::Semicolon) | Err(()) => result,
        _ => input.err_consume_until_after(Delimiter::Semicolon)
    }
}

fn parse_at_rule<R, AP, P>(name: CowString, input: &mut Parser, parser: &mut P)
                           -> Result<R, ()>
                           where P: AtRuleParser<AP, R> {
    let delimiters = Delimiter::Semicolon | Delimiter::CurlyBracketBlock;
    let result = try!(input.parse_until_before(delimiters).parse_entirely(|input| {
        parser.parse_prelude(name.as_slice(), input)
    }).or_else(|()| input.err_consume_until_after(delimiters)));
    match result {
        AtRulePrelude::WithoutBlock(rule) => {
            match input.next() {
                Ok(Token::Semicolon) | Err(()) => Ok(rule),
                _ => input.err_consume_until_after(delimiters)
            }
        }
        AtRulePrelude::WithBlock(prelude) => {
            match input.next() {
                Ok(Token::CurlyBracketBlock) => {
                    // FIXME: Make parse_entirely take `FnOnce`
                    // and remove this Option dance.
                    let mut prelude = Some(prelude);
                    input.parse_nested_block().parse_entirely(|input| {
                        parser.parse_block(prelude.take().unwrap(), input)
                    })
                }
                _ => input.err_consume_until_after(delimiters)
            }
        }
        AtRulePrelude::OptionalBlock(prelude) => {
            match input.next() {
                Ok(Token::Semicolon) | Err(()) => parser.rule_without_block(prelude),
                Ok(Token::CurlyBracketBlock) => {
                    // FIXME: Make parse_entirely take `FnOnce`
                    // and remove this Option dance.
                    let mut prelude = Some(prelude);
                    input.parse_nested_block().parse_entirely(|input| {
                        parser.parse_block(prelude.take().unwrap(), input)
                    })
                }
                _ => input.err_consume_until_after(delimiters)
            }
        }
    }
}

fn parse_qualified_rule<R, AP, P>(input: &mut Parser, parser: &mut P)
                                  -> Result<R, ()>
                                  where P: QualifiedRuleParser<AP, R> {
    let prelude = try!(input.parse_until_before(Delimiter::CurlyBracketBlock)
                            .parse_entirely(|input| {
        parser.parse_prelude(input)
    }).or_else(|()| input.err_consume_until_after(Delimiter::CurlyBracketBlock)));
    match input.next() {
        Ok(Token::CurlyBracketBlock) => {
            // FIXME: Make parse_entirely take `FnOnce`
            // and remove this Option dance.
            let mut prelude = Some(prelude);
            input.parse_nested_block().parse_entirely(|input| {
                parser.parse_block(prelude.take().unwrap(), input)
            })
        }
        _ => input.err_consume_until_after(Delimiter::CurlyBracketBlock)
    }
}
<commit_msg>Make {Rule,Declaration}RuleListParser fields public.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// http://dev.w3.org/csswg/css-syntax/#parsing

use std::ascii::AsciiExt;
use std::str::CowString;
use super::{Token, Parser, Delimiter};

#[deriving(Copy, Eq, PartialEq)]
pub enum Priority {
    Normal,
    Important,
}

pub fn parse_important(input: &mut Parser) -> Result<Priority, ()> {
    match input.next() {
        Ok(Token::Delim('!')) => {
            match try!(input.next()) {
                Token::Ident(ref value) if value.eq_ignore_ascii_case("important") => {
                    Ok(Priority::Important)
                }
                token => input.unexpected(token)
            }
        }
        token => {
            input.push_back_result(token);
            Ok(Priority::Normal)
        }
    }
}

pub enum AtRulePrelude<P, R> {
    WithoutBlock(R),
    WithBlock(P),
    OptionalBlock(P),
}

// FIXME: Use associated types
pub trait DeclarationParser<D> {
    fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<D, ()> {
        let _ = name;
        let _ = input;
        Err(())
    }
}

pub trait AtRuleParser<P, R> {
    fn parse_prelude(&mut self, name: &str, input: &mut Parser)
                     -> Result<AtRulePrelude<P, R>, ()> {
        let _ = name;
        let _ = input;
        Err(())
    }

    fn parse_block(&mut self, prelude: P, input: &mut Parser) -> Result<R, ()> {
        let _ = prelude;
        let _ = input;
        Err(())
    }

    /// An `OptionalBlock` prelude was followed by `;`
    fn rule_without_block(&mut self, prelude: P) -> Result<R, ()> {
        let _ = prelude;
        Err(())
    }
}

pub trait QualifiedRuleParser<P, R> {
    fn parse_prelude(&mut self, input: &mut Parser) -> Result<P, ()> {
        let _ = input;
        Err(())
    }

    fn parse_block(&mut self, prelude: P, input: &mut Parser) -> Result<R, ()> {
        let _ = prelude;
        let _ = input;
        Err(())
    }
}

pub struct DeclarationListParser<'i: 't, 't: 'a, 'a, AP, I, P>
where P: DeclarationParser<I> + AtRuleParser<AP, I> {
    pub input: &'a mut Parser<'i, 't>,
    pub parser: P,
}

impl<'i, 't, 'a, AP, I, P> DeclarationListParser<'i, 't, 'a, AP, I, P>
where P: DeclarationParser<I> + AtRuleParser<AP, I> {
    pub fn new(input: &'a mut Parser<'i, 't>, parser: P)
               -> DeclarationListParser<'i, 't, 'a, AP, I, P> {
        DeclarationListParser {
            input: input,
            parser: parser,
        }
    }
}

impl<'i, 't, 'a, AP, I, P> Iterator<Result<I, ()>>
for DeclarationListParser<'i, 't, 'a, AP, I, P>
where P: DeclarationParser<I> + AtRuleParser<AP, I> {
    fn next(&mut self) -> Option<Result<I, ()>> {
        loop {
            match self.input.next() {
                Ok(Token::Semicolon) => {}
                Ok(Token::Ident(name)) => {
                    return Some(parse_declaration(name, self.input, &mut self.parser))
                }
                Ok(Token::AtKeyword(name)) => {
                    return Some(parse_at_rule(name, self.input, &mut self.parser))
                }
                Ok(_) => {
                    return Some(self.input.err_consume_until_after(Delimiter::Semicolon))
                }
                Err(()) => return None,
            }
        }
    }
}

pub struct RuleListParser<'i: 't, 't: 'a, 'a, R, QP, AP, P>
where P: QualifiedRuleParser<QP, R> + AtRuleParser<AP, R> {
    pub input: &'a mut Parser<'i, 't>,
    pub parser: P,
    is_stylesheet: bool,
}

impl<'i: 't, 't: 'a, 'a, R, QP, AP, P> RuleListParser<'i, 't, 'a, R, QP, AP, P>
where P: QualifiedRuleParser<QP, R> + AtRuleParser<AP, R> {
    pub fn new_for_stylesheet(input: &'a mut Parser<'i, 't>, parser: P)
                              -> RuleListParser<'i, 't, 'a, R, QP, AP, P> {
        RuleListParser {
            input: input,
            parser: parser,
            is_stylesheet: true,
        }
    }

    pub fn new_for_nested_rule(input: &'a mut Parser<'i, 't>, parser: P)
                               -> RuleListParser<'i, 't, 'a, R, QP, AP, P> {
        RuleListParser {
            input: input,
            parser: parser,
            is_stylesheet: false,
        }
    }
}

impl<'i, 't, 'a, R, QP, AP, P> Iterator<Result<R, ()>>
for RuleListParser<'i, 't, 'a, R, QP, AP, P>
where P: QualifiedRuleParser<QP, R> + AtRuleParser<AP, R> {
    fn next(&mut self) -> Option<Result<R, ()>> {
        loop {
            match self.input.next() {
                Ok(Token::CDO) | Ok(Token::CDC) if self.is_stylesheet => {}
                Ok(Token::AtKeyword(name)) => {
                    return Some(parse_at_rule(name, self.input, &mut self.parser))
                }
                Ok(token) => {
                    self.input.push_back(token);
                    return Some(parse_qualified_rule(self.input, &mut self.parser))
                }
                Err(()) => return None,
            }
        }
    }
}

pub fn parse_one_declaration<D, P>(input: &mut Parser, parser: &mut P)
                                   -> Result<D, ()>
                                   where P: DeclarationParser<D> {
    input.parse_entirely(|input| {
        let name = try!(input.expect_ident());
        try!(input.expect_colon());
        parser.parse_value(name.as_slice(), input)
    })
}

pub fn parse_one_rule<QP, AP, R, P>(input: &mut Parser, parser: &mut P)
                                    -> Result<R, ()>
                                    where P: QualifiedRuleParser<QP, R> + AtRuleParser<AP, R> {
    input.parse_entirely(|input| {
        match try!(input.next()) {
            Token::AtKeyword(name) => {
                parse_at_rule(name, input, parser)
            }
            token => {
                input.push_back(token);
                parse_qualified_rule(input, parser)
            }
        }
    })
}

fn parse_declaration<D, P>(name: CowString, input: &mut Parser, parser: &mut P)
                           -> Result<D, ()>
                           where P: DeclarationParser<D> {
    let result = input.parse_until_before(Delimiter::Semicolon).parse_entirely(|input| {
        try!(input.expect_colon());
        parser.parse_value(name.as_slice(), input)
    });
    match input.next() {
        Ok(Token::Semicolon) | Err(()) => result,
        _ => input.err_consume_until_after(Delimiter::Semicolon)
    }
}

fn parse_at_rule<R, AP, P>(name: CowString, input: &mut Parser, parser: &mut P)
                           -> Result<R, ()>
                           where P: AtRuleParser<AP, R> {
    let delimiters = Delimiter::Semicolon | Delimiter::CurlyBracketBlock;
    let result = try!(input.parse_until_before(delimiters).parse_entirely(|input| {
        parser.parse_prelude(name.as_slice(), input)
    }).or_else(|()| input.err_consume_until_after(delimiters)));
    match result {
        AtRulePrelude::WithoutBlock(rule) => {
            match input.next() {
                Ok(Token::Semicolon) | Err(()) => Ok(rule),
                _ => input.err_consume_until_after(delimiters)
            }
        }
        AtRulePrelude::WithBlock(prelude) => {
            match input.next() {
                Ok(Token::CurlyBracketBlock) => {
                    // FIXME: Make parse_entirely take `FnOnce`
                    // and remove this Option dance.
                    let mut prelude = Some(prelude);
                    input.parse_nested_block().parse_entirely(|input| {
                        parser.parse_block(prelude.take().unwrap(), input)
                    })
                }
                _ => input.err_consume_until_after(delimiters)
            }
        }
        AtRulePrelude::OptionalBlock(prelude) => {
            match input.next() {
                Ok(Token::Semicolon) | Err(()) => parser.rule_without_block(prelude),
                Ok(Token::CurlyBracketBlock) => {
                    // FIXME: Make parse_entirely take `FnOnce`
                    // and remove this Option dance.
                    let mut prelude = Some(prelude);
                    input.parse_nested_block().parse_entirely(|input| {
                        parser.parse_block(prelude.take().unwrap(), input)
                    })
                }
                _ => input.err_consume_until_after(delimiters)
            }
        }
    }
}

fn parse_qualified_rule<R, AP, P>(input: &mut Parser, parser: &mut P)
                                  -> Result<R, ()>
                                  where P: QualifiedRuleParser<AP, R> {
    let prelude = try!(input.parse_until_before(Delimiter::CurlyBracketBlock)
                            .parse_entirely(|input| {
        parser.parse_prelude(input)
    }).or_else(|()| input.err_consume_until_after(Delimiter::CurlyBracketBlock)));
    match input.next() {
        Ok(Token::CurlyBracketBlock) => {
            // FIXME: Make parse_entirely take `FnOnce`
            // and remove this Option dance.
            let mut prelude = Some(prelude);
            input.parse_nested_block().parse_entirely(|input| {
                parser.parse_block(prelude.take().unwrap(), input)
            })
        }
        _ => input.err_consume_until_after(Delimiter::CurlyBracketBlock)
    }
}
<|endoftext|>