<commit_before>//! A set of builders to generate Rust source for PHF data structures at
//! compile time.
//!
//! The provided builders are intended to be used in a Cargo build script to
//! generate a Rust source file that will be included in a library at build
//! time.
//!
//! # Examples
//!
//! build.rs
//!
//! ```rust,no_run
//! extern crate phf_codegen;
//!
//! use std::env;
//! use std::fs::File;
//! use std::io::{BufWriter, Write};
//! use std::path::Path;
//!
//! fn main() {
//!     let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs");
//!     let mut file = BufWriter::new(File::create(&path).unwrap());
//!
//!     writeln!(
//!         &mut file,
//!          "static KEYWORDS: phf::Map<&'static str, Keyword> = \n{};\n",
//!          phf_codegen::Map::new()
//!              .entry("loop", "Keyword::Loop")
//!              .entry("continue", "Keyword::Continue")
//!              .entry("break", "Keyword::Break")
//!              .entry("fn", "Keyword::Fn")
//!              .entry("extern", "Keyword::Extern")
//!              .build()
//!     ).unwrap();
//! }
//! ```
//!
//! lib.rs
//!
//! ```ignore
//! extern crate phf;
//!
//! #[derive(Clone)]
//! enum Keyword {
//!     Loop,
//!     Continue,
//!     Break,
//!     Fn,
//!     Extern,
//! }
//!
//! include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
//!
//! pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
//!     KEYWORDS.get(keyword).cloned()
//! }
//! ```
//!
//! ##### Byte-String Keys
//! Byte strings by default produce references to fixed-size arrays; the compiler needs a hint
//! to coerce them to slices:
//!
//! build.rs
//!
//! ```rust,no_run
//! extern crate phf_codegen;
//!
//! use std::env;
//! use std::fs::File;
//! use std::io::{BufWriter, Write};
//! use std::path::Path;
//!
//! fn main() {
//!     let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs");
//!     let mut file = BufWriter::new(File::create(&path).unwrap());
//!
//!     writeln!(
//!         &mut file,
//!          "static KEYWORDS: phf::Map<&'static [u8], Keyword> = \n{};\n",
//!          phf_codegen::Map::<&[u8]>::new()
//!              .entry(b"loop", "Keyword::Loop")
//!              .entry(b"continue", "Keyword::Continue")
//!              .entry(b"break", "Keyword::Break")
//!              .entry(b"fn", "Keyword::Fn")
//!              .entry(b"extern", "Keyword::Extern")
//!              .build()
//!     ).unwrap();
//! }
//! ```
//!
//! lib.rs
//!
//! ```rust,ignore
//! extern crate phf;
//!
//! #[derive(Clone)]
//! enum Keyword {
//!     Loop,
//!     Continue,
//!     Break,
//!     Fn,
//!     Extern,
//! }
//!
//! include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
//!
//! pub fn parse_keyword(keyword: &[u8]) -> Option<Keyword> {
//!     KEYWORDS.get(keyword).cloned()
//! }
//! ```
//!
//! # Note
//!
//! The compiler's stack will overflow when processing extremely long method
//! chains (500+ calls). When generating large PHF data structures, consider
//! looping over the entries or making each call a separate statement:
//!
//! ```rust
//! let entries = [("hello", "1"), ("world", "2")];
//!
//! let mut builder = phf_codegen::Map::new();
//! for &(key, value) in &entries {
//!     builder.entry(key, value);
//! }
//! // ...
//! ```
//!
//! ```rust
//! let mut builder = phf_codegen::Map::new();
//! builder.entry("hello", "1");
//! builder.entry("world", "2");
//! // ...
//! ```
#![doc(html_root_url = "https://docs.rs/phf_codegen/0.7")]

use phf_shared::{PhfHash, FmtConst};
use std::collections::HashSet;
use std::fmt;
use std::hash::Hash;

use phf_generator::HashState;

struct Delegate<T>(T);

impl<T: FmtConst> fmt::Display for Delegate<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt_const(f)
    }
}

/// A builder for the [`phf::Map`](::phf::Map) type.
pub struct Map<K> {
    keys: Vec<K>,
    values: Vec<String>,
    path: String,
}

impl<K: Hash + PhfHash + Eq + FmtConst> Map<K> {
    /// Creates a new `phf::Map` builder.
    pub fn new() -> Map<K> {
        // FIXME rust#27438
        //
        // On Windows/MSVC there are major problems with the handling of dllimport.
        // Here, because downstream build scripts only invoke generics from phf_codegen,
        // the linker ends up throwing a way a bunch of static symbols we actually need.
        // This works around the problem, assuming that all clients call `Map::new` by
        // calling a non-generic function.
        fn noop_fix_for_27438() {}
        noop_fix_for_27438();

        Map {
            keys: vec![],
            values: vec![],
            path: String::from("::phf"),
        }
    }

    /// Set the path to the `phf` crate from the global namespace
    pub fn phf_path(&mut self, path: &str) -> &mut Map<K> {
        self.path = path.to_owned();
        self
    }

    /// Adds an entry to the builder.
    ///
    /// `value` will be written exactly as provided in the constructed source.
    pub fn entry(&mut self, key: K, value: &str) -> &mut Map<K> {
        self.keys.push(key);
        self.values.push(value.to_owned());
        self
    }

    /// Calculate the hash parameters and return a struct implementing
    /// [`Display`](::std::fmt::Display) which will print the constructed [`phf::Map`](::phf::Map).
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build(&self) -> DisplayMap<K> {
        let mut set = HashSet::new();
        for key in &self.keys {
            if !set.insert(key) {
                panic!("duplicate key `{}`", Delegate(key));
            }
        }

        let state = phf_generator::generate_hash(&self.keys);

        DisplayMap {
            path: &self.path,
            keys: &self.keys,
            values: &self.values,
            state,
        }
    }
}

/// An adapter for printing a [`Map`](::Map).
pub struct DisplayMap<'a, K> {
    path: &'a str,
    state: HashState,
    keys: &'a [K],
    values: &'a [String],

}

impl<'a, K: FmtConst + 'a> fmt::Display for DisplayMap<'a, K> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // funky formatting here for nice output
        write!(f,
               "{}::Map {{
    key: {:?},
    disps: {}::Slice::Static(&[",
               self.path, self.state.key, self.path)?;

        // write map displacements
        for &(d1, d2) in &self.state.disps {
            write!(f,
                   "
        ({}, {}),",
                   d1,
                   d2)?;
        }

        write!(f,
               "
    ]),
    entries: {}::Slice::Static(&[", self.path)?;

        // write map entries
        for &idx in &self.state.map {
            write!(f,
                   "
        ({}, {}),",
                   Delegate(&self.keys[idx]),
                   &self.values[idx])?;
        }

        write!(f,
               "
    ]),
}}")
    }
}

/// A builder for the [`phf::Set`](::phf::Set) type.
pub struct Set<T> {
    map: Map<T>,
}

impl<T: Hash + PhfHash + Eq + FmtConst> Set<T> {
    /// Constructs a new `phf::Set` builder.
    pub fn new() -> Set<T> {
        Set {
            map: Map::new(),
        }
    }

    /// Set the path to the `phf` crate from the global namespace
    pub fn phf_path(&mut self, path: &str) -> &mut Set<T> {
        self.map.phf_path(path);
        self
    }

    /// Adds an entry to the builder.
    pub fn entry(&mut self, entry: T) -> &mut Set<T> {
        self.map.entry(entry, "()");
        self
    }

    /// Calculate the hash parameters and return a struct implementing
    /// [`Display`](::std::fmt::Display) which will print the constructed [`phf::Set`](::phf::Set).
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build(&self) -> DisplaySet<T> {
        DisplaySet {
            inner: self.map.build()
        }
    }
}

/// An adapter for printing a [`Set`](::Set).
pub struct DisplaySet<'a, T: 'a> {
    inner: DisplayMap<'a, T>,
}

impl<'a, T: FmtConst + 'a> fmt::Display for DisplaySet<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}::Set {{ map: {} }}", self.inner.path, self.inner)
    }
}

/// A builder for the `phf::OrderedMap` type.
pub struct OrderedMap<K> {
    keys: Vec<K>,
    values: Vec<String>,
    path: String,
}

impl<K: Hash + PhfHash + Eq + FmtConst> OrderedMap<K> {
    /// Constructs a enw `phf::OrderedMap` builder.
    pub fn new() -> OrderedMap<K> {
        OrderedMap {
            keys: vec![],
            values: vec![],
            path: String::from("::phf"),
        }
    }

    /// Set the path to the `phf` crate from the global namespace
    pub fn phf_path(&mut self, path: &str) -> &mut OrderedMap<K> {
        self.path = path.to_owned();
        self
    }

    /// Adds an entry to the builder.
    ///
    /// `value` will be written exactly as provided in the constructed source.
    pub fn entry(&mut self, key: K, value: &str) -> &mut OrderedMap<K> {
        self.keys.push(key);
        self.values.push(value.to_owned());
        self
    }

    /// Calculate the hash parameters and return a struct implementing
    /// [`Display`](::std::fmt::Display) which will print the constructed
    /// [`phf::OrderedMap`](::phf::OrderedMap).
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build(&self) -> DisplayOrderedMap<K> {
        let mut set = HashSet::new();
        for key in &self.keys {
            if !set.insert(key) {
                panic!("duplicate key `{}`", Delegate(key));
            }
        }

        let state = phf_generator::generate_hash(&self.keys);

        DisplayOrderedMap {
            path: &self.path,
            state,
            keys: &self.keys,
            values: &self.values,
        }
    }
}

/// An adapter for printing a [`OrderedMap`](::OrderedMap).
pub struct DisplayOrderedMap<'a, K: 'a> {
    path: &'a str,
    state: HashState,
    keys: &'a [K],
    values: &'a [String],
}

impl<'a, K: FmtConst + 'a> fmt::Display for DisplayOrderedMap<'a, K> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}::OrderedMap {{
    key: {:?},
    disps: {}::Slice::Static(&[",
               self.path, self.state.key, self.path)?;
        for &(d1, d2) in &self.state.disps {
            write!(f,
                   "
        ({}, {}),",
                   d1,
                   d2)?;
        }
        write!(f,
               "
    ]),
    idxs: {}::Slice::Static(&[", self.path)?;
        for &idx in &self.state.map {
            write!(f,
                   "
        {},",
                   idx)?;
        }
        write!(f,
               "
    ]),
    entries: {}::Slice::Static(&[", self.path)?;
        for (key, value) in self.keys.iter().zip(self.values.iter()) {
            write!(f,
                   "
        ({}, {}),",
                   Delegate(key),
                   value)?;
        }
        write!(f,
               "
    ]),
}}")
    }
}

/// A builder for the `phf::OrderedSet` type.
pub struct OrderedSet<T> {
    map: OrderedMap<T>,
}

impl<T: Hash + PhfHash + Eq + FmtConst> OrderedSet<T> {
    /// Constructs a new `phf::OrderedSet` builder.
    pub fn new() -> OrderedSet<T> {
        OrderedSet {
            map: OrderedMap::new(),
        }
    }

    /// Set the path to the `phf` crate from the global namespace
    pub fn phf_path(&mut self, path: &str) -> &mut OrderedSet<T> {
        self.map.phf_path(path);
        self
    }

    /// Adds an entry to the builder.
    pub fn entry(&mut self, entry: T) -> &mut OrderedSet<T> {
        self.map.entry(entry, "()");
        self
    }

    /// Calculate the hash parameters and return a struct implementing
    /// [`Display`](::std::fmt::Display) which will print the constructed
    /// [`phf::OrderedSet`](::phf::OrderedSet).
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build(&self) -> DisplayOrderedSet<T> {
        DisplayOrderedSet {
            inner: self.map.build()
        }
    }
}

/// An adapter for printing a [`OrderedSet`](::OrderedSet).
pub struct DisplayOrderedSet<'a, T: 'a> {
    inner: DisplayOrderedMap<'a, T>,
}

impl<'a, T: FmtConst + 'a> fmt::Display for DisplayOrderedSet<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}::OrderedSet {{ map: {} }}", self.inner.path, self.inner)
    }
}
<commit_msg>remove links to `phf` types since that crate is not linked<commit_after>//! A set of builders to generate Rust source for PHF data structures at
//! compile time.
//!
//! The provided builders are intended to be used in a Cargo build script to
//! generate a Rust source file that will be included in a library at build
//! time.
//!
//! # Examples
//!
//! build.rs
//!
//! ```rust,no_run
//! extern crate phf_codegen;
//!
//! use std::env;
//! use std::fs::File;
//! use std::io::{BufWriter, Write};
//! use std::path::Path;
//!
//! fn main() {
//!     let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs");
//!     let mut file = BufWriter::new(File::create(&path).unwrap());
//!
//!     writeln!(
//!         &mut file,
//!          "static KEYWORDS: phf::Map<&'static str, Keyword> = \n{};\n",
//!          phf_codegen::Map::new()
//!              .entry("loop", "Keyword::Loop")
//!              .entry("continue", "Keyword::Continue")
//!              .entry("break", "Keyword::Break")
//!              .entry("fn", "Keyword::Fn")
//!              .entry("extern", "Keyword::Extern")
//!              .build()
//!     ).unwrap();
//! }
//! ```
//!
//! lib.rs
//!
//! ```ignore
//! extern crate phf;
//!
//! #[derive(Clone)]
//! enum Keyword {
//!     Loop,
//!     Continue,
//!     Break,
//!     Fn,
//!     Extern,
//! }
//!
//! include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
//!
//! pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
//!     KEYWORDS.get(keyword).cloned()
//! }
//! ```
//!
//! ##### Byte-String Keys
//! Byte strings by default produce references to fixed-size arrays; the compiler needs a hint
//! to coerce them to slices:
//!
//! build.rs
//!
//! ```rust,no_run
//! extern crate phf_codegen;
//!
//! use std::env;
//! use std::fs::File;
//! use std::io::{BufWriter, Write};
//! use std::path::Path;
//!
//! fn main() {
//!     let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs");
//!     let mut file = BufWriter::new(File::create(&path).unwrap());
//!
//!     writeln!(
//!         &mut file,
//!          "static KEYWORDS: phf::Map<&'static [u8], Keyword> = \n{};\n",
//!          phf_codegen::Map::<&[u8]>::new()
//!              .entry(b"loop", "Keyword::Loop")
//!              .entry(b"continue", "Keyword::Continue")
//!              .entry(b"break", "Keyword::Break")
//!              .entry(b"fn", "Keyword::Fn")
//!              .entry(b"extern", "Keyword::Extern")
//!              .build()
//!     ).unwrap();
//! }
//! ```
//!
//! lib.rs
//!
//! ```rust,ignore
//! extern crate phf;
//!
//! #[derive(Clone)]
//! enum Keyword {
//!     Loop,
//!     Continue,
//!     Break,
//!     Fn,
//!     Extern,
//! }
//!
//! include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
//!
//! pub fn parse_keyword(keyword: &[u8]) -> Option<Keyword> {
//!     KEYWORDS.get(keyword).cloned()
//! }
//! ```
//!
//! # Note
//!
//! The compiler's stack will overflow when processing extremely long method
//! chains (500+ calls). When generating large PHF data structures, consider
//! looping over the entries or making each call a separate statement:
//!
//! ```rust
//! let entries = [("hello", "1"), ("world", "2")];
//!
//! let mut builder = phf_codegen::Map::new();
//! for &(key, value) in &entries {
//!     builder.entry(key, value);
//! }
//! // ...
//! ```
//!
//! ```rust
//! let mut builder = phf_codegen::Map::new();
//! builder.entry("hello", "1");
//! builder.entry("world", "2");
//! // ...
//! ```
#![doc(html_root_url = "https://docs.rs/phf_codegen/0.7")]

use phf_shared::{PhfHash, FmtConst};
use std::collections::HashSet;
use std::fmt;
use std::hash::Hash;

use phf_generator::HashState;

struct Delegate<T>(T);

impl<T: FmtConst> fmt::Display for Delegate<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt_const(f)
    }
}

/// A builder for the `phf::Map` type.
pub struct Map<K> {
    keys: Vec<K>,
    values: Vec<String>,
    path: String,
}

impl<K: Hash + PhfHash + Eq + FmtConst> Map<K> {
    /// Creates a new `phf::Map` builder.
    pub fn new() -> Map<K> {
        // FIXME rust#27438
        //
        // On Windows/MSVC there are major problems with the handling of dllimport.
        // Here, because downstream build scripts only invoke generics from phf_codegen,
        // the linker ends up throwing a way a bunch of static symbols we actually need.
        // This works around the problem, assuming that all clients call `Map::new` by
        // calling a non-generic function.
        fn noop_fix_for_27438() {}
        noop_fix_for_27438();

        Map {
            keys: vec![],
            values: vec![],
            path: String::from("::phf"),
        }
    }

    /// Set the path to the `phf` crate from the global namespace
    pub fn phf_path(&mut self, path: &str) -> &mut Map<K> {
        self.path = path.to_owned();
        self
    }

    /// Adds an entry to the builder.
    ///
    /// `value` will be written exactly as provided in the constructed source.
    pub fn entry(&mut self, key: K, value: &str) -> &mut Map<K> {
        self.keys.push(key);
        self.values.push(value.to_owned());
        self
    }

    /// Calculate the hash parameters and return a struct implementing
    /// [`Display`](::std::fmt::Display) which will print the constructed `phf::Map`.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build(&self) -> DisplayMap<K> {
        let mut set = HashSet::new();
        for key in &self.keys {
            if !set.insert(key) {
                panic!("duplicate key `{}`", Delegate(key));
            }
        }

        let state = phf_generator::generate_hash(&self.keys);

        DisplayMap {
            path: &self.path,
            keys: &self.keys,
            values: &self.values,
            state,
        }
    }
}

/// An adapter for printing a [`Map`](::Map).
pub struct DisplayMap<'a, K> {
    path: &'a str,
    state: HashState,
    keys: &'a [K],
    values: &'a [String],

}

impl<'a, K: FmtConst + 'a> fmt::Display for DisplayMap<'a, K> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // funky formatting here for nice output
        write!(f,
               "{}::Map {{
    key: {:?},
    disps: {}::Slice::Static(&[",
               self.path, self.state.key, self.path)?;

        // write map displacements
        for &(d1, d2) in &self.state.disps {
            write!(f,
                   "
        ({}, {}),",
                   d1,
                   d2)?;
        }

        write!(f,
               "
    ]),
    entries: {}::Slice::Static(&[", self.path)?;

        // write map entries
        for &idx in &self.state.map {
            write!(f,
                   "
        ({}, {}),",
                   Delegate(&self.keys[idx]),
                   &self.values[idx])?;
        }

        write!(f,
               "
    ]),
}}")
    }
}

/// A builder for the `phf::Set` type.
pub struct Set<T> {
    map: Map<T>,
}

impl<T: Hash + PhfHash + Eq + FmtConst> Set<T> {
    /// Constructs a new `phf::Set` builder.
    pub fn new() -> Set<T> {
        Set {
            map: Map::new(),
        }
    }

    /// Set the path to the `phf` crate from the global namespace
    pub fn phf_path(&mut self, path: &str) -> &mut Set<T> {
        self.map.phf_path(path);
        self
    }

    /// Adds an entry to the builder.
    pub fn entry(&mut self, entry: T) -> &mut Set<T> {
        self.map.entry(entry, "()");
        self
    }

    /// Calculate the hash parameters and return a struct implementing
    /// [`Display`](::std::fmt::Display) which will print the constructed `phf::Set`.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build(&self) -> DisplaySet<T> {
        DisplaySet {
            inner: self.map.build()
        }
    }
}

/// An adapter for printing a [`Set`](::Set).
pub struct DisplaySet<'a, T: 'a> {
    inner: DisplayMap<'a, T>,
}

impl<'a, T: FmtConst + 'a> fmt::Display for DisplaySet<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}::Set {{ map: {} }}", self.inner.path, self.inner)
    }
}

/// A builder for the `phf::OrderedMap` type.
pub struct OrderedMap<K> {
    keys: Vec<K>,
    values: Vec<String>,
    path: String,
}

impl<K: Hash + PhfHash + Eq + FmtConst> OrderedMap<K> {
    /// Constructs a enw `phf::OrderedMap` builder.
    pub fn new() -> OrderedMap<K> {
        OrderedMap {
            keys: vec![],
            values: vec![],
            path: String::from("::phf"),
        }
    }

    /// Set the path to the `phf` crate from the global namespace
    pub fn phf_path(&mut self, path: &str) -> &mut OrderedMap<K> {
        self.path = path.to_owned();
        self
    }

    /// Adds an entry to the builder.
    ///
    /// `value` will be written exactly as provided in the constructed source.
    pub fn entry(&mut self, key: K, value: &str) -> &mut OrderedMap<K> {
        self.keys.push(key);
        self.values.push(value.to_owned());
        self
    }

    /// Calculate the hash parameters and return a struct implementing
    /// [`Display`](::std::fmt::Display) which will print the constructed
    /// `phf::OrderedMap`.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build(&self) -> DisplayOrderedMap<K> {
        let mut set = HashSet::new();
        for key in &self.keys {
            if !set.insert(key) {
                panic!("duplicate key `{}`", Delegate(key));
            }
        }

        let state = phf_generator::generate_hash(&self.keys);

        DisplayOrderedMap {
            path: &self.path,
            state,
            keys: &self.keys,
            values: &self.values,
        }
    }
}

/// An adapter for printing a [`OrderedMap`](::OrderedMap).
pub struct DisplayOrderedMap<'a, K: 'a> {
    path: &'a str,
    state: HashState,
    keys: &'a [K],
    values: &'a [String],
}

impl<'a, K: FmtConst + 'a> fmt::Display for DisplayOrderedMap<'a, K> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}::OrderedMap {{
    key: {:?},
    disps: {}::Slice::Static(&[",
               self.path, self.state.key, self.path)?;
        for &(d1, d2) in &self.state.disps {
            write!(f,
                   "
        ({}, {}),",
                   d1,
                   d2)?;
        }
        write!(f,
               "
    ]),
    idxs: {}::Slice::Static(&[", self.path)?;
        for &idx in &self.state.map {
            write!(f,
                   "
        {},",
                   idx)?;
        }
        write!(f,
               "
    ]),
    entries: {}::Slice::Static(&[", self.path)?;
        for (key, value) in self.keys.iter().zip(self.values.iter()) {
            write!(f,
                   "
        ({}, {}),",
                   Delegate(key),
                   value)?;
        }
        write!(f,
               "
    ]),
}}")
    }
}

/// A builder for the `phf::OrderedSet` type.
pub struct OrderedSet<T> {
    map: OrderedMap<T>,
}

impl<T: Hash + PhfHash + Eq + FmtConst> OrderedSet<T> {
    /// Constructs a new `phf::OrderedSet` builder.
    pub fn new() -> OrderedSet<T> {
        OrderedSet {
            map: OrderedMap::new(),
        }
    }

    /// Set the path to the `phf` crate from the global namespace
    pub fn phf_path(&mut self, path: &str) -> &mut OrderedSet<T> {
        self.map.phf_path(path);
        self
    }

    /// Adds an entry to the builder.
    pub fn entry(&mut self, entry: T) -> &mut OrderedSet<T> {
        self.map.entry(entry, "()");
        self
    }

    /// Calculate the hash parameters and return a struct implementing
    /// [`Display`](::std::fmt::Display) which will print the constructed
    /// `phf::OrderedSet`.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build(&self) -> DisplayOrderedSet<T> {
        DisplayOrderedSet {
            inner: self.map.build()
        }
    }
}

/// An adapter for printing a [`OrderedSet`](::OrderedSet).
pub struct DisplayOrderedSet<'a, T: 'a> {
    inner: DisplayOrderedMap<'a, T>,
}

impl<'a, T: FmtConst + 'a> fmt::Display for DisplayOrderedSet<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}::OrderedSet {{ map: {} }}", self.inner.path, self.inner)
    }
}
<|endoftext|>


<commit_before>// -*- rust -*-

use std;

type cell = tup(mutable @list);
type list = tag(link(@cell), nil());

fn main() {
  let @cell first = tup(@nil());
  let @cell second = tup(@link(first));
  first._0 = link(second);
  std.sys.rustrt.gc();
  let @cell third = tup(@nil());
}
<commit_msg>Fix the next typo in mlist-cycle.rs; still doesn't work.<commit_after>// -*- rust -*-

use std;

type cell = tup(mutable @list);
type list = tag(link(@cell), nil());

fn main() {
  let @cell first = tup(@nil());
  let @cell second = tup(@link(first));
  first._0 = @link(second);
  std.sys.rustrt.gc();
  let @cell third = tup(@nil());
}
<|endoftext|>


<commit_before>//! A small TCP server to handle collection of diagnostics information in a
//! cross-platform way for the `cargo fix` command.

use std::collections::HashSet;
use std::env;
use std::io::{BufReader, Read, Write};
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{self, JoinHandle};

use failure::{Error, ResultExt};
use serde_json;

use util::{Config, ProcessBuilder};
use util::errors::CargoResult;

const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
const PLEASE_REPORT_THIS_BUG: &str =
    "\
     This likely indicates a bug in either rustc or cargo itself,\n\
     and we would appreciate a bug report! You're likely to see \n\
     a number of compiler warnings after this message which cargo\n\
     attempted to fix but failed. If you could open an issue at\n\
     https://github.com/rust-lang/cargo/issues\n\
     quoting the full output of this command we'd be very appreciative!\n\n\
     ";

#[derive(Deserialize, Serialize)]
pub enum Message {
    Fixing {
        file: String,
        fixes: u32,
    },
    FixFailed {
        files: Vec<String>,
        krate: Option<String>,
    },
    ReplaceFailed {
        file: String,
        message: String,
    },
    PreviewNotFound {
        file: String,
        edition: String,
    },
    EditionAlreadyEnabled {
        file: String,
        edition: String,
    },
    IdiomEditionMismatch {
        file: String,
        idioms: String,
        edition: Option<String>,
    },
}

impl Message {
    pub fn post(&self) -> Result<(), Error> {
        let addr = env::var(DIAGNOSICS_SERVER_VAR)
            .context("diagnostics collector misconfigured")?;
        let mut client =
            TcpStream::connect(&addr).context("failed to connect to parent diagnostics target")?;

        let s = serde_json::to_string(self).context("failed to serialize message")?;
        client
            .write_all(s.as_bytes())
            .context("failed to write message to diagnostics target")?;
        client
            .shutdown(Shutdown::Write)
            .context("failed to shutdown")?;

        let mut tmp = Vec::new();
        client
            .read_to_end(&mut tmp)
            .context("failed to receive a disconnect")?;

        Ok(())
    }
}

pub struct DiagnosticPrinter<'a> {
    config: &'a Config,
    preview_not_found: HashSet<String>,
    edition_already_enabled: HashSet<String>,
    idiom_mismatch: HashSet<String>,
}

impl<'a> DiagnosticPrinter<'a> {
    pub fn new(config: &'a Config) -> DiagnosticPrinter<'a> {
        DiagnosticPrinter {
            config,
            preview_not_found: HashSet::new(),
            edition_already_enabled: HashSet::new(),
            idiom_mismatch: HashSet::new(),
        }
    }

    pub fn print(&mut self, msg: &Message) -> CargoResult<()> {
        match msg {
            Message::Fixing { file, fixes } => {
                let msg = if *fixes == 1 { "fix" } else { "fixes" };
                let msg = format!("{} ({} {})", file, fixes, msg);
                self.config.shell().status("Fixing", msg)
            }
            Message::ReplaceFailed { file, message } => {
                let msg = format!("error applying suggestions to `{}`\n", file);
                self.config.shell().warn(&msg)?;
                write!(
                    self.config.shell().err(),
                    "The full error message was:\n\n> {}\n\n",
                    message,
                )?;
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::FixFailed { files, krate } => {
                if let Some(ref krate) = *krate {
                    self.config.shell().warn(&format!(
                        "failed to automatically apply fixes suggested by rustc \
                         to crate `{}`",
                        krate,
                    ))?;
                } else {
                    self.config.shell().warn(
                        "failed to automatically apply fixes suggested by rustc"
                    )?;
                }
                if !files.is_empty() {
                    writeln!(
                        self.config.shell().err(),
                        "\nafter fixes were automatically applied the compiler \
                         reported errors within these files:\n"
                    )?;
                    for file in files {
                        writeln!(self.config.shell().err(), "  * {}", file)?;
                    }
                    writeln!(self.config.shell().err())?;
                }
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::PreviewNotFound { file, edition } => {
                // By default we're fixing a lot of things concurrently, don't
                // warn about the same file multiple times.
                if !self.preview_not_found.insert(file.clone()) {
                    return Ok(())
                }
                self.config.shell().warn(&format!(
                    "failed to find `#![feature(rust_{}_preview)]` in `{}`\n\
                     this may cause `cargo fix` to not be able to fix all\n\
                     issues in preparation for the {0} edition",
                    edition,
                    file,
                ))?;
                Ok(())
            }
            Message::EditionAlreadyEnabled { file, edition } => {
                // Like above, only warn once per file
                if !self.edition_already_enabled.insert(file.clone()) {
                    return Ok(())
                }

                let msg = format!(
                    "\
cannot prepare for the {} edition when it is enabled, so cargo cannot
automatically fix errors in `{}`

To prepare for the {0} edition you should first remove `edition = '{0}'` from
your `Cargo.toml` and then rerun this command. Once all warnings have been fixed
then you can re-enable the `edition` key in `Cargo.toml`. For some more
information about transitioning to the {0} edition see:

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-your-code-to-a-new-edition.html
",
                    edition,
                    file,
                );
                self.config.shell().error(&msg)?;
                Ok(())
            }
            Message::IdiomEditionMismatch { file, idioms, edition } => {
                // Same as above
                if !self.idiom_mismatch.insert(file.clone()) {
                    return Ok(())
                }
                self.config.shell().error(&format!(
                    "\
cannot migrate to the idioms of the {} edition for `{}`
because it is compiled {}, which doesn't match {0}

consider migrating to the {0} edition by adding `edition = '{0}'` to
`Cargo.toml` and then rerunning this command; a more detailed transition
guide can be found at

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-your-code-to-a-new-edition.html
",
                    idioms,
                    file,
                    match edition {
                        Some(s) => format!("with the {} edition", s),
                        None => "without an edition".to_string(),
                    },
                ))?;
                Ok(())
            }
        }
    }
}

#[derive(Debug)]
pub struct RustfixDiagnosticServer {
    listener: TcpListener,
    addr: SocketAddr,
}

pub struct StartedServer {
    addr: SocketAddr,
    done: Arc<AtomicBool>,
    thread: Option<JoinHandle<()>>,
}

impl RustfixDiagnosticServer {
    pub fn new() -> Result<Self, Error> {
        let listener = TcpListener::bind("127.0.0.1:0")
            .with_context(|_| "failed to bind TCP listener to manage locking")?;
        let addr = listener.local_addr()?;

        Ok(RustfixDiagnosticServer { listener, addr })
    }

    pub fn configure(&self, process: &mut ProcessBuilder) {
        process.env(DIAGNOSICS_SERVER_VAR, self.addr.to_string());
    }

    pub fn start<F>(self, on_message: F) -> Result<StartedServer, Error>
    where
        F: Fn(Message) + Send + 'static,
    {
        let addr = self.addr;
        let done = Arc::new(AtomicBool::new(false));
        let done2 = done.clone();
        let thread = thread::spawn(move || {
            self.run(&on_message, &done2);
        });

        Ok(StartedServer {
            addr,
            thread: Some(thread),
            done,
        })
    }

    fn run(self, on_message: &Fn(Message), done: &AtomicBool) {
        while let Ok((client, _)) = self.listener.accept() {
            let client = BufReader::new(client);
            match serde_json::from_reader(client) {
                Ok(message) => on_message(message),
                Err(e) => warn!("invalid diagnostics message: {}", e),
            }
            if done.load(Ordering::SeqCst) {
                break
            }
        }
    }
}

impl Drop for StartedServer {
    fn drop(&mut self) {
        self.done.store(true, Ordering::SeqCst);
        // Ignore errors here as this is largely best-effort
        if TcpStream::connect(&self.addr).is_err() {
            return;
        }
        drop(self.thread.take().unwrap().join());
    }
}
<commit_msg>Auto merge of #6053 - dwijnand:finish-removing-PreviewNotFound, r=alexcrichton<commit_after>//! A small TCP server to handle collection of diagnostics information in a
//! cross-platform way for the `cargo fix` command.

use std::collections::HashSet;
use std::env;
use std::io::{BufReader, Read, Write};
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{self, JoinHandle};

use failure::{Error, ResultExt};
use serde_json;

use util::{Config, ProcessBuilder};
use util::errors::CargoResult;

const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
const PLEASE_REPORT_THIS_BUG: &str =
    "\
     This likely indicates a bug in either rustc or cargo itself,\n\
     and we would appreciate a bug report! You're likely to see \n\
     a number of compiler warnings after this message which cargo\n\
     attempted to fix but failed. If you could open an issue at\n\
     https://github.com/rust-lang/cargo/issues\n\
     quoting the full output of this command we'd be very appreciative!\n\n\
     ";

#[derive(Deserialize, Serialize)]
pub enum Message {
    Fixing {
        file: String,
        fixes: u32,
    },
    FixFailed {
        files: Vec<String>,
        krate: Option<String>,
    },
    ReplaceFailed {
        file: String,
        message: String,
    },
    EditionAlreadyEnabled {
        file: String,
        edition: String,
    },
    IdiomEditionMismatch {
        file: String,
        idioms: String,
        edition: Option<String>,
    },
}

impl Message {
    pub fn post(&self) -> Result<(), Error> {
        let addr = env::var(DIAGNOSICS_SERVER_VAR)
            .context("diagnostics collector misconfigured")?;
        let mut client =
            TcpStream::connect(&addr).context("failed to connect to parent diagnostics target")?;

        let s = serde_json::to_string(self).context("failed to serialize message")?;
        client
            .write_all(s.as_bytes())
            .context("failed to write message to diagnostics target")?;
        client
            .shutdown(Shutdown::Write)
            .context("failed to shutdown")?;

        let mut tmp = Vec::new();
        client
            .read_to_end(&mut tmp)
            .context("failed to receive a disconnect")?;

        Ok(())
    }
}

pub struct DiagnosticPrinter<'a> {
    config: &'a Config,
    edition_already_enabled: HashSet<String>,
    idiom_mismatch: HashSet<String>,
}

impl<'a> DiagnosticPrinter<'a> {
    pub fn new(config: &'a Config) -> DiagnosticPrinter<'a> {
        DiagnosticPrinter {
            config,
            edition_already_enabled: HashSet::new(),
            idiom_mismatch: HashSet::new(),
        }
    }

    pub fn print(&mut self, msg: &Message) -> CargoResult<()> {
        match msg {
            Message::Fixing { file, fixes } => {
                let msg = if *fixes == 1 { "fix" } else { "fixes" };
                let msg = format!("{} ({} {})", file, fixes, msg);
                self.config.shell().status("Fixing", msg)
            }
            Message::ReplaceFailed { file, message } => {
                let msg = format!("error applying suggestions to `{}`\n", file);
                self.config.shell().warn(&msg)?;
                write!(
                    self.config.shell().err(),
                    "The full error message was:\n\n> {}\n\n",
                    message,
                )?;
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::FixFailed { files, krate } => {
                if let Some(ref krate) = *krate {
                    self.config.shell().warn(&format!(
                        "failed to automatically apply fixes suggested by rustc \
                         to crate `{}`",
                        krate,
                    ))?;
                } else {
                    self.config.shell().warn(
                        "failed to automatically apply fixes suggested by rustc"
                    )?;
                }
                if !files.is_empty() {
                    writeln!(
                        self.config.shell().err(),
                        "\nafter fixes were automatically applied the compiler \
                         reported errors within these files:\n"
                    )?;
                    for file in files {
                        writeln!(self.config.shell().err(), "  * {}", file)?;
                    }
                    writeln!(self.config.shell().err())?;
                }
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::EditionAlreadyEnabled { file, edition } => {
                // Like above, only warn once per file
                if !self.edition_already_enabled.insert(file.clone()) {
                    return Ok(())
                }

                let msg = format!(
                    "\
cannot prepare for the {} edition when it is enabled, so cargo cannot
automatically fix errors in `{}`

To prepare for the {0} edition you should first remove `edition = '{0}'` from
your `Cargo.toml` and then rerun this command. Once all warnings have been fixed
then you can re-enable the `edition` key in `Cargo.toml`. For some more
information about transitioning to the {0} edition see:

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-your-code-to-a-new-edition.html
",
                    edition,
                    file,
                );
                self.config.shell().error(&msg)?;
                Ok(())
            }
            Message::IdiomEditionMismatch { file, idioms, edition } => {
                // Same as above
                if !self.idiom_mismatch.insert(file.clone()) {
                    return Ok(())
                }
                self.config.shell().error(&format!(
                    "\
cannot migrate to the idioms of the {} edition for `{}`
because it is compiled {}, which doesn't match {0}

consider migrating to the {0} edition by adding `edition = '{0}'` to
`Cargo.toml` and then rerunning this command; a more detailed transition
guide can be found at

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-your-code-to-a-new-edition.html
",
                    idioms,
                    file,
                    match edition {
                        Some(s) => format!("with the {} edition", s),
                        None => "without an edition".to_string(),
                    },
                ))?;
                Ok(())
            }
        }
    }
}

#[derive(Debug)]
pub struct RustfixDiagnosticServer {
    listener: TcpListener,
    addr: SocketAddr,
}

pub struct StartedServer {
    addr: SocketAddr,
    done: Arc<AtomicBool>,
    thread: Option<JoinHandle<()>>,
}

impl RustfixDiagnosticServer {
    pub fn new() -> Result<Self, Error> {
        let listener = TcpListener::bind("127.0.0.1:0")
            .with_context(|_| "failed to bind TCP listener to manage locking")?;
        let addr = listener.local_addr()?;

        Ok(RustfixDiagnosticServer { listener, addr })
    }

    pub fn configure(&self, process: &mut ProcessBuilder) {
        process.env(DIAGNOSICS_SERVER_VAR, self.addr.to_string());
    }

    pub fn start<F>(self, on_message: F) -> Result<StartedServer, Error>
    where
        F: Fn(Message) + Send + 'static,
    {
        let addr = self.addr;
        let done = Arc::new(AtomicBool::new(false));
        let done2 = done.clone();
        let thread = thread::spawn(move || {
            self.run(&on_message, &done2);
        });

        Ok(StartedServer {
            addr,
            thread: Some(thread),
            done,
        })
    }

    fn run(self, on_message: &Fn(Message), done: &AtomicBool) {
        while let Ok((client, _)) = self.listener.accept() {
            let client = BufReader::new(client);
            match serde_json::from_reader(client) {
                Ok(message) => on_message(message),
                Err(e) => warn!("invalid diagnostics message: {}", e),
            }
            if done.load(Ordering::SeqCst) {
                break
            }
        }
    }
}

impl Drop for StartedServer {
    fn drop(&mut self) {
        self.done.store(true, Ordering::SeqCst);
        // Ignore errors here as this is largely best-effort
        if TcpStream::connect(&self.addr).is_err() {
            return;
        }
        drop(self.thread.take().unwrap().join());
    }
}
<|endoftext|>


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

use app_units::Au;
use webrender_traits::{FontKey, FontRenderMode, GlyphDimensions};
use webrender_traits::{NativeFontHandle, GlyphOptions};
use webrender_traits::{GlyphKey};

use freetype::freetype::{FT_Render_Mode, FT_Pixel_Mode};
use freetype::freetype::{FT_Done_FreeType, FT_Library_SetLcdFilter};
use freetype::freetype::{FT_Library, FT_Set_Char_Size};
use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6};
use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph, FT_Render_Glyph};
use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot, FT_LcdFilter};
use freetype::freetype::{FT_Done_Face, FT_Error};

use std::{cmp, mem, ptr, slice};
use std::collections::HashMap;

struct Face {
    face: FT_Face,
}

pub struct FontContext {
    lib: FT_Library,
    faces: HashMap<FontKey, Face>,
}

pub struct RasterizedGlyph {
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

fn float_to_fixed(before: usize, f: f64) -> i32 {
    ((1i32 << before) as f64 * f) as i32
}

fn float_to_fixed_ft(f: f64) -> i32 {
    float_to_fixed(6, f)
}

const SUCCESS: FT_Error = FT_Error(0);

impl FontContext {
    pub fn new() -> FontContext {
        let mut lib: FT_Library = ptr::null_mut();
        unsafe {
            let result = FT_Init_FreeType(&mut lib);
            assert!(result.succeeded(), "Unable to initialize FreeType library {:?}", result);

            // TODO(gw): Check result of this to determine if freetype build supports subpixel.
            let result = FT_Library_SetLcdFilter(lib, FT_LcdFilter::FT_LCD_FILTER_DEFAULT);
            if !result.succeeded() {
                println!("WARN: Initializing a FreeType library build without subpixel AA enabled!");
            }
        }

        FontContext {
            lib: lib,
            faces: HashMap::new(),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8], index: u32) {
        if !self.faces.contains_key(&font_key) {
            let mut face: FT_Face = ptr::null_mut();
            let result = unsafe {
                FT_New_Memory_Face(self.lib,
                                   bytes.as_ptr(),
                                   bytes.len() as FT_Long,
                                   index as FT_Long,
                                   &mut face)
            };
            if result.succeeded() && !face.is_null() {
                self.faces.insert(*font_key, Face {
                    face: face,
                    //_bytes: bytes
                });
            } else {
                println!("WARN: webrender failed to load font {:?}", font_key);
            }
        }
    }

    pub fn add_native_font(&mut self, _font_key: &FontKey, _native_font_handle: NativeFontHandle) {
        panic!("TODO: Not supported on Linux");
    }

    pub fn delete_font(&mut self, font_key: &FontKey) {
        if let Some(face) = self.faces.remove(font_key) {
            let result = unsafe {
                FT_Done_Face(face.face)
            };
            assert!(result.succeeded());
        }
    }

    fn load_glyph(&self,
                  font_key: FontKey,
                  size: Au,
                  character: u32) -> Option<FT_GlyphSlot> {

        debug_assert!(self.faces.contains_key(&font_key));
        let face = self.faces.get(&font_key).unwrap();
        let char_size = float_to_fixed_ft(size.to_f64_px());

        assert_eq!(SUCCESS, unsafe {
            FT_Set_Char_Size(face.face, char_size as FT_F26Dot6, 0, 0, 0)
        });

        let result = unsafe {
            FT_Load_Glyph(face.face, character as FT_UInt, 0)
        };

        if result == SUCCESS {
            let slot = unsafe { (*face.face).glyph };
            assert!(slot != ptr::null_mut());
            Some(slot)
        } else {
            error!("Unable to load glyph for {} of size {:?} from font {:?}, {:?}",
                character, size, font_key, result);
            None
        }
    }

    fn get_glyph_dimensions_impl(slot: FT_GlyphSlot) -> Option<GlyphDimensions> {
        let metrics = unsafe { &(*slot).metrics };
        if metrics.width == 0 || metrics.height == 0 {
            None
        } else {
            let left = metrics.horiBearingX >> 6;
            let top = metrics.horiBearingY >> 6;
            let right = (metrics.horiBearingX + metrics.width + 0x3f) >> 6;
            let bottom = (metrics.horiBearingY + metrics.height + 0x3f) >> 6;
            Some(GlyphDimensions {
                left: left as i32,
                top: top as i32,
                width: (right - left) as u32,
                height: (bottom - top) as u32,
            })
        }
    }

    pub fn get_glyph_dimensions(&mut self,
                                key: &GlyphKey) -> Option<GlyphDimensions> {
        self.load_glyph(key.font_key, key.size, key.index)
            .and_then(Self::get_glyph_dimensions_impl)
    }

    pub fn rasterize_glyph(&mut self,
                           key: &GlyphKey,
                           render_mode: FontRenderMode,
                           _glyph_options: Option<GlyphOptions>)
                           -> Option<RasterizedGlyph> {

        let slot = match self.load_glyph(key.font_key, key.size, key.index) {
            Some(slot) => slot,
            None => return None,
        };
        let render_mode = match render_mode {
            FontRenderMode::Mono => FT_Render_Mode::FT_RENDER_MODE_MONO,
            FontRenderMode::Alpha => FT_Render_Mode::FT_RENDER_MODE_NORMAL,
            FontRenderMode::Subpixel => FT_Render_Mode::FT_RENDER_MODE_LCD,
        };

        let result = unsafe { FT_Render_Glyph(slot, render_mode) };
        if result != SUCCESS {
            error!("Unable to rasterize {:?} with {:?}, {:?}", key, render_mode, result);
            return None;
        }

        let dimensions = Self::get_glyph_dimensions_impl(slot).unwrap();
        let bitmap = unsafe { &(*slot).bitmap };
        let pixel_mode = unsafe { mem::transmute(bitmap.pixel_mode as u32) };
        info!("Rasterizing {:?} as {:?} with dimensions {:?}", key, render_mode, dimensions);
        // we may be filling only a part of the buffer, so initialize the whole thing with 0
        let mut final_buffer = Vec::with_capacity(dimensions.width as usize *
                                                  dimensions.height as usize *
                                                  4);

        let offset_x = dimensions.left - unsafe { (*slot).bitmap_left };

        for y in 0 .. dimensions.height {
            let src_y = y as i32 + dimensions.top - unsafe { (*slot).bitmap_top };
            if src_y < 0 || src_y >= bitmap.rows as i32 {
                for _x in 0 .. dimensions.width {
                    final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
                }
                continue
            }
            let base = unsafe {
                bitmap.buffer.offset((src_y * bitmap.pitch) as isize)
            };
            // determine the destination range of texels that `bitmap` provides data for
            let dst_start = cmp::max(0, -offset_x);
            let dst_end = cmp::min(dimensions.width as i32, bitmap.width as i32 - offset_x);
            for _x in 0 .. dst_start {
                final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
            }
            match pixel_mode {
                FT_Pixel_Mode::FT_PIXEL_MODE_MONO => {
                    for x in dst_start .. dst_end {
                        let src_x = x + offset_x;
                        let mask = 0x80 >> (src_x & 0x7);
                        let byte = unsafe {
                            *base.offset((src_x >> 3) as isize)
                        };
                        let alpha = if byte & mask != 0 { 0xff } else { 0 };
                        final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, alpha]);
                    }
                }
                FT_Pixel_Mode::FT_PIXEL_MODE_GRAY => {
                    for x in dst_start .. dst_end {
                        let alpha = unsafe {
                            *base.offset((x + offset_x) as isize)
                        };
                        final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, alpha]);
                    }
                }
                FT_Pixel_Mode::FT_PIXEL_MODE_LCD => {
                    for x in dst_start .. dst_end {
                        let src_x = ((x + offset_x) * 3) as isize;
                        assert!(src_x+2 < bitmap.pitch as isize);
                        let t = unsafe {
                            slice::from_raw_parts(base.offset(src_x), 3)
                        };
                        final_buffer.extend_from_slice(&[t[2], t[1], t[0], 0xff]);
                    }
                }
                _ => panic!("Unsupported {:?}", pixel_mode)
            }
            for _x in dst_end .. dimensions.width as i32 {
                final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
            }
            assert_eq!(final_buffer.len(), ((y+1) * dimensions.width * 4) as usize);
        }

        Some(RasterizedGlyph {
            width: dimensions.width as u32,
            height: dimensions.height as u32,
            bytes: final_buffer,
        })
    }
}

impl Drop for FontContext {
    fn drop(&mut self) {
        unsafe {
            FT_Done_FreeType(self.lib);
        }
    }
}
<commit_msg>Auto merge of #1241 - kvark:font, r=glennw<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use webrender_traits::{FontKey, FontRenderMode, GlyphDimensions};
use webrender_traits::{NativeFontHandle, GlyphOptions};
use webrender_traits::{GlyphKey};

use freetype::freetype::{FT_Render_Mode, FT_Pixel_Mode};
use freetype::freetype::{FT_Done_FreeType, FT_Library_SetLcdFilter};
use freetype::freetype::{FT_Library, FT_Set_Char_Size};
use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6};
use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph, FT_Render_Glyph};
use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot, FT_LcdFilter};
use freetype::freetype::{FT_Done_Face, FT_Error};

use std::{cmp, mem, ptr, slice};
use std::collections::HashMap;

struct Face {
    face: FT_Face,
}

pub struct FontContext {
    lib: FT_Library,
    faces: HashMap<FontKey, Face>,
}

pub struct RasterizedGlyph {
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

fn float_to_fixed(before: usize, f: f64) -> i32 {
    ((1i32 << before) as f64 * f) as i32
}

fn float_to_fixed_ft(f: f64) -> i32 {
    float_to_fixed(6, f)
}

const SUCCESS: FT_Error = FT_Error(0);

impl FontContext {
    pub fn new() -> FontContext {
        let mut lib: FT_Library = ptr::null_mut();
        unsafe {
            let result = FT_Init_FreeType(&mut lib);
            assert!(result.succeeded(), "Unable to initialize FreeType library {:?}", result);

            // TODO(gw): Check result of this to determine if freetype build supports subpixel.
            let result = FT_Library_SetLcdFilter(lib, FT_LcdFilter::FT_LCD_FILTER_DEFAULT);
            if !result.succeeded() {
                println!("WARN: Initializing a FreeType library build without subpixel AA enabled!");
            }
        }

        FontContext {
            lib: lib,
            faces: HashMap::new(),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8], index: u32) {
        if !self.faces.contains_key(&font_key) {
            let mut face: FT_Face = ptr::null_mut();
            let result = unsafe {
                FT_New_Memory_Face(self.lib,
                                   bytes.as_ptr(),
                                   bytes.len() as FT_Long,
                                   index as FT_Long,
                                   &mut face)
            };
            if result.succeeded() && !face.is_null() {
                self.faces.insert(*font_key, Face {
                    face: face,
                    //_bytes: bytes
                });
            } else {
                println!("WARN: webrender failed to load font {:?}", font_key);
            }
        }
    }

    pub fn add_native_font(&mut self, _font_key: &FontKey, _native_font_handle: NativeFontHandle) {
        panic!("TODO: Not supported on Linux");
    }

    pub fn delete_font(&mut self, font_key: &FontKey) {
        if let Some(face) = self.faces.remove(font_key) {
            let result = unsafe {
                FT_Done_Face(face.face)
            };
            assert!(result.succeeded());
        }
    }

    fn load_glyph(&self,
                  font_key: FontKey,
                  size: Au,
                  character: u32) -> Option<FT_GlyphSlot> {

        debug_assert!(self.faces.contains_key(&font_key));
        let face = self.faces.get(&font_key).unwrap();
        let char_size = float_to_fixed_ft(size.to_f64_px());

        assert_eq!(SUCCESS, unsafe {
            FT_Set_Char_Size(face.face, char_size as FT_F26Dot6, 0, 0, 0)
        });

        let result = unsafe {
            FT_Load_Glyph(face.face, character as FT_UInt, 0)
        };

        if result == SUCCESS {
            let slot = unsafe { (*face.face).glyph };
            assert!(slot != ptr::null_mut());
            Some(slot)
        } else {
            error!("Unable to load glyph for {} of size {:?} from font {:?}, {:?}",
                character, size, font_key, result);
            None
        }
    }

    fn get_glyph_dimensions_impl(slot: FT_GlyphSlot) -> Option<GlyphDimensions> {
        let metrics = unsafe { &(*slot).metrics };
        if metrics.width == 0 || metrics.height == 0 {
            None
        } else {
            let left = metrics.horiBearingX >> 6;
            let top = metrics.horiBearingY >> 6;
            let right = (metrics.horiBearingX + metrics.width + 0x3f) >> 6;
            let bottom = (metrics.horiBearingY + metrics.height + 0x3f) >> 6;
            Some(GlyphDimensions {
                left: left as i32,
                top: top as i32,
                width: (right - left) as u32,
                height: (bottom - top) as u32,
            })
        }
    }

    pub fn get_glyph_dimensions(&mut self,
                                key: &GlyphKey) -> Option<GlyphDimensions> {
        self.load_glyph(key.font_key, key.size, key.index)
            .and_then(Self::get_glyph_dimensions_impl)
    }

    pub fn rasterize_glyph(&mut self,
                           key: &GlyphKey,
                           render_mode: FontRenderMode,
                           _glyph_options: Option<GlyphOptions>)
                           -> Option<RasterizedGlyph> {

        let slot = match self.load_glyph(key.font_key, key.size, key.index) {
            Some(slot) => slot,
            None => return None,
        };
        let render_mode = match render_mode {
            FontRenderMode::Mono => FT_Render_Mode::FT_RENDER_MODE_MONO,
            FontRenderMode::Alpha => FT_Render_Mode::FT_RENDER_MODE_NORMAL,
            FontRenderMode::Subpixel => FT_Render_Mode::FT_RENDER_MODE_LCD,
        };

        let result = unsafe { FT_Render_Glyph(slot, render_mode) };
        if result != SUCCESS {
            error!("Unable to rasterize {:?} with {:?}, {:?}", key, render_mode, result);
            return None;
        }

        let dimensions = Self::get_glyph_dimensions_impl(slot).unwrap();
        let bitmap = unsafe { &(*slot).bitmap };
        let pixel_mode = unsafe { mem::transmute(bitmap.pixel_mode as u32) };
        info!("Rasterizing {:?} as {:?} with dimensions {:?}", key, render_mode, dimensions);
        // we may be filling only a part of the buffer, so initialize the whole thing with 0
        let mut final_buffer = Vec::with_capacity(dimensions.width as usize *
                                                  dimensions.height as usize *
                                                  4);

        let offset_x = dimensions.left - unsafe { (*slot).bitmap_left };

        for y in 0 .. dimensions.height {
            let src_y = y as i32 - dimensions.top + unsafe { (*slot).bitmap_top };
            if src_y < 0 || src_y >= bitmap.rows as i32 {
                for _x in 0 .. dimensions.width {
                    final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
                }
                continue
            }
            let base = unsafe {
                bitmap.buffer.offset((src_y * bitmap.pitch) as isize)
            };
            // determine the destination range of texels that `bitmap` provides data for
            let dst_start = cmp::max(0, -offset_x);
            let dst_end = cmp::min(dimensions.width as i32, bitmap.width as i32 - offset_x);
            for _x in 0 .. dst_start {
                final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
            }
            match pixel_mode {
                FT_Pixel_Mode::FT_PIXEL_MODE_MONO => {
                    for x in dst_start .. dst_end {
                        let src_x = x + offset_x;
                        let mask = 0x80 >> (src_x & 0x7);
                        let byte = unsafe {
                            *base.offset((src_x >> 3) as isize)
                        };
                        let alpha = if byte & mask != 0 { 0xff } else { 0 };
                        final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, alpha]);
                    }
                }
                FT_Pixel_Mode::FT_PIXEL_MODE_GRAY => {
                    for x in dst_start .. dst_end {
                        let alpha = unsafe {
                            *base.offset((x + offset_x) as isize)
                        };
                        final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, alpha]);
                    }
                }
                FT_Pixel_Mode::FT_PIXEL_MODE_LCD => {
                    for x in dst_start .. dst_end {
                        let src_x = ((x + offset_x) * 3) as isize;
                        assert!(src_x+2 < bitmap.pitch as isize);
                        let t = unsafe {
                            slice::from_raw_parts(base.offset(src_x), 3)
                        };
                        final_buffer.extend_from_slice(&[t[2], t[1], t[0], 0xff]);
                    }
                }
                _ => panic!("Unsupported {:?}", pixel_mode)
            }
            for _x in dst_end .. dimensions.width as i32 {
                final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
            }
            assert_eq!(final_buffer.len(), ((y+1) * dimensions.width * 4) as usize);
        }

        Some(RasterizedGlyph {
            width: dimensions.width as u32,
            height: dimensions.height as u32,
            bytes: final_buffer,
        })
    }
}

impl Drop for FontContext {
    fn drop(&mut self) {
        unsafe {
            FT_Done_FreeType(self.lib);
        }
    }
}
<|endoftext|>


<commit_before>// This requires running with:
//
// ```bash
// cargo run --example https --features native-tls-example
// ```
//
// Generate an identity like so:
//
// ```bash
// openssl req -x509 -newkey rsa:4096 -nodes -keyout localhost.key -out localhost.crt -days 3650
// openssl pkcs12 -export -out identity.p12 -inkey localhost.key -in localhost.crt --password mypass
//
// ```

extern crate iron;
#[cfg(feature = "native-tls-example")]
extern crate hyper_native_tls;

#[cfg(feature = "native-tls-example")]
fn main() {
    // Avoid unused errors due to conditional compilation ('native-tls-example' feature is not default)
    use hyper_native_tls::NativeTlsServer;
    use iron::{Iron, Request, Response};
    use iron::status;
    use std::result::Result;

    let ssl = NativeTlsServer::new("identity.p12", "mypass").unwrap();

    match Iron::new(|_: &mut Request| {
        Ok(Response::with((status::Ok, "Hello world!")))
    }).https("127.0.0.1:3000", ssl) {
        Result::Ok(listening) => println!("{:?}", listening),
        Result::Err(err) => panic!("{:?}", err),
    }
    // curl -vvvv https://127.0.0.1:3000/ -k
}

#[cfg(not(feature = "native-tls-example"))]
fn main() {
    // We need to do this to make sure `cargo test` passes.
}
<commit_msg>Fix typo in openssl example (#552)<commit_after>// This requires running with:
//
// ```bash
// cargo run --example https --features native-tls-example
// ```
//
// Generate an identity like so:
//
// ```bash
// openssl req -x509 -newkey rsa:4096 -nodes -keyout localhost.key -out localhost.crt -days 3650
// openssl pkcs12 -export -out identity.p12 -inkey localhost.key -in localhost.crt -password mypass
//
// ```

extern crate iron;
#[cfg(feature = "native-tls-example")]
extern crate hyper_native_tls;

#[cfg(feature = "native-tls-example")]
fn main() {
    // Avoid unused errors due to conditional compilation ('native-tls-example' feature is not default)
    use hyper_native_tls::NativeTlsServer;
    use iron::{Iron, Request, Response};
    use iron::status;
    use std::result::Result;

    let ssl = NativeTlsServer::new("identity.p12", "mypass").unwrap();

    match Iron::new(|_: &mut Request| {
        Ok(Response::with((status::Ok, "Hello world!")))
    }).https("127.0.0.1:3000", ssl) {
        Result::Ok(listening) => println!("{:?}", listening),
        Result::Err(err) => panic!("{:?}", err),
    }
    // curl -vvvv https://127.0.0.1:3000/ -k
}

#[cfg(not(feature = "native-tls-example"))]
fn main() {
    // We need to do this to make sure `cargo test` passes.
}
<|endoftext|>


<commit_before>//! ARM C Language Extensions (ACLE)
//!
//! # Developer notes
//!
//! Below is a list of built-in targets that are representative of the different ARM
//! architectures; the list includes the `target_feature`s they possess.
//!
//! - `armv4t-unknown-linux-gnueabi` - **ARMv4** - `+v4t`
//! - `armv5te-unknown-linux-gnueabi` - **ARMv5TE** - `+v4t +v5te`
//! - `arm-unknown-linux-gnueabi` - **ARMv6** - `+v4t +v5te +v6`
//! - `thumbv6m-none-eabi` - **ARMv6-M** - `+v4t +v5te +v6 +thumb-mode +mclass`
//! - `armv7-unknown-linux-gnueabihf` - **ARMv7-A** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +dsp +thumb2 +aclass`
//! - `armv7r-none-eabi` - **ARMv7-R** - `+v4t +v5te +v6 +v6k +v6t2  +v7 +dsp +thumb2 +rclass`
//! - `thumbv7m-none-eabi` - **ARMv7-M** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +thumb2 +thumb-mode +mclass`
//! - `thumbv7em-none-eabi` - **ARMv7E-M** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +dsp +thumb2 +thumb-mode +mclass`
//! - `aarch64-unknown-linux-gnu` - **ARMv8-A (AArch64)** - `+fp +neon`
//!
//! Section 10.1 of ACLE says:
//!
//! - "In the sequence of Arm architectures { v5, v5TE, v6, v6T2, v7 } each architecture includes
//! its predecessor instruction set."
//!
//! - "In the sequence of Thumb-only architectures { v6-M, v7-M, v7E-M } each architecture includes
//! its predecessor instruction set."
//!
//! From that info and from looking at how LLVM features work (using custom targets) we can identify
//! features that are subsets of others:
//!
//! Legend: `a < b` reads as "`a` is a subset of `b`"; this means that if `b` is enabled then `a` is
//! enabled as well.
//!
//! - `v4t < v5te < v6 < v6k < v6t2 < v7 < v8`
//! - `v6 < v8m < v6t2`
//! - `v7 < v8m.main`
//!
//! # References
//!
//! - [ACLE Q2 2018](https://developer.arm.com/docs/101028/latest)

// Supported arches: 8, 7, 6-M. See Section 10.1 of ACLE (e.g. DMB)
// But this is further refined within the module
#[cfg(any(
    // v8
    target_arch = "aarch64",
    // v7
    target_feature = "v7",
    // v6-M
    target_feature = "mclass"
))]
mod barrier;

#[cfg(any(
    target_arch = "aarch64",
    target_feature = "v7",
    target_feature = "mclass"
))]
pub use self::barrier::*;

mod hints;

pub use self::hints::*;

mod registers;

pub use self::registers::*;

// Supported arches: 5TE, 7E-M. See Section 10.1 of ACLE (e.g. QADD)
// But we also exclude the A profile because DSP is deprecated on that profile as of ACLE 2.0 (see
// section 5.4.7)
#[cfg(any(
    // >= v5TE but excludes v7-A
    all(target_feature = "v5te", not(target_feature = "mclass"), not(target_feature = "aclass")),
    // v7E-M
    all(target_feature = "mclass", target_feature = "dsp"),
))]
mod dsp;

#[cfg(any(
    all(
        target_feature = "v5te",
        not(target_feature = "mclass"),
        not(target_feature = "aclass")
    ),
    all(target_feature = "mclass", target_feature = "dsp"),
))]
pub use dsp::*;

// Deprecated in ACLE 2.0 for the A profile but fully supported on the M and R profiles, says
// Section 5.4.9 of ACLE.
#[cfg(any(
    // v7-R
    target_feature = "rclass",
    // v7E-M
    all(target_feature = "mclass", target_feature = "dsp")
))]
mod simd32;

mod sealed {
    pub trait Dmb {
        unsafe fn __dmb(&self);
    }

    pub trait Dsb {
        unsafe fn __dsb(&self);
    }

    pub trait Isb {
        unsafe fn __isb(&self);
    }

    pub trait Rsr {
        unsafe fn __rsr(&self) -> u32;
    }

    pub trait Rsr64 {
        unsafe fn __rsr64(&self) -> u64;
    }

    pub trait Rsrp {
        unsafe fn __rsrp(&self) -> *const u8;
    }

    pub trait Wsr {
        unsafe fn __wsr(&self, value: u32);
    }

    pub trait Wsr64 {
        unsafe fn __wsr64(&self, value: u64);
    }

    pub trait Wsrp {
        unsafe fn __wsrp(&self, value: *const u8);
    }
}
<commit_msg>fix relative import<commit_after>//! ARM C Language Extensions (ACLE)
//!
//! # Developer notes
//!
//! Below is a list of built-in targets that are representative of the different ARM
//! architectures; the list includes the `target_feature`s they possess.
//!
//! - `armv4t-unknown-linux-gnueabi` - **ARMv4** - `+v4t`
//! - `armv5te-unknown-linux-gnueabi` - **ARMv5TE** - `+v4t +v5te`
//! - `arm-unknown-linux-gnueabi` - **ARMv6** - `+v4t +v5te +v6`
//! - `thumbv6m-none-eabi` - **ARMv6-M** - `+v4t +v5te +v6 +thumb-mode +mclass`
//! - `armv7-unknown-linux-gnueabihf` - **ARMv7-A** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +dsp +thumb2 +aclass`
//! - `armv7r-none-eabi` - **ARMv7-R** - `+v4t +v5te +v6 +v6k +v6t2  +v7 +dsp +thumb2 +rclass`
//! - `thumbv7m-none-eabi` - **ARMv7-M** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +thumb2 +thumb-mode +mclass`
//! - `thumbv7em-none-eabi` - **ARMv7E-M** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +dsp +thumb2 +thumb-mode +mclass`
//! - `aarch64-unknown-linux-gnu` - **ARMv8-A (AArch64)** - `+fp +neon`
//!
//! Section 10.1 of ACLE says:
//!
//! - "In the sequence of Arm architectures { v5, v5TE, v6, v6T2, v7 } each architecture includes
//! its predecessor instruction set."
//!
//! - "In the sequence of Thumb-only architectures { v6-M, v7-M, v7E-M } each architecture includes
//! its predecessor instruction set."
//!
//! From that info and from looking at how LLVM features work (using custom targets) we can identify
//! features that are subsets of others:
//!
//! Legend: `a < b` reads as "`a` is a subset of `b`"; this means that if `b` is enabled then `a` is
//! enabled as well.
//!
//! - `v4t < v5te < v6 < v6k < v6t2 < v7 < v8`
//! - `v6 < v8m < v6t2`
//! - `v7 < v8m.main`
//!
//! # References
//!
//! - [ACLE Q2 2018](https://developer.arm.com/docs/101028/latest)

// Supported arches: 8, 7, 6-M. See Section 10.1 of ACLE (e.g. DMB)
// But this is further refined within the module
#[cfg(any(
    // v8
    target_arch = "aarch64",
    // v7
    target_feature = "v7",
    // v6-M
    target_feature = "mclass"
))]
mod barrier;

#[cfg(any(
    target_arch = "aarch64",
    target_feature = "v7",
    target_feature = "mclass"
))]
pub use self::barrier::*;

mod hints;

pub use self::hints::*;

mod registers;

pub use self::registers::*;

// Supported arches: 5TE, 7E-M. See Section 10.1 of ACLE (e.g. QADD)
// But we also exclude the A profile because DSP is deprecated on that profile as of ACLE 2.0 (see
// section 5.4.7)
#[cfg(any(
    // >= v5TE but excludes v7-A
    all(target_feature = "v5te", not(target_feature = "mclass"), not(target_feature = "aclass")),
    // v7E-M
    all(target_feature = "mclass", target_feature = "dsp"),
))]
mod dsp;

#[cfg(any(
    all(
        target_feature = "v5te",
        not(target_feature = "mclass"),
        not(target_feature = "aclass")
    ),
    all(target_feature = "mclass", target_feature = "dsp"),
))]
pub use self::dsp::*;

// Deprecated in ACLE 2.0 for the A profile but fully supported on the M and R profiles, says
// Section 5.4.9 of ACLE.
#[cfg(any(
    // v7-R
    target_feature = "rclass",
    // v7E-M
    all(target_feature = "mclass", target_feature = "dsp")
))]
mod simd32;

mod sealed {
    pub trait Dmb {
        unsafe fn __dmb(&self);
    }

    pub trait Dsb {
        unsafe fn __dsb(&self);
    }

    pub trait Isb {
        unsafe fn __isb(&self);
    }

    pub trait Rsr {
        unsafe fn __rsr(&self) -> u32;
    }

    pub trait Rsr64 {
        unsafe fn __rsr64(&self) -> u64;
    }

    pub trait Rsrp {
        unsafe fn __rsrp(&self) -> *const u8;
    }

    pub trait Wsr {
        unsafe fn __wsr(&self, value: u32);
    }

    pub trait Wsr64 {
        unsafe fn __wsr64(&self, value: u64);
    }

    pub trait Wsrp {
        unsafe fn __wsrp(&self, value: *const u8);
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(test, feature(step_by))]

use std::cmp;

pub trait ZipLongestIteratorExt: Iterator + Sized {
    /// Creates an iterator which iterates over both this and the specified
    /// iterators simultaneously, yielding pairs of two optional elements.
    /// When both iterators return None, all further invocations of next() will
    /// return None.
    ///
    /// # Example
    ///
    /// ```rust
    /// let a = [0i];
    /// let b = [1i, 2i];
    /// let mut it = a.iter().zip(b.iter());
    /// let (x0, x1, x2) = (0i, 1i, 2i);
    /// assert_eq!(it.next().unwrap(), (Some(&x0), Some(&x1)));
    /// assert_eq!(it.next().unwrap(), (None, Some(&x2)));
    /// assert!(it.next().is_none());
    /// ```
    #[inline]
    fn zip_longest<U: Iterator>(self, other: U) -> ZipLongest<Self, U> {
        ZipLongest{a: self, b: other}
    }
}

/// An iterator which iterates two other iterators simultaneously
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct ZipLongest<T, U> {
    a: T,
    b: U
}

impl<A, B, T: Iterator<Item = A>, U: Iterator<Item = B>> Iterator for ZipLongest<T, U> {
    type Item = EitherOrBoth<A, B>;

    #[inline]
    fn next(&mut self) -> Option<EitherOrBoth<A, B>> {
        match (self.a.next(), self.b.next()) {
            (None, None) => None,
            (Some(a), None) => Some(EitherOrBoth::Left(a)),
            (None, Some(b)) => Some(EitherOrBoth::Right(b)),
            (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (a_lower, a_upper) = self.a.size_hint();
        let (b_lower, b_upper) = self.b.size_hint();

        let lower = cmp::max(a_lower, b_lower);

        let upper = match (a_upper, b_upper) {
            (Some(x), Some(y)) => Some(cmp::max(x,y)),
            _ => None
        };

        (lower, upper)
    }
}

impl<T, U> DoubleEndedIterator for ZipLongest<T, U>
where T: DoubleEndedIterator + ExactSizeIterator, U: DoubleEndedIterator + ExactSizeIterator {
    #[inline]
    fn next_back(&mut self) -> Option<<Self as Iterator>::Item> {
        use std::cmp::Ordering::{Equal, Greater, Less};
        match self.a.len().cmp(&self.b.len()) {
            Equal => match (self.a.next_back(), self.b.next_back()) {
                (None, None) => None,
                (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
                // XXX these can only happen if .len() is inconsistent with .next_back()
                (Some(a), None) => Some(EitherOrBoth::Left(a)),
                (None, Some(b)) => Some(EitherOrBoth::Right(b)),
            },
            Greater => self.a.next_back().map(EitherOrBoth::Left),
            Less => self.b.next_back().map(EitherOrBoth::Right),
        }
    }
}

impl<T: ExactSizeIterator, U: ExactSizeIterator> ExactSizeIterator for ZipLongest<T, U> {}

impl<I> ZipLongestIteratorExt for I where I: Iterator {}

/// A value yielded by `ZipLongest`.
/// Contains one or two values,
/// depending on which of the input iterators are exhausted.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum EitherOrBoth<A, B> {
    /// Neither input iterator is exhausted yet, yielding two values.
    Both(A, B),
    /// The parameter iterator of `.zip_longest()` is exhausted,
    /// only yielding a value from the `self` iterator.
    Left(A),
    /// The `self` iterator of `.zip_longest()` is exhausted,
    /// only yielding a value from the parameter iterator.
    Right(B),
}

#[test]
fn test_iterator_size_hint() {
    use std::usize;

    let c = (0i32..).step_by(1);
    let v: &[_] = &[0i32, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    let v2 = &[10i32, 11, 12];
    let vi = v.iter();
    assert_eq!(c.zip_longest(vi.clone()).size_hint(), (usize::MAX, None));
    assert_eq!(vi.zip_longest(v2.iter()).size_hint(), (10, Some(10)));
}

#[test]
fn test_double_ended() {
    let xs = [1i32, 2, 3, 4, 5, 6];
    let ys = [1i32, 2, 3, 7];
    let a = xs.iter().map(|&x| x);
    let b = ys.iter().map(|&x| x);
    let mut it = a.zip_longest(b);
    assert_eq!(it.next(), Some(EitherOrBoth::Both(1, 1)));
    assert_eq!(it.next(), Some(EitherOrBoth::Both(2, 2)));
    assert_eq!(it.next_back(), Some(EitherOrBoth::Left(6)));
    assert_eq!(it.next_back(), Some(EitherOrBoth::Left(5)));
    assert_eq!(it.next_back(), Some(EitherOrBoth::Both(4, 7)));
    assert_eq!(it.next(), Some(EitherOrBoth::Both(3, 3)));
    assert_eq!(it.next(), None);
}
<commit_msg>Upgrade to rustc 1.20.0-nightly (3610a70ce 2017-07-05)<commit_after>use std::cmp;

pub trait ZipLongestIteratorExt: Iterator + Sized {
    /// Creates an iterator which iterates over both this and the specified
    /// iterators simultaneously, yielding pairs of two optional elements.
    /// When both iterators return None, all further invocations of next() will
    /// return None.
    ///
    /// # Example
    ///
    /// ```rust
    /// let a = [0i];
    /// let b = [1i, 2i];
    /// let mut it = a.iter().zip(b.iter());
    /// let (x0, x1, x2) = (0i, 1i, 2i);
    /// assert_eq!(it.next().unwrap(), (Some(&x0), Some(&x1)));
    /// assert_eq!(it.next().unwrap(), (None, Some(&x2)));
    /// assert!(it.next().is_none());
    /// ```
    #[inline]
    fn zip_longest<U: Iterator>(self, other: U) -> ZipLongest<Self, U> {
        ZipLongest{a: self, b: other}
    }
}

/// An iterator which iterates two other iterators simultaneously
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct ZipLongest<T, U> {
    a: T,
    b: U
}

impl<A, B, T: Iterator<Item = A>, U: Iterator<Item = B>> Iterator for ZipLongest<T, U> {
    type Item = EitherOrBoth<A, B>;

    #[inline]
    fn next(&mut self) -> Option<EitherOrBoth<A, B>> {
        match (self.a.next(), self.b.next()) {
            (None, None) => None,
            (Some(a), None) => Some(EitherOrBoth::Left(a)),
            (None, Some(b)) => Some(EitherOrBoth::Right(b)),
            (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (a_lower, a_upper) = self.a.size_hint();
        let (b_lower, b_upper) = self.b.size_hint();

        let lower = cmp::max(a_lower, b_lower);

        let upper = match (a_upper, b_upper) {
            (Some(x), Some(y)) => Some(cmp::max(x,y)),
            _ => None
        };

        (lower, upper)
    }
}

impl<T, U> DoubleEndedIterator for ZipLongest<T, U>
where T: DoubleEndedIterator + ExactSizeIterator, U: DoubleEndedIterator + ExactSizeIterator {
    #[inline]
    fn next_back(&mut self) -> Option<<Self as Iterator>::Item> {
        use std::cmp::Ordering::{Equal, Greater, Less};
        match self.a.len().cmp(&self.b.len()) {
            Equal => match (self.a.next_back(), self.b.next_back()) {
                (None, None) => None,
                (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
                // XXX these can only happen if .len() is inconsistent with .next_back()
                (Some(a), None) => Some(EitherOrBoth::Left(a)),
                (None, Some(b)) => Some(EitherOrBoth::Right(b)),
            },
            Greater => self.a.next_back().map(EitherOrBoth::Left),
            Less => self.b.next_back().map(EitherOrBoth::Right),
        }
    }
}

impl<T: ExactSizeIterator, U: ExactSizeIterator> ExactSizeIterator for ZipLongest<T, U> {}

impl<I> ZipLongestIteratorExt for I where I: Iterator {}

/// A value yielded by `ZipLongest`.
/// Contains one or two values,
/// depending on which of the input iterators are exhausted.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum EitherOrBoth<A, B> {
    /// Neither input iterator is exhausted yet, yielding two values.
    Both(A, B),
    /// The parameter iterator of `.zip_longest()` is exhausted,
    /// only yielding a value from the `self` iterator.
    Left(A),
    /// The `self` iterator of `.zip_longest()` is exhausted,
    /// only yielding a value from the parameter iterator.
    Right(B),
}

#[test]
fn test_iterator_size_hint() {
    use std::usize;

    let c = 0i32..;
    let v: &[_] = &[0i32, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    let v2 = &[10i32, 11, 12];
    let vi = v.iter();
    assert_eq!(c.zip_longest(vi.clone()).size_hint(), (usize::MAX, None));
    assert_eq!(vi.zip_longest(v2.iter()).size_hint(), (10, Some(10)));
}

#[test]
fn test_double_ended() {
    let xs = [1i32, 2, 3, 4, 5, 6];
    let ys = [1i32, 2, 3, 7];
    let a = xs.iter().map(|&x| x);
    let b = ys.iter().map(|&x| x);
    let mut it = a.zip_longest(b);
    assert_eq!(it.next(), Some(EitherOrBoth::Both(1, 1)));
    assert_eq!(it.next(), Some(EitherOrBoth::Both(2, 2)));
    assert_eq!(it.next_back(), Some(EitherOrBoth::Left(6)));
    assert_eq!(it.next_back(), Some(EitherOrBoth::Left(5)));
    assert_eq!(it.next_back(), Some(EitherOrBoth::Both(4, 7)));
    assert_eq!(it.next(), Some(EitherOrBoth::Both(3, 3)));
    assert_eq!(it.next(), None);
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]

#![deny(clippy)]
#![allow(boxed_local)]
#![allow(blacklisted_name)]

pub fn test(foo: &Box<bool>) { //~ ERROR you seem to be trying to use `&Box<T>`
    println!("{:?}", foo)
}

fn main(){
    test(&Box::new(false));
}
<commit_msg>Add more exhaustive tests for borrow_box<commit_after>#![feature(plugin)]
#![plugin(clippy)]

#![deny(clippy)]
#![allow(boxed_local)]
#![allow(blacklisted_name)]
#![allow(unused_variables)]
#![allow(dead_code)]

pub fn test1(foo: &Box<bool>) { //~ ERROR you seem to be trying to use `&Box<T>`
    println!("{:?}", foo)
}

pub fn test2() {
    let foo: &Box<bool>; //~ ERROR you seem to be trying to use `&Box<T>`
}

struct Test3<'a> {
    foo: &'a Box<bool> //~ ERROR you seem to be trying to use `&Box<T>`
}

fn main(){
    test1(&Box::new(false));
    test2();
}
<|endoftext|>


<commit_before>//! `StructureContainer` data description.
use super::super::resources::ResourceType;
use super::super::resources::Store;
use crate::data::RoomName;

with_base_fields_and_update_struct! {
    /// A container structure - a structure which can store a small number of any combination of
    /// resources, and can be built in any room, but decays over time.
    #[derive(Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureContainer {
        /// The current number of hit-points this structure has.
        #[serde(default)]
        pub hits: i32,
        /// The maximum number of hit-points this structure has.
        #[serde(default)]
        pub hits_max: i32,
        /// Total capacity for this structure.
        #[serde(rename = "energyCapacity")]
        pub capacity: i32,
        /// The next game tick when this structure's hits will decrease naturally.
        pub next_decay_time: u32,
        /// Whether or not an attack on this structure will send an email to the owner automatically.
        pub notify_when_attacked: bool,
        /// The resources and amounts of each resource some game object holds.
        pub store: Store,
    }

    /// The update structure for an extension structure.
    #[derive(Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureContainerUpdate {
        - hits: i32,
        - hits_max: i32,
        #[serde(rename = "energyCapacity")]
        - capacity: i32,
        - next_decay_time: u32,
        - notify_when_attacked: bool,
        - store: Store,
    }
}

impl StructureContainer {
    /// Iterates over this structure's resources.
    pub fn resources(&self) -> impl Iterator<Item = (ResourceType, i32)> + '_ {
        self.store.iter()
    }
}

#[cfg(test)]
mod test {
    use serde::Deserialize;

    use super::StructureContainer;
    use crate::websocket::types::room::resources::ResourceType;

    #[test]
    fn parse_container() {
        let json = json!({
            "_id": "58cc8143050a8f701678f22e",
            "store": {
                "energy": 2000,
            },
            "energyCapacity": 2000,
            "hits": 250000,
            "hitsMax": 250000,
            "nextDecayTime": 20233841,
            "notifyWhenAttacked": true,
            "room": "E9N23",
            "type": "container",
            "x": 19,
            "y": 22
        });

        let obj = StructureContainer::deserialize(json).unwrap();

        match obj {
            StructureContainer {
                capacity: 2000,
                hits: 250000,
                hits_max: 250000,
                next_decay_time: 20233841,
                notify_when_attacked: true,
                x: 19,
                y: 22,
                ref id,
                ref store,
                ..
            } if id == "58cc8143050a8f701678f22e" && *store == store! {Energy: 2000} => (),
            other => panic!(
                "expected pre-set StructureContainer to match, found {:#?}",
                other
            ),
        }

        assert_eq!(
            {
                let mut contents = obj.resources().collect::<Vec<_>>();
                contents.sort();
                contents
            },
            {
                let mut expected = vec![(ResourceType::Energy, 2000)];
                expected.sort();
                expected
            }
        );
    }
}
<commit_msg>Updated StructureContainer<commit_after>//! `StructureContainer` data description.
use super::super::resources::ResourceType;
use super::super::resources::Store;
use crate::data::RoomName;

with_base_fields_and_update_struct! {
    /// A container structure - a structure which can store a small number of any combination of
    /// resources, and can be built in any room, but decays over time.
    #[derive(Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureContainer {
        /// The current number of hit-points this structure has.
        #[serde(default)]
        pub hits: i32,
        /// The maximum number of hit-points this structure has.
        #[serde(default)]
        pub hits_max: i32,
        /// Total capacity for this structure.
        #[serde(rename = "storeCapacity")]
        pub capacity: i32,
        /// The next game tick when this structure's hits will decrease naturally.
        pub next_decay_time: u32,
        /// Whether or not an attack on this structure will send an email to the owner automatically.
        pub notify_when_attacked: bool,
        /// The resources and amounts of each resource some game object holds.
        pub store: Store,
    }

    /// The update structure for an extension structure.
    #[derive(Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureContainerUpdate {
        - hits: i32,
        - hits_max: i32,
        #[serde(rename = "storeCapacity")]
        - capacity: i32,
        - next_decay_time: u32,
        - notify_when_attacked: bool,
        - store: Store,
    }
}

impl StructureContainer {
    /// Iterates over this structure's resources.
    pub fn resources(&self) -> impl Iterator<Item = (ResourceType, i32)> + '_ {
        self.store.iter()
    }
}

#[cfg(test)]
mod test {
    use serde::Deserialize;

    use super::StructureContainer;
    use crate::websocket::types::room::resources::ResourceType;

    #[test]
    fn parse_container() {
        let json = json!({
          "_id": "5c229f613f9ca9206752338c",
          "type": "container",
          "x": 20,
          "y": 24,
          "room": "E9S32",
          "notifyWhenAttacked": true,
          "hits": 230000,
          "hitsMax": 250000,
          "nextDecayTime": 30246717,
          "store": {
            "energy": 447,
            "XLHO2": 0,
            "Z": 5,
            "XGHO2": 0,
            "XUH2O": 0,
            "XZHO2": 0,
            "GO": 0,
            "KO": 0,
            "ZH": 0,
            "UH": 0,
            "UO": 0
          },
          "storeCapacity": 2000
        });

        let obj = StructureContainer::deserialize(json).unwrap();

        match obj {
            StructureContainer {
                capacity: 2000,
                hits: 230000,
                hits_max: 250000,
                next_decay_time: 30246717,
                notify_when_attacked: true,
                x: 20,
                y: 24,
                ref id,
                ref store,
                ..
            } if id == "5c229f613f9ca9206752338c" && *store == store! {Energy: 447, Zynthium: 5} => (),
            other => panic!(
                "expected pre-set StructureContainer to match, found {:#?}",
                other
            ),
        }

        assert_eq!(
            {
                let mut contents = obj.resources().collect::<Vec<_>>();
                contents.sort();
                contents
            },
            {
                let mut expected = vec![(ResourceType::Energy, 447), (ResourceType::Zynthium, 5)];
                expected.sort();
                expected
            }
        );
    }
}
<|endoftext|>


<commit_before>
use std::borrow::Cow;
use std::fmt;

use assembler::source_file_location::SourceFileLocation;

#[derive(PartialEq, Debug, Clone)]
pub enum Token<'a> {
  /// A single-line comment. Value includes ';' but not the newline.
  SingleLineComment(&'a str, SourceFileLocation<'a>),
  /// A period.
  DirectiveMarker(SourceFileLocation<'a>),
  /// An identifier (starts with an _ or a letter, is an underscore or alphanumeric).
  Identifier(&'a str, SourceFileLocation<'a>),
  /// A colon.
  LabelMarker(SourceFileLocation<'a>),
  /// A string literal, contained in double-quotes. Quotes are not included in the value and it is unescaped.
  StringLiteral(&'a str, SourceFileLocation<'a>),
  /// A numeric literal value.
  NumericLiteral(usize, SourceFileLocation<'a>),
  /// List separator token ','.
  Comma(SourceFileLocation<'a>),
  /// Newline, a \n character.
  Newline(SourceFileLocation<'a>),
  /// An including the reason that the tokenization failed.
  Error(Cow<'a, str>, SourceFileLocation<'a>)
}

impl<'a> Token<'a> {
  /**
   @return A reference to the source file location corresponding to any variant of Token.
   */
  pub fn location(&self) -> &SourceFileLocation<'a> {
    match *self {
      Token::SingleLineComment(_, ref loc)  => loc,
      Token::DirectiveMarker(ref loc)       => loc,
      Token::Identifier(_, ref loc)         => loc,
      Token::LabelMarker(ref loc)           => loc,
      Token::StringLiteral(_, ref loc)      => loc,
      Token::NumericLiteral(_, ref loc)     => loc,
      Token::Comma(ref loc)                 => loc,
      Token::Newline(ref loc)               => loc,
      Token::Error(_, ref loc)              => loc
    }
  }
}

impl<'a> fmt::Display for Token<'a> {
  /**
   Formats the receiver for display purposes. This includes the associated value if any
   while omitting the source file location component. Names are lower-case.
   @param f Formatter to write into.
   @return A result representing the formatted receiver or a failure to write into the Formatter.
   */
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match *self {
      Token::SingleLineComment(_, _)        => write!(f, "single-line comment"),
      Token::DirectiveMarker(_)             => write!(f, "directive marker"),
      Token::Identifier(ref value, _)       => write!(f, "identifier ({})", value),
      Token::LabelMarker(_)                 => write!(f, "label marker"),
      Token::StringLiteral(ref value, _)    => write!(f, "string literal (\"{}\")", value),
      Token::NumericLiteral(ref value, _)   => write!(f, "numeric literal ({} / ${:X})", value, value),
      Token::Comma(_)                       => write!(f, "comma"),
      Token::Newline(_)                     => write!(f, "newline"),
      Token::Error(ref reason, _)           => write!(f, "{}", reason)
    }
  }
}

#[cfg(test)]
mod tests {

  use std::borrow::Cow;

  use super::*;

  use assembler::source_file_location::SourceFileLocation;

  #[test]
  fn test_display_fmt() {
    let location = SourceFileLocation::new("test_file.s", 1, 1, 1);
    assert_eq!(format!("{}", Token::SingleLineComment("; Hello", location.clone())), "single-line comment");
    assert_eq!(format!("{}", Token::DirectiveMarker(location.clone())), "directive marker");
    assert_eq!(format!("{}", Token::Identifier("test_id", location.clone())), "identifier (test_id)");
    assert_eq!(format!("{}", Token::LabelMarker(location.clone())), "label marker");
    assert_eq!(format!("{}", Token::StringLiteral("Hello", location.clone())), "string literal (\"Hello\")");
    assert_eq!(format!("{}", Token::NumericLiteral(12, location.clone())), "numeric literal (12 / $C)");
    assert_eq!(format!("{}", Token::Comma(location.clone())), "comma");
    assert_eq!(format!("{}", Token::Newline(location.clone())), "newline");
    assert_eq!(format!("{}", Token::Error(Cow::Borrowed("error_reason"), location.clone())), "error_reason");
  }

}
<commit_msg>Add constants for token display names.<commit_after>
use std::borrow::Cow;
use std::fmt;

use assembler::source_file_location::SourceFileLocation;

#[derive(PartialEq, Debug, Clone)]
pub enum Token<'a> {
  /// A single-line comment. Value includes ';' but not the newline.
  SingleLineComment(&'a str, SourceFileLocation<'a>),
  /// A period.
  DirectiveMarker(SourceFileLocation<'a>),
  /// An identifier (starts with an _ or a letter, is an underscore or alphanumeric).
  Identifier(&'a str, SourceFileLocation<'a>),
  /// A colon.
  LabelMarker(SourceFileLocation<'a>),
  /// A string literal, contained in double-quotes. Quotes are not included in the value and it is unescaped.
  StringLiteral(&'a str, SourceFileLocation<'a>),
  /// A numeric literal value.
  NumericLiteral(usize, SourceFileLocation<'a>),
  /// List separator token ','.
  Comma(SourceFileLocation<'a>),
  /// Newline, a \n character.
  Newline(SourceFileLocation<'a>),
  /// An including the reason that the tokenization failed.
  Error(Cow<'a, str>, SourceFileLocation<'a>)
}

impl<'a> Token<'a> {
  /**
   @return A reference to the source file location corresponding to any variant of Token.
   */
  pub fn location(&self) -> &SourceFileLocation<'a> {
    match *self {
      Token::SingleLineComment(_, ref loc)  => loc,
      Token::DirectiveMarker(ref loc)       => loc,
      Token::Identifier(_, ref loc)         => loc,
      Token::LabelMarker(ref loc)           => loc,
      Token::StringLiteral(_, ref loc)      => loc,
      Token::NumericLiteral(_, ref loc)     => loc,
      Token::Comma(ref loc)                 => loc,
      Token::Newline(ref loc)               => loc,
      Token::Error(_, ref loc)              => loc
    }
  }
}

/**
 Un-parameterized display names for tokens.
 */
pub mod display_names {
  pub const SINGLE_LINE_COMMENT: &'static str = "single-line comment";
  pub const DIRECTIVE_MARKER: &'static str = "directive marker";
  pub const IDENTIFIER: &'static str = "identifier";
  pub const LABEL_MARKER: &'static str = "label marker";
  pub const STRING_LITERAL: &'static str = "string literal";
  pub const NUMERIC_LITERAL: &'static str = "numeric literal";
  pub const COMMA: &'static str = "comma";
  pub const NEWLINE: &'static str = "newline";
}

impl<'a> fmt::Display for Token<'a> {
  /**
   Formats the receiver for display purposes. This includes the associated value if any
   while omitting the source file location component. Names are lower-case.
   @param f Formatter to write into.
   @return A result representing the formatted receiver or a failure to write into the Formatter.
   */
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match *self {
      Token::SingleLineComment(_, _)        => write!(f, "{}", display_names::SINGLE_LINE_COMMENT),
      Token::DirectiveMarker(_)             => write!(f, "{}", display_names::DIRECTIVE_MARKER),
      Token::LabelMarker(_)                 => write!(f, "{}", display_names::LABEL_MARKER),
      Token::Comma(_)                       => write!(f, "{}", display_names::COMMA),
      Token::Newline(_)                     => write!(f, "{}", display_names::NEWLINE),
      Token::Identifier(ref value, _)       => write!(f, "{} ({})", display_names::IDENTIFIER, value),
      Token::StringLiteral(ref value, _)    => write!(f, "{} (\"{}\")", display_names::STRING_LITERAL, value),
      Token::NumericLiteral(ref value, _)   => write!(f, "{} ({} / ${:X})", display_names::NUMERIC_LITERAL, value, value),
      Token::Error(ref reason, _)           => write!(f, "{}", reason)
    }
  }
}

#[cfg(test)]
mod tests {

  use std::borrow::Cow;

  use super::*;

  use assembler::source_file_location::SourceFileLocation;

  #[test]
  fn test_display_fmt() {
    let location = SourceFileLocation::new("test_file.s", 1, 1, 1);
    assert_eq!(format!("{}", Token::SingleLineComment("; Hello", location.clone())), "single-line comment");
    assert_eq!(format!("{}", Token::DirectiveMarker(location.clone())), "directive marker");
    assert_eq!(format!("{}", Token::Identifier("test_id", location.clone())), "identifier (test_id)");
    assert_eq!(format!("{}", Token::LabelMarker(location.clone())), "label marker");
    assert_eq!(format!("{}", Token::StringLiteral("Hello", location.clone())), "string literal (\"Hello\")");
    assert_eq!(format!("{}", Token::NumericLiteral(12, location.clone())), "numeric literal (12 / $C)");
    assert_eq!(format!("{}", Token::Comma(location.clone())), "comma");
    assert_eq!(format!("{}", Token::Newline(location.clone())), "newline");
    assert_eq!(format!("{}", Token::Error(Cow::Borrowed("error_reason"), location.clone())), "error_reason");
  }

}
<|endoftext|>