<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::{
    ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId,
};
use once_cell::sync::Lazy;
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::{
    builtin_type::BuiltinType,
    db::DefDatabase,
    nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
    path::ModPath,
    per_ns::PerNs,
    AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
};

/// 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,
        }
    }

    /// 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: ModuleScope,

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

    pub impls: Vec<ImplId>,
}

#[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct Declarations {
    fns: FxHashMap<FileAstId<ast::FnDef>, FunctionId>,
}

#[derive(Debug, Default, PartialEq, Eq)]
pub struct ModuleScope {
    items: FxHashMap<Name, Resolution>,
    /// Macros visable in current module in legacy textual scope
    ///
    /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first.
    /// If it yields no result, then it turns to module scoped `macros`.
    /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
    /// and only normal scoped `macros` will be searched in.
    ///
    /// Note that this automatically inherit macros defined textually before the definition of module itself.
    ///
    /// Module scoped macros will be inserted into `items` instead of here.
    // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
    // be all resolved to the last one defined if shadowing happens.
    legacy_macros: FxHashMap<Name, MacroDefId>,
}

static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
    BuiltinType::ALL
        .iter()
        .map(|(name, ty)| {
            (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None })
        })
        .collect()
});

/// Shadow mode for builtin type which can be shadowed by module.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BuiltinShadowMode {
    // Prefer Module
    Module,
    // Prefer Other Types
    Other,
}

/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
/// Other methods will only resolve values, types and module scoped macros only.
impl ModuleScope {
    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
        //FIXME: shadowing
        self.items.iter().chain(BUILTIN_SCOPE.iter())
    }

    pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
        self.entries()
            .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
            .flat_map(|per_ns| {
                per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
            })
    }

    /// Iterate over all module scoped macros
    pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.items
            .iter()
            .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_)))
    }

    /// Iterate over all legacy textual scoped macros visable at the end of the module
    pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.legacy_macros.iter().map(|(name, def)| (name, *def))
    }

    /// Get a name from current module scope, legacy macros are not included
    pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> {
        match shadow {
            BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)),
            BuiltinShadowMode::Other => {
                let item = self.items.get(name);
                if let Some(res) = item {
                    if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() {
                        return BUILTIN_SCOPE.get(name).or(item);
                    }
                }

                item.or_else(|| BUILTIN_SCOPE.get(name))
            }
        }
    }

    pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
        self.items.values().filter_map(|r| match r.def.take_types() {
            Some(ModuleDefId::TraitId(t)) => Some(t),
            _ => None,
        })
    }

    fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
        self.legacy_macros.get(name).copied()
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Resolution {
    /// None for unresolved
    pub def: PerNs,
    /// ident by which this is imported into local scope.
    pub import: Option<LocalImportId>,
}

impl CrateDefMap {
    pub(crate) fn 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("crate_def_map_query");
        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 code that never was alive?<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, MacroDefId};
use once_cell::sync::Lazy;
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::{
    builtin_type::BuiltinType,
    db::DefDatabase,
    nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
    path::ModPath,
    per_ns::PerNs,
    AstId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
};

/// 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,
        }
    }

    /// 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: ModuleScope,

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

    pub impls: Vec<ImplId>,
}

#[derive(Debug, Default, PartialEq, Eq)]
pub struct ModuleScope {
    items: FxHashMap<Name, Resolution>,
    /// Macros visable in current module in legacy textual scope
    ///
    /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first.
    /// If it yields no result, then it turns to module scoped `macros`.
    /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
    /// and only normal scoped `macros` will be searched in.
    ///
    /// Note that this automatically inherit macros defined textually before the definition of module itself.
    ///
    /// Module scoped macros will be inserted into `items` instead of here.
    // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
    // be all resolved to the last one defined if shadowing happens.
    legacy_macros: FxHashMap<Name, MacroDefId>,
}

static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
    BuiltinType::ALL
        .iter()
        .map(|(name, ty)| {
            (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None })
        })
        .collect()
});

/// Shadow mode for builtin type which can be shadowed by module.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BuiltinShadowMode {
    // Prefer Module
    Module,
    // Prefer Other Types
    Other,
}

/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
/// Other methods will only resolve values, types and module scoped macros only.
impl ModuleScope {
    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
        //FIXME: shadowing
        self.items.iter().chain(BUILTIN_SCOPE.iter())
    }

    pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
        self.entries()
            .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
            .flat_map(|per_ns| {
                per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
            })
    }

    /// Iterate over all module scoped macros
    pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.items
            .iter()
            .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_)))
    }

    /// Iterate over all legacy textual scoped macros visable at the end of the module
    pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.legacy_macros.iter().map(|(name, def)| (name, *def))
    }

    /// Get a name from current module scope, legacy macros are not included
    pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> {
        match shadow {
            BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)),
            BuiltinShadowMode::Other => {
                let item = self.items.get(name);
                if let Some(res) = item {
                    if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() {
                        return BUILTIN_SCOPE.get(name).or(item);
                    }
                }

                item.or_else(|| BUILTIN_SCOPE.get(name))
            }
        }
    }

    pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
        self.items.values().filter_map(|r| match r.def.take_types() {
            Some(ModuleDefId::TraitId(t)) => Some(t),
            _ => None,
        })
    }

    fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
        self.legacy_macros.get(name).copied()
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Resolution {
    /// None for unresolved
    pub def: PerNs,
    /// ident by which this is imported into local scope.
    pub import: Option<LocalImportId>,
}

impl CrateDefMap {
    pub(crate) fn 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("crate_def_map_query");
        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(),
                    })
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::convert::TryFrom;

/// Intcode Programming error
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ProgramError {
    /// Unrecognized opcode. Argument is the given opcode
    UnknownOpcode(isize),
    /// Invalid parameter mode for the given opcode. Argument is the given parameter mode
    InvalidParameterMode(isize),
    /// Address out of bounds. Argument is the given address
    InvalidAddress(isize),
    /// Expected a position parameter, but received a non-position parameter
    ExpectedPosition,
}

#[derive(Debug, Clone, Copy)]
enum Parameter {
    Ptr(usize),
    Value(isize),
}

impl Default for Parameter {
    fn default() -> Self {
        Self::Value(0)
    }
}

#[derive(Debug, Clone)]
pub struct Interpreter<'a> {
    tape: Vec<isize>,
    position: usize,
    input: &'a [isize],
    output: Vec<isize>,
}

impl<'a> Interpreter<'a> {
    /// Set up a new interpreter with the given program tape
    pub fn new(tape: &[isize]) -> Self {
        Self::with_input(tape, &[])
    }
    /// Set up a new interpreter with the given program tape and input
    pub fn with_input(tape: &[isize], input: &'a [isize]) -> Self {
        Self {
            tape: tape.to_vec(),
            position: 0,
            input,
            output: Vec::new(),
        }
    }

    /// Run the interpreter
    pub fn run(mut self) -> Result<Output, ProgramError> {
        loop {
            let instruction = self.tape[self.position];
            if self.run_instruction(instruction)? {
                break;
            }
        }
        Ok(Output {
            tape: self.tape,
            output: self.output,
        })
    }

    pub fn run_with_noun_and_verb(
        mut self,
        noun: isize,
        verb: isize,
    ) -> Result<Output, ProgramError> {
        self.tape[1] = noun;
        self.tape[2] = verb;
        self.run()
    }

    fn deref_mut(&mut self, param: Parameter) -> Result<&mut isize, ProgramError> {
        match param {
            Parameter::Ptr(idx) => Ok(&mut self.tape[idx]),
            Parameter::Value(_) => Err(ProgramError::ExpectedPosition),
        }
    }

    fn value_of(&self, param: Parameter) -> isize {
        match param {
            Parameter::Ptr(idx) => self.tape[idx],
            Parameter::Value(val) => val,
        }
    }

    /// Fill the given buffer with parameters for an opcode.
    /// The number of parameters read equals the length of the buffer, and parameters are filled
    /// from left to right.
    /// Assumes current program position is on the opcode for which we are filling in the
    /// parameters.
    fn get_params(
        &self,
        parameter_mode: isize,
        buffer: &mut [Parameter],
    ) -> Result<(), ProgramError> {
        use ProgramError::*;
        let mut mode = parameter_mode;
        for (offset, elem) in buffer.iter_mut().enumerate() {
            let value: isize = self.tape[self.position + offset + 1];
            match mode % 10 {
                0 => {
                    // position mode
                    *elem = Parameter::Ptr(
                        usize::try_from(value).map_err(|_| ProgramError::InvalidAddress(value))?,
                    );
                }
                1 => {
                    // immediate mode
                    *elem = Parameter::Value(value);
                }
                _ => return Err(InvalidParameterMode(parameter_mode)),
            }
            mode /= 10;
        }
        Ok(())
    }

    /// Run a single instruction, mutating self as necessary. On success, return a boolean
    /// expressing whether program should terminate
    fn run_instruction(&mut self, instruction: isize) -> Result<bool, ProgramError> {
        use ProgramError::*;
        let opcode = instruction % 100;
        let parameter_mode = instruction / 100;
        match opcode {
            1 => {
                let mut params = [Parameter::default(); 3];
                self.get_params(parameter_mode, &mut params)?;
                *self.deref_mut(params[2])? = self.value_of(params[0]) + self.value_of(params[1]);
                self.position += 4;
            }
            2 => {
                let mut params = [Parameter::default(); 3];
                self.get_params(parameter_mode, &mut params)?;
                *self.deref_mut(params[2])? = self.value_of(params[0]) * self.value_of(params[1]);
                self.position += 4;
            }
            3 => {
                let mut params = [Parameter::default(); 1];
                self.get_params(parameter_mode, &mut params)?;
                *self.deref_mut(params[0])? = self.input[0];
                self.input = &self.input[1..];
                self.position += 2;
            }
            4 => {
                let mut params = [Parameter::default(); 1];
                self.get_params(parameter_mode, &mut params)?;
                self.output.push(self.value_of(params[0]));
                self.input = &self.input[1..];
                self.position += 2;
            }
            99 => return Ok(true),
            _ => return Err(UnknownOpcode(opcode)),
        }
        Ok(false)
    }
}

pub struct Output {
    output: Vec<isize>,
    tape: Vec<isize>,
}

impl Output {
    pub fn output(&self) -> &[isize] {
        &self.output
    }
    pub fn first_elem(&self) -> isize {
        self.tape[0]
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_run() {
        let expected = vec![
            (
                vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50],
                vec![3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50],
            ),
            (vec![1, 0, 0, 0, 99], vec![2, 0, 0, 0, 99]),
            (vec![2, 3, 0, 3, 99], vec![2, 3, 0, 6, 99]),
            (vec![2, 4, 4, 5, 99, 0], vec![2, 4, 4, 5, 99, 9801]),
            (
                vec![1, 1, 1, 4, 99, 5, 6, 0, 99],
                vec![30, 1, 1, 4, 2, 5, 6, 0, 99],
            ),
        ];
        for (input, output) in expected {
            let result = Interpreter::new(&input).run().map(|out| out.tape);
            assert_eq!(result, Ok(output));
        }
    }
}
<commit_msg>Fix a bug in the intcode interpreter<commit_after>use std::convert::TryFrom;

/// Intcode Programming error
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ProgramError {
    /// Unrecognized opcode. Argument is the given opcode
    UnknownOpcode(isize),
    /// Invalid parameter mode for the given opcode. Argument is the given parameter mode
    InvalidParameterMode(isize),
    /// Address out of bounds. Argument is the given address
    InvalidAddress(isize),
    /// Expected a position parameter, but received a non-position parameter
    ExpectedPosition,
    /// Ran out of input
    NoMoreInput,
}

#[derive(Debug, Clone, Copy)]
enum Parameter {
    Ptr(usize),
    Value(isize),
}

impl Default for Parameter {
    fn default() -> Self {
        Self::Value(0)
    }
}

#[derive(Debug, Clone)]
pub struct Interpreter<'a> {
    tape: Vec<isize>,
    position: usize,
    input: &'a [isize],
    output: Vec<isize>,
}

impl<'a> Interpreter<'a> {
    /// Set up a new interpreter with the given program tape
    pub fn new(tape: &[isize]) -> Self {
        Self::with_input(tape, &[])
    }
    /// Set up a new interpreter with the given program tape and input
    pub fn with_input(tape: &[isize], input: &'a [isize]) -> Self {
        Self {
            tape: tape.to_vec(),
            position: 0,
            input,
            output: Vec::new(),
        }
    }

    /// Run the interpreter
    pub fn run(mut self) -> Result<Output, ProgramError> {
        loop {
            let instruction = self.tape[self.position];
            if self.run_instruction(instruction)? {
                break;
            }
        }
        Ok(Output {
            tape: self.tape,
            output: self.output,
        })
    }

    pub fn run_with_noun_and_verb(
        mut self,
        noun: isize,
        verb: isize,
    ) -> Result<Output, ProgramError> {
        self.tape[1] = noun;
        self.tape[2] = verb;
        self.run()
    }

    fn deref_mut(&mut self, param: Parameter) -> Result<&mut isize, ProgramError> {
        match param {
            Parameter::Ptr(idx) => Ok(&mut self.tape[idx]),
            Parameter::Value(_) => Err(ProgramError::ExpectedPosition),
        }
    }

    fn value_of(&self, param: Parameter) -> isize {
        match param {
            Parameter::Ptr(idx) => self.tape[idx],
            Parameter::Value(val) => val,
        }
    }

    /// Fill the given buffer with parameters for an opcode.
    /// The number of parameters read equals the length of the buffer, and parameters are filled
    /// from left to right.
    /// Assumes current program position is on the opcode for which we are filling in the
    /// parameters.
    fn get_params(
        &self,
        parameter_mode: isize,
        buffer: &mut [Parameter],
    ) -> Result<(), ProgramError> {
        use ProgramError::*;
        let mut mode = parameter_mode;
        for (offset, elem) in buffer.iter_mut().enumerate() {
            let value: isize = self.tape[self.position + offset + 1];
            match mode % 10 {
                0 => {
                    // position mode
                    *elem = Parameter::Ptr(
                        usize::try_from(value).map_err(|_| ProgramError::InvalidAddress(value))?,
                    );
                }
                1 => {
                    // immediate mode
                    *elem = Parameter::Value(value);
                }
                _ => return Err(InvalidParameterMode(parameter_mode)),
            }
            mode /= 10;
        }
        Ok(())
    }

    /// Run a single instruction, mutating self as necessary. On success, return a boolean
    /// expressing whether program should terminate
    fn run_instruction(&mut self, instruction: isize) -> Result<bool, ProgramError> {
        let opcode = instruction % 100;
        let parameter_mode = instruction / 100;
        match opcode {
            1 => {
                let mut params = [Parameter::default(); 3];
                self.get_params(parameter_mode, &mut params)?;
                *self.deref_mut(params[2])? = self.value_of(params[0]) + self.value_of(params[1]);
                self.position += 4;
            }
            2 => {
                let mut params = [Parameter::default(); 3];
                self.get_params(parameter_mode, &mut params)?;
                *self.deref_mut(params[2])? = self.value_of(params[0]) * self.value_of(params[1]);
                self.position += 4;
            }
            3 => {
                let mut params = [Parameter::default(); 1];
                self.get_params(parameter_mode, &mut params)?;
                let (input, rest) = self.input.split_first().ok_or(ProgramError::NoMoreInput)?;
                *self.deref_mut(params[0])? = *input;
                self.input = rest;
                self.position += 2;
            }
            4 => {
                let mut params = [Parameter::default(); 1];
                self.get_params(parameter_mode, &mut params)?;
                self.output.push(self.value_of(params[0]));
                self.position += 2;
            }
            99 => return Ok(true),
            _ => return Err(ProgramError::UnknownOpcode(opcode)),
        }
        Ok(false)
    }
}

pub struct Output {
    output: Vec<isize>,
    tape: Vec<isize>,
}

impl Output {
    pub fn output(&self) -> &[isize] {
        &self.output
    }
    pub fn first_elem(&self) -> isize {
        self.tape[0]
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_run() {
        let expected = vec![
            (
                vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50],
                vec![3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50],
            ),
            (vec![1, 0, 0, 0, 99], vec![2, 0, 0, 0, 99]),
            (vec![2, 3, 0, 3, 99], vec![2, 3, 0, 6, 99]),
            (vec![2, 4, 4, 5, 99, 0], vec![2, 4, 4, 5, 99, 9801]),
            (
                vec![1, 1, 1, 4, 99, 5, 6, 0, 99],
                vec![30, 1, 1, 4, 2, 5, 6, 0, 99],
            ),
        ];
        for (input, output) in expected {
            let result = Interpreter::new(&input).run().map(|out| out.tape);
            assert_eq!(result, Ok(output));
        }
    }
}
<|endoftext|>


<commit_before>use cairo;

use crate::float_eq_cairo::ApproxEqCairo;

pub trait RectangleExt {
    fn new(x: f64, y: f64, width: f64, height: f64) -> cairo::Rectangle;
    fn is_empty(&self) -> bool;
    fn intersect(&self, rect: &cairo::Rectangle) -> cairo::Rectangle;
    fn union(&self, rect: &cairo::Rectangle) -> cairo::Rectangle;
    fn transform(&self, affine: &cairo::Matrix) -> cairo::Rectangle;
    fn outer(&self) -> cairo::Rectangle;
}

impl RectangleExt for cairo::Rectangle {
    fn new(x: f64, y: f64, width: f64, height: f64) -> cairo::Rectangle {
        cairo::Rectangle {
            x,
            y,
            width,
            height,
        }
    }

    fn is_empty(&self) -> bool {
        self.width.approx_eq_cairo(0.0) || self.height.approx_eq_cairo(0.0)
    }

    fn intersect(&self, rect: &cairo::Rectangle) -> cairo::Rectangle {
        let (x1, y1, x2, y2) = (
            self.x.max(rect.x),
            self.y.max(rect.y),
            (self.x + self.width).min(rect.x + rect.width),
            (self.y + self.height).min(rect.y + rect.height),
        );

        if x2 > x1 && y2 > y1 {
            cairo::Rectangle {
                x: x1,
                y: y1,
                width: x2 - x1,
                height: y2 - y1,
            }
        } else {
            cairo::Rectangle {
                x: 0.0,
                y: 0.0,
                width: 0.0,
                height: 0.0,
            }
        }
    }

    fn union(&self, rect: &cairo::Rectangle) -> cairo::Rectangle {
        let (x1, y1, x2, y2) = (
            self.x.min(rect.x),
            self.y.min(rect.y),
            (self.x + self.width).max(rect.x + rect.width),
            (self.y + self.height).max(rect.y + rect.height),
        );

        cairo::Rectangle {
            x: x1,
            y: y1,
            width: x2 - x1,
            height: y2 - y1,
        }
    }

    fn transform(&self, affine: &cairo::Matrix) -> cairo::Rectangle {
        let points = vec![
            affine.transform_point(self.x, self.y),
            affine.transform_point(self.x + self.width, self.y),
            affine.transform_point(self.x, self.y + self.height),
            affine.transform_point(self.x + self.width, self.y + self.height),
        ];

        let (mut xmin, mut ymin, mut xmax, mut ymax) = {
            let (x, y) = points[0];

            (x, y, x, y)
        };

        for &(x, y) in points.iter().take(4).skip(1) {
            if x < xmin {
                xmin = x;
            }

            if x > xmax {
                xmax = x;
            }

            if y < ymin {
                ymin = y;
            }

            if y > ymax {
                ymax = y;
            }
        }

        cairo::Rectangle {
            x: xmin,
            y: ymin,
            width: xmax - xmin,
            height: ymax - ymin,
        }
    }

    fn outer(&self) -> cairo::Rectangle {
        let (x, y) = (self.x.floor(), self.y.floor());

        cairo::Rectangle {
            x,
            y,
            width: (self.x + self.width).ceil() - x,
            height: (self.y + self.height).ceil() - y,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IRect {
    pub x0: i32,
    pub y0: i32,
    pub x1: i32,
    pub y1: i32,
}

impl IRect {
    /// Returns true if the `IRect` contains the given coordinates.
    #[inline]
    pub fn contains(self, x: i32, y: i32) -> bool {
        x >= self.x0 && x < self.x1 && y >= self.y0 && y < self.y1
    }

    /// Returns an `IRect` scaled by the given amounts.
    ///
    /// The returned `IRect` encompasses all, even partially covered, pixels after the scaling.
    #[inline]
    pub fn scale(self, x: f64, y: f64) -> IRect {
        IRect {
            x0: (f64::from(self.x0) * x).floor() as i32,
            y0: (f64::from(self.y0) * y).floor() as i32,
            x1: (f64::from(self.x1) * x).ceil() as i32,
            y1: (f64::from(self.y1) * y).ceil() as i32,
        }
    }
}

impl From<cairo::Rectangle> for IRect {
    #[inline]
    fn from(
        cairo::Rectangle {
            x,
            y,
            width,
            height,
        }: cairo::Rectangle,
    ) -> Self {
        Self {
            x0: x.floor() as i32,
            y0: y.floor() as i32,
            x1: (x + width).ceil() as i32,
            y1: (y + height).ceil() as i32,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn empty_rect() {
        let empty = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 0.0,
            height: 0.0,
        };
        let not_empty = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        assert!(empty.is_empty());
        assert!(!not_empty.is_empty());
    }

    #[test]
    fn intersect_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };
        let r3 = cairo::Rectangle {
            x: 10.0,
            y: 10.0,
            width: 3.14,
            height: 3.14,
        };

        let r = r1.intersect(&r2);
        assert_approx_eq_cairo!(0.42_f64, r.x);
        assert_approx_eq_cairo!(0.42_f64, r.y);
        assert_approx_eq_cairo!(2.94_f64, r.width);
        assert_approx_eq_cairo!(2.94_f64, r.height);

        let r = r1.intersect(&r3);
        assert!(r.is_empty());
    }

    #[test]
    fn union_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        let r = r1.union(&r2);
        assert_approx_eq_cairo!(0.22_f64, r.x);
        assert_approx_eq_cairo!(0.22_f64, r.y);
        assert_approx_eq_cairo!(4.34_f64, r.width);
        assert_approx_eq_cairo!(4.34_f64, r.height);
    }

    #[test]
    fn transform_rect() {
        let r = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 3.14,
            height: 3.14,
        };

        let m = cairo::Matrix::identity();
        let tr = r.transform(&m);
        assert_eq!(tr, r);

        let m = cairo::Matrix::new(2.0, 0.0, 0.0, 2.0, 1.5, 1.5);
        let tr = r.transform(&m);
        assert_approx_eq_cairo!(2.34_f64, tr.x);
        assert_approx_eq_cairo!(2.34_f64, tr.y);
        assert_approx_eq_cairo!(6.28_f64, tr.width);
        assert_approx_eq_cairo!(6.28_f64, tr.height);
    }

    #[test]
    fn outer_rect() {
        let r = cairo::Rectangle {
            x: 1.42,
            y: 1.42,
            width: 3.14,
            height: 3.14,
        };

        let or = r.outer();
        assert_eq!(1.0, or.x);
        assert_eq!(1.0, or.y);
        assert_eq!(4.0, or.width);
        assert_eq!(4.0, or.height);
    }
}
<commit_msg>rect: add conversion to cairo::Rectangle<commit_after>use cairo;

use crate::float_eq_cairo::ApproxEqCairo;

pub trait RectangleExt {
    fn new(x: f64, y: f64, width: f64, height: f64) -> cairo::Rectangle;
    fn is_empty(&self) -> bool;
    fn intersect(&self, rect: &cairo::Rectangle) -> cairo::Rectangle;
    fn union(&self, rect: &cairo::Rectangle) -> cairo::Rectangle;
    fn transform(&self, affine: &cairo::Matrix) -> cairo::Rectangle;
    fn outer(&self) -> cairo::Rectangle;
}

impl RectangleExt for cairo::Rectangle {
    fn new(x: f64, y: f64, width: f64, height: f64) -> cairo::Rectangle {
        cairo::Rectangle {
            x,
            y,
            width,
            height,
        }
    }

    fn is_empty(&self) -> bool {
        self.width.approx_eq_cairo(0.0) || self.height.approx_eq_cairo(0.0)
    }

    fn intersect(&self, rect: &cairo::Rectangle) -> cairo::Rectangle {
        let (x1, y1, x2, y2) = (
            self.x.max(rect.x),
            self.y.max(rect.y),
            (self.x + self.width).min(rect.x + rect.width),
            (self.y + self.height).min(rect.y + rect.height),
        );

        if x2 > x1 && y2 > y1 {
            cairo::Rectangle {
                x: x1,
                y: y1,
                width: x2 - x1,
                height: y2 - y1,
            }
        } else {
            cairo::Rectangle {
                x: 0.0,
                y: 0.0,
                width: 0.0,
                height: 0.0,
            }
        }
    }

    fn union(&self, rect: &cairo::Rectangle) -> cairo::Rectangle {
        let (x1, y1, x2, y2) = (
            self.x.min(rect.x),
            self.y.min(rect.y),
            (self.x + self.width).max(rect.x + rect.width),
            (self.y + self.height).max(rect.y + rect.height),
        );

        cairo::Rectangle {
            x: x1,
            y: y1,
            width: x2 - x1,
            height: y2 - y1,
        }
    }

    fn transform(&self, affine: &cairo::Matrix) -> cairo::Rectangle {
        let points = vec![
            affine.transform_point(self.x, self.y),
            affine.transform_point(self.x + self.width, self.y),
            affine.transform_point(self.x, self.y + self.height),
            affine.transform_point(self.x + self.width, self.y + self.height),
        ];

        let (mut xmin, mut ymin, mut xmax, mut ymax) = {
            let (x, y) = points[0];

            (x, y, x, y)
        };

        for &(x, y) in points.iter().take(4).skip(1) {
            if x < xmin {
                xmin = x;
            }

            if x > xmax {
                xmax = x;
            }

            if y < ymin {
                ymin = y;
            }

            if y > ymax {
                ymax = y;
            }
        }

        cairo::Rectangle {
            x: xmin,
            y: ymin,
            width: xmax - xmin,
            height: ymax - ymin,
        }
    }

    fn outer(&self) -> cairo::Rectangle {
        let (x, y) = (self.x.floor(), self.y.floor());

        cairo::Rectangle {
            x,
            y,
            width: (self.x + self.width).ceil() - x,
            height: (self.y + self.height).ceil() - y,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IRect {
    pub x0: i32,
    pub y0: i32,
    pub x1: i32,
    pub y1: i32,
}

impl IRect {
    /// Returns true if the `IRect` contains the given coordinates.
    #[inline]
    pub fn contains(self, x: i32, y: i32) -> bool {
        x >= self.x0 && x < self.x1 && y >= self.y0 && y < self.y1
    }

    /// Returns an `IRect` scaled by the given amounts.
    ///
    /// The returned `IRect` encompasses all, even partially covered, pixels after the scaling.
    #[inline]
    pub fn scale(self, x: f64, y: f64) -> IRect {
        IRect {
            x0: (f64::from(self.x0) * x).floor() as i32,
            y0: (f64::from(self.y0) * y).floor() as i32,
            x1: (f64::from(self.x1) * x).ceil() as i32,
            y1: (f64::from(self.y1) * y).ceil() as i32,
        }
    }
}

impl From<cairo::Rectangle> for IRect {
    #[inline]
    fn from(
        cairo::Rectangle {
            x,
            y,
            width,
            height,
        }: cairo::Rectangle,
    ) -> Self {
        Self {
            x0: x.floor() as i32,
            y0: y.floor() as i32,
            x1: (x + width).ceil() as i32,
            y1: (y + height).ceil() as i32,
        }
    }
}

impl From<IRect> for cairo::Rectangle {
    #[inline]
    fn from(IRect { x0, y0, x1, y1 }: IRect) -> Self {
        Self {
            x: f64::from(x0),
            y: f64::from(y0),
            width: f64::from(x1 - x0),
            height: f64::from(y1 - y0),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn empty_rect() {
        let empty = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 0.0,
            height: 0.0,
        };
        let not_empty = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        assert!(empty.is_empty());
        assert!(!not_empty.is_empty());
    }

    #[test]
    fn intersect_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };
        let r3 = cairo::Rectangle {
            x: 10.0,
            y: 10.0,
            width: 3.14,
            height: 3.14,
        };

        let r = r1.intersect(&r2);
        assert_approx_eq_cairo!(0.42_f64, r.x);
        assert_approx_eq_cairo!(0.42_f64, r.y);
        assert_approx_eq_cairo!(2.94_f64, r.width);
        assert_approx_eq_cairo!(2.94_f64, r.height);

        let r = r1.intersect(&r3);
        assert!(r.is_empty());
    }

    #[test]
    fn union_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        let r = r1.union(&r2);
        assert_approx_eq_cairo!(0.22_f64, r.x);
        assert_approx_eq_cairo!(0.22_f64, r.y);
        assert_approx_eq_cairo!(4.34_f64, r.width);
        assert_approx_eq_cairo!(4.34_f64, r.height);
    }

    #[test]
    fn transform_rect() {
        let r = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 3.14,
            height: 3.14,
        };

        let m = cairo::Matrix::identity();
        let tr = r.transform(&m);
        assert_eq!(tr, r);

        let m = cairo::Matrix::new(2.0, 0.0, 0.0, 2.0, 1.5, 1.5);
        let tr = r.transform(&m);
        assert_approx_eq_cairo!(2.34_f64, tr.x);
        assert_approx_eq_cairo!(2.34_f64, tr.y);
        assert_approx_eq_cairo!(6.28_f64, tr.width);
        assert_approx_eq_cairo!(6.28_f64, tr.height);
    }

    #[test]
    fn outer_rect() {
        let r = cairo::Rectangle {
            x: 1.42,
            y: 1.42,
            width: 3.14,
            height: 3.14,
        };

        let or = r.outer();
        assert_eq!(1.0, or.x);
        assert_eq!(1.0, or.y);
        assert_eq!(4.0, or.width);
        assert_eq!(4.0, or.height);
    }
}
<|endoftext|>


<commit_before>/*
    Txtrevise (rust)
    Command line text editing tool
    Version 1.0.0 (equivalent to Python impl. 1.1)
    Copyright (c) 2015 Sam Saint-Pettersen
    Released under the MIT License.
*/

extern crate regex;
use std::env;
use std::io::{BufRead, BufReader, Write};
use std::fs::File;
use regex::Regex;

// Display error and then usage information.
fn display_error(err: &str) {
    println!("Error: {}.", err);
    display_usage();
}

/// Display usage information.
fn display_usage() {
    println!("\nTxtrevise v 1.0.0 (rust)");
    println!("Command line text editing tool");
    println!("Copyright (c) 2015 Sam Saint-Pettersen");
    println!("\nReleased under the MIT License");
    println!("Usage: txtrevise.py [-h] (-q) -f <file> -l <line #> -m <word(s)>");
    println!("-r <word(s)>");
    println!("\n-f: File to edit");
    println!("-l: Line number to edit text on (starts at 1)");
    println!("-m: Word(s) to match");
    println!("-r: Replacement word(s) for matched word(s)");
    println!("-q: Quiet mode. Only output to console for errors");
    println!("-h: This help information");
}

/// Process file.
fn process_file(filename: &str, line_no: usize, matches: &str, repl: &str, verbose: bool) {
    let mut line_num: usize = 0;
    let mut index: usize = 0;
    let mut all_lines: Vec<String> = Vec::new();

    // Read each line in file sequentially, store selected line no.
    let f = File::open(filename).unwrap();
    let file = BufReader::new(&f);
    for line in file.lines() {
        all_lines.push(line.unwrap());
        if line_num == line_no - 1 { // - 1, because lines start at 0.
            index = line_num;
        }
        line_num += 1;
    }

    // Revise the selected line and append newline.
    all_lines[index] = match_replace(&all_lines[index], line_no, matches, repl, verbose);
    all_lines.push(String::new());

    // Write out changed lines to file.
    let mut w = File::create(filename).unwrap();
    let _ = w.write_all(all_lines.join("\n").as_bytes());
}

/// Match and replace word(s).
fn match_replace(line: &str, line_no: usize, matches: &str, repl: &str, verbose: bool) -> String {
    let new_line: String;
    let re = Regex::new(matches).unwrap();

    // If word(s) are matched, return edited line with replacment word(s).
    if re.is_match(line) {
        if verbose {
            println!("\nMatched at Line {}: {}", line_no, line);
        }
        new_line = re.replace_all(line, repl);
        if verbose {
            println!("Replaced with: {}", new_line);
        }
    }
    // Otherwise, return same line as before.
    else {
        if verbose {
            println!("\nNo matches at Line {}", line_no);
        }
        new_line = line.to_string();
    }
    new_line
}

/// Get next argument.
fn next_argument(i: usize) -> String {
    let a = env::args().nth(i + 1);
    let arg = match a {
        Some(a) => a,
        None => {
            display_error("Invalid argument");
            return String::new();
        }
    };
    arg
}

/// Entry method.
fn main() {
    let args: Vec<_> = env::args().collect();
    let mut i: usize = 0;
    let mut filename = String::new();
    let mut matches = String::new();
    let mut repl = String::new();
    let mut verbose: bool = true;
    let mut line_no: usize = 1;
    if args.len() > 1 {
        for a in args {
            if a == "-h" {
                display_usage();
            }
            if a == "-f" {
                filename = next_argument(i);
            }
            if a == "-l" {
                let l = next_argument(i);
                let ol = l.parse::<usize>().ok();
                line_no = match ol {
                    Some(line_no) => line_no,
                    None => {
                        display_error("Line number must be an integer");
                        return;
                    }
                };
                if line_no == 0 {
                    display_error("Line number must be greater than 0");
                    return;
                }
            }
            if a == "-m" {
                matches = next_argument(i);
            }
            if a == "-r" {
                repl = next_argument(i);
            }
            if a == "-q" {
                verbose = false;
            }
            i = i + 1;
        }
    }
    else {
        display_error("No options specified");
    }

    // With necessary arguments, process file.
    if env::args().len() > 2 && filename.len() > 0 {
        process_file(&filename, line_no, &matches, &repl, verbose);
    }
}
<commit_msg>i = i + 1 => i += 1<commit_after>/*
    Txtrevise (rust)
    Command line text editing tool
    Version 1.0.0 (equivalent to Python impl. 1.1)
    Copyright (c) 2015 Sam Saint-Pettersen
    Released under the MIT License.
*/

extern crate regex;
use std::env;
use std::io::{BufRead, BufReader, Write};
use std::fs::File;
use regex::Regex;

// Display error and then usage information.
fn display_error(err: &str) {
    println!("Error: {}.", err);
    display_usage();
}

/// Display usage information.
fn display_usage() {
    println!("\nTxtrevise v 1.0.0 (rust)");
    println!("Command line text editing tool");
    println!("Copyright (c) 2015 Sam Saint-Pettersen");
    println!("\nReleased under the MIT License");
    println!("Usage: txtrevise.py [-h] (-q) -f <file> -l <line #> -m <word(s)>");
    println!("-r <word(s)>");
    println!("\n-f: File to edit");
    println!("-l: Line number to edit text on (starts at 1)");
    println!("-m: Word(s) to match");
    println!("-r: Replacement word(s) for matched word(s)");
    println!("-q: Quiet mode. Only output to console for errors");
    println!("-h: This help information");
}

/// Process file.
fn process_file(filename: &str, line_no: usize, matches: &str, repl: &str, verbose: bool) {
    let mut line_num: usize = 0;
    let mut index: usize = 0;
    let mut all_lines: Vec<String> = Vec::new();

    // Read each line in file sequentially, store selected line no.
    let f = File::open(filename).unwrap();
    let file = BufReader::new(&f);
    for line in file.lines() {
        all_lines.push(line.unwrap());
        if line_num == line_no - 1 { // - 1, because lines start at 0.
            index = line_num;
        }
        line_num += 1;
    }

    // Revise the selected line and append newline.
    all_lines[index] = match_replace(&all_lines[index], line_no, matches, repl, verbose);
    all_lines.push(String::new());

    // Write out changed lines to file.
    let mut w = File::create(filename).unwrap();
    let _ = w.write_all(all_lines.join("\n").as_bytes());
}

/// Match and replace word(s).
fn match_replace(line: &str, line_no: usize, matches: &str, repl: &str, verbose: bool) -> String {
    let new_line: String;
    let re = Regex::new(matches).unwrap();

    // If word(s) are matched, return edited line with replacment word(s).
    if re.is_match(line) {
        if verbose {
            println!("\nMatched at Line {}: {}", line_no, line);
        }
        new_line = re.replace_all(line, repl);
        if verbose {
            println!("Replaced with: {}", new_line);
        }
    }
    // Otherwise, return same line as before.
    else {
        if verbose {
            println!("\nNo matches at Line {}", line_no);
        }
        new_line = line.to_string();
    }
    new_line
}

/// Get next argument.
fn next_argument(i: usize) -> String {
    let a = env::args().nth(i + 1);
    let arg = match a {
        Some(a) => a,
        None => {
            display_error("Invalid argument");
            return String::new();
        }
    };
    arg
}

/// Entry method.
fn main() {
    let args: Vec<_> = env::args().collect();
    let mut i: usize = 0;
    let mut filename = String::new();
    let mut matches = String::new();
    let mut repl = String::new();
    let mut verbose: bool = true;
    let mut line_no: usize = 1;
    if args.len() > 1 {
        for a in args {
            if a == "-h" {
                display_usage();
            }
            if a == "-f" {
                filename = next_argument(i);
            }
            if a == "-l" {
                let l = next_argument(i);
                let ol = l.parse::<usize>().ok();
                line_no = match ol {
                    Some(line_no) => line_no,
                    None => {
                        display_error("Line number must be an integer");
                        return;
                    }
                };
                if line_no == 0 {
                    display_error("Line number must be greater than 0");
                    return;
                }
            }
            if a == "-m" {
                matches = next_argument(i);
            }
            if a == "-r" {
                repl = next_argument(i);
            }
            if a == "-q" {
                verbose = false;
            }
            i += 1;
        }
    }
    else {
        display_error("No options specified");
    }

    // With necessary arguments, process file.
    if env::args().len() > 2 && filename.len() > 0 {
        process_file(&filename, line_no, &matches, &repl, verbose);
    }
}
<|endoftext|>


<commit_before>use std::rand::{task_rng, Rng};

fn rnd_select<'a, T: Clone>(list: &'a [T], n: uint) -> ~[&'a T] {
    task_rng().sample(list.iter(), n)
}

fn main() {
    let list = ~['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
    println!("{:?}", rnd_select(list, 3));
}

<commit_msg>Cleanup Problem 23<commit_after>use std::rand::{task_rng, Rng};

fn rnd_select<'a, T>(list: &'a [T], n: uint) -> ~[&'a T] {
    task_rng().sample(list.iter(), n)
}

fn main() {
    let list = ~['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
    println!("{:?}", rnd_select(list, 3));
}

<|endoftext|>


<commit_before>
pub fn from_hex(hex_in: &str) -> Vec<u8>
{
    let mut bin_out = Vec::new();

    let mut combined = 0u8;
    let mut second_byte = false;
    for c in hex_in.bytes() {
        let nibble = (c & 0x0f) + ((c & 0x40) >> 6) * 9;

        if second_byte {
            combined += nibble;
            second_byte = false;

            bin_out.push(combined);
        } else {
            combined = nibble << 4;
            second_byte = true;
        }
    }

    return bin_out;
}

fn encode_single_base64(byte_in: u8) -> char {
    match byte_in {
        0...25 => (65u8 + byte_in) as char,
        26...51 => (71u8 + byte_in) as char,
        52...61 => (byte_in - 4u8) as char,
        62 => '+',
        63 => '/',
        _ => ' ' // FIXME: error
    }
}

pub fn to_base64(bin_in: &[u8]) -> String {
    let mut result = String::new();

    let mut i = 0u;
    let total = bin_in.len();
    while i < total {
        // combine three bytes
        let mut current = bin_in[i] as u32 << 16;
        let mut fill_bytes = 0u;
        current += if i+1 < total { bin_in[i+1] as u32 << 8 } else { fill_bytes +=1; 0 };
        current += if i+2 < total { bin_in[i+2] as u32 } else { fill_bytes +=1; 0 };

        // encode
        result.push(encode_single_base64(((current & 0x00fc0000) >> 18) as u8));
        result.push(encode_single_base64(((current & 0x0003f000) >> 12) as u8));
        result.push(if fill_bytes < 2 { encode_single_base64(((current & 0x00000fc0) >> 6) as u8) } else { '=' });
        result.push(if fill_bytes < 1 { encode_single_base64((current & 0x0000003f) as u8 ) } else { '=' });

        i += 3;
    }

    result
}

#[test]
fn from_hex_basics() {
    assert_eq!(from_hex(""), vec![]);
    assert_eq!(from_hex("01"), vec![1u8]);
    assert_eq!(from_hex("ff"), vec![255u8]);
    assert_eq!(from_hex("A0"), vec![160u8]);
    assert_eq!(from_hex("A00AFf"), vec![160u8, 10u8, 255u8]);
}

#[test]
fn to_base64_rfc4648() {
   assert_eq!(to_base64([]), String::from_str(""));// ""
   assert_eq!(to_base64([102]), String::from_str("Zg=="));// "f"
   assert_eq!(to_base64([102,111]), String::from_str("Zm8="));// "fo"
   assert_eq!(to_base64([102,111,111]), String::from_str("Zm9v"));// "foo"
   assert_eq!(to_base64([102,111,111,98]), String::from_str("Zm9vYg==")); // "foob"
   assert_eq!(to_base64([102,111,111,98,97]), String::from_str("Zm9vYmE=")); // "fooba"
   assert_eq!(to_base64([102,111,111,98,97,114]), String::from_str("Zm9vYmFy")); // "foobar"
}

#[test]
fn challenge1() {
    let input = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
    let output = to_base64( &*from_hex(input) );
    assert_eq!(output, String::from_str("SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t"));
}<commit_msg>Improve tests by using newly learned methods<commit_after>
pub fn from_hex(hex_in: &str) -> Vec<u8>
{
    let mut bin_out = Vec::new();

    let mut combined = 0u8;
    let mut second_byte = false;
    for c in hex_in.bytes() {
        let nibble = (c & 0x0f) + ((c & 0x40) >> 6) * 9;

        if second_byte {
            combined += nibble;
            second_byte = false;

            bin_out.push(combined);
        } else {
            combined = nibble << 4;
            second_byte = true;
        }
    }

    return bin_out;
}

fn encode_single_base64(byte_in: u8) -> char {
    match byte_in {
        0...25 => (65u8 + byte_in) as char,
        26...51 => (71u8 + byte_in) as char,
        52...61 => (byte_in - 4u8) as char,
        62 => '+',
        63 => '/',
        _ => ' ' // FIXME: error
    }
}

pub fn to_base64(bin_in: &[u8]) -> String {
    let mut result = String::new();

    let mut i = 0u;
    let total = bin_in.len();
    while i < total {
        // combine three bytes
        let mut current = bin_in[i] as u32 << 16;
        let mut fill_bytes = 0u;
        current += if i+1 < total { bin_in[i+1] as u32 << 8 } else { fill_bytes +=1; 0 };
        current += if i+2 < total { bin_in[i+2] as u32 } else { fill_bytes +=1; 0 };

        // encode
        result.push(encode_single_base64(((current & 0x00fc0000) >> 18) as u8));
        result.push(encode_single_base64(((current & 0x0003f000) >> 12) as u8));
        result.push(if fill_bytes < 2 { encode_single_base64(((current & 0x00000fc0) >> 6) as u8) } else { '=' });
        result.push(if fill_bytes < 1 { encode_single_base64((current & 0x0000003f) as u8 ) } else { '=' });

        i += 3;
    }

    result
}

#[test]
fn from_hex_basics() {
    assert_eq!(from_hex(""), vec![]);
    assert_eq!(from_hex("01"), vec![1]);
    assert_eq!(from_hex("ff"), vec![255]);
    assert_eq!(from_hex("A0"), vec![160]);
    assert_eq!(from_hex("A00AFf"), vec![160, 10, 255]);
}

#[test]
fn to_base64_rfc4648() {
   assert_eq!(to_base64([]), String::from_str(""));// ""
   assert_eq!(to_base64("f".as_bytes()), String::from_str("Zg=="));
   assert_eq!(to_base64("fo".as_bytes()), String::from_str("Zm8="));
   assert_eq!(to_base64("foo".as_bytes()), String::from_str("Zm9v"));
   assert_eq!(to_base64("foob".as_bytes()), String::from_str("Zm9vYg=="));
   assert_eq!(to_base64("fooba".as_bytes()), String::from_str("Zm9vYmE="));
   assert_eq!(to_base64("foobar".as_bytes()), String::from_str("Zm9vYmFy"));
}

#[test]
fn challenge1() {
    let input = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
    let output = to_base64( &*from_hex(input) );
    assert_eq!(output, String::from_str("SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t"));
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use std::mem;
use std::slice;
use libc;

use super::memory::*;

pub struct Buffer<T> {
    data: *const T,
    len: i32,
}

impl<T> Buffer<T> {
    pub fn new(data: *const T, len: i32) -> Self {
        Buffer { data, len }
    }

    pub fn len(&self) -> i32 {
        self.len
    }

    pub fn data(&self) -> *const T {
        self.data
    }

    pub fn slice(&self, start: usize, end: usize) -> &[T] {
        unsafe { slice::from_raw_parts(self.data.offset(start as isize), (end - start) as usize) }
    }

    pub fn get(&self, i: usize) -> &T {
        unsafe { &(*self.data.offset(i as isize)) }
    }

    pub fn set(&mut self, i: usize, v: T) {
        unsafe {
            let p = mem::transmute::<*const T, *mut T>(self.data);
            *p.offset(i as isize) = v;
        }
    }

    pub fn iter(&self) -> BufferIterator<T> {
        BufferIterator {
            data: self.data,
            len: self.len,
            index: 0
        }
    }

}

impl<T> Drop for Buffer<T> {
    fn drop(&mut self) {
        mem::drop(self.data)
    }
}

pub struct BufferIterator<T> {
    data: *const T,
    len: i32,
    index: isize
}

impl<T> Iterator for BufferIterator<T> where T: Copy {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index < self.len as isize {
            self.index += 1;
            Some(unsafe { *self.data.offset(self.index-1) })
        } else {
            None
        }
    }
}

macro_rules! array_from_primitive {
    ($DT: ty) => {
        impl From<Vec<$DT>> for Buffer<$DT> {
            fn from(v: Vec<$DT>) -> Self {
                // allocate aligned memory buffer
                let len = v.len();
                let sz = mem::size_of::<$DT>();
                let buffer = allocate_aligned((len * sz) as i64).unwrap();
                Buffer {
                    len: len as i32,
                    data: unsafe {
                        let dst = mem::transmute::<*const u8, *mut libc::c_void>(buffer);
                        libc::memcpy(
                            dst,
                            mem::transmute::<*const $DT, *const libc::c_void>(v.as_ptr()),
                            len * sz,
                        );
                        mem::transmute::<*mut libc::c_void, *const $DT>(dst)
                    },
                }
            }
        }
    };
}

array_from_primitive!(bool);
array_from_primitive!(f32);
array_from_primitive!(f64);
array_from_primitive!(u8);
array_from_primitive!(u16);
array_from_primitive!(u32);
array_from_primitive!(u64);
array_from_primitive!(i8);
array_from_primitive!(i16);
array_from_primitive!(i32);
array_from_primitive!(i64);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_buffer_i32() {
        let b: Buffer<i32> = Buffer::from(vec![1, 2, 3, 4, 5]);
        assert_eq!(5, b.len);
    }

    #[test]
    fn test_iterator_i32() {
        let b: Buffer<i32> = Buffer::from(vec![1, 2, 3, 4, 5]);
        let it = b.iter();
        let v : Vec<i32> = it.map(|n| n+1).collect();
        assert_eq!(vec![2,3,4,5,6], v);
    }
}
<commit_msg>ARROW-2375: [Rust] Implement Drop for Buffer so memory is released<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use std::mem;
use std::slice;
use libc;

use super::memory::*;

pub struct Buffer<T> {
    data: *const T,
    len: i32,
}

impl<T> Buffer<T> {
    pub fn new(data: *const T, len: i32) -> Self {
        Buffer { data, len }
    }

    pub fn len(&self) -> i32 {
        self.len
    }

    pub fn data(&self) -> *const T {
        self.data
    }

    pub fn slice(&self, start: usize, end: usize) -> &[T] {
        unsafe { slice::from_raw_parts(self.data.offset(start as isize), (end - start) as usize) }
    }

    pub fn get(&self, i: usize) -> &T {
        unsafe { &(*self.data.offset(i as isize)) }
    }

    pub fn set(&mut self, i: usize, v: T) {
        unsafe {
            let p = mem::transmute::<*const T, *mut T>(self.data);
            *p.offset(i as isize) = v;
        }
    }

    pub fn iter(&self) -> BufferIterator<T> {
        BufferIterator {
            data: self.data,
            len: self.len,
            index: 0
        }
    }

}

impl<T> Drop for Buffer<T> {
    fn drop(&mut self) {
        mem::drop(self.data)
    }
}

pub struct BufferIterator<T> {
    data: *const T,
    len: i32,
    index: isize
}

impl<T> Iterator for BufferIterator<T> where T: Copy {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index < self.len as isize {
            self.index += 1;
            Some(unsafe { *self.data.offset(self.index-1) })
        } else {
            None
        }
    }
}

impl<T> Drop for Buffer<T> {
    fn drop(&mut self) {
        mem::drop(self.data)
    }
}

macro_rules! array_from_primitive {
    ($DT: ty) => {
        impl From<Vec<$DT>> for Buffer<$DT> {
            fn from(v: Vec<$DT>) -> Self {
                // allocate aligned memory buffer
                let len = v.len();
                let sz = mem::size_of::<$DT>();
                let buffer = allocate_aligned((len * sz) as i64).unwrap();
                Buffer {
                    len: len as i32,
                    data: unsafe {
                        let dst = mem::transmute::<*const u8, *mut libc::c_void>(buffer);
                        libc::memcpy(
                            dst,
                            mem::transmute::<*const $DT, *const libc::c_void>(v.as_ptr()),
                            len * sz,
                        );
                        mem::transmute::<*mut libc::c_void, *const $DT>(dst)
                    },
                }
            }
        }
    };
}

array_from_primitive!(bool);
array_from_primitive!(f32);
array_from_primitive!(f64);
array_from_primitive!(u8);
array_from_primitive!(u16);
array_from_primitive!(u32);
array_from_primitive!(u64);
array_from_primitive!(i8);
array_from_primitive!(i16);
array_from_primitive!(i32);
array_from_primitive!(i64);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_buffer_i32() {
        let b: Buffer<i32> = Buffer::from(vec![1, 2, 3, 4, 5]);
        assert_eq!(5, b.len);
    }

    #[test]
    fn test_iterator_i32() {
        let b: Buffer<i32> = Buffer::from(vec![1, 2, 3, 4, 5]);
        let it = b.iter();
        let v : Vec<i32> = it.map(|n| n+1).collect();
        assert_eq!(vec![2,3,4,5,6], v);
    }
}
<|endoftext|>


<commit_before>extern crate abra;
extern crate rocksdb;
extern crate rustc_serialize;

use std::sync::Arc;

use rocksdb::{DB, Writable, Options};
use abra::schema::{Schema, FieldType, FieldRef, AddFieldError};
use rustc_serialize::{json, Encodable};

pub struct RocksDBIndexStore {
    schema: Arc<Schema>,
    db: DB,
}

impl RocksDBIndexStore {
    pub fn create(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        let db = try!(DB::open(&opts, path));

        // Schema
        let schema = Schema::new();
        db.put(b"schema", json::encode(&schema).unwrap().as_bytes());

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn open(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        let db = try!(DB::open(&opts, path));

        let schema = match db.get(b"schema") {
            Ok(Some(schema)) => {
                let schema = schema.to_utf8().unwrap().to_string();
                json::decode(&schema).unwrap()
            }
            Ok(None) => Schema::new(),  // TODO: error
            Err(_) => Schema::new(),  // TODO: error
        };

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn add_field(&mut self, name: String, field_type: FieldType) -> Result<FieldRef, AddFieldError> {
        let mut schema_copy = (*self.schema).clone();
        let field_ref = try!(schema_copy.add_field(name, field_type));
        self.schema = Arc::new(schema_copy);

        self.db.put(b"schema", json::encode(&self.schema).unwrap().as_bytes());

        Ok(field_ref)
    }
}

#[cfg(test)]
mod tests {
    use rocksdb::{DB, Options};

    use super::RocksDBIndexStore;

    #[test]
    fn test_create() {
        let store = RocksDBIndexStore::create("test_indices/test_create");
        assert!(store.is_ok());
    }

    #[test]
    fn test_open() {
        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_err());

        // Create DB
        let mut opts = Options::default();
        opts.create_if_missing(true);
        DB::open(&opts, "test_indices/test_open").unwrap();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_ok());
    }
}
<commit_msg>Delete test_indices between each test run<commit_after>extern crate abra;
extern crate rocksdb;
extern crate rustc_serialize;

use std::sync::Arc;

use rocksdb::{DB, Writable, Options};
use abra::schema::{Schema, FieldType, FieldRef, AddFieldError};
use rustc_serialize::{json, Encodable};

pub struct RocksDBIndexStore {
    schema: Arc<Schema>,
    db: DB,
}

impl RocksDBIndexStore {
    pub fn create(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        let db = try!(DB::open(&opts, path));

        // Schema
        let schema = Schema::new();
        db.put(b"schema", json::encode(&schema).unwrap().as_bytes());

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn open(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        let db = try!(DB::open(&opts, path));

        let schema = match db.get(b"schema") {
            Ok(Some(schema)) => {
                let schema = schema.to_utf8().unwrap().to_string();
                json::decode(&schema).unwrap()
            }
            Ok(None) => Schema::new(),  // TODO: error
            Err(_) => Schema::new(),  // TODO: error
        };

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn add_field(&mut self, name: String, field_type: FieldType) -> Result<FieldRef, AddFieldError> {
        let mut schema_copy = (*self.schema).clone();
        let field_ref = try!(schema_copy.add_field(name, field_type));
        self.schema = Arc::new(schema_copy);

        self.db.put(b"schema", json::encode(&self.schema).unwrap().as_bytes());

        Ok(field_ref)
    }
}

#[cfg(test)]
mod tests {
    use rocksdb::{DB, Options};

    use super::RocksDBIndexStore;

    fn clean_test_indices() {
        use std::fs::remove_dir_all;

        remove_dir_all("test_indices");
    }

    #[test]
    fn test_create() {
        clean_test_indices();

        let store = RocksDBIndexStore::create("test_indices/test_create");
        assert!(store.is_ok());
    }

    #[test]
    fn test_open() {
        clean_test_indices();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_err());

        // Create DB
        let mut opts = Options::default();
        opts.create_if_missing(true);
        DB::open(&opts, "test_indices/test_open").unwrap();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_ok());
    }
}
<|endoftext|>