<commit_before>/**
 * http://static.rust-lang.org/doc/0.7/std/hashmap.html
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */
use std::hashmap::HashMap;

fn main() {
	println("Using borrowed pointers as keys.");
	let mut h = HashMap::new::<&str, int>();
	h.insert("foo", 42);
	println(fmt!("Is there a key foo?  => %?", h.contains_key(& &"foo"))); // => true
	println(fmt!("Is there a key baz?  => %?", h.contains_key(& &"baz"))); // => false
	println(fmt!("The value for foo is => %?", h.find(& &"foo"))); // => Some(&42)
	h.insert(key, 1);
	println(fmt!("Is there a key baz?  => %?", h.contains_key(& &"baz"))); // => false

	// You don't actually need the HashMap to own the keys (but
	// unless all keys are static, this will be likely to lead
	// to problems, so I don't suggest you do it in reality)

	println("Using owned pointers as keys.");
	let mut h = HashMap::new::<~str, int>();
	h.insert(~"foo", 42);
	println(fmt!("Is there a key foo?  => %?", h.contains_key(&~"foo"))); // => true
	println(fmt!("Is there a key baz?  => %?", h.contains_key(&~"baz"))); // => false
	println(fmt!("The value for foo is => %?", h.find(&~"foo"))); // => Some(&42)
	let key = "baz";
	h.insert(key.to_owned(), 1);
	println(fmt!("Is there a key baz?  => %?", h.contains_key(&~"baz"))); // => true
}
<commit_msg>Minor changes<commit_after>/**
 * http://static.rust-lang.org/doc/0.7/std/hashmap.html
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */
use std::hashmap::HashMap;

fn main() {
	println("Using borrowed pointers as keys.");
	let mut h = HashMap::new::<&str, int>();
	h.insert("foo", 42);
	println(fmt!("Is there a key foo?  => %?", h.contains_key(& &"foo"))); // => true
	println(fmt!("Is there a key baz?  => %?", h.contains_key(& &"baz"))); // => false
	println(fmt!("The value for foo is => %?", h.find(& &"foo"))); // => Some(&42)
	let key = "baz";
	h.insert(key, 1);
	println(fmt!("Is there a key baz?  => %?", h.contains_key(& &"baz"))); // => false

	// You don't actually need the HashMap to own the keys (but
	// unless all keys are static, this will be likely to lead
	// to problems, so I don't suggest you do it in reality)

	println("Using owned pointers as keys.");
	let mut h = HashMap::new::<~str, int>();
	h.insert(~"foo", 42);
	println(fmt!("Is there a key foo?  => %?", h.contains_key(&~"foo"))); // => true
	println(fmt!("Is there a key baz?  => %?", h.contains_key(&~"baz"))); // => false
	println(fmt!("The value for foo is => %?", h.find(&~"foo"))); // => Some(&42)
	h.insert(key.to_owned(), 1);
	println(fmt!("Is there a key baz?  => %?", h.contains_key(&~"baz"))); // => true
}
<|endoftext|>


<commit_before>use core::cmp::{Eq, Ord};

pub trait PersistentMap<K: Copy Eq Ord, V: Copy> {
  pure fn get(k: K) -> @Option<V>;
  pure fn put(k: K, v: V) -> self;
  pure fn delete(k: K) -> self;
  pure fn traverse(f: fn((&K), (@Option<V>)));
}

enum RBColor {
  Red,
  Black
}

pub enum RBMap<K: Copy Eq Ord, V: Copy> {
  //   color    left         k  value       right
  Tree(RBColor, @RBMap<K,V>, K, @Option<V>, @RBMap<K,V>),
  Leaf
}

pure fn RBMap<K: Copy Eq Ord, V: Copy>(key: K, value: V) -> @RBMap<K, V> {
  @Tree(Red, @Leaf, key, @Some(value), @Leaf)
}

/**
 * A purely functional Left-Leaning Red-Black Tree.
 */
impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> : PersistentMap<K, V> {
  pure fn get(k: K) -> @Option<V> {
    match self {
      @Leaf => @None,
      @Tree(_, left, key, maybe_value, right) => {
        if (k.lt(&key)) {
          left.get(k)
        } else if (k.gt(&key)) {
          right.get(k)
        } else {
          maybe_value
        }
      }
    }
  }

  /// Visit all pairs in the map in order.
  pure fn traverse(f: fn((&K), (@Option<V>))) {
    match *self {
      Leaf => (),
      Tree(_, left, key, maybe_value, right) => {
        left.traverse(f);
        f(&key, maybe_value);
        right.traverse(f);
      }
    }
  }

  pure fn put(k: K, new_value: V) -> @RBMap<K, V> {
    self.modify(k, @Some(new_value))
  }

  pure fn delete(k: K) -> @RBMap<K, V> {
    self.modify(k, @None)
  }

  priv pure fn modify(k: K, new_value: @Option<V>) -> @RBMap<K, V> {
    match self {
      @Leaf => @Tree(Red, self, k, new_value, self),
      @Tree(color, left, key, original_value, right) => {
        if (k.lt(&key)) {
          self.balanceLeft(color, left.modify(k, new_value), key, original_value, right)
        } else if (k == key) {
          @Tree(color, left, k, new_value, right)
        } else {
          self.balanceRight(color, left, key, original_value, right.modify(k, new_value))
        }
      }
    }
  }

  priv pure fn balanceLeft(c: RBColor, l: @RBMap<K,V>, k: K, v: @Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black,@Tree(Red,@Tree(Red,a,xK,xV,b),yK,yV,c),zK,zV,d) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }

  priv pure fn balanceRight(c: RBColor, l: @RBMap<K,V>, k: K, v: @Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black, @Tree(Red, t1, k1, v1, t2), k0, v0, @Tree(Red, t3, k2, v2, t4)) =>
        @Tree(Red, @Tree(Black, t1, k1, v1, t2), k0, v0, @Tree(Black, t3, k2, v2, t4)),
      (c, l, k, v, @Tree(Red, t1, k1, v1, t2)) =>
        @Tree(c, @Tree(Red, l, k, v, t1), k1, v1, t2),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }

}

#[test]
fn test_rb_tree() {
  let v1 = RBMap("stevej", 150);
  let v2 = v1.put("thatstacy", 187);

  assert(v2.get("stevej") == @Some(150));
  assert(v2.get("thatstacy") == @Some(187));

  let v3 = v2.delete("stevej");
  assert(v3.get("stevej") == @None);
  assert(v3.get("thatstacy") == @Some(187));

  let v4 = v2.put("jeremy", 16);

  let v5 = v4.put("ev", 20);
  let v6 = v5.put("zhana", 51573);

  assert(v6.get("jeremy") == @Some(16));
  assert(v6.get("stevej") == @Some(150));
  assert(v6.get("thatstacy") == @Some(187));
  assert(v6.get("ev") == @Some(20));
  assert(v6.get("zhana") == @Some(51573));
}

#[test]
fn test_traverse() {
  let v1 = RBMap(1, 0);
  let v2 = v1.put(4, 0);
  let v3 = v2.put(3, 0);
  let v4 = v3.put(5, 0);
  let v5 = v4.put(2, 0);

  let n = @mut 1;

  fn t(n: @mut int, k: int, _v: Option<int>) {
    assert (*n == k); *n += 1;
  }

  v5.traverse(|x,y| t(n, *x, *y));
}
<commit_msg>remove traverse, implement BaseIter instead<commit_after>use core::cmp::{Eq, Ord};
use iter::BaseIter;

pub trait PersistentMap<K: Copy Eq Ord, V: Copy> {
  pure fn get(k: K) -> @Option<V>;
  pure fn put(k: K, v: V) -> self;
  pure fn delete(k: K) -> self;
}

enum RBColor {
  Red,
  Black
}

pub enum RBMap<K: Copy Eq Ord, V: Copy> {
  //   color    left         k  value       right
  Tree(RBColor, @RBMap<K,V>, K, @Option<V>, @RBMap<K,V>),
  Leaf
}

pure fn RBMap<K: Copy Eq Ord, V: Copy>(key: K, value: V) -> @RBMap<K, V> {
  @Tree(Red, @Leaf, key, @Some(value), @Leaf)
}

/**
 * A purely functional Left-Leaning Red-Black Tree.
 */
impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> : PersistentMap<K, V> {
  pure fn get(k: K) -> @Option<V> {
    match self {
      @Leaf => @None,
      @Tree(_, left, key, maybe_value, right) => {
        if (k.lt(&key)) {
          left.get(k)
        } else if (k.gt(&key)) {
          right.get(k)
        } else {
          maybe_value
        }
      }
    }
  }

  pure fn put(k: K, new_value: V) -> @RBMap<K, V> {
    self.modify(k, @Some(new_value))
  }

  pure fn delete(k: K) -> @RBMap<K, V> {
    self.modify(k, @None)
  }

  priv pure fn modify(k: K, new_value: @Option<V>) -> @RBMap<K, V> {
    match self {
      @Leaf => @Tree(Red, self, k, new_value, self),
      @Tree(color, left, key, original_value, right) => {
        if (k.lt(&key)) {
          self.balanceLeft(color, left.modify(k, new_value), key, original_value, right)
        } else if (k == key) {
          @Tree(color, left, k, new_value, right)
        } else {
          self.balanceRight(color, left, key, original_value, right.modify(k, new_value))
        }
      }
    }
  }

  priv pure fn balanceLeft(c: RBColor, l: @RBMap<K,V>, k: K, v: @Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black,@Tree(Red,@Tree(Red,a,xK,xV,b),yK,yV,c),zK,zV,d) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }

  priv pure fn balanceRight(c: RBColor, l: @RBMap<K,V>, k: K, v: @Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black, @Tree(Red, t1, k1, v1, t2), k0, v0, @Tree(Red, t3, k2, v2, t4)) =>
        @Tree(Red, @Tree(Black, t1, k1, v1, t2), k0, v0, @Tree(Black, t3, k2, v2, t4)),
      (c, l, k, v, @Tree(Red, t1, k1, v1, t2)) =>
        @Tree(c, @Tree(Red, l, k, v, t1), k1, v1, t2),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }
}

impl<K: Copy Eq Ord, V: Copy> RBMap<K, V>: iter::BaseIter<(&K, &V)> {
  pure fn size_hint() -> Option<uint> {
    None
  }

  pure fn each(f: fn(&(&K, &V)) -> bool) {
    match self {
      Leaf => (),
      Tree(_, left, key, maybe_value, right) => {
        left.each(f);
        match maybe_value {
          @Some(value) => f(&(&key, &value)),
          @None => false,
        };
        right.each(f);
      }
    }
  }
}

#[test]
fn test_rb_tree() {
  let v1 = RBMap("stevej", 150);
  let v2 = v1.put("thatstacy", 187);

  assert(v2.get("stevej") == @Some(150));
  assert(v2.get("thatstacy") == @Some(187));

  let v3 = v2.delete("stevej");
  assert(v3.get("stevej") == @None);
  assert(v3.get("thatstacy") == @Some(187));

  let v4 = v2.put("jeremy", 16);

  let v5 = v4.put("ev", 20);
  let v6 = v5.put("zhana", 51573);

  assert(v6.get("jeremy") == @Some(16));
  assert(v6.get("stevej") == @Some(150));
  assert(v6.get("thatstacy") == @Some(187));
  assert(v6.get("ev") == @Some(20));
  assert(v6.get("zhana") == @Some(51573));
}

#[test]
fn test_base_iter_each() {
  let v1 = RBMap(1, 0);
  let v2 = v1.put(4, 0);
  let v3 = v2.put(3, 0);
  let v4 = v3.put(5, 0);
  let v5 = v4.put(2, 0);

  let n = @mut 1;

  fn t(n: @mut int, kv: &(&int, &int)) -> bool{
    match kv {
      &(k, _) => {
        assert (*n == *k);
        *n += 1;
      }
    }
    false
  }

  v5.each(|z| t(n, z));
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    let teams = vec![String::from("Blue"), String::from("Yellow")];
    let initial_scores = vec![10, 50];

    let different_scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();

    // Hash map becomes the owner of values used during inserting

    let team_name = String::from("Blue");
    let score = different_scores.get(&team_name);

    for (key, value) in &different_scores {
        println!("{}: {}", key, value);
    }

    // Insert overwrites things by default

    scores.entry(String::from("Blue")).or_insert(100);
    scores.entry(String::from("Red")).or_insert(200);

    println!("{:?}", scores);

    let text = "hello wonderful world world";

    let mut map = HashMap::new();

    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0)
        *count += 1;
    }

    println!("{:?}", map);
}
<commit_msg>Add note about using different hashers<commit_after>use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    let teams = vec![String::from("Blue"), String::from("Yellow")];
    let initial_scores = vec![10, 50];

    let different_scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();

    // Hash map becomes the owner of values used during inserting

    let team_name = String::from("Blue");
    let score = different_scores.get(&team_name);

    for (key, value) in &different_scores {
        println!("{}: {}", key, value);
    }

    // Insert overwrites things by default

    scores.entry(String::from("Blue")).or_insert(100);
    scores.entry(String::from("Red")).or_insert(200);

    println!("{:?}", scores);

    let text = "hello wonderful world world";

    let mut map = HashMap::new();

    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0)
        *count += 1;
    }

    println!("{:?}", map);

    // It's possible to use different hasher than default one
}
<|endoftext|>


<commit_before>use std::env;
use std::collections::HashMap;
use std::path::PathBuf;
use std::fs;

use http::app::App;
use common::error::Error;

const DEFAULT_APP_HOME: &'static str = "~/.zas";

pub struct AppManager {
    next_port: u16,
    app_home: String,
    apps: HashMap<String, App>,
}

impl AppManager {
    pub fn new() -> AppManager {
        let app_home = env::var("ZAS_HOME").unwrap_or(DEFAULT_APP_HOME.to_string());

        AppManager {
            next_port: 12050,
            app_home: app_home,
            apps: HashMap::new(),
        }
    }

    fn start_app(&mut self, app_name: &str) {
        let next_port = self.next_port;
        let app = App::new(&app_name, next_port, &self.app_home);
        self.apps.insert(app_name.to_string(), app);
        self.next_port = next_port + 1;
    }

    pub fn ensure_app_running(&mut self, app_name: &str) -> Result<u16, Error> {
        if !self.apps.contains_key(app_name) {
            let mut path_buf = PathBuf::from(&self.app_home);
            path_buf.push(&app_name);

            if fs::metadata(path_buf.as_path()).is_err() {
                return Err(Error::AppNotConfigured);
            }

            self.start_app(app_name);
        }

        let app = self.apps.get(app_name).unwrap();

        Ok(app.port)
    }
}
<commit_msg>fix: Default app home<commit_after>use std::env;
use std::collections::HashMap;
use std::path::PathBuf;
use std::fs;

use http::app::App;
use common::error::Error;

pub struct AppManager {
    next_port: u16,
    app_home: String,
    apps: HashMap<String, App>,
}

impl AppManager {
    pub fn new() -> AppManager {
        let app_home = env::var("ZAS_HOME").unwrap_or(AppManager::default_app_home());

        AppManager {
            next_port: 12050,
            app_home: app_home,
            apps: HashMap::new(),
        }
    }

    fn default_app_home() -> String {
        env::home_dir().unwrap().to_str().unwrap().to_string()
    }

    fn start_app(&mut self, app_name: &str) {
        let next_port = self.next_port;
        let app = App::new(&app_name, next_port, &self.app_home);
        self.apps.insert(app_name.to_string(), app);
        self.next_port = next_port + 1;
    }

    pub fn ensure_app_running(&mut self, app_name: &str) -> Result<u16, Error> {
        if !self.apps.contains_key(app_name) {
            let mut path_buf = PathBuf::from(&self.app_home);
            path_buf.push(&app_name);

            if fs::metadata(path_buf.as_path()).is_err() {
                return Err(Error::AppNotConfigured);
            }

            self.start_app(app_name);
        }

        let app = self.apps.get(app_name).unwrap();

        Ok(app.port)
    }
}
<|endoftext|>


<commit_before>//! This module implements import-resolution/macro expansion algorithm.
//!
//! The result of this module is `CrateDefMap`: a data structure which contains:
//!
//!   * a tree of modules for the crate
//!   * for each module, a set of items visible in the module (directly declared
//!     or imported)
//!
//! Note that `CrateDefMap` contains fully macro expanded code.
//!
//! Computing `CrateDefMap` can be partitioned into several logically
//! independent "phases". The phases are mutually recursive though, there's no
//! strict ordering.
//!
//! ## Collecting RawItems
//!
//! This happens in the `raw` module, which parses a single source file into a
//! set of top-level items. Nested imports are desugared to flat imports in this
//! phase. Macro calls are represented as a triple of (Path, Option<Name>,
//! TokenTree).
//!
//! ## Collecting Modules
//!
//! This happens in the `collector` module. In this phase, we recursively walk
//! tree of modules, collect raw items from submodules, populate module scopes
//! with defined items (so, we assign item ids in this phase) and record the set
//! of unresolved imports and macros.
//!
//! While we walk tree of modules, we also record macro_rules definitions and
//! expand calls to macro_rules defined macros.
//!
//! ## Resolving Imports
//!
//! We maintain a list of currently unresolved imports. On every iteration, we
//! try to resolve some imports from this list. If the import is resolved, we
//! record it, by adding an item to current module scope and, if necessary, by
//! recursively populating glob imports.
//!
//! ## Resolving Macros
//!
//! macro_rules from the same crate use a global mutable namespace. We expand
//! them immediately, when we collect modules.
//!
//! Macros from other crates (including proc-macros) can be used with
//! `foo::bar!` syntax. We handle them similarly to imports. There's a list of
//! unexpanded macros. On every iteration, we try to resolve each macro call
//! path and, upon success, we run macro expansion and "collect module" phase on
//! the result

pub(crate) mod raw;
mod collector;
mod mod_resolution;
mod path_resolution;

#[cfg(test)]
mod tests;

use std::sync::Arc;

use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile};
use ra_arena::Arena;
use ra_db::{CrateId, Edition, FileId, FilePosition};
use ra_prof::profile;
use ra_syntax::{
    ast::{self, AstNode},
    SyntaxNode,
};
use rustc_hash::FxHashMap;

use crate::{
    db::DefDatabase,
    item_scope::{BuiltinShadowMode, ItemScope},
    nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
    path::ModPath,
    per_ns::PerNs,
    AstId, LocalModuleId, ModuleDefId, ModuleId,
};

/// Contains all top-level defs from a macro-expanded crate
#[derive(Debug, PartialEq, Eq)]
pub struct CrateDefMap {
    pub root: LocalModuleId,
    pub modules: Arena<LocalModuleId, ModuleData>,
    pub(crate) krate: CrateId,
    /// The prelude module for this crate. This either comes from an import
    /// marked with the `prelude_import` attribute, or (in the normal case) from
    /// a dependency (`std` or `core`).
    pub(crate) prelude: Option<ModuleId>,
    pub(crate) extern_prelude: FxHashMap<Name, ModuleDefId>,

    edition: Edition,
    diagnostics: Vec<DefDiagnostic>,
}

impl std::ops::Index<LocalModuleId> for CrateDefMap {
    type Output = ModuleData;
    fn index(&self, id: LocalModuleId) -> &ModuleData {
        &self.modules[id]
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum ModuleOrigin {
    CrateRoot {
        definition: FileId,
    },
    /// Note that non-inline modules, by definition, live inside non-macro file.
    File {
        declaration: AstId<ast::Module>,
        definition: FileId,
    },
    Inline {
        definition: AstId<ast::Module>,
    },
}

impl Default for ModuleOrigin {
    fn default() -> Self {
        ModuleOrigin::CrateRoot { definition: FileId(0) }
    }
}

impl ModuleOrigin {
    pub(crate) fn not_sure_file(file: Option<FileId>, declaration: AstId<ast::Module>) -> Self {
        match file {
            None => ModuleOrigin::Inline { definition: declaration },
            Some(definition) => ModuleOrigin::File { declaration, definition },
        }
    }

    fn declaration(&self) -> Option<AstId<ast::Module>> {
        match self {
            ModuleOrigin::File { declaration: module, .. }
            | ModuleOrigin::Inline { definition: module, .. } => Some(*module),
            ModuleOrigin::CrateRoot { .. } => None,
        }
    }

    pub fn file_id(&self) -> Option<FileId> {
        match self {
            ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
                Some(*definition)
            }
            _ => None,
        }
    }

    pub fn is_inline(&self) -> bool {
        match self {
            ModuleOrigin::Inline { .. } => true,
            ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false,
        }
    }

    /// Returns a node which defines this module.
    /// That is, a file or a `mod foo {}` with items.
    fn definition_source(&self, db: &impl DefDatabase) -> InFile<ModuleSource> {
        match self {
            ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
                let file_id = *definition;
                let sf = db.parse(file_id).tree();
                return InFile::new(file_id.into(), ModuleSource::SourceFile(sf));
            }
            ModuleOrigin::Inline { definition } => {
                InFile::new(definition.file_id, ModuleSource::Module(definition.to_node(db)))
            }
        }
    }
}

#[derive(Default, Debug, PartialEq, Eq)]
pub struct ModuleData {
    pub parent: Option<LocalModuleId>,
    pub children: FxHashMap<Name, LocalModuleId>,
    pub scope: ItemScope,

    /// Where does this module come from?
    pub origin: ModuleOrigin,
}

impl CrateDefMap {
    pub(crate) fn compute_crate_def_map_query(
        // Note that this doesn't have `+ AstDatabase`!
        // This gurantess that `CrateDefMap` is stable across reparses.
        db: &impl DefDatabase,
        krate: CrateId,
    ) -> Arc<CrateDefMap> {
        let _p = profile("compute_crate_def_map");
        let def_map = {
            let crate_graph = db.crate_graph();
            let edition = crate_graph.edition(krate);
            let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
            let root = modules.alloc(ModuleData::default());
            CrateDefMap {
                krate,
                edition,
                extern_prelude: FxHashMap::default(),
                prelude: None,
                root,
                modules,
                diagnostics: Vec::new(),
            }
        };
        let def_map = collector::collect_defs(db, def_map);
        Arc::new(def_map)
    }

    pub fn add_diagnostics(
        &self,
        db: &impl DefDatabase,
        module: LocalModuleId,
        sink: &mut DiagnosticSink,
    ) {
        self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
    }

    pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
        self.modules
            .iter()
            .filter(move |(_id, data)| data.origin.file_id() == Some(file_id))
            .map(|(id, _data)| id)
    }

    pub(crate) fn resolve_path(
        &self,
        db: &impl DefDatabase,
        original_module: LocalModuleId,
        path: &ModPath,
        shadow: BuiltinShadowMode,
    ) -> (PerNs, Option<usize>) {
        let res =
            self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow);
        (res.resolved_def, res.segment_index)
    }
}

impl ModuleData {
    /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
    pub fn definition_source(&self, db: &impl DefDatabase) -> InFile<ModuleSource> {
        self.origin.definition_source(db)
    }

    /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
    /// `None` for the crate root or block.
    pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<InFile<ast::Module>> {
        let decl = self.origin.declaration()?;
        let value = decl.to_node(db);
        Some(InFile { file_id: decl.file_id, value })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ModuleSource {
    SourceFile(ast::SourceFile),
    Module(ast::Module),
}

impl ModuleSource {
    // FIXME: this methods do not belong here
    pub fn from_position(db: &impl DefDatabase, position: FilePosition) -> ModuleSource {
        let parse = db.parse(position.file_id);
        match &ra_syntax::algo::find_node_at_offset::<ast::Module>(
            parse.tree().syntax(),
            position.offset,
        ) {
            Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()),
            _ => {
                let source_file = parse.tree();
                ModuleSource::SourceFile(source_file)
            }
        }
    }

    pub fn from_child_node(db: &impl DefDatabase, child: InFile<&SyntaxNode>) -> ModuleSource {
        if let Some(m) =
            child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi())
        {
            ModuleSource::Module(m)
        } else {
            let file_id = child.file_id.original_file(db);
            let source_file = db.parse(file_id).tree();
            ModuleSource::SourceFile(source_file)
        }
    }
}

mod diagnostics {
    use hir_expand::diagnostics::DiagnosticSink;
    use ra_db::RelativePathBuf;
    use ra_syntax::{ast, AstPtr};

    use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId};

    #[derive(Debug, PartialEq, Eq)]
    pub(super) enum DefDiagnostic {
        UnresolvedModule {
            module: LocalModuleId,
            declaration: AstId<ast::Module>,
            candidate: RelativePathBuf,
        },
    }

    impl DefDiagnostic {
        pub(super) fn add_to(
            &self,
            db: &impl DefDatabase,
            target_module: LocalModuleId,
            sink: &mut DiagnosticSink,
        ) {
            match self {
                DefDiagnostic::UnresolvedModule { module, declaration, candidate } => {
                    if *module != target_module {
                        return;
                    }
                    let decl = declaration.to_node(db);
                    sink.push(UnresolvedModule {
                        file: declaration.file_id,
                        decl: AstPtr::new(&decl),
                        candidate: candidate.clone(),
                    })
                }
            }
        }
    }
}
<commit_msg>Remove dead code<commit_after>//! This module implements import-resolution/macro expansion algorithm.
//!
//! The result of this module is `CrateDefMap`: a data structure which contains:
//!
//!   * a tree of modules for the crate
//!   * for each module, a set of items visible in the module (directly declared
//!     or imported)
//!
//! Note that `CrateDefMap` contains fully macro expanded code.
//!
//! Computing `CrateDefMap` can be partitioned into several logically
//! independent "phases". The phases are mutually recursive though, there's no
//! strict ordering.
//!
//! ## Collecting RawItems
//!
//! This happens in the `raw` module, which parses a single source file into a
//! set of top-level items. Nested imports are desugared to flat imports in this
//! phase. Macro calls are represented as a triple of (Path, Option<Name>,
//! TokenTree).
//!
//! ## Collecting Modules
//!
//! This happens in the `collector` module. In this phase, we recursively walk
//! tree of modules, collect raw items from submodules, populate module scopes
//! with defined items (so, we assign item ids in this phase) and record the set
//! of unresolved imports and macros.
//!
//! While we walk tree of modules, we also record macro_rules definitions and
//! expand calls to macro_rules defined macros.
//!
//! ## Resolving Imports
//!
//! We maintain a list of currently unresolved imports. On every iteration, we
//! try to resolve some imports from this list. If the import is resolved, we
//! record it, by adding an item to current module scope and, if necessary, by
//! recursively populating glob imports.
//!
//! ## Resolving Macros
//!
//! macro_rules from the same crate use a global mutable namespace. We expand
//! them immediately, when we collect modules.
//!
//! Macros from other crates (including proc-macros) can be used with
//! `foo::bar!` syntax. We handle them similarly to imports. There's a list of
//! unexpanded macros. On every iteration, we try to resolve each macro call
//! path and, upon success, we run macro expansion and "collect module" phase on
//! the result

pub(crate) mod raw;
mod collector;
mod mod_resolution;
mod path_resolution;

#[cfg(test)]
mod tests;

use std::sync::Arc;

use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile};
use ra_arena::Arena;
use ra_db::{CrateId, Edition, FileId};
use ra_prof::profile;
use ra_syntax::ast;
use rustc_hash::FxHashMap;

use crate::{
    db::DefDatabase,
    item_scope::{BuiltinShadowMode, ItemScope},
    nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
    path::ModPath,
    per_ns::PerNs,
    AstId, LocalModuleId, ModuleDefId, ModuleId,
};

/// Contains all top-level defs from a macro-expanded crate
#[derive(Debug, PartialEq, Eq)]
pub struct CrateDefMap {
    pub root: LocalModuleId,
    pub modules: Arena<LocalModuleId, ModuleData>,
    pub(crate) krate: CrateId,
    /// The prelude module for this crate. This either comes from an import
    /// marked with the `prelude_import` attribute, or (in the normal case) from
    /// a dependency (`std` or `core`).
    pub(crate) prelude: Option<ModuleId>,
    pub(crate) extern_prelude: FxHashMap<Name, ModuleDefId>,

    edition: Edition,
    diagnostics: Vec<DefDiagnostic>,
}

impl std::ops::Index<LocalModuleId> for CrateDefMap {
    type Output = ModuleData;
    fn index(&self, id: LocalModuleId) -> &ModuleData {
        &self.modules[id]
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum ModuleOrigin {
    CrateRoot {
        definition: FileId,
    },
    /// Note that non-inline modules, by definition, live inside non-macro file.
    File {
        declaration: AstId<ast::Module>,
        definition: FileId,
    },
    Inline {
        definition: AstId<ast::Module>,
    },
}

impl Default for ModuleOrigin {
    fn default() -> Self {
        ModuleOrigin::CrateRoot { definition: FileId(0) }
    }
}

impl ModuleOrigin {
    pub(crate) fn not_sure_file(file: Option<FileId>, declaration: AstId<ast::Module>) -> Self {
        match file {
            None => ModuleOrigin::Inline { definition: declaration },
            Some(definition) => ModuleOrigin::File { declaration, definition },
        }
    }

    fn declaration(&self) -> Option<AstId<ast::Module>> {
        match self {
            ModuleOrigin::File { declaration: module, .. }
            | ModuleOrigin::Inline { definition: module, .. } => Some(*module),
            ModuleOrigin::CrateRoot { .. } => None,
        }
    }

    pub fn file_id(&self) -> Option<FileId> {
        match self {
            ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
                Some(*definition)
            }
            _ => None,
        }
    }

    pub fn is_inline(&self) -> bool {
        match self {
            ModuleOrigin::Inline { .. } => true,
            ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false,
        }
    }

    /// Returns a node which defines this module.
    /// That is, a file or a `mod foo {}` with items.
    fn definition_source(&self, db: &impl DefDatabase) -> InFile<ModuleSource> {
        match self {
            ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
                let file_id = *definition;
                let sf = db.parse(file_id).tree();
                return InFile::new(file_id.into(), ModuleSource::SourceFile(sf));
            }
            ModuleOrigin::Inline { definition } => {
                InFile::new(definition.file_id, ModuleSource::Module(definition.to_node(db)))
            }
        }
    }
}

#[derive(Default, Debug, PartialEq, Eq)]
pub struct ModuleData {
    pub parent: Option<LocalModuleId>,
    pub children: FxHashMap<Name, LocalModuleId>,
    pub scope: ItemScope,

    /// Where does this module come from?
    pub origin: ModuleOrigin,
}

impl CrateDefMap {
    pub(crate) fn compute_crate_def_map_query(
        // Note that this doesn't have `+ AstDatabase`!
        // This gurantess that `CrateDefMap` is stable across reparses.
        db: &impl DefDatabase,
        krate: CrateId,
    ) -> Arc<CrateDefMap> {
        let _p = profile("compute_crate_def_map");
        let def_map = {
            let crate_graph = db.crate_graph();
            let edition = crate_graph.edition(krate);
            let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
            let root = modules.alloc(ModuleData::default());
            CrateDefMap {
                krate,
                edition,
                extern_prelude: FxHashMap::default(),
                prelude: None,
                root,
                modules,
                diagnostics: Vec::new(),
            }
        };
        let def_map = collector::collect_defs(db, def_map);
        Arc::new(def_map)
    }

    pub fn add_diagnostics(
        &self,
        db: &impl DefDatabase,
        module: LocalModuleId,
        sink: &mut DiagnosticSink,
    ) {
        self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
    }

    pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
        self.modules
            .iter()
            .filter(move |(_id, data)| data.origin.file_id() == Some(file_id))
            .map(|(id, _data)| id)
    }

    pub(crate) fn resolve_path(
        &self,
        db: &impl DefDatabase,
        original_module: LocalModuleId,
        path: &ModPath,
        shadow: BuiltinShadowMode,
    ) -> (PerNs, Option<usize>) {
        let res =
            self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow);
        (res.resolved_def, res.segment_index)
    }
}

impl ModuleData {
    /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
    pub fn definition_source(&self, db: &impl DefDatabase) -> InFile<ModuleSource> {
        self.origin.definition_source(db)
    }

    /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
    /// `None` for the crate root or block.
    pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<InFile<ast::Module>> {
        let decl = self.origin.declaration()?;
        let value = decl.to_node(db);
        Some(InFile { file_id: decl.file_id, value })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ModuleSource {
    SourceFile(ast::SourceFile),
    Module(ast::Module),
}

mod diagnostics {
    use hir_expand::diagnostics::DiagnosticSink;
    use ra_db::RelativePathBuf;
    use ra_syntax::{ast, AstPtr};

    use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId};

    #[derive(Debug, PartialEq, Eq)]
    pub(super) enum DefDiagnostic {
        UnresolvedModule {
            module: LocalModuleId,
            declaration: AstId<ast::Module>,
            candidate: RelativePathBuf,
        },
    }

    impl DefDiagnostic {
        pub(super) fn add_to(
            &self,
            db: &impl DefDatabase,
            target_module: LocalModuleId,
            sink: &mut DiagnosticSink,
        ) {
            match self {
                DefDiagnostic::UnresolvedModule { module, declaration, candidate } => {
                    if *module != target_module {
                        return;
                    }
                    let decl = declaration.to_node(db);
                    sink.push(UnresolvedModule {
                        file: declaration.file_id,
                        decl: AstPtr::new(&decl),
                        candidate: candidate.clone(),
                    })
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use std::fmt;

use ra_syntax::{ast, SmolStr};

/// `Name` is a wrapper around string, which is used in hir for both references
/// and declarations. In theory, names should also carry hygiene info, but we are
/// not there yet!
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Name(Repr);

#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
enum Repr {
    Text(SmolStr),
    TupleField(usize),
}

impl fmt::Display for Name {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self.0 {
            Repr::Text(text) => fmt::Display::fmt(&text, f),
            Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
        }
    }
}

impl Name {
    /// Note: this is private to make creating name from random string hard.
    /// Hopefully, this should allow us to integrate hygiene cleaner in the
    /// future, and to switch to interned representation of names.
    const fn new_text(text: SmolStr) -> Name {
        Name(Repr::Text(text))
    }

    pub fn new_tuple_field(idx: usize) -> Name {
        Name(Repr::TupleField(idx))
    }

    /// Shortcut to create inline plain text name
    const fn new_inline_ascii(len: usize, text: &[u8]) -> Name {
        Name::new_text(SmolStr::new_inline_from_ascii(len, text))
    }

    /// Resolve a name from the text of token.
    fn resolve(raw_text: &SmolStr) -> Name {
        let raw_start = "r#";
        if raw_text.as_str().starts_with(raw_start) {
            Name::new_text(SmolStr::new(&raw_text[raw_start.len()..]))
        } else {
            Name::new_text(raw_text.clone())
        }
    }

    pub fn missing() -> Name {
        Name::new_text("[missing name]".into())
    }

    pub fn as_tuple_index(&self) -> Option<usize> {
        match self.0 {
            Repr::TupleField(idx) => Some(idx),
            _ => None,
        }
    }
}

pub trait AsName {
    fn as_name(&self) -> Name;
}

impl AsName for ast::NameRef {
    fn as_name(&self) -> Name {
        match self.as_tuple_field() {
            Some(idx) => Name::new_tuple_field(idx),
            None => Name::resolve(self.text()),
        }
    }
}

impl AsName for ast::Name {
    fn as_name(&self) -> Name {
        Name::resolve(self.text())
    }
}

impl AsName for tt::Ident {
    fn as_name(&self) -> Name {
        Name::resolve(&self.text)
    }
}

impl AsName for ast::FieldKind {
    fn as_name(&self) -> Name {
        match self {
            ast::FieldKind::Name(nr) => nr.as_name(),
            ast::FieldKind::Index(idx) => Name::new_tuple_field(idx.text().parse().unwrap()),
        }
    }
}

impl AsName for ra_db::Dependency {
    fn as_name(&self) -> Name {
        Name::new_text(self.name.clone())
    }
}

// Primitives
pub const ISIZE: Name = Name::new_inline_ascii(5, b"isize");
pub const I8: Name = Name::new_inline_ascii(2, b"i8");
pub const I16: Name = Name::new_inline_ascii(3, b"i16");
pub const I32: Name = Name::new_inline_ascii(3, b"i32");
pub const I64: Name = Name::new_inline_ascii(3, b"i64");
pub const I128: Name = Name::new_inline_ascii(4, b"i128");
pub const USIZE: Name = Name::new_inline_ascii(5, b"usize");
pub const U8: Name = Name::new_inline_ascii(2, b"u8");
pub const U16: Name = Name::new_inline_ascii(3, b"u16");
pub const U32: Name = Name::new_inline_ascii(3, b"u32");
pub const U64: Name = Name::new_inline_ascii(3, b"u64");
pub const U128: Name = Name::new_inline_ascii(4, b"u128");
pub const F32: Name = Name::new_inline_ascii(3, b"f32");
pub const F64: Name = Name::new_inline_ascii(3, b"f64");
pub const BOOL: Name = Name::new_inline_ascii(4, b"bool");
pub const CHAR: Name = Name::new_inline_ascii(4, b"char");
pub const STR: Name = Name::new_inline_ascii(3, b"str");

// Special names
pub const SELF_PARAM: Name = Name::new_inline_ascii(4, b"self");
pub const SELF_TYPE: Name = Name::new_inline_ascii(4, b"Self");
pub const MACRO_RULES: Name = Name::new_inline_ascii(11, b"macro_rules");

// Components of known path (value or mod name)
pub const STD: Name = Name::new_inline_ascii(3, b"std");
pub const ITER: Name = Name::new_inline_ascii(4, b"iter");
pub const OPS: Name = Name::new_inline_ascii(3, b"ops");
pub const FUTURE: Name = Name::new_inline_ascii(6, b"future");
pub const RESULT: Name = Name::new_inline_ascii(6, b"result");
pub const BOXED: Name = Name::new_inline_ascii(5, b"boxed");

// Components of known path (type name)
pub const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(12, b"IntoIterator");
pub const ITEM_TYPE: Name = Name::new_inline_ascii(4, b"Item");
pub const TRY_TYPE: Name = Name::new_inline_ascii(3, b"Try");
pub const OK_TYPE: Name = Name::new_inline_ascii(2, b"Ok");
pub const FUTURE_TYPE: Name = Name::new_inline_ascii(6, b"Future");
pub const RESULT_TYPE: Name = Name::new_inline_ascii(6, b"Result");
pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(6, b"Output");
pub const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target");
pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box");
pub const RANGE_FROM_TYPE: Name = Name::new_inline_ascii(9, b"RangeFrom");
pub const RANGE_FULL_TYPE: Name = Name::new_inline_ascii(9, b"RangeFull");
pub const RANGE_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(14, b"RangeInclusive");
pub const RANGE_TO_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(16, b"RangeToInclusive");
pub const RANGE_TO_TYPE: Name = Name::new_inline_ascii(7, b"RangeTo");
pub const RANGE_TYPE: Name = Name::new_inline_ascii(5, b"Range");

// Builtin Macros
pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file");
pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column");
pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(13, b"compile_error");
pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line");
pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify");
pub const FORMAT_ARGS_MACRO: Name = Name::new_inline_ascii(11, b"format_args");
pub const FORMAT_ARGS_NL_MACRO: Name = Name::new_inline_ascii(14, b"format_args_nl");

// Builtin derives
pub const COPY_TRAIT: Name = Name::new_inline_ascii(4, b"Copy");
pub const CLONE_TRAIT: Name = Name::new_inline_ascii(5, b"Clone");
pub const DEFAULT_TRAIT: Name = Name::new_inline_ascii(7, b"Default");
pub const DEBUG_TRAIT: Name = Name::new_inline_ascii(5, b"Debug");
pub const HASH_TRAIT: Name = Name::new_inline_ascii(4, b"Hash");
pub const ORD_TRAIT: Name = Name::new_inline_ascii(3, b"Ord");
pub const PARTIAL_ORD_TRAIT: Name = Name::new_inline_ascii(10, b"PartialOrd");
pub const EQ_TRAIT: Name = Name::new_inline_ascii(2, b"Eq");
pub const PARTIAL_EQ_TRAIT: Name = Name::new_inline_ascii(9, b"PartialEq");
<commit_msg>Remove unnecessary len parameter for Name::new_inline_ascii<commit_after>//! FIXME: write short doc here

use std::fmt;

use ra_syntax::{ast, SmolStr};

/// `Name` is a wrapper around string, which is used in hir for both references
/// and declarations. In theory, names should also carry hygiene info, but we are
/// not there yet!
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Name(Repr);

#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
enum Repr {
    Text(SmolStr),
    TupleField(usize),
}

impl fmt::Display for Name {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self.0 {
            Repr::Text(text) => fmt::Display::fmt(&text, f),
            Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
        }
    }
}

impl Name {
    /// Note: this is private to make creating name from random string hard.
    /// Hopefully, this should allow us to integrate hygiene cleaner in the
    /// future, and to switch to interned representation of names.
    const fn new_text(text: SmolStr) -> Name {
        Name(Repr::Text(text))
    }

    pub fn new_tuple_field(idx: usize) -> Name {
        Name(Repr::TupleField(idx))
    }

    /// Shortcut to create inline plain text name
    const fn new_inline_ascii(text: &[u8]) -> Name {
        Name::new_text(SmolStr::new_inline_from_ascii(text.len(), text))
    }

    /// Resolve a name from the text of token.
    fn resolve(raw_text: &SmolStr) -> Name {
        let raw_start = "r#";
        if raw_text.as_str().starts_with(raw_start) {
            Name::new_text(SmolStr::new(&raw_text[raw_start.len()..]))
        } else {
            Name::new_text(raw_text.clone())
        }
    }

    pub fn missing() -> Name {
        Name::new_text("[missing name]".into())
    }

    pub fn as_tuple_index(&self) -> Option<usize> {
        match self.0 {
            Repr::TupleField(idx) => Some(idx),
            _ => None,
        }
    }
}

pub trait AsName {
    fn as_name(&self) -> Name;
}

impl AsName for ast::NameRef {
    fn as_name(&self) -> Name {
        match self.as_tuple_field() {
            Some(idx) => Name::new_tuple_field(idx),
            None => Name::resolve(self.text()),
        }
    }
}

impl AsName for ast::Name {
    fn as_name(&self) -> Name {
        Name::resolve(self.text())
    }
}

impl AsName for tt::Ident {
    fn as_name(&self) -> Name {
        Name::resolve(&self.text)
    }
}

impl AsName for ast::FieldKind {
    fn as_name(&self) -> Name {
        match self {
            ast::FieldKind::Name(nr) => nr.as_name(),
            ast::FieldKind::Index(idx) => Name::new_tuple_field(idx.text().parse().unwrap()),
        }
    }
}

impl AsName for ra_db::Dependency {
    fn as_name(&self) -> Name {
        Name::new_text(self.name.clone())
    }
}

// Primitives
pub const ISIZE: Name = Name::new_inline_ascii(b"isize");
pub const I8: Name = Name::new_inline_ascii(b"i8");
pub const I16: Name = Name::new_inline_ascii(b"i16");
pub const I32: Name = Name::new_inline_ascii(b"i32");
pub const I64: Name = Name::new_inline_ascii(b"i64");
pub const I128: Name = Name::new_inline_ascii(b"i128");
pub const USIZE: Name = Name::new_inline_ascii(b"usize");
pub const U8: Name = Name::new_inline_ascii(b"u8");
pub const U16: Name = Name::new_inline_ascii(b"u16");
pub const U32: Name = Name::new_inline_ascii(b"u32");
pub const U64: Name = Name::new_inline_ascii(b"u64");
pub const U128: Name = Name::new_inline_ascii(b"u128");
pub const F32: Name = Name::new_inline_ascii(b"f32");
pub const F64: Name = Name::new_inline_ascii(b"f64");
pub const BOOL: Name = Name::new_inline_ascii(b"bool");
pub const CHAR: Name = Name::new_inline_ascii(b"char");
pub const STR: Name = Name::new_inline_ascii(b"str");

// Special names
pub const SELF_PARAM: Name = Name::new_inline_ascii(b"self");
pub const SELF_TYPE: Name = Name::new_inline_ascii(b"Self");
pub const MACRO_RULES: Name = Name::new_inline_ascii(b"macro_rules");

// Components of known path (value or mod name)
pub const STD: Name = Name::new_inline_ascii(b"std");
pub const ITER: Name = Name::new_inline_ascii(b"iter");
pub const OPS: Name = Name::new_inline_ascii(b"ops");
pub const FUTURE: Name = Name::new_inline_ascii(b"future");
pub const RESULT: Name = Name::new_inline_ascii(b"result");
pub const BOXED: Name = Name::new_inline_ascii(b"boxed");

// Components of known path (type name)
pub const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(b"IntoIterator");
pub const ITEM_TYPE: Name = Name::new_inline_ascii(b"Item");
pub const TRY_TYPE: Name = Name::new_inline_ascii(b"Try");
pub const OK_TYPE: Name = Name::new_inline_ascii(b"Ok");
pub const FUTURE_TYPE: Name = Name::new_inline_ascii(b"Future");
pub const RESULT_TYPE: Name = Name::new_inline_ascii(b"Result");
pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(b"Output");
pub const TARGET_TYPE: Name = Name::new_inline_ascii(b"Target");
pub const BOX_TYPE: Name = Name::new_inline_ascii(b"Box");
pub const RANGE_FROM_TYPE: Name = Name::new_inline_ascii(b"RangeFrom");
pub const RANGE_FULL_TYPE: Name = Name::new_inline_ascii(b"RangeFull");
pub const RANGE_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeInclusive");
pub const RANGE_TO_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeToInclusive");
pub const RANGE_TO_TYPE: Name = Name::new_inline_ascii(b"RangeTo");
pub const RANGE_TYPE: Name = Name::new_inline_ascii(b"Range");

// Builtin Macros
pub const FILE_MACRO: Name = Name::new_inline_ascii(b"file");
pub const COLUMN_MACRO: Name = Name::new_inline_ascii(b"column");
pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(b"compile_error");
pub const LINE_MACRO: Name = Name::new_inline_ascii(b"line");
pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(b"stringify");
pub const FORMAT_ARGS_MACRO: Name = Name::new_inline_ascii(b"format_args");
pub const FORMAT_ARGS_NL_MACRO: Name = Name::new_inline_ascii(b"format_args_nl");

// Builtin derives
pub const COPY_TRAIT: Name = Name::new_inline_ascii(b"Copy");
pub const CLONE_TRAIT: Name = Name::new_inline_ascii(b"Clone");
pub const DEFAULT_TRAIT: Name = Name::new_inline_ascii(b"Default");
pub const DEBUG_TRAIT: Name = Name::new_inline_ascii(b"Debug");
pub const HASH_TRAIT: Name = Name::new_inline_ascii(b"Hash");
pub const ORD_TRAIT: Name = Name::new_inline_ascii(b"Ord");
pub const PARTIAL_ORD_TRAIT: Name = Name::new_inline_ascii(b"PartialOrd");
pub const EQ_TRAIT: Name = Name::new_inline_ascii(b"Eq");
pub const PARTIAL_EQ_TRAIT: Name = Name::new_inline_ascii(b"PartialEq");
<|endoftext|>


<commit_before>
use std::ops::Range;

use assembler::u12;
use assembler::u12::*;

#[derive(PartialEq, Eq, Debug)]
pub struct DataRange {
  /// The first address populated by the bytes in the range.
  start_address: U12,
  /// The bytes occupying the range.
  data: Vec<u8>
}

impl DataRange {

  /**
   @param start_address The address of the first element in the data range in the result.
   @return A new data range from the start address with zero elements.
   */
  pub fn new(start_address: U12) -> Self {
    DataRange {
      start_address: start_address,
      data: Vec::new()
    }
  }

  /**
   @return The number of bytes in the data range.
   */
  pub fn len(&self) -> usize {
    self.data.len()
  }

  /**
   @return An immutable reference to the data underlying the range.
   */
  pub fn data(&self) -> &Vec<u8> {
    &self.data
  }

  /**
   @return A half-open range { address | start <= address < end } representing addresses in the range.
   */
  pub fn address_range(&self) -> Range<U12> {
    Range {
      start: self.start_address,
        end: self.start_address.wrapping_add(self.len().as_u12().unwrap())
    }
  }

  /**
   @return The number of bytes remaining to store data in the range.
   */
  pub fn bytes_remaining(&self) -> usize {
    let total_space_in_range = (u12::MAX - self.start_address).as_usize() + 1;
    total_space_in_range - self.len()
  }

  /**
   Appends the slice to the end of the data range. Checks for capacity in advance.
   @param data The bytes to append to the data range.
   */
  pub fn append(&mut self, data: &[u8]) -> bool {
    if self.bytes_remaining() >= data.len() {
      self.data.extend_from_slice(data);
      true
    } else {
      false
    }
  }

}

#[cfg(test)]
mod tests {

  use super::*;

  use assembler::u12;
  use assembler::u12::*;

  #[test]
  fn test_empty_ranges() {
    let zero_range = DataRange::new(U12::zero());
    assert_eq!(zero_range.len(), 0);
    assert_eq!(zero_range.bytes_remaining(), 4096);
    assert_eq!(zero_range.address_range(), U12::zero() .. U12::zero());

    let half_address = 0x800.as_u12().unwrap();
    let half_range = DataRange::new(half_address);
    assert_eq!(half_range.len(), 0);
    assert_eq!(half_range.bytes_remaining(), 2048);
    assert_eq!(half_range.address_range(), half_address .. half_address);

    let max_range = DataRange::new(u12::MAX);
    assert_eq!(max_range.len(), 0);
    assert_eq!(max_range.bytes_remaining(), 1);
    assert_eq!(max_range.address_range(), u12::MAX .. u12::MAX);
  }

  #[test]
  fn test_append_within_range() {
    let program_space_start = 0x200.as_u12().unwrap();
    let mut program_space = DataRange::new(program_space_start);
    assert_eq!(program_space.len(), 0);
    assert_eq!(program_space.bytes_remaining(), 3584);
    assert_eq!(program_space.address_range(), program_space_start .. program_space_start);

    // Append a single byte to the data range.
    let one_byte_slice: &[u8] = &[1];
    assert_eq!(program_space.append(one_byte_slice), true);
    assert_eq!(program_space.len(), 1);
    assert_eq!(program_space.bytes_remaining(), 3583);
    assert_eq!(program_space.address_range(), program_space_start .. program_space_start.wrapping_add(U12::from(1)));

    // Append a single byte to the data range.
    let two_byte_slice: &[u8] = &[2, 3];
    assert_eq!(program_space.append(two_byte_slice), true);
    assert_eq!(program_space.len(), 3);
    assert_eq!(program_space.bytes_remaining(), 3581);
    assert_eq!(program_space.address_range(), program_space_start .. program_space_start.wrapping_add(U12::from(3)));

    // Validate the data was appended.
    assert_eq!(program_space.data(), &vec![1,2,3]);
  }

  #[test]
  fn test_append_out_of_range() {
    let mut max_range = DataRange::new(u12::MAX);
    let one_byte_slice: &[u8] = &[1];

    // Append data into the only slot in the data range.
    assert_eq!(max_range.append(one_byte_slice), true);
    assert_eq!(max_range.len(), 1);
    assert_eq!(max_range.bytes_remaining(), 0);
    assert_eq!(max_range.address_range(), u12::MAX .. u12::MIN);

    // Validate the data was appended.
    assert_eq!(max_range.data(), &vec![1]);

    // Attempt to apppend past the end of the data range.
    assert_eq!(max_range.append(one_byte_slice), false);
    assert_eq!(max_range.len(), 1);
    assert_eq!(max_range.bytes_remaining(), 0);
    assert_eq!(max_range.address_range(), u12::MAX .. u12::MIN);

    // Validate the data was not appended.
    assert_eq!(max_range.data(), &vec![1]);
  }

}
<commit_msg>Add support for data range intersection checks.<commit_after>
use std::cmp;
use std::ops::Range;

use assembler::u12;
use assembler::u12::*;

#[derive(PartialEq, Eq, Debug)]
pub struct DataRange {
  /// The first address populated by the bytes in the range.
  start_address: U12,
  /// The bytes occupying the range.
  data: Vec<u8>
}

impl DataRange {

  /**
   @param start_address The address of the first element in the data range in the result.
   @return A new data range from the start address with zero elements.
   */
  pub fn new(start_address: U12) -> Self {
    DataRange {
      start_address: start_address,
      data: Vec::new()
    }
  }

  /**
   @return The number of bytes in the data range.
   */
  pub fn len(&self) -> usize {
    self.data.len()
  }

  /**
   @return An immutable reference to the data underlying the range.
   */
  pub fn data(&self) -> &Vec<u8> {
    &self.data
  }

  /**
   @return A half-open range { address | start <= address < end } representing addresses in the range.
   */
  pub fn address_range(&self) -> Range<U12> {
    Range {
      start: self.start_address,
        end: self.start_address.wrapping_add(self.len().as_u12().unwrap())
    }
  }

  /**
   @return The number of bytes remaining to store data in the range.
   */
  pub fn bytes_remaining(&self) -> usize {
    let total_space_in_range = (u12::MAX - self.start_address).as_usize() + 1;
    total_space_in_range - self.len()
  }

  /**
   Appends the slice to the end of the data range. Checks for capacity in advance.
   @param data The bytes to append to the data range.
   */
  pub fn append(&mut self, data: &[u8]) -> bool {
    if self.bytes_remaining() >= data.len() {
      self.data.extend_from_slice(data);
      true
    } else {
      false
    }
  }

  /**
   @return YES if the supplied range intersects the receiver.
   */
  pub fn intersects(&self, range: &DataRange) -> bool {
    let lhs_range =  self.address_range();
    let rhs_range = range.address_range();

    // Ranges intersect if the greater of the two starts is less than the smaller of the two ends (half-open).
    cmp::max(lhs_range.start, rhs_range.start) < cmp::min(lhs_range.end, rhs_range.end)
  }

}

// MARK: - Public Functions

/**
 @param ranges A list of data ranges.
 @return A list of pairs of overlapping data ranges.
 */
pub fn find_overlapping_data_ranges<'a>(ranges: &'a [DataRange]) -> Vec<(&'a DataRange, &'a DataRange)> {
  let mut overlapping_ranges = Vec::new();

  /*
   Compare each data range to each other data range. This is done by evaluating the mathematical
   combination pairs of the data range (order does not matter, pairs must be unique). This has
   complexity O(ranges.len() nCr 2).
   */
  for i in 0..ranges.len() {
    for j in i+1..ranges.len() {
      let lhs = &ranges[i];
      let rhs = &ranges[j];

      if lhs.intersects(rhs) {
        overlapping_ranges.push((lhs, rhs));
      }
    }
  }

  overlapping_ranges
}

// MARK: - Tests

#[cfg(test)]
mod tests {

  use std::iter::repeat;

  use super::*;

  use assembler::u12;
  use assembler::u12::*;

  #[test]
  fn test_empty_ranges() {
    let zero_range = DataRange::new(U12::zero());
    assert_eq!(zero_range.len(), 0);
    assert_eq!(zero_range.bytes_remaining(), 4096);
    assert_eq!(zero_range.address_range(), U12::zero() .. U12::zero());

    let half_address = 0x800.as_u12().unwrap();
    let half_range = DataRange::new(half_address);
    assert_eq!(half_range.len(), 0);
    assert_eq!(half_range.bytes_remaining(), 2048);
    assert_eq!(half_range.address_range(), half_address .. half_address);

    let max_range = DataRange::new(u12::MAX);
    assert_eq!(max_range.len(), 0);
    assert_eq!(max_range.bytes_remaining(), 1);
    assert_eq!(max_range.address_range(), u12::MAX .. u12::MAX);
  }

  #[test]
  fn test_append_within_range() {
    let program_space_start = 0x200.as_u12().unwrap();
    let mut program_space = DataRange::new(program_space_start);
    assert_eq!(program_space.len(), 0);
    assert_eq!(program_space.bytes_remaining(), 3584);
    assert_eq!(program_space.address_range(), program_space_start .. program_space_start);

    // Append a single byte to the data range.
    let one_byte_slice: &[u8] = &[1];
    assert_eq!(program_space.append(one_byte_slice), true);
    assert_eq!(program_space.len(), 1);
    assert_eq!(program_space.bytes_remaining(), 3583);
    assert_eq!(program_space.address_range(), program_space_start .. program_space_start.wrapping_add(U12::from(1)));

    // Append a single byte to the data range.
    let two_byte_slice: &[u8] = &[2, 3];
    assert_eq!(program_space.append(two_byte_slice), true);
    assert_eq!(program_space.len(), 3);
    assert_eq!(program_space.bytes_remaining(), 3581);
    assert_eq!(program_space.address_range(), program_space_start .. program_space_start.wrapping_add(U12::from(3)));

    // Validate the data was appended.
    assert_eq!(program_space.data(), &vec![1,2,3]);
  }

  #[test]
  fn test_append_out_of_range() {
    let mut max_range = DataRange::new(u12::MAX);
    let one_byte_slice: &[u8] = &[1];

    // Append data into the only slot in the data range.
    assert_eq!(max_range.append(one_byte_slice), true);
    assert_eq!(max_range.len(), 1);
    assert_eq!(max_range.bytes_remaining(), 0);
    assert_eq!(max_range.address_range(), u12::MAX .. u12::MIN);

    // Validate the data was appended.
    assert_eq!(max_range.data(), &vec![1]);

    // Attempt to apppend past the end of the data range.
    assert_eq!(max_range.append(one_byte_slice), false);
    assert_eq!(max_range.len(), 1);
    assert_eq!(max_range.bytes_remaining(), 0);
    assert_eq!(max_range.address_range(), u12::MAX .. u12::MIN);

    // Validate the data was not appended.
    assert_eq!(max_range.data(), &vec![1]);
  }

  #[test]
  fn test_intersects() {
    // Case 1: Obviously disjoint (+++++===++), distance: 3.
    let disjoint_1a = range_with_start_and_length(0, 5);
    let disjoint_1b = range_with_start_and_length(8, 2);
    assert_eq!(disjoint_1a.intersects(&disjoint_1b), false);
    assert_eq!(disjoint_1b.intersects(&disjoint_1a), false);

    // Case 2: Tightly disjoint (+++++===++), distance: 1.
    let disjoint_2a = range_with_start_and_length(0, 5);
    let disjoint_2b = range_with_start_and_length(6, 4);
    assert_eq!(disjoint_2a.intersects(&disjoint_2b), false);
    assert_eq!(disjoint_2b.intersects(&disjoint_2a), false);

    // Case 3: Adjacent (++++++++++), distance: 0.
    let adjacent_a = range_with_start_and_length(0, 5);
    let adjacent_b = range_with_start_and_length(5, 5);
    assert_eq!(adjacent_a.intersects(&adjacent_b), false);
    assert_eq!(adjacent_b.intersects(&adjacent_a), false);

    // Case 4: Tail Overlap (++++++v+++) distance: -1.
    let tail_overlap_a = range_with_start_and_length(0, 7);
    let tail_overlap_b = range_with_start_and_length(6, 4);
    assert_eq!(tail_overlap_a.intersects(&tail_overlap_b), true);
    assert_eq!(tail_overlap_b.intersects(&tail_overlap_a), true);

    // Case 5: Wholly Contained Head (v+++++++++) distance: -1.
    let wholly_contained_head_a = range_with_start_and_length(0, 10);
    let wholly_contained_head_b = range_with_start_and_length(0, 1);
    assert_eq!(wholly_contained_head_a.intersects(&wholly_contained_head_b), true);
    assert_eq!(wholly_contained_head_b.intersects(&wholly_contained_head_a), true);

    // Case 6: Wholly Contained Tail (+++++++++v) distance: -1.
    let wholly_contained_tail_a = range_with_start_and_length(0, 10);
    let wholly_contained_tail_b = range_with_start_and_length(9, 1);
    assert_eq!(wholly_contained_tail_a.intersects(&wholly_contained_tail_b), true);
    assert_eq!(wholly_contained_tail_b.intersects(&wholly_contained_tail_a), true);

    // Case 7: Middle of Range (++++vv++++) distance: -2.
    let middle_a = range_with_start_and_length(0, 10);
    let middle_b = range_with_start_and_length(4, 2);
    assert_eq!(middle_a.intersects(&middle_b), true);
    assert_eq!(middle_b.intersects(&middle_a), true);

    // Case 7: Zero Length Range (++++++++++) distance: 0.
    let zero_a = range_with_start_and_length(0, 10);
    let zero_b = range_with_start_and_length(4, 0);
    assert_eq!(zero_a.intersects(&zero_b), false);
    assert_eq!(zero_b.intersects(&zero_a), false);
  }

  // MARK: - Helper Methods

  /// Construct a new zero-filled range at the start address provided with the length provided.
  fn range_with_start_and_length(start: usize, length: usize) -> DataRange {
    let mut range = DataRange::new(start.as_u12().unwrap());
    let data: Vec<u8> = repeat(0u8).take(length).collect();
    range.append(data.as_slice());
    range
  }

}
<|endoftext|>


<commit_before>#[cfg(test)]
mod tests;

use std::collections::BTreeMap;
use rustc_serialize::json::{ToJson, Json};

/// This struct represents a FCM notification. Use the
/// corresponding `NotificationBuilder` to get an instance. You can then use
/// this notification instance when sending a FCM message.
#[derive(Debug, PartialEq, Clone)]
pub struct Notification<'a> {
    title: &'a str,
    body: Option<&'a str>,
    icon: &'a str,
    sound: Option<&'a str>,
    badge: Option<&'a str>,
    tag: Option<&'a str>,
    color: Option<&'a str>,
    click_action: Option<&'a str>,
    body_loc_key: Option<&'a str>,
    body_loc_args: Option<Vec<String>>,
    title_loc_key: Option<&'a str>,
    title_loc_args: Option<Vec<String>>,
}

impl <'a>ToJson for Notification<'a> {
    fn to_json(&self) -> Json {
        let mut root = BTreeMap::new();

        root.insert("title".to_string(), self.title.to_json());
        root.insert("icon".to_string(), self.icon.to_json());

        if self.body.is_some() {
            root.insert("body".to_string(), self.body.clone().unwrap().to_json());
        }

        if self.sound.is_some() {
            root.insert("sound".to_string(), self.sound.clone().unwrap().to_json());
        }

        if self.badge.is_some() {
            root.insert("badge".to_string(), self.badge.clone().unwrap().to_json());
        }

        if self.tag.is_some() {
            root.insert("tag".to_string(), self.tag.clone().unwrap().to_json());
        }

        if self.color.is_some() {
            root.insert("color".to_string(), self.color.clone().unwrap().to_json());
        }

        if self.click_action.is_some() {
            root.insert("click_action".to_string(), self.click_action.clone().unwrap().to_json());
        }

        if self.body_loc_key.is_some() {
            root.insert("body_loc_key".to_string(), self.body_loc_key.clone().unwrap().to_json());
        }

        if self.body_loc_args.is_some() {
            let body_loc_args_str = self.body_loc_args.clone().unwrap().to_json().to_string();
            root.insert("body_loc_args".to_string(), Json::String(body_loc_args_str));
        }

        if self.title_loc_key.is_some() {
            root.insert("title_loc_key".to_string(), self.title_loc_key.clone().unwrap().to_json());
        }

        if self.title_loc_args.is_some() {
            let title_loc_args_str = self.title_loc_args.clone().unwrap().to_json().to_string();
            root.insert("title_loc_args".to_string(), Json::String(title_loc_args_str));
        }

        Json::Object(root)
    }
}

/// A builder to get a `Notification` instance.
///
/// # Examples
///
/// ```rust
/// use fcm::NotificationBuilder;
///
/// let notification = NotificationBuilder::new("India vs. Australia")
///     .body("3 runs to win in 1 ball")
///     .finalize();
/// ```
pub struct NotificationBuilder<'a> {
    title: &'a str,
    body: Option<&'a str>,
    icon: &'a str,
    sound: Option<&'a str>,
    badge: Option<&'a str>,
    tag: Option<&'a str>,
    color: Option<&'a str>,
    click_action: Option<&'a str>,
    body_loc_key: Option<&'a str>,
    body_loc_args: Option<Vec<String>>,
    title_loc_key: Option<&'a str>,
    title_loc_args: Option<Vec<String>>,
}

impl <'a> NotificationBuilder<'a> {
    /// Get a new `NotificationBuilder` instance, with a title.
    pub fn new(title: &'a str) -> NotificationBuilder<'a> {
        NotificationBuilder {
            title: title,
            body: None,
            icon: "myicon",
            sound: None,
            badge: None,
            tag: None,
            color: None,
            click_action: None,
            body_loc_key: None,
            body_loc_args: None,
            title_loc_key: None,
            title_loc_args: None,
        }
    }

    /// Set the body of the notification
    pub fn body(&mut self, body: &'a str) -> &mut NotificationBuilder<'a> {
        self.body = Some(body);
        self
    }

    /// Set the notification icon. Defaults to `myicon`
    pub fn icon(&mut self, icon: &'a str) -> &mut NotificationBuilder<'a> {
        self.icon = icon;
        self
    }

    /// Set the sound to be played
    pub fn sound(&mut self, sound: &'a str) -> &mut NotificationBuilder<'a> {
        self.sound = Some(sound);
        self
    }

    /// Set the badge for iOS notifications
    pub fn badge(&mut self, badge: &'a str) -> &mut NotificationBuilder<'a> {
        self.badge = Some(badge);
        self
    }

    /// Tagging a notification allows you to replace existing notifications
    /// with the same tag with this new notification
    pub fn tag(&mut self, tag: &'a str) -> &mut NotificationBuilder<'a> {
        self.tag = Some(tag);
        self
    }

    /// The color of the icon, in #rrggbb format
    pub fn color(&mut self, color: &'a str) -> &mut NotificationBuilder<'a> {
        self.color = Some(color);
        self
    }

    /// What happens when the user clicks on the notification. Refer to
    /// https://developers.google.com/cloud-messaging/http-server-ref#table2 for
    /// details.
    pub fn click_action(&mut self, click_action: &'a str) -> &mut NotificationBuilder<'a> {
        self.click_action = Some(click_action);
        self
    }

    /// Set the body key string for localization
    pub fn body_loc_key(&mut self, body_loc_key: &'a str) -> &mut NotificationBuilder<'a> {
        self.body_loc_key = Some(body_loc_key);
        self
    }

    /// String value to replace format specifiers in the body string.
    pub fn body_loc_args(&mut self, body_loc_args: Vec<&'a str>) -> &mut NotificationBuilder<'a> {
        self.body_loc_args = Some(body_loc_args.iter().map(|s| s.to_string()).collect());
        self
    }

    /// Set the title key string for localization
    pub fn title_loc_key(&mut self, title_loc_key: &'a str) -> &mut NotificationBuilder<'a> {
        self.title_loc_key = Some(title_loc_key);
        self
    }

    /// String value to replace format specifiers in the title string.
    pub fn title_loc_args(&mut self, title_loc_args: Vec<&'a str>) -> &mut NotificationBuilder<'a> {
        self.title_loc_args = Some(title_loc_args.iter().map(|s| s.to_string()).collect());
        self
    }

    /// Complete the build and get a `Notification` instance
    pub fn finalize(&mut self) -> Notification<'a> {
        Notification {
            title: self.title,
            body: self.body,
            icon: self.icon,
            sound: self.sound,
            badge: self.badge,
            tag: self.tag,
            color: self.color,
            click_action: self.click_action,
            body_loc_key: self.body_loc_key,
            body_loc_args: self.body_loc_args.clone(),
            title_loc_key: self.title_loc_key,
            title_loc_args: self.title_loc_args.clone(),
        }
    }
}<commit_msg>Change notification vec args<commit_after>#[cfg(test)]
mod tests;

use std::collections::BTreeMap;
use rustc_serialize::json::{ToJson, Json};

/// This struct represents a FCM notification. Use the
/// corresponding `NotificationBuilder` to get an instance. You can then use
/// this notification instance when sending a FCM message.
#[derive(Debug, PartialEq, Clone)]
pub struct Notification<'a> {
    title: &'a str,
    body: Option<&'a str>,
    icon: &'a str,
    sound: Option<&'a str>,
    badge: Option<&'a str>,
    tag: Option<&'a str>,
    color: Option<&'a str>,
    click_action: Option<&'a str>,
    body_loc_key: Option<&'a str>,
    body_loc_args: Option<Vec<String>>,
    title_loc_key: Option<&'a str>,
    title_loc_args: Option<Vec<String>>,
}

impl <'a>ToJson for Notification<'a> {
    fn to_json(&self) -> Json {
        let mut root = BTreeMap::new();

        root.insert("title".to_string(), self.title.to_json());
        root.insert("icon".to_string(), self.icon.to_json());

        if self.body.is_some() {
            root.insert("body".to_string(), self.body.clone().unwrap().to_json());
        }

        if self.sound.is_some() {
            root.insert("sound".to_string(), self.sound.clone().unwrap().to_json());
        }

        if self.badge.is_some() {
            root.insert("badge".to_string(), self.badge.clone().unwrap().to_json());
        }

        if self.tag.is_some() {
            root.insert("tag".to_string(), self.tag.clone().unwrap().to_json());
        }

        if self.color.is_some() {
            root.insert("color".to_string(), self.color.clone().unwrap().to_json());
        }

        if self.click_action.is_some() {
            root.insert("click_action".to_string(), self.click_action.clone().unwrap().to_json());
        }

        if self.body_loc_key.is_some() {
            root.insert("body_loc_key".to_string(), self.body_loc_key.clone().unwrap().to_json());
        }

        if self.body_loc_args.is_some() {
            let body_loc_args_str = self.body_loc_args.clone().unwrap().to_json().to_string();
            root.insert("body_loc_args".to_string(), Json::String(body_loc_args_str));
        }

        if self.title_loc_key.is_some() {
            root.insert("title_loc_key".to_string(), self.title_loc_key.clone().unwrap().to_json());
        }

        if self.title_loc_args.is_some() {
            let title_loc_args_str = self.title_loc_args.clone().unwrap().to_json().to_string();
            root.insert("title_loc_args".to_string(), Json::String(title_loc_args_str));
        }

        Json::Object(root)
    }
}

/// A builder to get a `Notification` instance.
///
/// # Examples
///
/// ```rust
/// use fcm::NotificationBuilder;
///
/// let notification = NotificationBuilder::new("India vs. Australia")
///     .body("3 runs to win in 1 ball")
///     .finalize();
/// ```
pub struct NotificationBuilder<'a> {
    title: &'a str,
    body: Option<&'a str>,
    icon: &'a str,
    sound: Option<&'a str>,
    badge: Option<&'a str>,
    tag: Option<&'a str>,
    color: Option<&'a str>,
    click_action: Option<&'a str>,
    body_loc_key: Option<&'a str>,
    body_loc_args: Option<Vec<String>>,
    title_loc_key: Option<&'a str>,
    title_loc_args: Option<Vec<String>>,
}

impl<'a> NotificationBuilder<'a> {
    /// Get a new `NotificationBuilder` instance, with a title.
    pub fn new(title: &'a str) -> NotificationBuilder<'a> {
        NotificationBuilder {
            title: title,
            body: None,
            icon: "myicon",
            sound: None,
            badge: None,
            tag: None,
            color: None,
            click_action: None,
            body_loc_key: None,
            body_loc_args: None,
            title_loc_key: None,
            title_loc_args: None,
        }
    }

    /// Set the body of the notification
    pub fn body(&mut self, body: &'a str) -> &mut NotificationBuilder<'a> {
        self.body = Some(body);
        self
    }

    /// Set the notification icon. Defaults to `myicon`
    pub fn icon(&mut self, icon: &'a str) -> &mut NotificationBuilder<'a> {
        self.icon = icon;
        self
    }

    /// Set the sound to be played
    pub fn sound(&mut self, sound: &'a str) -> &mut NotificationBuilder<'a> {
        self.sound = Some(sound);
        self
    }

    /// Set the badge for iOS notifications
    pub fn badge(&mut self, badge: &'a str) -> &mut NotificationBuilder<'a> {
        self.badge = Some(badge);
        self
    }

    /// Tagging a notification allows you to replace existing notifications
    /// with the same tag with this new notification
    pub fn tag(&mut self, tag: &'a str) -> &mut NotificationBuilder<'a> {
        self.tag = Some(tag);
        self
    }

    /// The color of the icon, in #rrggbb format
    pub fn color(&mut self, color: &'a str) -> &mut NotificationBuilder<'a> {
        self.color = Some(color);
        self
    }

    /// What happens when the user clicks on the notification. Refer to
    /// https://developers.google.com/cloud-messaging/http-server-ref#table2 for
    /// details.
    pub fn click_action(&mut self, click_action: &'a str) -> &mut NotificationBuilder<'a> {
        self.click_action = Some(click_action);
        self
    }

    /// Set the body key string for localization
    pub fn body_loc_key(&mut self, body_loc_key: &'a str) -> &mut NotificationBuilder<'a> {
        self.body_loc_key = Some(body_loc_key);
        self
    }

    /// String value to replace format specifiers in the body string.
    pub fn body_loc_args<S: Into<String>>(&mut self, body_loc_args: Vec<S>) -> &mut NotificationBuilder<'a> {
        self.body_loc_args = Some(body_loc_args.into_iter().map(|s| s.into()).collect());
        self
    }

    /// Set the title key string for localization
    pub fn title_loc_key(&mut self, title_loc_key: &'a str) -> &mut NotificationBuilder<'a> {
        self.title_loc_key = Some(title_loc_key);
        self
    }

    /// String value to replace format specifiers in the title string.
    pub fn title_loc_args<S: Into<String>>(&mut self, title_loc_args: Vec<S>) -> &mut NotificationBuilder<'a> {
        self.title_loc_args = Some(title_loc_args.into_iter().map(|s| s.into()).collect());
        self
    }

    /// Complete the build and get a `Notification` instance
    pub fn finalize(&mut self) -> Notification<'a> {
        Notification {
            title: self.title,
            body: self.body,
            icon: self.icon,
            sound: self.sound,
            badge: self.badge,
            tag: self.tag,
            color: self.color,
            click_action: self.click_action,
            body_loc_key: self.body_loc_key,
            body_loc_args: self.body_loc_args.clone(),
            title_loc_key: self.title_loc_key,
            title_loc_args: self.title_loc_args.clone(),
        }
    }
}
<|endoftext|>


<commit_before>use support::{database, project};

#[test]
fn run_infer_schema() {
    let p = project("print_schema").build();
    let db = database(&p.database_url());

    // Make sure the project is setup
    p.command("setup").run();

    db.execute("CREATE TABLE users1 (id INTEGER PRIMARY KEY);");
    db.execute("CREATE TABLE users2 (id INTEGER PRIMARY KEY);");

    assert!(db.table_exists("users1"));
    assert!(db.table_exists("users2"));

    let result = p.command("print-schema").run();

    assert!(result.is_success(), "Result was unsuccessful {:?}", result);
    assert_eq!(result.stdout(),
r"mod infer_users1 {
    table! {
        users1(id) {
            id -> Nullable<Integer>,
        }
    }
}
pub use self::infer_users1::*;
mod infer_users2 {
    table! {
        users2(id) {
            id -> Nullable<Integer>,
        }
    }
}
pub use self::infer_users2::*;

");
}

#[test]
fn run_infer_schema_whitelist() {
    let p = project("print_schema").build();
    let db = database(&p.database_url());

    // Make sure the project is setup
    p.command("setup").run();

    db.execute("CREATE TABLE users1 (id INTEGER PRIMARY KEY);");
    db.execute("CREATE TABLE users2 (id INTEGER PRIMARY KEY);");

    assert!(db.table_exists("users1"));
    assert!(db.table_exists("users2"));

    let result = p.command("print-schema").arg("users1").arg("-w").run();

    assert!(result.is_success(), "Result was unsuccessful {:?}", result);
    assert_eq!(result.stdout(),
r"mod infer_users1 {
    table! {
        users1(id) {
            id -> Nullable<Integer>,
        }
    }
}
pub use self::infer_users1::*;

");
}

#[test]
fn run_infer_schema_blacklist() {
    let p = project("print_schema").build();
    let db = database(&p.database_url());

    // Make sure the project is setup
    p.command("setup").run();

    db.execute("CREATE TABLE users1 (id INTEGER PRIMARY KEY);");
    db.execute("CREATE TABLE users2 (id INTEGER PRIMARY KEY);");

    assert!(db.table_exists("users1"));
    assert!(db.table_exists("users2"));

    let result = p.command("print-schema").arg("users1").arg("-b").run();

    assert!(result.is_success(), "Result was unsuccessful {:?}", result);
    assert_eq!(result.stdout(),
r"mod infer_users2 {
    table! {
        users2(id) {
            id -> Nullable<Integer>,
        }
    }
}
pub use self::infer_users2::*;

");
}
<commit_msg>Fix postgres test results<commit_after>use support::{database, project};

#[test]
fn run_infer_schema() {
    let p = project("print_schema").build();
    let db = database(&p.database_url());

    // Make sure the project is setup
    p.command("setup").run();

    db.execute("CREATE TABLE users1 (id INTEGER PRIMARY KEY);");
    db.execute("CREATE TABLE users2 (id INTEGER PRIMARY KEY);");

    assert!(db.table_exists("users1"));
    assert!(db.table_exists("users2"));

    let result = p.command("print-schema").run();

    assert!(result.is_success(), "Result was unsuccessful {:?}", result);
    if cfg!(feature = "sqlite") {
        assert_eq!(result.stdout(),
r"mod infer_users1 {
    table! {
        users1(id) {
            id -> Nullable<Integer>,
        }
    }
}
pub use self::infer_users1::*;
mod infer_users2 {
    table! {
        users2(id) {
            id -> Nullable<Integer>,
        }
    }
}
pub use self::infer_users2::*;

");
    } else if cfg!(feature = "postgres") {
                assert_eq!(result.stdout(),
r"mod infer_users1 {
    table! {
        users1(id) {
            id -> Int4,
        }
    }
}
pub use self::infer_users1::*;
mod infer_users2 {
    table! {
        users2(id) {
            id -> Int4,
        }
    }
}
pub use self::infer_users2::*;

");
    }
}

#[test]
fn run_infer_schema_whitelist() {
    let p = project("print_schema_whitelist").build();
    let db = database(&p.database_url());

    // Make sure the project is setup
    p.command("setup").run();

    db.execute("CREATE TABLE users1 (id INTEGER PRIMARY KEY);");
    db.execute("CREATE TABLE users2 (id INTEGER PRIMARY KEY);");

    assert!(db.table_exists("users1"));
    assert!(db.table_exists("users2"));

    let result = p.command("print-schema").arg("users1").arg("-w").run();

    assert!(result.is_success(), "Result was unsuccessful {:?}", result);
    if cfg!(feature = "sqlite") {
        assert_eq!(result.stdout(),
r"mod infer_users1 {
    table! {
        users1(id) {
            id -> Nullable<Integer>,
        }
    }
}
pub use self::infer_users1::*;

");
    } else if cfg!(feature = "postgres") {
        assert_eq!(result.stdout(),
r"mod infer_users1 {
    table! {
        users1(id) {
            id -> Int4,
        }
    }
}
pub use self::infer_users1::*;

");
    }
}

#[test]
fn run_infer_schema_blacklist() {
    let p = project("print_schema_blacklist").build();
    let db = database(&p.database_url());

    // Make sure the project is setup
    p.command("setup").run();

    db.execute("CREATE TABLE users1 (id INTEGER PRIMARY KEY);");
    db.execute("CREATE TABLE users2 (id INTEGER PRIMARY KEY);");

    assert!(db.table_exists("users1"));
    assert!(db.table_exists("users2"));

    let result = p.command("print-schema").arg("users1").arg("-b").run();

    assert!(result.is_success(), "Result was unsuccessful {:?}", result);
    if cfg!(feature = "sqlite") {
        assert_eq!(result.stdout(),
r"mod infer_users2 {
    table! {
        users2(id) {
            id -> Nullable<Integer>,
        }
    }
}
pub use self::infer_users2::*;

");
    } else if cfg!(feature = "postgres") {
        assert_eq!(result.stdout(),
r"mod infer_users2 {
    table! {
        users2(id) {
            id -> Int4,
        }
    }
}
pub use self::infer_users2::*;

");
    }
}
<|endoftext|>