<commit_before>use super::*;
use redox::*;

impl Editor {
    /// Redraw the window
    pub fn redraw(&mut self) {
        // TODO: Only draw when relevant for the window
        let x = self.x();
        let y = self.y();
        // Redraw window
        self.window.set([0, 0, 0, 255]);

        self.window.rect(8 * (x - self.scroll_y) as isize,
                         16 * (y - self.scroll_x) as isize,
                         8,
                         16,
                         [255, 255, 255, 255]);

        for (y, row) in self.text.iter().enumerate() {
            for (x, c) in row.iter().enumerate() {
                if self.x() == x && self.y() == y {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     [0, 0, 0, 255]);
                } else {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     [255, 255, 255, 255]);
                }
            }
        }
        let h = self.window.height();
        let w = self.window.width();
        self.window.rect(0, h as isize - 18, w, 18, [74, 74, 74, 255]);

        for (n, c) in (if self.status_bar.mode.len() > w / (8 * 4) {
            self.status_bar.mode.chars().take(w / (8 * 4) - 5).chain(vec!['.', '.', '.']).collect::<Vec<_>>()
        } else {
            self.status_bar.mode.chars().collect()
        }).into_iter().enumerate() {
            self.window.char(n as isize * 8, h as isize - 16 - 1, c, [255, 255, 255, 255]);
        }

        self.window.sync();
    }
}

pub struct StatusBar {
    pub mode: String,
    pub file: String,
    pub cmd: String,
    pub msg: String,
}

impl StatusBar {
    pub fn new() -> Self {
        StatusBar {
            mode: String::new(),
            file: String::new(),
            cmd: String::new(),
            msg: String::new(),
        }
    }
}
<commit_msg>Switch to Color structs<commit_after>use super::*;
use redox::*;

impl Editor {
    /// Redraw the window
    pub fn redraw(&mut self) {
        // TODO: Only draw when relevant for the window
        let x = self.x();
        let y = self.y();
        // Redraw window
        self.window.set(Color::BLACK);

        self.window.rect(8 * (x - self.scroll_y) as isize,
                         16 * (y - self.scroll_x) as isize,
                         8,
                         16,
                         Color::WHITE);

        for (y, row) in self.text.iter().enumerate() {
            for (x, c) in row.iter().enumerate() {
                if self.x() == x && self.y() == y {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     Color::BLACK);
                } else {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     Color::WHITE);
                }
            }
        }
        let h = self.window.height();
        let w = self.window.width();
        self.window.rect(0, h as isize - 18, w, 18, Color::rgba(74, 74, 74, 255));

        for (n, c) in (if self.status_bar.mode.len() > w / (8 * 4) {
            self.status_bar.mode.chars().take(w / (8 * 4) - 5).chain(vec!['.', '.', '.']).collect::<Vec<_>>()
        } else {
            self.status_bar.mode.chars().collect()
        }).into_iter().enumerate() {
            self.window.char(n as isize * 8, h as isize - 16 - 1, c, Color::BLACK);
        }

        self.window.sync();
    }
}

pub struct StatusBar {
    pub mode: String,
    pub file: String,
    pub cmd: String,
    pub msg: String,
}

impl StatusBar {
    pub fn new() -> Self {
        StatusBar {
            mode: String::new(),
            file: String::new(),
            cmd: String::new(),
            msg: String::new(),
        }
    }
}
<|endoftext|>


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

//! The `bitflags!` macro generates a `struct` that holds a set of C-style
//! bitmask flags. It is useful for creating typesafe wrappers for C APIs.
//!
//! The flags should only be defined for integer types, otherwise unexpected
//! type errors may occur at compile time.
//!
//! # Example
//!
//! ~~~rust
//! #[feature(phase)];
//! #[phase(syntax)] extern crate collections;
//!
//! bitflags!(Flags: u32 {
//!     FlagA       = 0x00000001,
//!     FlagB       = 0x00000010,
//!     FlagC       = 0x00000100,
//!     FlagABC     = FlagA.bits
//!                 | FlagB.bits
//!                 | FlagC.bits
//! })
//!
//! fn main() {
//!     let e1 = FlagA | FlagC;
//!     let e2 = FlagB | FlagC;
//!     assert!((e1 | e2) == FlagABC);   // union
//!     assert!((e1 & e2) == FlagC);     // intersection
//!     assert!((e1 - e2) == FlagA);     // set difference
//! }
//! ~~~
//!
//! The generated `struct`s can also be extended with type and trait implementations:
//!
//! ~~~rust
//! #[feature(phase)];
//! #[phase(syntax)] extern crate collections;
//!
//! use std::fmt;
//!
//! bitflags!(Flags: u32 {
//!     FlagA   = 0x00000001,
//!     FlagB   = 0x00000010
//! })
//!
//! impl Flags {
//!     pub fn clear(&mut self) {
//!         self.bits = 0;  // The `bits` field can be accessed from within the
//!                         // same module where the `bitflags!` macro was invoked.
//!     }
//! }
//!
//! impl fmt::Show for Flags {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f.buf, "hi!")
//!     }
//! }
//!
//! fn main() {
//!     let mut flags = FlagA | FlagB;
//!     flags.clear();
//!     assert!(flags.is_empty());
//!     assert_eq!(format!("{}", flags), ~"hi!");
//! }
//! ~~~
//!
//! # Operators
//!
//! The following operator traits are implemented for the generated `struct`:
//!
//! - `BitOr`: union
//! - `BitAnd`: intersection
//! - `Sub`: set difference
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//!
//! - `empty`: an empty set of flags
//! - `bits`: the raw value of the flags currently stored
//! - `is_empty`: `true` if no flags are currently stored
//! - `intersects`: `true` if there are flags common to both `self` and `other`
//! - `contains`: `true` all of the flags in `other` are contained within `self`
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place

#[macro_export]
macro_rules! bitflags(
    ($BitFlags:ident: $T:ty {
        $($Flag:ident = $value:expr),+
    }) => (
        #[deriving(Eq, TotalEq, Clone)]
        pub struct $BitFlags {
            priv bits: $T,
        }

        $(pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the raw value of the flags currently stored.
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            pub fn contains(&self, other: $BitFlags) -> bool {
                (self & other) == other
            }

            /// Inserts the specified flags in-place.
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }
        }

        impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl Sub<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }
    )
)

#[cfg(test)]
mod tests {
    bitflags!(Flags: u32 {
        FlagA       = 0x00000001,
        FlagB       = 0x00000010,
        FlagC       = 0x00000100,
        FlagABC     = FlagA.bits
                    | FlagB.bits
                    | FlagC.bits
    })

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0x00000000);
        assert_eq!(FlagA.bits(), 0x00000001);
        assert_eq!(FlagABC.bits(), 0x00000111);
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);   // union
        assert!((e1 & e2) == FlagC);     // intersection
        assert!((e1 - e2) == FlagA);     // set difference
    }
}
<commit_msg>Document derived traits for bitset! macro<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `bitflags!` macro generates a `struct` that holds a set of C-style
//! bitmask flags. It is useful for creating typesafe wrappers for C APIs.
//!
//! The flags should only be defined for integer types, otherwise unexpected
//! type errors may occur at compile time.
//!
//! # Example
//!
//! ~~~rust
//! #[feature(phase)];
//! #[phase(syntax)] extern crate collections;
//!
//! bitflags!(Flags: u32 {
//!     FlagA       = 0x00000001,
//!     FlagB       = 0x00000010,
//!     FlagC       = 0x00000100,
//!     FlagABC     = FlagA.bits
//!                 | FlagB.bits
//!                 | FlagC.bits
//! })
//!
//! fn main() {
//!     let e1 = FlagA | FlagC;
//!     let e2 = FlagB | FlagC;
//!     assert!((e1 | e2) == FlagABC);   // union
//!     assert!((e1 & e2) == FlagC);     // intersection
//!     assert!((e1 - e2) == FlagA);     // set difference
//! }
//! ~~~
//!
//! The generated `struct`s can also be extended with type and trait implementations:
//!
//! ~~~rust
//! #[feature(phase)];
//! #[phase(syntax)] extern crate collections;
//!
//! use std::fmt;
//!
//! bitflags!(Flags: u32 {
//!     FlagA   = 0x00000001,
//!     FlagB   = 0x00000010
//! })
//!
//! impl Flags {
//!     pub fn clear(&mut self) {
//!         self.bits = 0;  // The `bits` field can be accessed from within the
//!                         // same module where the `bitflags!` macro was invoked.
//!     }
//! }
//!
//! impl fmt::Show for Flags {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f.buf, "hi!")
//!     }
//! }
//!
//! fn main() {
//!     let mut flags = FlagA | FlagB;
//!     flags.clear();
//!     assert!(flags.is_empty());
//!     assert_eq!(format!("{}", flags), ~"hi!");
//! }
//! ~~~
//!
//! # Derived traits
//!
//! The `Eq`, `TotalEq`, and `Clone` traits are automatically derived for the
//! `struct` using the `deriving` attribute.
//!
//! # Operators
//!
//! The following operator traits are implemented for the generated `struct`:
//!
//! - `BitOr`: union
//! - `BitAnd`: intersection
//! - `Sub`: set difference
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//!
//! - `empty`: an empty set of flags
//! - `bits`: the raw value of the flags currently stored
//! - `is_empty`: `true` if no flags are currently stored
//! - `intersects`: `true` if there are flags common to both `self` and `other`
//! - `contains`: `true` all of the flags in `other` are contained within `self`
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place

#[macro_export]
macro_rules! bitflags(
    ($BitFlags:ident: $T:ty {
        $($Flag:ident = $value:expr),+
    }) => (
        #[deriving(Eq, TotalEq, Clone)]
        pub struct $BitFlags {
            priv bits: $T,
        }

        $(pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the raw value of the flags currently stored.
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            pub fn contains(&self, other: $BitFlags) -> bool {
                (self & other) == other
            }

            /// Inserts the specified flags in-place.
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }
        }

        impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl Sub<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }
    )
)

#[cfg(test)]
mod tests {
    bitflags!(Flags: u32 {
        FlagA       = 0x00000001,
        FlagB       = 0x00000010,
        FlagC       = 0x00000100,
        FlagABC     = FlagA.bits
                    | FlagB.bits
                    | FlagC.bits
    })

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0x00000000);
        assert_eq!(FlagA.bits(), 0x00000001);
        assert_eq!(FlagABC.bits(), 0x00000111);
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);   // union
        assert!((e1 & e2) == FlagC);     // intersection
        assert!((e1 - e2) == FlagA);     // set difference
    }
}
<|endoftext|>


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

/*!
 * Generic hashing support.
 *
 * This module provides a generic way to compute the hash of a value. The
 * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
 *
 * # Example
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 *
 * #[deriving(Hash)]
 * struct Person {
 *     id: uint,
 *     name: String,
 *     phone: u64,
 * }
 *
 * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) != hash::hash(&person2));
 * ```
 *
 * If you need more control over how a value is hashed, you need to implement
 * the trait `Hash`:
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 * use std::hash::sip::SipState;
 *
 * struct Person {
 *     id: uint,
 *     name: String,
 *     phone: u64,
 * }
 *
 * impl Hash for Person {
 *     fn hash(&self, state: &mut SipState) {
 *         self.id.hash(state);
 *         self.phone.hash(state);
 *     }
 * }
 *
 * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) == hash::hash(&person2));
 * ```
 */

#![allow(unused_must_use)]

use core::prelude::*;

use alloc::boxed::Box;
use alloc::rc::Rc;
use core::intrinsics::TypeId;
use core::mem;

use vec::Vec;

/// Reexport the `sip::hash` function as our default hasher.
pub use hash = self::sip::hash;

pub mod sip;

/// A trait that represents a hashable type. The `S` type parameter is an
/// abstract hash state that is used by the `Hash` to compute the hash.
/// It defaults to `std::hash::sip::SipState`.
pub trait Hash<S = sip::SipState> {
    /// Compute a hash of the value.
    fn hash(&self, state: &mut S);
}

/// A trait that computes a hash for a value. The main users of this trait are
/// containers like `HashMap`, which need a generic way hash multiple types.
pub trait Hasher<S> {
    /// Compute a hash of the value.
    fn hash<T: Hash<S>>(&self, value: &T) -> u64;
}

pub trait Writer {
    fn write(&mut self, bytes: &[u8]);
}

//////////////////////////////////////////////////////////////////////////////

macro_rules! impl_hash {
    ($ty:ident, $uty:ident) => {
        impl<S: Writer> Hash<S> for $ty {
            #[inline]
            fn hash(&self, state: &mut S) {
                let a: [u8, ..::core::$ty::BYTES] = unsafe {
                    mem::transmute((*self as $uty).to_le() as $ty)
                };
                state.write(a.as_slice())
            }
        }
    }
}

impl_hash!(u8, u8)
impl_hash!(u16, u16)
impl_hash!(u32, u32)
impl_hash!(u64, u64)
impl_hash!(uint, uint)
impl_hash!(i8, u8)
impl_hash!(i16, u16)
impl_hash!(i32, u32)
impl_hash!(i64, u64)
impl_hash!(int, uint)

impl<S: Writer> Hash<S> for bool {
    #[inline]
    fn hash(&self, state: &mut S) {
        (*self as u8).hash(state);
    }
}

impl<S: Writer> Hash<S> for char {
    #[inline]
    fn hash(&self, state: &mut S) {
        (*self as u32).hash(state);
    }
}

impl<'a, S: Writer> Hash<S> for &'a str {
    #[inline]
    fn hash(&self, state: &mut S) {
        state.write(self.as_bytes());
        0xffu8.hash(state)
    }
}

macro_rules! impl_hash_tuple(
    () => (
        impl<S: Writer> Hash<S> for () {
            #[inline]
            fn hash(&self, state: &mut S) {
                state.write([]);
            }
        }
    );

    ($A:ident $($B:ident)*) => (
        impl<
            S: Writer,
            $A: Hash<S> $(, $B: Hash<S>)*
        > Hash<S> for ($A, $($B),*) {
            #[inline]
            fn hash(&self, state: &mut S) {
                match *self {
                    (ref $A, $(ref $B),*) => {
                        $A.hash(state);
                        $(
                            $B.hash(state);
                        )*
                    }
                }
            }
        }

        impl_hash_tuple!($($B)*)
    );
)

impl_hash_tuple!(a0 a1 a2 a3 a4 a5 a6 a7)

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a [T] {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.len().hash(state);
        for elt in self.iter() {
            elt.hash(state);
        }
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut [T] {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state);
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Box<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Option<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        match *self {
            Some(ref x) => {
                0u8.hash(state);
                x.hash(state);
            }
            None => {
                1u8.hash(state);
            }
        }
    }
}

impl<S: Writer, T> Hash<S> for *const T {
    #[inline]
    fn hash(&self, state: &mut S) {
        // NB: raw-pointer Hash does _not_ dereference
        // to the target; it just gives you the pointer-bytes.
        (*self as uint).hash(state);
    }
}

impl<S: Writer, T> Hash<S> for *mut T {
    #[inline]
    fn hash(&self, state: &mut S) {
        // NB: raw-pointer Hash does _not_ dereference
        // to the target; it just gives you the pointer-bytes.
        (*self as uint).hash(state);
    }
}

impl<S: Writer> Hash<S> for TypeId {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.hash().hash(state)
    }
}

impl<S: Writer, T: Hash<S>, U: Hash<S>> Hash<S> for Result<T, U> {
    #[inline]
    fn hash(&self, state: &mut S) {
        match *self {
            Ok(ref t) => { 1u.hash(state); t.hash(state); }
            Err(ref t) => { 2u.hash(state); t.hash(state); }
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use std::prelude::*;
    use std::mem;

    use slice::ImmutableVector;
    use super::{Hash, Hasher, Writer};

    struct MyWriterHasher;

    impl Hasher<MyWriter> for MyWriterHasher {
        fn hash<T: Hash<MyWriter>>(&self, value: &T) -> u64 {
            let mut state = MyWriter { hash: 0 };
            value.hash(&mut state);
            state.hash
        }
    }

    struct MyWriter {
        hash: u64,
    }

    impl Writer for MyWriter {
        // Most things we'll just add up the bytes.
        fn write(&mut self, buf: &[u8]) {
            for byte in buf.iter() {
                self.hash += *byte as u64;
            }
        }
    }

    #[test]
    fn test_writer_hasher() {
        let hasher = MyWriterHasher;

        assert_eq!(hasher.hash(&()), 0);

        assert_eq!(hasher.hash(&5u8), 5);
        assert_eq!(hasher.hash(&5u16), 5);
        assert_eq!(hasher.hash(&5u32), 5);
        assert_eq!(hasher.hash(&5u64), 5);
        assert_eq!(hasher.hash(&5u), 5);

        assert_eq!(hasher.hash(&5i8), 5);
        assert_eq!(hasher.hash(&5i16), 5);
        assert_eq!(hasher.hash(&5i32), 5);
        assert_eq!(hasher.hash(&5i64), 5);
        assert_eq!(hasher.hash(&5i), 5);

        assert_eq!(hasher.hash(&false), 0);
        assert_eq!(hasher.hash(&true), 1);

        assert_eq!(hasher.hash(&'a'), 97);

        assert_eq!(hasher.hash(&("a")), 97 + 0xFF);
        assert_eq!(hasher.hash(& &[1u8, 2u8, 3u8]), 9);

        unsafe {
            let ptr: *const int = mem::transmute(5i);
            assert_eq!(hasher.hash(&ptr), 5);
        }

        unsafe {
            let ptr: *mut int = mem::transmute(5i);
            assert_eq!(hasher.hash(&ptr), 5);
        }
    }

    struct Custom {
        hash: u64
    }

    impl Hash<u64> for Custom {
        fn hash(&self, state: &mut u64) {
            *state = self.hash;
        }
    }

    #[test]
    fn test_custom_state() {
        let custom = Custom { hash: 5 };
        let mut state = 0;
        custom.hash(&mut state);
        assert_eq!(state, 5);
    }
}
<commit_msg>Implement Hash for tuples of up to arity 12. Also change the style to be consistent with core::tuple<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * Generic hashing support.
 *
 * This module provides a generic way to compute the hash of a value. The
 * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
 *
 * # Example
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 *
 * #[deriving(Hash)]
 * struct Person {
 *     id: uint,
 *     name: String,
 *     phone: u64,
 * }
 *
 * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) != hash::hash(&person2));
 * ```
 *
 * If you need more control over how a value is hashed, you need to implement
 * the trait `Hash`:
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 * use std::hash::sip::SipState;
 *
 * struct Person {
 *     id: uint,
 *     name: String,
 *     phone: u64,
 * }
 *
 * impl Hash for Person {
 *     fn hash(&self, state: &mut SipState) {
 *         self.id.hash(state);
 *         self.phone.hash(state);
 *     }
 * }
 *
 * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) == hash::hash(&person2));
 * ```
 */

#![allow(unused_must_use)]

use core::prelude::*;

use alloc::boxed::Box;
use alloc::rc::Rc;
use core::intrinsics::TypeId;
use core::mem;

use vec::Vec;

/// Reexport the `sip::hash` function as our default hasher.
pub use hash = self::sip::hash;

pub mod sip;

/// A trait that represents a hashable type. The `S` type parameter is an
/// abstract hash state that is used by the `Hash` to compute the hash.
/// It defaults to `std::hash::sip::SipState`.
pub trait Hash<S = sip::SipState> {
    /// Compute a hash of the value.
    fn hash(&self, state: &mut S);
}

/// A trait that computes a hash for a value. The main users of this trait are
/// containers like `HashMap`, which need a generic way hash multiple types.
pub trait Hasher<S> {
    /// Compute a hash of the value.
    fn hash<T: Hash<S>>(&self, value: &T) -> u64;
}

pub trait Writer {
    fn write(&mut self, bytes: &[u8]);
}

//////////////////////////////////////////////////////////////////////////////

macro_rules! impl_hash {
    ($ty:ident, $uty:ident) => {
        impl<S: Writer> Hash<S> for $ty {
            #[inline]
            fn hash(&self, state: &mut S) {
                let a: [u8, ..::core::$ty::BYTES] = unsafe {
                    mem::transmute((*self as $uty).to_le() as $ty)
                };
                state.write(a.as_slice())
            }
        }
    }
}

impl_hash!(u8, u8)
impl_hash!(u16, u16)
impl_hash!(u32, u32)
impl_hash!(u64, u64)
impl_hash!(uint, uint)
impl_hash!(i8, u8)
impl_hash!(i16, u16)
impl_hash!(i32, u32)
impl_hash!(i64, u64)
impl_hash!(int, uint)

impl<S: Writer> Hash<S> for bool {
    #[inline]
    fn hash(&self, state: &mut S) {
        (*self as u8).hash(state);
    }
}

impl<S: Writer> Hash<S> for char {
    #[inline]
    fn hash(&self, state: &mut S) {
        (*self as u32).hash(state);
    }
}

impl<'a, S: Writer> Hash<S> for &'a str {
    #[inline]
    fn hash(&self, state: &mut S) {
        state.write(self.as_bytes());
        0xffu8.hash(state)
    }
}

macro_rules! impl_hash_tuple(
    () => (
        impl<S: Writer> Hash<S> for () {
            #[inline]
            fn hash(&self, state: &mut S) {
                state.write([]);
            }
        }
    );

    ( $($name:ident)+) => (
        impl<S: Writer, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
            #[allow(uppercase_variables)]
            #[inline]
            fn hash(&self, state: &mut S) {
                match *self {
                    ($(ref $name,)*) => {
                        $(
                            $name.hash(state);
                        )*
                    }
                }
            }
        }
    );
)

impl_hash_tuple!()
impl_hash_tuple!(A)
impl_hash_tuple!(A B)
impl_hash_tuple!(A B C)
impl_hash_tuple!(A B C D)
impl_hash_tuple!(A B C D E)
impl_hash_tuple!(A B C D E F)
impl_hash_tuple!(A B C D E F G)
impl_hash_tuple!(A B C D E F G H)
impl_hash_tuple!(A B C D E F G H I)
impl_hash_tuple!(A B C D E F G H I J)
impl_hash_tuple!(A B C D E F G H I J K)
impl_hash_tuple!(A B C D E F G H I J K L)

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a [T] {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.len().hash(state);
        for elt in self.iter() {
            elt.hash(state);
        }
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut [T] {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state);
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Box<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Option<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        match *self {
            Some(ref x) => {
                0u8.hash(state);
                x.hash(state);
            }
            None => {
                1u8.hash(state);
            }
        }
    }
}

impl<S: Writer, T> Hash<S> for *const T {
    #[inline]
    fn hash(&self, state: &mut S) {
        // NB: raw-pointer Hash does _not_ dereference
        // to the target; it just gives you the pointer-bytes.
        (*self as uint).hash(state);
    }
}

impl<S: Writer, T> Hash<S> for *mut T {
    #[inline]
    fn hash(&self, state: &mut S) {
        // NB: raw-pointer Hash does _not_ dereference
        // to the target; it just gives you the pointer-bytes.
        (*self as uint).hash(state);
    }
}

impl<S: Writer> Hash<S> for TypeId {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.hash().hash(state)
    }
}

impl<S: Writer, T: Hash<S>, U: Hash<S>> Hash<S> for Result<T, U> {
    #[inline]
    fn hash(&self, state: &mut S) {
        match *self {
            Ok(ref t) => { 1u.hash(state); t.hash(state); }
            Err(ref t) => { 2u.hash(state); t.hash(state); }
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use std::prelude::*;
    use std::mem;

    use slice::ImmutableVector;
    use super::{Hash, Hasher, Writer};

    struct MyWriterHasher;

    impl Hasher<MyWriter> for MyWriterHasher {
        fn hash<T: Hash<MyWriter>>(&self, value: &T) -> u64 {
            let mut state = MyWriter { hash: 0 };
            value.hash(&mut state);
            state.hash
        }
    }

    struct MyWriter {
        hash: u64,
    }

    impl Writer for MyWriter {
        // Most things we'll just add up the bytes.
        fn write(&mut self, buf: &[u8]) {
            for byte in buf.iter() {
                self.hash += *byte as u64;
            }
        }
    }

    #[test]
    fn test_writer_hasher() {
        let hasher = MyWriterHasher;

        assert_eq!(hasher.hash(&()), 0);

        assert_eq!(hasher.hash(&5u8), 5);
        assert_eq!(hasher.hash(&5u16), 5);
        assert_eq!(hasher.hash(&5u32), 5);
        assert_eq!(hasher.hash(&5u64), 5);
        assert_eq!(hasher.hash(&5u), 5);

        assert_eq!(hasher.hash(&5i8), 5);
        assert_eq!(hasher.hash(&5i16), 5);
        assert_eq!(hasher.hash(&5i32), 5);
        assert_eq!(hasher.hash(&5i64), 5);
        assert_eq!(hasher.hash(&5i), 5);

        assert_eq!(hasher.hash(&false), 0);
        assert_eq!(hasher.hash(&true), 1);

        assert_eq!(hasher.hash(&'a'), 97);

        assert_eq!(hasher.hash(&("a")), 97 + 0xFF);
        assert_eq!(hasher.hash(& &[1u8, 2u8, 3u8]), 9);

        unsafe {
            let ptr: *const int = mem::transmute(5i);
            assert_eq!(hasher.hash(&ptr), 5);
        }

        unsafe {
            let ptr: *mut int = mem::transmute(5i);
            assert_eq!(hasher.hash(&ptr), 5);
        }
    }

    struct Custom {
        hash: u64
    }

    impl Hash<u64> for Custom {
        fn hash(&self, state: &mut u64) {
            *state = self.hash;
        }
    }

    #[test]
    fn test_custom_state() {
        let custom = Custom { hash: 5 };
        let mut state = 0;
        custom.hash(&mut state);
        assert_eq!(state, 5);
    }
}
<|endoftext|>


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

//! Support for inlining external documentation into the current AST.

use syntax::ast;
use syntax::ast_util;
use syntax::attr::AttrMetaMethods;

use rustc::metadata::csearch;
use rustc::metadata::decoder;
use rustc::middle::ty;

use core;
use doctree;
use clean;

use super::Clean;

/// Attempt to inline the definition of a local node id into this AST.
///
/// This function will fetch the definition of the id specified, and if it is
/// from another crate it will attempt to inline the documentation from the
/// other crate into this crate.
///
/// This is primarily used for `pub use` statements which are, in general,
/// implementation details. Inlining the documentation should help provide a
/// better experience when reading the documentation in this use case.
///
/// The returned value is `None` if the `id` could not be inlined, and `Some`
/// of a vector of items if it was successfully expanded.
pub fn try_inline(id: ast::NodeId) -> Option<Vec<clean::Item>> {
    let cx = ::ctxtkey.get().unwrap();
    let tcx = match cx.maybe_typed {
        core::Typed(ref tycx) => tycx,
        core::NotTyped(_) => return None,
    };
    let def = match tcx.def_map.borrow().find(&id) {
        Some(def) => *def,
        None => return None,
    };
    let did = ast_util::def_id_of_def(def);
    if ast_util::is_local(did) { return None }
    try_inline_def(&**cx, tcx, def)
}

fn try_inline_def(cx: &core::DocContext,
                  tcx: &ty::ctxt,
                  def: ast::Def) -> Option<Vec<clean::Item>> {
    let mut ret = Vec::new();
    let did = ast_util::def_id_of_def(def);
    let inner = match def {
        ast::DefTrait(did) => {
            record_extern_fqn(cx, did, clean::TypeTrait);
            clean::TraitItem(build_external_trait(tcx, did))
        }
        ast::DefFn(did, style) => {
            // If this function is a tuple struct constructor, we just skip it
            if csearch::get_tuple_struct_definition_if_ctor(&tcx.sess.cstore,
                                                            did).is_some() {
                return None
            }
            record_extern_fqn(cx, did, clean::TypeFunction);
            clean::FunctionItem(build_external_function(tcx, did, style))
        }
        ast::DefStruct(did) => {
            record_extern_fqn(cx, did, clean::TypeStruct);
            ret.extend(build_impls(cx, tcx, did).move_iter());
            clean::StructItem(build_struct(tcx, did))
        }
        ast::DefTy(did) => {
            record_extern_fqn(cx, did, clean::TypeEnum);
            ret.extend(build_impls(cx, tcx, did).move_iter());
            build_type(tcx, did)
        }
        // Assume that the enum type is reexported next to the variant, and
        // variants don't show up in documentation specially.
        ast::DefVariant(..) => return Some(Vec::new()),
        ast::DefMod(did) => {
            record_extern_fqn(cx, did, clean::TypeModule);
            clean::ModuleItem(build_module(cx, tcx, did))
        }
        _ => return None,
    };
    let fqn = csearch::get_item_path(tcx, did);
    cx.inlined.borrow_mut().get_mut_ref().insert(did);
    ret.push(clean::Item {
        source: clean::Span::empty(),
        name: Some(fqn.last().unwrap().to_str().to_string()),
        attrs: load_attrs(tcx, did),
        inner: inner,
        visibility: Some(ast::Public),
        def_id: did,
    });
    Some(ret)
}

pub fn load_attrs(tcx: &ty::ctxt, did: ast::DefId) -> Vec<clean::Attribute> {
    let mut attrs = Vec::new();
    csearch::get_item_attrs(&tcx.sess.cstore, did, |v| {
        attrs.extend(v.move_iter().map(|mut a| {
            // FIXME this isn't quite always true, it's just true about 99% of
            //       the time when dealing with documentation. For example,
            //       this would treat doc comments of the form `#[doc = "foo"]`
            //       incorrectly.
            if a.name().get() == "doc" && a.value_str().is_some() {
                a.node.is_sugared_doc = true;
            }
            a.clean()
        }));
    });
    attrs
}

/// Record an external fully qualified name in the external_paths cache.
///
/// These names are used later on by HTML rendering to generate things like
/// source links back to the original item.
pub fn record_extern_fqn(cx: &core::DocContext,
                         did: ast::DefId,
                         kind: clean::TypeKind) {
    match cx.maybe_typed {
        core::Typed(ref tcx) => {
            let fqn = csearch::get_item_path(tcx, did);
            let fqn = fqn.move_iter().map(|i| i.to_str()).collect();
            cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
        }
        core::NotTyped(..) => {}
    }
}

pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait {
    let def = ty::lookup_trait_def(tcx, did);
    let methods = ty::trait_methods(tcx, did).clean();
    let provided = ty::provided_trait_methods(tcx, did);
    let mut methods = methods.move_iter().map(|meth| {
        if provided.iter().any(|a| a.def_id == meth.def_id) {
            clean::Provided(meth)
        } else {
            clean::Required(meth)
        }
    });
    clean::Trait {
        generics: def.generics.clean(),
        methods: methods.collect(),
        parents: Vec::new(), // FIXME: this is likely wrong
    }
}

fn build_external_function(tcx: &ty::ctxt,
                           did: ast::DefId,
                           style: ast::FnStyle) -> clean::Function {
    let t = ty::lookup_item_type(tcx, did);
    clean::Function {
        decl: match ty::get(t.ty).sty {
            ty::ty_bare_fn(ref f) => (did, &f.sig).clean(),
            _ => fail!("bad function"),
        },
        generics: t.generics.clean(),
        fn_style: style,
    }
}

fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct {
    use syntax::parse::token::special_idents::unnamed_field;

    let t = ty::lookup_item_type(tcx, did);
    let fields = ty::lookup_struct_fields(tcx, did);

    clean::Struct {
        struct_type: match fields.as_slice() {
            [] => doctree::Unit,
            [ref f] if f.name == unnamed_field.name => doctree::Newtype,
            [ref f, ..] if f.name == unnamed_field.name => doctree::Tuple,
            _ => doctree::Plain,
        },
        generics: t.generics.clean(),
        fields: fields.iter().map(|f| f.clean()).collect(),
        fields_stripped: false,
    }
}

fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
    let t = ty::lookup_item_type(tcx, did);
    match ty::get(t.ty).sty {
        ty::ty_enum(edid, _) => {
            return clean::EnumItem(clean::Enum {
                generics: t.generics.clean(),
                variants_stripped: false,
                variants: ty::enum_variants(tcx, edid).clean(),
            })
        }
        _ => {}
    }

    clean::TypedefItem(clean::Typedef {
        type_: t.ty.clean(),
        generics: t.generics.clean(),
    })
}

fn build_impls(cx: &core::DocContext,
               tcx: &ty::ctxt,
               did: ast::DefId) -> Vec<clean::Item> {
    ty::populate_implementations_for_type_if_necessary(tcx, did);
    let mut impls = Vec::new();

    match tcx.inherent_impls.borrow().find(&did) {
        None => {}
        Some(i) => {
            impls.extend(i.borrow().iter().map(|&did| { build_impl(cx, tcx, did) }));
        }
    }

    // If this is the first time we've inlined something from this crate, then
    // we inline *all* impls from the crate into this crate. Note that there's
    // currently no way for us to filter this based on type, and we likely need
    // many impls for a variety of reasons.
    //
    // Primarily, the impls will be used to populate the documentation for this
    // type being inlined, but impls can also be used when generating
    // documentation for primitives (no way to find those specifically).
    if cx.populated_crate_impls.borrow_mut().insert(did.krate) {
        csearch::each_top_level_item_of_crate(&tcx.sess.cstore,
                                              did.krate,
                                              |def, _, _| {
            populate_impls(cx, tcx, def, &mut impls)
        });

        fn populate_impls(cx: &core::DocContext,
                          tcx: &ty::ctxt,
                          def: decoder::DefLike,
                          impls: &mut Vec<Option<clean::Item>>) {
            match def {
                decoder::DlImpl(did) => impls.push(build_impl(cx, tcx, did)),
                decoder::DlDef(ast::DefMod(did)) => {
                    csearch::each_child_of_item(&tcx.sess.cstore,
                                                did,
                                                |def, _, _| {
                        populate_impls(cx, tcx, def, impls)
                    })
                }
                _ => {}
            }
        }
    }

    impls.move_iter().filter_map(|a| a).collect()
}

fn build_impl(cx: &core::DocContext,
              tcx: &ty::ctxt,
              did: ast::DefId) -> Option<clean::Item> {
    if !cx.inlined.borrow_mut().get_mut_ref().insert(did) {
        return None
    }

    let associated_trait = csearch::get_impl_trait(tcx, did);
    let attrs = load_attrs(tcx, did);
    let ty = ty::lookup_item_type(tcx, did);
    let methods = csearch::get_impl_methods(&tcx.sess.cstore,
                                            did).iter().filter_map(|did| {
        let method = ty::method(tcx, *did);
        if method.vis != ast::Public && associated_trait.is_none() {
            return None
        }
        let mut item = ty::method(tcx, *did).clean();
        item.inner = match item.inner.clone() {
            clean::TyMethodItem(clean::TyMethod {
                fn_style, decl, self_, generics
            }) => {
                clean::MethodItem(clean::Method {
                    fn_style: fn_style,
                    decl: decl,
                    self_: self_,
                    generics: generics,
                })
            }
            _ => fail!("not a tymethod"),
        };
        Some(item)
    }).collect();
    Some(clean::Item {
        inner: clean::ImplItem(clean::Impl {
            derived: clean::detect_derived(attrs.as_slice()),
            trait_: associated_trait.clean().map(|bound| {
                match bound {
                    clean::TraitBound(ty) => ty,
                    clean::RegionBound => unreachable!(),
                }
            }),
            for_: ty.ty.clean(),
            generics: ty.generics.clean(),
            methods: methods,
        }),
        source: clean::Span::empty(),
        name: None,
        attrs: attrs,
        visibility: Some(ast::Inherited),
        def_id: did,
    })
}

fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
                did: ast::DefId) -> clean::Module {
    let mut items = Vec::new();

    // FIXME: this doesn't handle reexports inside the module itself.
    //        Should they be handled?
    csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, vis| {
        if vis != ast::Public { return }
        match def {
            decoder::DlDef(def) => {
                match try_inline_def(cx, tcx, def) {
                    Some(i) => items.extend(i.move_iter()),
                    None => {}
                }
            }
            // All impls were inlined above
            decoder::DlImpl(..) => {}
            decoder::DlField => fail!("unimplemented field"),
        }
    });

    clean::Module {
        items: items,
        is_crate: false,
    }
}
<commit_msg>rustdoc: Include supertraits on inlined traits<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Support for inlining external documentation into the current AST.

use syntax::ast;
use syntax::ast_util;
use syntax::attr::AttrMetaMethods;

use rustc::metadata::csearch;
use rustc::metadata::decoder;
use rustc::middle::ty;

use core;
use doctree;
use clean;

use super::Clean;

/// Attempt to inline the definition of a local node id into this AST.
///
/// This function will fetch the definition of the id specified, and if it is
/// from another crate it will attempt to inline the documentation from the
/// other crate into this crate.
///
/// This is primarily used for `pub use` statements which are, in general,
/// implementation details. Inlining the documentation should help provide a
/// better experience when reading the documentation in this use case.
///
/// The returned value is `None` if the `id` could not be inlined, and `Some`
/// of a vector of items if it was successfully expanded.
pub fn try_inline(id: ast::NodeId) -> Option<Vec<clean::Item>> {
    let cx = ::ctxtkey.get().unwrap();
    let tcx = match cx.maybe_typed {
        core::Typed(ref tycx) => tycx,
        core::NotTyped(_) => return None,
    };
    let def = match tcx.def_map.borrow().find(&id) {
        Some(def) => *def,
        None => return None,
    };
    let did = ast_util::def_id_of_def(def);
    if ast_util::is_local(did) { return None }
    try_inline_def(&**cx, tcx, def)
}

fn try_inline_def(cx: &core::DocContext,
                  tcx: &ty::ctxt,
                  def: ast::Def) -> Option<Vec<clean::Item>> {
    let mut ret = Vec::new();
    let did = ast_util::def_id_of_def(def);
    let inner = match def {
        ast::DefTrait(did) => {
            record_extern_fqn(cx, did, clean::TypeTrait);
            clean::TraitItem(build_external_trait(tcx, did))
        }
        ast::DefFn(did, style) => {
            // If this function is a tuple struct constructor, we just skip it
            if csearch::get_tuple_struct_definition_if_ctor(&tcx.sess.cstore,
                                                            did).is_some() {
                return None
            }
            record_extern_fqn(cx, did, clean::TypeFunction);
            clean::FunctionItem(build_external_function(tcx, did, style))
        }
        ast::DefStruct(did) => {
            record_extern_fqn(cx, did, clean::TypeStruct);
            ret.extend(build_impls(cx, tcx, did).move_iter());
            clean::StructItem(build_struct(tcx, did))
        }
        ast::DefTy(did) => {
            record_extern_fqn(cx, did, clean::TypeEnum);
            ret.extend(build_impls(cx, tcx, did).move_iter());
            build_type(tcx, did)
        }
        // Assume that the enum type is reexported next to the variant, and
        // variants don't show up in documentation specially.
        ast::DefVariant(..) => return Some(Vec::new()),
        ast::DefMod(did) => {
            record_extern_fqn(cx, did, clean::TypeModule);
            clean::ModuleItem(build_module(cx, tcx, did))
        }
        _ => return None,
    };
    let fqn = csearch::get_item_path(tcx, did);
    cx.inlined.borrow_mut().get_mut_ref().insert(did);
    ret.push(clean::Item {
        source: clean::Span::empty(),
        name: Some(fqn.last().unwrap().to_str().to_string()),
        attrs: load_attrs(tcx, did),
        inner: inner,
        visibility: Some(ast::Public),
        def_id: did,
    });
    Some(ret)
}

pub fn load_attrs(tcx: &ty::ctxt, did: ast::DefId) -> Vec<clean::Attribute> {
    let mut attrs = Vec::new();
    csearch::get_item_attrs(&tcx.sess.cstore, did, |v| {
        attrs.extend(v.move_iter().map(|mut a| {
            // FIXME this isn't quite always true, it's just true about 99% of
            //       the time when dealing with documentation. For example,
            //       this would treat doc comments of the form `#[doc = "foo"]`
            //       incorrectly.
            if a.name().get() == "doc" && a.value_str().is_some() {
                a.node.is_sugared_doc = true;
            }
            a.clean()
        }));
    });
    attrs
}

/// Record an external fully qualified name in the external_paths cache.
///
/// These names are used later on by HTML rendering to generate things like
/// source links back to the original item.
pub fn record_extern_fqn(cx: &core::DocContext,
                         did: ast::DefId,
                         kind: clean::TypeKind) {
    match cx.maybe_typed {
        core::Typed(ref tcx) => {
            let fqn = csearch::get_item_path(tcx, did);
            let fqn = fqn.move_iter().map(|i| i.to_str()).collect();
            cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
        }
        core::NotTyped(..) => {}
    }
}

pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait {
    let def = ty::lookup_trait_def(tcx, did);
    let methods = ty::trait_methods(tcx, did).clean();
    let provided = ty::provided_trait_methods(tcx, did);
    let mut methods = methods.move_iter().map(|meth| {
        if provided.iter().any(|a| a.def_id == meth.def_id) {
            clean::Provided(meth)
        } else {
            clean::Required(meth)
        }
    });
    let supertraits = ty::trait_supertraits(tcx, did);
    let mut parents = supertraits.iter().map(|i| {
        match i.clean() {
            clean::TraitBound(ty) => ty,
            clean::RegionBound => unreachable!()
        }
    });

    clean::Trait {
        generics: def.generics.clean(),
        methods: methods.collect(),
        parents: parents.collect()
    }
}

fn build_external_function(tcx: &ty::ctxt,
                           did: ast::DefId,
                           style: ast::FnStyle) -> clean::Function {
    let t = ty::lookup_item_type(tcx, did);
    clean::Function {
        decl: match ty::get(t.ty).sty {
            ty::ty_bare_fn(ref f) => (did, &f.sig).clean(),
            _ => fail!("bad function"),
        },
        generics: t.generics.clean(),
        fn_style: style,
    }
}

fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct {
    use syntax::parse::token::special_idents::unnamed_field;

    let t = ty::lookup_item_type(tcx, did);
    let fields = ty::lookup_struct_fields(tcx, did);

    clean::Struct {
        struct_type: match fields.as_slice() {
            [] => doctree::Unit,
            [ref f] if f.name == unnamed_field.name => doctree::Newtype,
            [ref f, ..] if f.name == unnamed_field.name => doctree::Tuple,
            _ => doctree::Plain,
        },
        generics: t.generics.clean(),
        fields: fields.iter().map(|f| f.clean()).collect(),
        fields_stripped: false,
    }
}

fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
    let t = ty::lookup_item_type(tcx, did);
    match ty::get(t.ty).sty {
        ty::ty_enum(edid, _) => {
            return clean::EnumItem(clean::Enum {
                generics: t.generics.clean(),
                variants_stripped: false,
                variants: ty::enum_variants(tcx, edid).clean(),
            })
        }
        _ => {}
    }

    clean::TypedefItem(clean::Typedef {
        type_: t.ty.clean(),
        generics: t.generics.clean(),
    })
}

fn build_impls(cx: &core::DocContext,
               tcx: &ty::ctxt,
               did: ast::DefId) -> Vec<clean::Item> {
    ty::populate_implementations_for_type_if_necessary(tcx, did);
    let mut impls = Vec::new();

    match tcx.inherent_impls.borrow().find(&did) {
        None => {}
        Some(i) => {
            impls.extend(i.borrow().iter().map(|&did| { build_impl(cx, tcx, did) }));
        }
    }

    // If this is the first time we've inlined something from this crate, then
    // we inline *all* impls from the crate into this crate. Note that there's
    // currently no way for us to filter this based on type, and we likely need
    // many impls for a variety of reasons.
    //
    // Primarily, the impls will be used to populate the documentation for this
    // type being inlined, but impls can also be used when generating
    // documentation for primitives (no way to find those specifically).
    if cx.populated_crate_impls.borrow_mut().insert(did.krate) {
        csearch::each_top_level_item_of_crate(&tcx.sess.cstore,
                                              did.krate,
                                              |def, _, _| {
            populate_impls(cx, tcx, def, &mut impls)
        });

        fn populate_impls(cx: &core::DocContext,
                          tcx: &ty::ctxt,
                          def: decoder::DefLike,
                          impls: &mut Vec<Option<clean::Item>>) {
            match def {
                decoder::DlImpl(did) => impls.push(build_impl(cx, tcx, did)),
                decoder::DlDef(ast::DefMod(did)) => {
                    csearch::each_child_of_item(&tcx.sess.cstore,
                                                did,
                                                |def, _, _| {
                        populate_impls(cx, tcx, def, impls)
                    })
                }
                _ => {}
            }
        }
    }

    impls.move_iter().filter_map(|a| a).collect()
}

fn build_impl(cx: &core::DocContext,
              tcx: &ty::ctxt,
              did: ast::DefId) -> Option<clean::Item> {
    if !cx.inlined.borrow_mut().get_mut_ref().insert(did) {
        return None
    }

    let associated_trait = csearch::get_impl_trait(tcx, did);
    let attrs = load_attrs(tcx, did);
    let ty = ty::lookup_item_type(tcx, did);
    let methods = csearch::get_impl_methods(&tcx.sess.cstore,
                                            did).iter().filter_map(|did| {
        let method = ty::method(tcx, *did);
        if method.vis != ast::Public && associated_trait.is_none() {
            return None
        }
        let mut item = ty::method(tcx, *did).clean();
        item.inner = match item.inner.clone() {
            clean::TyMethodItem(clean::TyMethod {
                fn_style, decl, self_, generics
            }) => {
                clean::MethodItem(clean::Method {
                    fn_style: fn_style,
                    decl: decl,
                    self_: self_,
                    generics: generics,
                })
            }
            _ => fail!("not a tymethod"),
        };
        Some(item)
    }).collect();
    Some(clean::Item {
        inner: clean::ImplItem(clean::Impl {
            derived: clean::detect_derived(attrs.as_slice()),
            trait_: associated_trait.clean().map(|bound| {
                match bound {
                    clean::TraitBound(ty) => ty,
                    clean::RegionBound => unreachable!(),
                }
            }),
            for_: ty.ty.clean(),
            generics: ty.generics.clean(),
            methods: methods,
        }),
        source: clean::Span::empty(),
        name: None,
        attrs: attrs,
        visibility: Some(ast::Inherited),
        def_id: did,
    })
}

fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
                did: ast::DefId) -> clean::Module {
    let mut items = Vec::new();

    // FIXME: this doesn't handle reexports inside the module itself.
    //        Should they be handled?
    csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, vis| {
        if vis != ast::Public { return }
        match def {
            decoder::DlDef(def) => {
                match try_inline_def(cx, tcx, def) {
                    Some(i) => items.extend(i.move_iter()),
                    None => {}
                }
            }
            // All impls were inlined above
            decoder::DlImpl(..) => {}
            decoder::DlField => fail!("unimplemented field"),
        }
    });

    clean::Module {
        items: items,
        is_crate: false,
    }
}
<|endoftext|>


<commit_before>//! SGX-specific access to architectural features.
//!
//! The functionality in this module is further documented in the Intel
//! Software Developer's Manual, Volume 3, Chapter 40.
#![unstable(feature = "sgx_platform", issue = "56975")]

use mem::MaybeUninit;

/// Wrapper struct to force 16-byte alignment.
#[repr(align(16))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align16<T>(pub T);

/// Wrapper struct to force 128-byte alignment.
#[repr(align(128))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align128<T>(pub T);

/// Wrapper struct to force 512-byte alignment.
#[repr(align(512))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align512<T>(pub T);

const ENCLU_EREPORT: u32 = 0;
const ENCLU_EGETKEY: u32 = 1;

/// Call the `EGETKEY` instruction to obtain a 128-bit secret key.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32> {
    unsafe {
        let mut out = MaybeUninit::uninitialized();
        let error;

        asm!(
            "enclu"
            : "={eax}"(error)
            : "{eax}"(ENCLU_EGETKEY),
              "{rbx}"(request),
              "{rcx}"(out.get_mut())
            : "flags"
        );

        match error {
            0 => Ok(out.into_inner()),
            err => Err(err),
        }
    }
}

/// Call the `EREPORT` instruction.
///
/// This creates a cryptographic report describing the contents of the current
/// enclave. The report may be verified by the enclave described in
/// `targetinfo`.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn ereport(
    targetinfo: &Align512<[u8; 512]>,
    reportdata: &Align128<[u8; 64]>,
) -> Align512<[u8; 432]> {
    unsafe {
        let mut report = MaybeUninit::uninitialized();

        asm!(
            "enclu"
            : /* no output registers */
            : "{eax}"(ENCLU_EREPORT),
              "{rbx}"(targetinfo),
              "{rcx}"(reportdata),
              "{rdx}"(report.get_mut())
        );

        report.into_inner()
    }
}
<commit_msg>Rollup merge of #57511 - jethrogb:jb/fix-undef, r=cramertj<commit_after>//! SGX-specific access to architectural features.
//!
//! The functionality in this module is further documented in the Intel
//! Software Developer's Manual, Volume 3, Chapter 40.
#![unstable(feature = "sgx_platform", issue = "56975")]

use mem::MaybeUninit;

/// Wrapper struct to force 16-byte alignment.
#[repr(align(16))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align16<T>(pub T);

/// Wrapper struct to force 128-byte alignment.
#[repr(align(128))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align128<T>(pub T);

/// Wrapper struct to force 512-byte alignment.
#[repr(align(512))]
#[unstable(feature = "sgx_platform", issue = "56975")]
pub struct Align512<T>(pub T);

const ENCLU_EREPORT: u32 = 0;
const ENCLU_EGETKEY: u32 = 1;

/// Call the `EGETKEY` instruction to obtain a 128-bit secret key.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32> {
    unsafe {
        let mut out = MaybeUninit::uninitialized();
        let error;

        asm!(
            "enclu"
            : "={eax}"(error)
            : "{eax}"(ENCLU_EGETKEY),
              "{rbx}"(request),
              "{rcx}"(out.as_mut_ptr())
            : "flags"
        );

        match error {
            0 => Ok(out.into_inner()),
            err => Err(err),
        }
    }
}

/// Call the `EREPORT` instruction.
///
/// This creates a cryptographic report describing the contents of the current
/// enclave. The report may be verified by the enclave described in
/// `targetinfo`.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn ereport(
    targetinfo: &Align512<[u8; 512]>,
    reportdata: &Align128<[u8; 64]>,
) -> Align512<[u8; 432]> {
    unsafe {
        let mut report = MaybeUninit::uninitialized();

        asm!(
            "enclu"
            : /* no output registers */
            : "{eax}"(ENCLU_EREPORT),
              "{rbx}"(targetinfo),
              "{rcx}"(reportdata),
              "{rdx}"(report.as_mut_ptr())
        );

        report.into_inner()
    }
}
<|endoftext|>


<commit_before>#![allow(unused_must_use)]

extern crate syntax;
extern crate rustc;
extern crate serialize;
extern crate getopts;
extern crate rustc_trans;
extern crate rustc_driver;

use getopts::{optflag,getopts};

use std::io;
use std::os;
use std::io::Reader;
use std::string::String;
use serialize::json;
use serialize::json::{Json};
use syntax::diagnostics::registry;

use rustc::session;
use rustc::session::config;
use rustc::session::config::Input;

use rustc_driver::driver;

fn filter_json(j: &mut json::Json) {
    let mut replace = None;

    match *j {
        Json::Object(ref mut ob) => {
            // remove
            ob.remove(&String::from_str("span"));
            ob.remove(&String::from_str("id"));
            let mut kv : Option<(String,Vec<Json>)> = None;
            match ob.get(&String::from_str("node")) {
                Some(&Json::Object(ref ob2)) => {
                    match (ob2.get(&String::from_str("variant")),
                           ob2.get(&String::from_str("fields"))) {
                        (Some(&Json::String(ref s)), Some(&Json::Array(ref ls))) => {
                            kv = Some((s.clone(), ls.clone()));
                        }
                        _ => ()
                    }
                }
                _ => ()
            }
            match kv {
                None => (),
                Some((k, v)) => {
                    ob.remove(&String::from_str("node"));
                    ob.insert(k, Json::Array(v));
                }
            }
            for (_, v) in ob.iter_mut() {
                filter_json(v);
            }
        }
        Json::Array(ref mut ls) => {
            for v in ls.iter_mut() {
                filter_json(v)
            }
            if ls.len() == 1 {
                replace = Some(ls.as_slice()[0].clone())
            }
        }
        _ => ()
    }
    match replace {
        None => (),
        Some(jj) => *j = jj
    }
}

static INDENT_STEP: int = 4;

fn print_indent(indent: int) {
    let mut out = io::stdout();
    for i in range(0, indent) {
        if i % INDENT_STEP == 0 {
            out.write_str("|");
        } else {
            out.write_str(" ");
        }
    }
}

fn print_sexp(indent: int, j: &json::Json) {
    let mut out = io::stdout();

    match *j {

        Json::Object(ref ob) => {
            {
                for (k, v) in ob.iter() {
                    print_indent(indent);
                    out.write_str("(");
                    out.write_str(k.as_slice());
                    out.write_str("\n");
                    print_sexp(indent + INDENT_STEP, v);
                    print_indent(indent);
                    out.write_str(")\n");
                }
            }
        }
        Json::Array(ref ls) => {
            print_indent(indent);
            out.write_str("(\n");
            for v in ls.iter() {
                print_sexp(indent + INDENT_STEP, v);
            }
            print_indent(indent);
            out.write_str(")\n");
        }
        Json::String(ref s) => {
            print_indent(indent);
            out.write_str(s.as_slice());
            out.write_str("\n");
        }
        Json::Null => {
            print_indent(indent);
            out.write_str("<nil>\n");
        }
        Json::Boolean(true) => {
            print_indent(indent);
            out.write_str("true\n");
        }
        Json::Boolean(false) => {
            print_indent(indent);
            out.write_str("false\n");
        }
        Json::I64(n) => {
            print_indent(indent);
            out.write_str(n.to_string().as_slice());
            out.write_str("\n");
        }
        Json::U64(n) => {
            print_indent(indent);
            out.write_str(n.to_string().as_slice());
            out.write_str("\n");
        }
        Json::F64(n) => {
            print_indent(indent);
            out.write_str(n.to_string().as_slice());
            out.write_str("\n");
        }
    }
}

fn main() {

    let args = os::args().into_iter().collect::<Vec<String>>();
    let opts = [ optflag("j", "", "dump output in JSON, not sexp") ];
    let matches = match getopts(args.tail(), &opts) {
        Ok(m) => { m }
        Err(f) => { panic!(f) }
    };
    let dump_json = matches.opt_present("j");

    match io::stdin().read_to_string() {
        Ok(text) => {
            let opt = config::basic_options();
            let sess = session::build_session(opt, None,
                                              registry::Registry::new(&rustc::DIAGNOSTICS));
            let cfg = config::build_configuration(&sess);
            let input = Input::Str(text);
            let cr = driver::phase_1_parse_input(&sess, cfg, &input);

            // JSON-ify, meaning "encode then re-parse as just json", ugh.
            let ast_str = json::encode(&cr.module);
            let chars = ast_str.as_slice().chars().collect::<Vec<char>>();
            let mut b = json::Builder::new(chars.into_iter());
            let mut j = b.build().ok().unwrap();

            filter_json(&mut j);
            if dump_json {
                let mut writer = io::stdout();
                j.to_pretty_writer(&mut writer as &mut io::Writer);
            } else {
                print_sexp(0, &j);
            }
        },
        Err(ioerr) => {
            panic!("I/O Error: {}", ioerr.desc);
        }
    }
}
<commit_msg>Update rparse for library changes<commit_after>#![allow(unused_must_use)]

extern crate syntax;
extern crate rustc;
extern crate serialize;
extern crate getopts;
extern crate rustc_trans;
extern crate rustc_driver;

use getopts::{optflag,getopts};

use std::io;
use std::os;
use std::io::Reader;
use std::string::String;
use serialize::json;
use serialize::json::{Json};
use syntax::diagnostics::registry;

use rustc::session;
use rustc::session::config;
use rustc::session::config::Input;

use rustc_driver::driver;

fn filter_json(j: &mut json::Json) {
    let mut replace = None;

    match *j {
        Json::Object(ref mut ob) => {
            // remove
            ob.remove(&String::from_str("span"));
            ob.remove(&String::from_str("id"));
            let mut kv : Option<(String,Vec<Json>)> = None;
            match ob.get(&String::from_str("node")) {
                Some(&Json::Object(ref ob2)) => {
                    match (ob2.get(&String::from_str("variant")),
                           ob2.get(&String::from_str("fields"))) {
                        (Some(&Json::String(ref s)), Some(&Json::Array(ref ls))) => {
                            kv = Some((s.clone(), ls.clone()));
                        }
                        _ => ()
                    }
                }
                _ => ()
            }
            match kv {
                None => (),
                Some((k, v)) => {
                    ob.remove(&String::from_str("node"));
                    ob.insert(k, Json::Array(v));
                }
            }
            for (_, v) in ob.iter_mut() {
                filter_json(v);
            }
        }
        Json::Array(ref mut ls) => {
            for v in ls.iter_mut() {
                filter_json(v)
            }
            if ls.len() == 1 {
                replace = Some(ls.as_slice()[0].clone())
            }
        }
        _ => ()
    }
    match replace {
        None => (),
        Some(jj) => *j = jj
    }
}

static INDENT_STEP: int = 4;

fn print_indent(indent: int) {
    let mut out = io::stdout();
    for i in range(0, indent) {
        if i % INDENT_STEP == 0 {
            out.write_str("|");
        } else {
            out.write_str(" ");
        }
    }
}

fn print_sexp(indent: int, j: &json::Json) {
    let mut out = io::stdout();

    match *j {

        Json::Object(ref ob) => {
            {
                for (k, v) in ob.iter() {
                    print_indent(indent);
                    out.write_str("(");
                    out.write_str(k.as_slice());
                    out.write_str("\n");
                    print_sexp(indent + INDENT_STEP, v);
                    print_indent(indent);
                    out.write_str(")\n");
                }
            }
        }
        Json::Array(ref ls) => {
            print_indent(indent);
            out.write_str("(\n");
            for v in ls.iter() {
                print_sexp(indent + INDENT_STEP, v);
            }
            print_indent(indent);
            out.write_str(")\n");
        }
        Json::String(ref s) => {
            print_indent(indent);
            out.write_str(s.as_slice());
            out.write_str("\n");
        }
        Json::Null => {
            print_indent(indent);
            out.write_str("<nil>\n");
        }
        Json::Boolean(true) => {
            print_indent(indent);
            out.write_str("true\n");
        }
        Json::Boolean(false) => {
            print_indent(indent);
            out.write_str("false\n");
        }
        Json::I64(n) => {
            print_indent(indent);
            out.write_str(n.to_string().as_slice());
            out.write_str("\n");
        }
        Json::U64(n) => {
            print_indent(indent);
            out.write_str(n.to_string().as_slice());
            out.write_str("\n");
        }
        Json::F64(n) => {
            print_indent(indent);
            out.write_str(n.to_string().as_slice());
            out.write_str("\n");
        }
    }
}

fn main() {

    let args = os::args().into_iter().collect::<Vec<String>>();
    let opts = [ optflag("j", "", "dump output in JSON, not sexp") ];
    let matches = match getopts(args.tail(), &opts) {
        Ok(m) => { m }
        Err(f) => { panic!(f) }
    };
    let dump_json = matches.opt_present("j");

    match io::stdin().read_to_string() {
        Ok(text) => {
            let opt = config::basic_options();
            let sess = session::build_session(opt, None,
                                              registry::Registry::new(&rustc::DIAGNOSTICS));
            let cfg = config::build_configuration(&sess);
            let input = Input::Str(text);
            let cr = driver::phase_1_parse_input(&sess, cfg, &input);

            // JSON-ify, meaning "encode then re-parse as just json", ugh.
            let ast_str = json::encode(&cr.module);
            let chars = ast_str.as_slice().chars().collect::<Vec<char>>();
            let mut b = json::Builder::new(chars.into_iter());
            let mut j = b.build().ok().unwrap();

            filter_json(&mut j);
            if dump_json {
                println!("{}", j.pretty());
            } else {
                print_sexp(0, &j);
            }
        },
        Err(ioerr) => {
            panic!("I/O Error: {}", ioerr.desc);
        }
    }
}
<|endoftext|>