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

use std::{fmt, sync::Arc, time};

use ra_db::{
    salsa::{Database, Durability, SweepStrategy},
    CrateGraph, CrateId, FileId, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot,
    SourceRootId,
};
use ra_prof::{memory_usage, profile, Bytes};
use ra_syntax::SourceFile;
#[cfg(not(feature = "wasm"))]
use rayon::prelude::*;
use rustc_hash::FxHashMap;

use crate::{
    db::{DebugData, RootDatabase},
    symbol_index::{SymbolIndex, SymbolsDatabase},
};

#[derive(Default)]
pub struct AnalysisChange {
    new_roots: Vec<(SourceRootId, bool)>,
    roots_changed: FxHashMap<SourceRootId, RootChange>,
    files_changed: Vec<(FileId, Arc<String>)>,
    libraries_added: Vec<LibraryData>,
    crate_graph: Option<CrateGraph>,
    debug_data: DebugData,
}

impl fmt::Debug for AnalysisChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut d = fmt.debug_struct("AnalysisChange");
        if !self.new_roots.is_empty() {
            d.field("new_roots", &self.new_roots);
        }
        if !self.roots_changed.is_empty() {
            d.field("roots_changed", &self.roots_changed);
        }
        if !self.files_changed.is_empty() {
            d.field("files_changed", &self.files_changed.len());
        }
        if !self.libraries_added.is_empty() {
            d.field("libraries_added", &self.libraries_added.len());
        }
        if !self.crate_graph.is_none() {
            d.field("crate_graph", &self.crate_graph);
        }
        d.finish()
    }
}

impl AnalysisChange {
    pub fn new() -> AnalysisChange {
        AnalysisChange::default()
    }

    pub fn add_root(&mut self, root_id: SourceRootId, is_local: bool) {
        self.new_roots.push((root_id, is_local));
    }

    pub fn add_file(
        &mut self,
        root_id: SourceRootId,
        file_id: FileId,
        path: RelativePathBuf,
        text: Arc<String>,
    ) {
        let file = AddFile { file_id, path, text };
        self.roots_changed.entry(root_id).or_default().added.push(file);
    }

    pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) {
        self.files_changed.push((file_id, new_text))
    }

    pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) {
        let file = RemoveFile { file_id, path };
        self.roots_changed.entry(root_id).or_default().removed.push(file);
    }

    pub fn add_library(&mut self, data: LibraryData) {
        self.libraries_added.push(data)
    }

    pub fn set_crate_graph(&mut self, graph: CrateGraph) {
        self.crate_graph = Some(graph);
    }

    pub fn set_debug_crate_name(&mut self, crate_id: CrateId, name: String) {
        self.debug_data.crate_names.insert(crate_id, name);
    }

    pub fn set_debug_root_path(&mut self, source_root_id: SourceRootId, path: String) {
        self.debug_data.root_paths.insert(source_root_id, path);
    }
}

#[derive(Debug)]
struct AddFile {
    file_id: FileId,
    path: RelativePathBuf,
    text: Arc<String>,
}

#[derive(Debug)]
struct RemoveFile {
    file_id: FileId,
    path: RelativePathBuf,
}

#[derive(Default)]
struct RootChange {
    added: Vec<AddFile>,
    removed: Vec<RemoveFile>,
}

impl fmt::Debug for RootChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("AnalysisChange")
            .field("added", &self.added.len())
            .field("removed", &self.removed.len())
            .finish()
    }
}

pub struct LibraryData {
    root_id: SourceRootId,
    root_change: RootChange,
    symbol_index: SymbolIndex,
}

impl fmt::Debug for LibraryData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LibraryData")
            .field("root_id", &self.root_id)
            .field("root_change", &self.root_change)
            .field("n_symbols", &self.symbol_index.len())
            .finish()
    }
}

impl LibraryData {
    pub fn prepare(
        root_id: SourceRootId,
        files: Vec<(FileId, RelativePathBuf, Arc<String>)>,
    ) -> LibraryData {
        #[cfg(not(feature = "wasm"))]
        let iter = files.par_iter();
        #[cfg(feature = "wasm")]
        let iter = files.iter();

        let symbol_index = SymbolIndex::for_files(iter.map(|(file_id, _, text)| {
            let parse = SourceFile::parse(text);
            (*file_id, parse)
        }));
        let mut root_change = RootChange::default();
        root_change.added = files
            .into_iter()
            .map(|(file_id, path, text)| AddFile { file_id, path, text })
            .collect();
        LibraryData { root_id, root_change, symbol_index }
    }
}

const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);

impl RootDatabase {
    pub(crate) fn apply_change(&mut self, change: AnalysisChange) {
        let _p = profile("RootDatabase::apply_change");
        log::info!("apply_change {:?}", change);
        {
            let _p = profile("RootDatabase::apply_change/cancellation");
            self.salsa_runtime_mut().synthetic_write(Durability::LOW);
        }
        if !change.new_roots.is_empty() {
            let mut local_roots = Vec::clone(&self.local_roots());
            for (root_id, is_local) in change.new_roots {
                let root = if is_local { SourceRoot::new() } else { SourceRoot::new_library() };
                let durability = durability(&root);
                self.set_source_root_with_durability(root_id, Arc::new(root), durability);
                if is_local {
                    local_roots.push(root_id);
                }
            }
            self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
        }

        for (root_id, root_change) in change.roots_changed {
            self.apply_root_change(root_id, root_change);
        }
        for (file_id, text) in change.files_changed {
            let source_root_id = self.file_source_root(file_id);
            let source_root = self.source_root(source_root_id);
            let durability = durability(&source_root);
            self.set_file_text_with_durability(file_id, text, durability)
        }
        if !change.libraries_added.is_empty() {
            let mut libraries = Vec::clone(&self.library_roots());
            for library in change.libraries_added {
                libraries.push(library.root_id);
                self.set_source_root_with_durability(
                    library.root_id,
                    Default::default(),
                    Durability::HIGH,
                );
                self.set_library_symbols_with_durability(
                    library.root_id,
                    Arc::new(library.symbol_index),
                    Durability::HIGH,
                );
                self.apply_root_change(library.root_id, library.root_change);
            }
            self.set_library_roots_with_durability(Arc::new(libraries), Durability::HIGH);
        }
        if let Some(crate_graph) = change.crate_graph {
            self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH)
        }

        Arc::make_mut(&mut self.debug_data).merge(change.debug_data)
    }

    fn apply_root_change(&mut self, root_id: SourceRootId, root_change: RootChange) {
        let mut source_root = SourceRoot::clone(&self.source_root(root_id));
        let durability = durability(&source_root);
        for add_file in root_change.added {
            self.set_file_text_with_durability(add_file.file_id, add_file.text, durability);
            self.set_file_relative_path_with_durability(
                add_file.file_id,
                add_file.path.clone(),
                durability,
            );
            self.set_file_source_root_with_durability(add_file.file_id, root_id, durability);
            source_root.insert_file(add_file.path, add_file.file_id);
        }
        for remove_file in root_change.removed {
            self.set_file_text_with_durability(remove_file.file_id, Default::default(), durability);
            source_root.remove_file(&remove_file.path);
        }
        self.set_source_root_with_durability(root_id, Arc::new(source_root), durability);
    }

    pub(crate) fn maybe_collect_garbage(&mut self) {
        if cfg!(feature = "wasm") {
            return;
        }

        if self.last_gc_check.elapsed() > GC_COOLDOWN {
            self.last_gc_check = crate::wasm_shims::Instant::now();
        }
    }

    pub(crate) fn collect_garbage(&mut self) {
        if cfg!(feature = "wasm") {
            return;
        }

        let _p = profile("RootDatabase::collect_garbage");
        self.last_gc = crate::wasm_shims::Instant::now();

        let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();

        self.query(ra_db::ParseQuery).sweep(sweep);
        self.query(hir::db::ParseMacroQuery).sweep(sweep);

        // Macros do take significant space, but less then the syntax trees
        // self.query(hir::db::MacroDefQuery).sweep(sweep);
        // self.query(hir::db::MacroArgQuery).sweep(sweep);
        // self.query(hir::db::MacroExpandQuery).sweep(sweep);

        self.query(hir::db::AstIdMapQuery).sweep(sweep);

        self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep);

        self.query(hir::db::ExprScopesQuery).sweep(sweep);
        self.query(hir::db::DoInferQuery).sweep(sweep);
        self.query(hir::db::BodyQuery).sweep(sweep);
    }

    pub(crate) fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> {
        let mut acc: Vec<(String, Bytes)> = vec![];
        let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
        macro_rules! sweep_each_query {
            ($($q:path)*) => {$(
                let before = memory_usage().allocated;
                self.query($q).sweep(sweep);
                let after = memory_usage().allocated;
                let q: $q = Default::default();
                let name = format!("{:?}", q);
                acc.push((name, before - after));

                let before = memory_usage().allocated;
                self.query($q).sweep(sweep.discard_everything());
                let after = memory_usage().allocated;
                let q: $q = Default::default();
                let name = format!("{:?} (deps)", q);
                acc.push((name, before - after));
            )*}
        }
        sweep_each_query![
            ra_db::ParseQuery
            ra_db::SourceRootCratesQuery
            hir::db::AstIdMapQuery
            hir::db::ParseMacroQuery
            hir::db::MacroDefQuery
            hir::db::MacroArgQuery
            hir::db::MacroExpandQuery
            hir::db::StructDataQuery
            hir::db::EnumDataQuery
            hir::db::TraitDataQuery
            hir::db::RawItemsQuery
            hir::db::ComputeCrateDefMapQuery
            hir::db::GenericParamsQuery
            hir::db::FunctionDataQuery
            hir::db::TypeAliasDataQuery
            hir::db::ConstDataQuery
            hir::db::StaticDataQuery
            hir::db::ModuleLangItemsQuery
            hir::db::CrateLangItemsQuery
            hir::db::LangItemQuery
            hir::db::DocumentationQuery
            hir::db::ExprScopesQuery
            hir::db::DoInferQuery
            hir::db::TyQuery
            hir::db::ValueTyQuery
            hir::db::FieldTypesQuery
            hir::db::CallableItemSignatureQuery
            hir::db::GenericPredicatesQuery
            hir::db::GenericDefaultsQuery
            hir::db::BodyWithSourceMapQuery
            hir::db::BodyQuery
            hir::db::ImplsInCrateQuery
            hir::db::ImplsForTraitQuery
            hir::db::AssociatedTyDataQuery
            hir::db::TraitDatumQuery
            hir::db::StructDatumQuery
            hir::db::ImplDatumQuery
            hir::db::ImplDataQuery
            hir::db::TraitSolveQuery
        ];
        acc.sort_by_key(|it| std::cmp::Reverse(it.1));
        acc
    }
}

fn durability(source_root: &SourceRoot) -> Durability {
    if source_root.is_library {
        Durability::HIGH
    } else {
        Durability::LOW
    }
}
<commit_msg>Fix a problem with `Durability` of libraries<commit_after>//! FIXME: write short doc here

use std::{fmt, sync::Arc, time};

use ra_db::{
    salsa::{Database, Durability, SweepStrategy},
    CrateGraph, CrateId, FileId, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot,
    SourceRootId,
};
use ra_prof::{memory_usage, profile, Bytes};
use ra_syntax::SourceFile;
#[cfg(not(feature = "wasm"))]
use rayon::prelude::*;
use rustc_hash::FxHashMap;

use crate::{
    db::{DebugData, RootDatabase},
    symbol_index::{SymbolIndex, SymbolsDatabase},
};

#[derive(Default)]
pub struct AnalysisChange {
    new_roots: Vec<(SourceRootId, bool)>,
    roots_changed: FxHashMap<SourceRootId, RootChange>,
    files_changed: Vec<(FileId, Arc<String>)>,
    libraries_added: Vec<LibraryData>,
    crate_graph: Option<CrateGraph>,
    debug_data: DebugData,
}

impl fmt::Debug for AnalysisChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut d = fmt.debug_struct("AnalysisChange");
        if !self.new_roots.is_empty() {
            d.field("new_roots", &self.new_roots);
        }
        if !self.roots_changed.is_empty() {
            d.field("roots_changed", &self.roots_changed);
        }
        if !self.files_changed.is_empty() {
            d.field("files_changed", &self.files_changed.len());
        }
        if !self.libraries_added.is_empty() {
            d.field("libraries_added", &self.libraries_added.len());
        }
        if !self.crate_graph.is_none() {
            d.field("crate_graph", &self.crate_graph);
        }
        d.finish()
    }
}

impl AnalysisChange {
    pub fn new() -> AnalysisChange {
        AnalysisChange::default()
    }

    pub fn add_root(&mut self, root_id: SourceRootId, is_local: bool) {
        self.new_roots.push((root_id, is_local));
    }

    pub fn add_file(
        &mut self,
        root_id: SourceRootId,
        file_id: FileId,
        path: RelativePathBuf,
        text: Arc<String>,
    ) {
        let file = AddFile { file_id, path, text };
        self.roots_changed.entry(root_id).or_default().added.push(file);
    }

    pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) {
        self.files_changed.push((file_id, new_text))
    }

    pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) {
        let file = RemoveFile { file_id, path };
        self.roots_changed.entry(root_id).or_default().removed.push(file);
    }

    pub fn add_library(&mut self, data: LibraryData) {
        self.libraries_added.push(data)
    }

    pub fn set_crate_graph(&mut self, graph: CrateGraph) {
        self.crate_graph = Some(graph);
    }

    pub fn set_debug_crate_name(&mut self, crate_id: CrateId, name: String) {
        self.debug_data.crate_names.insert(crate_id, name);
    }

    pub fn set_debug_root_path(&mut self, source_root_id: SourceRootId, path: String) {
        self.debug_data.root_paths.insert(source_root_id, path);
    }
}

#[derive(Debug)]
struct AddFile {
    file_id: FileId,
    path: RelativePathBuf,
    text: Arc<String>,
}

#[derive(Debug)]
struct RemoveFile {
    file_id: FileId,
    path: RelativePathBuf,
}

#[derive(Default)]
struct RootChange {
    added: Vec<AddFile>,
    removed: Vec<RemoveFile>,
}

impl fmt::Debug for RootChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("AnalysisChange")
            .field("added", &self.added.len())
            .field("removed", &self.removed.len())
            .finish()
    }
}

pub struct LibraryData {
    root_id: SourceRootId,
    root_change: RootChange,
    symbol_index: SymbolIndex,
}

impl fmt::Debug for LibraryData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LibraryData")
            .field("root_id", &self.root_id)
            .field("root_change", &self.root_change)
            .field("n_symbols", &self.symbol_index.len())
            .finish()
    }
}

impl LibraryData {
    pub fn prepare(
        root_id: SourceRootId,
        files: Vec<(FileId, RelativePathBuf, Arc<String>)>,
    ) -> LibraryData {
        #[cfg(not(feature = "wasm"))]
        let iter = files.par_iter();
        #[cfg(feature = "wasm")]
        let iter = files.iter();

        let symbol_index = SymbolIndex::for_files(iter.map(|(file_id, _, text)| {
            let parse = SourceFile::parse(text);
            (*file_id, parse)
        }));
        let mut root_change = RootChange::default();
        root_change.added = files
            .into_iter()
            .map(|(file_id, path, text)| AddFile { file_id, path, text })
            .collect();
        LibraryData { root_id, root_change, symbol_index }
    }
}

const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);

impl RootDatabase {
    pub(crate) fn apply_change(&mut self, change: AnalysisChange) {
        let _p = profile("RootDatabase::apply_change");
        log::info!("apply_change {:?}", change);
        {
            let _p = profile("RootDatabase::apply_change/cancellation");
            self.salsa_runtime_mut().synthetic_write(Durability::LOW);
        }
        if !change.new_roots.is_empty() {
            let mut local_roots = Vec::clone(&self.local_roots());
            for (root_id, is_local) in change.new_roots {
                let root = if is_local { SourceRoot::new() } else { SourceRoot::new_library() };
                let durability = durability(&root);
                self.set_source_root_with_durability(root_id, Arc::new(root), durability);
                if is_local {
                    local_roots.push(root_id);
                }
            }
            self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
        }

        for (root_id, root_change) in change.roots_changed {
            self.apply_root_change(root_id, root_change);
        }
        for (file_id, text) in change.files_changed {
            let source_root_id = self.file_source_root(file_id);
            let source_root = self.source_root(source_root_id);
            let durability = durability(&source_root);
            self.set_file_text_with_durability(file_id, text, durability)
        }
        if !change.libraries_added.is_empty() {
            let mut libraries = Vec::clone(&self.library_roots());
            for library in change.libraries_added {
                libraries.push(library.root_id);
                self.set_source_root_with_durability(
                    library.root_id,
                    Arc::new(SourceRoot::new_library()),
                    Durability::HIGH,
                );
                self.set_library_symbols_with_durability(
                    library.root_id,
                    Arc::new(library.symbol_index),
                    Durability::HIGH,
                );
                self.apply_root_change(library.root_id, library.root_change);
            }
            self.set_library_roots_with_durability(Arc::new(libraries), Durability::HIGH);
        }
        if let Some(crate_graph) = change.crate_graph {
            self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH)
        }

        Arc::make_mut(&mut self.debug_data).merge(change.debug_data)
    }

    fn apply_root_change(&mut self, root_id: SourceRootId, root_change: RootChange) {
        let mut source_root = SourceRoot::clone(&self.source_root(root_id));
        let durability = durability(&source_root);
        for add_file in root_change.added {
            self.set_file_text_with_durability(add_file.file_id, add_file.text, durability);
            self.set_file_relative_path_with_durability(
                add_file.file_id,
                add_file.path.clone(),
                durability,
            );
            self.set_file_source_root_with_durability(add_file.file_id, root_id, durability);
            source_root.insert_file(add_file.path, add_file.file_id);
        }
        for remove_file in root_change.removed {
            self.set_file_text_with_durability(remove_file.file_id, Default::default(), durability);
            source_root.remove_file(&remove_file.path);
        }
        self.set_source_root_with_durability(root_id, Arc::new(source_root), durability);
    }

    pub(crate) fn maybe_collect_garbage(&mut self) {
        if cfg!(feature = "wasm") {
            return;
        }

        if self.last_gc_check.elapsed() > GC_COOLDOWN {
            self.last_gc_check = crate::wasm_shims::Instant::now();
        }
    }

    pub(crate) fn collect_garbage(&mut self) {
        if cfg!(feature = "wasm") {
            return;
        }

        let _p = profile("RootDatabase::collect_garbage");
        self.last_gc = crate::wasm_shims::Instant::now();

        let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();

        self.query(ra_db::ParseQuery).sweep(sweep);
        self.query(hir::db::ParseMacroQuery).sweep(sweep);

        // Macros do take significant space, but less then the syntax trees
        // self.query(hir::db::MacroDefQuery).sweep(sweep);
        // self.query(hir::db::MacroArgQuery).sweep(sweep);
        // self.query(hir::db::MacroExpandQuery).sweep(sweep);

        self.query(hir::db::AstIdMapQuery).sweep(sweep);

        self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep);

        self.query(hir::db::ExprScopesQuery).sweep(sweep);
        self.query(hir::db::DoInferQuery).sweep(sweep);
        self.query(hir::db::BodyQuery).sweep(sweep);
    }

    pub(crate) fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> {
        let mut acc: Vec<(String, Bytes)> = vec![];
        let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
        macro_rules! sweep_each_query {
            ($($q:path)*) => {$(
                let before = memory_usage().allocated;
                self.query($q).sweep(sweep);
                let after = memory_usage().allocated;
                let q: $q = Default::default();
                let name = format!("{:?}", q);
                acc.push((name, before - after));

                let before = memory_usage().allocated;
                self.query($q).sweep(sweep.discard_everything());
                let after = memory_usage().allocated;
                let q: $q = Default::default();
                let name = format!("{:?} (deps)", q);
                acc.push((name, before - after));
            )*}
        }
        sweep_each_query![
            ra_db::ParseQuery
            ra_db::SourceRootCratesQuery
            hir::db::AstIdMapQuery
            hir::db::ParseMacroQuery
            hir::db::MacroDefQuery
            hir::db::MacroArgQuery
            hir::db::MacroExpandQuery
            hir::db::StructDataQuery
            hir::db::EnumDataQuery
            hir::db::TraitDataQuery
            hir::db::RawItemsQuery
            hir::db::ComputeCrateDefMapQuery
            hir::db::GenericParamsQuery
            hir::db::FunctionDataQuery
            hir::db::TypeAliasDataQuery
            hir::db::ConstDataQuery
            hir::db::StaticDataQuery
            hir::db::ModuleLangItemsQuery
            hir::db::CrateLangItemsQuery
            hir::db::LangItemQuery
            hir::db::DocumentationQuery
            hir::db::ExprScopesQuery
            hir::db::DoInferQuery
            hir::db::TyQuery
            hir::db::ValueTyQuery
            hir::db::FieldTypesQuery
            hir::db::CallableItemSignatureQuery
            hir::db::GenericPredicatesQuery
            hir::db::GenericDefaultsQuery
            hir::db::BodyWithSourceMapQuery
            hir::db::BodyQuery
            hir::db::ImplsInCrateQuery
            hir::db::ImplsForTraitQuery
            hir::db::AssociatedTyDataQuery
            hir::db::TraitDatumQuery
            hir::db::StructDatumQuery
            hir::db::ImplDatumQuery
            hir::db::ImplDataQuery
            hir::db::TraitSolveQuery
        ];
        acc.sort_by_key(|it| std::cmp::Reverse(it.1));
        acc
    }
}

fn durability(source_root: &SourceRoot) -> Durability {
    if source_root.is_library {
        Durability::HIGH
    } else {
        Durability::LOW
    }
}
<|endoftext|>


<commit_before>//! Defines the `IntoIter` owned iterator for arrays.

use crate::{
    fmt,
    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
    mem::{self, MaybeUninit},
    ops::Range,
    ptr,
};
use super::LengthAtMost32;

/// A by-value [array] iterator.
///
/// [array]: ../../std/primitive.array.html
#[unstable(feature = "array_value_iter", issue = "65798")]
pub struct IntoIter<T, const N: usize>
where
    [T; N]: LengthAtMost32,
{
    /// This is the array we are iterating over.
    ///
    /// Elements with index `i` where `alive.start <= i < alive.end` have not
    /// been yielded yet and are valid array entries. Elements with indices `i
    /// < alive.start` or `i >= alive.end` have been yielded already and must
    /// not be accessed anymore! Those dead elements might even be in a
    /// completely uninitialized state!
    ///
    /// So the invariants are:
    /// - `data[alive]` is alive (i.e. contains valid elements)
    /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
    ///   elements were already read and must not be touched anymore!)
    data: [MaybeUninit<T>; N],

    /// The elements in `data` that have not been yielded yet.
    ///
    /// Invariants:
    /// - `alive.start <= alive.end`
    /// - `alive.end <= N`
    alive: Range<usize>,
}

impl<T, const N: usize> IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    /// Creates a new iterator over the given `array`.
    ///
    /// *Note*: this method might never get stabilized and/or removed in the
    /// future as there will likely be another, preferred way of obtaining this
    /// iterator (either via `IntoIterator` for arrays or via another way).
    #[unstable(feature = "array_value_iter", issue = "65798")]
    pub fn new(array: [T; N]) -> Self {
        // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
        // promise:
        //
        // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
        // > as `T`.
        //
        // The docs even show a transmute from an array of `MaybeUninit<T>` to
        // an array of `T`.
        //
        // With that, this initialization satisfies the invariants.

        // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
        // works with const generics:
        //     `mem::transmute::<[T; {N}], [MaybeUninit<T>; {N}]>(array)`
        //
        // Until then, we do it manually here. We first create a bitwise copy
        // but cast the pointer so that it is treated as a different type. Then
        // we forget `array` so that it is not dropped.
        let data = unsafe {
            let data = ptr::read(&array as *const [T; N] as *const [MaybeUninit<T>; N]);
            mem::forget(array);
            data
        };

        Self {
            data,
            alive: 0..N,
        }
    }

    /// Returns an immutable slice of all elements that have not been yielded
    /// yet.
    fn as_slice(&self) -> &[T] {
        let slice = &self.data[self.alive.clone()];
        // SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
        // the size and alignment of `T`. Furthermore, we know that all
        // elements within `alive` are properly initialized.
        unsafe {
            mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Iterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        if self.alive.start == self.alive.end {
            return None;
        }

        // Bump start index.
        //
        // From the check above we know that `alive.start != alive.end`.
        // Combine this with the invariant `alive.start <= alive.end`, we know
        // that `alive.start < alive.end`. Increasing `alive.start` by 1
        // maintains the invariant regarding `alive`. However, due to this
        // change, for a short time, the alive zone is not `data[alive]`
        // anymore, but `data[idx..alive.end]`.
        let idx = self.alive.start;
        self.alive.start += 1;

        // Read the element from the array.
        // SAFETY: This is safe: `idx` is an index
        // into the "alive" region of the array. Reading this element means
        // that `data[idx]` is regarded as dead now (i.e. do not touch). As
        // `idx` was the start of the alive-zone, the alive zone is now
        // `data[alive]` again, restoring all invariants.
        let out = unsafe { self.data.get_unchecked(idx).read() };

        Some(out)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len();
        (len, Some(len))
    }

    fn count(self) -> usize {
        self.len()
    }

    fn last(mut self) -> Option<Self::Item> {
        self.next_back()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.alive.start == self.alive.end {
            return None;
        }

        // Decrease end index.
        //
        // From the check above we know that `alive.start != alive.end`.
        // Combine this with the invariant `alive.start <= alive.end`, we know
        // that `alive.start < alive.end`. As `alive.start` cannot be negative,
        // `alive.end` is at least 1, meaning that we can safely decrement it
        // by one. This also maintains the invariant `alive.start <=
        // alive.end`. However, due to this change, for a short time, the alive
        // zone is not `data[alive]` anymore, but `data[alive.start..alive.end
        // + 1]`.
        self.alive.end -= 1;

        // Read the element from the array.
        // SAFETY: This is safe: `alive.end` is an
        // index into the "alive" region of the array. Compare the previous
        // comment that states that the alive region is
        // `data[alive.start..alive.end + 1]`. Reading this element means that
        // `data[alive.end]` is regarded as dead now (i.e. do not touch). As
        // `alive.end` was the end of the alive-zone, the alive zone is now
        // `data[alive]` again, restoring all invariants.
        let out = unsafe { self.data.get_unchecked(self.alive.end).read() };

        Some(out)
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Drop for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn drop(&mut self) {
        // We simply drop each element via `for_each`. This should not incur
        // any significant runtime overhead and avoids adding another `unsafe`
        // block.
        self.by_ref().for_each(drop);
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn len(&self) -> usize {
        // Will never underflow due to the invariant `alive.start <=
        // alive.end`.
        self.alive.end - self.alive.start
    }
    fn is_empty(&self) -> bool {
        self.alive.is_empty()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> FusedIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{}

// The iterator indeed reports the correct length. The number of "alive"
// elements (that will still be yielded) is the length of the range `alive`.
// This range is decremented in length in either `next` or `next_back`. It is
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn clone(&self) -> Self {
        // SAFETY: each point of unsafety is documented inside the unsafe block
        unsafe {
            // This creates a new uninitialized array. Note that the `assume_init`
            // refers to the array, not the individual elements. And it is Ok if
            // the array is in an uninitialized state as all elements may be
            // uninitialized (all bit patterns are valid). Compare the
            // `MaybeUninit` docs for more information.
            let mut new_data: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init();

            // Clone all alive elements.
            for idx in self.alive.clone() {
                // The element at `idx` in the old array is alive, so we can
                // safely call `get_ref()`. We then clone it, and write the
                // clone into the new array.
                let clone = self.data.get_unchecked(idx).get_ref().clone();
                new_data.get_unchecked_mut(idx).write(clone);
            }

            Self {
                data: new_data,
                alive: self.alive.clone(),
            }
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Only print the elements that were not yielded yet: we cannot
        // access the yielded elements anymore.
        f.debug_tuple("IntoIter")
            .field(&self.as_slice())
            .finish()
    }
}
<commit_msg>Use `drop_in_place` in `array::IntoIter::drop`<commit_after>//! Defines the `IntoIter` owned iterator for arrays.

use crate::{
    fmt,
    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
    mem::{self, MaybeUninit},
    ops::Range,
    ptr,
};
use super::LengthAtMost32;

/// A by-value [array] iterator.
///
/// [array]: ../../std/primitive.array.html
#[unstable(feature = "array_value_iter", issue = "65798")]
pub struct IntoIter<T, const N: usize>
where
    [T; N]: LengthAtMost32,
{
    /// This is the array we are iterating over.
    ///
    /// Elements with index `i` where `alive.start <= i < alive.end` have not
    /// been yielded yet and are valid array entries. Elements with indices `i
    /// < alive.start` or `i >= alive.end` have been yielded already and must
    /// not be accessed anymore! Those dead elements might even be in a
    /// completely uninitialized state!
    ///
    /// So the invariants are:
    /// - `data[alive]` is alive (i.e. contains valid elements)
    /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
    ///   elements were already read and must not be touched anymore!)
    data: [MaybeUninit<T>; N],

    /// The elements in `data` that have not been yielded yet.
    ///
    /// Invariants:
    /// - `alive.start <= alive.end`
    /// - `alive.end <= N`
    alive: Range<usize>,
}

impl<T, const N: usize> IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    /// Creates a new iterator over the given `array`.
    ///
    /// *Note*: this method might never get stabilized and/or removed in the
    /// future as there will likely be another, preferred way of obtaining this
    /// iterator (either via `IntoIterator` for arrays or via another way).
    #[unstable(feature = "array_value_iter", issue = "65798")]
    pub fn new(array: [T; N]) -> Self {
        // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
        // promise:
        //
        // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
        // > as `T`.
        //
        // The docs even show a transmute from an array of `MaybeUninit<T>` to
        // an array of `T`.
        //
        // With that, this initialization satisfies the invariants.

        // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
        // works with const generics:
        //     `mem::transmute::<[T; {N}], [MaybeUninit<T>; {N}]>(array)`
        //
        // Until then, we do it manually here. We first create a bitwise copy
        // but cast the pointer so that it is treated as a different type. Then
        // we forget `array` so that it is not dropped.
        let data = unsafe {
            let data = ptr::read(&array as *const [T; N] as *const [MaybeUninit<T>; N]);
            mem::forget(array);
            data
        };

        Self {
            data,
            alive: 0..N,
        }
    }

    /// Returns an immutable slice of all elements that have not been yielded
    /// yet.
    fn as_slice(&self) -> &[T] {
        let slice = &self.data[self.alive.clone()];
        // SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
        // the size and alignment of `T`. Furthermore, we know that all
        // elements within `alive` are properly initialized.
        unsafe {
            mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
        }
    }

    /// Returns a mutable slice of all elements that have not been yielded yet.
    fn as_mut_slice(&mut self) -> &mut [T] {
        // This transmute is safe, same as in `as_slice` above.
        let slice = &mut self.data[self.alive.clone()];
        // SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
        // the size and alignment of `T`. Furthermore, we know that all
        // elements within `alive` are properly initialized.
        unsafe {
            mem::transmute::<&mut [MaybeUninit<T>], &mut [T]>(slice)
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Iterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        if self.alive.start == self.alive.end {
            return None;
        }

        // Bump start index.
        //
        // From the check above we know that `alive.start != alive.end`.
        // Combine this with the invariant `alive.start <= alive.end`, we know
        // that `alive.start < alive.end`. Increasing `alive.start` by 1
        // maintains the invariant regarding `alive`. However, due to this
        // change, for a short time, the alive zone is not `data[alive]`
        // anymore, but `data[idx..alive.end]`.
        let idx = self.alive.start;
        self.alive.start += 1;

        // Read the element from the array.
        // SAFETY: This is safe: `idx` is an index
        // into the "alive" region of the array. Reading this element means
        // that `data[idx]` is regarded as dead now (i.e. do not touch). As
        // `idx` was the start of the alive-zone, the alive zone is now
        // `data[alive]` again, restoring all invariants.
        let out = unsafe { self.data.get_unchecked(idx).read() };

        Some(out)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len();
        (len, Some(len))
    }

    fn count(self) -> usize {
        self.len()
    }

    fn last(mut self) -> Option<Self::Item> {
        self.next_back()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.alive.start == self.alive.end {
            return None;
        }

        // Decrease end index.
        //
        // From the check above we know that `alive.start != alive.end`.
        // Combine this with the invariant `alive.start <= alive.end`, we know
        // that `alive.start < alive.end`. As `alive.start` cannot be negative,
        // `alive.end` is at least 1, meaning that we can safely decrement it
        // by one. This also maintains the invariant `alive.start <=
        // alive.end`. However, due to this change, for a short time, the alive
        // zone is not `data[alive]` anymore, but `data[alive.start..alive.end
        // + 1]`.
        self.alive.end -= 1;

        // Read the element from the array.
        // SAFETY: This is safe: `alive.end` is an
        // index into the "alive" region of the array. Compare the previous
        // comment that states that the alive region is
        // `data[alive.start..alive.end + 1]`. Reading this element means that
        // `data[alive.end]` is regarded as dead now (i.e. do not touch). As
        // `alive.end` was the end of the alive-zone, the alive zone is now
        // `data[alive]` again, restoring all invariants.
        let out = unsafe { self.data.get_unchecked(self.alive.end).read() };

        Some(out)
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Drop for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn drop(&mut self) {
        // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
        // of elements that have not been moved out yet and that remain
        // to be dropped.
        unsafe {
            ptr::drop_in_place(self.as_mut_slice())
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn len(&self) -> usize {
        // Will never underflow due to the invariant `alive.start <=
        // alive.end`.
        self.alive.end - self.alive.start
    }
    fn is_empty(&self) -> bool {
        self.alive.is_empty()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> FusedIterator for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{}

// The iterator indeed reports the correct length. The number of "alive"
// elements (that will still be yielded) is the length of the range `alive`.
// This range is decremented in length in either `next` or `next_back`. It is
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn clone(&self) -> Self {
        // SAFETY: each point of unsafety is documented inside the unsafe block
        unsafe {
            // This creates a new uninitialized array. Note that the `assume_init`
            // refers to the array, not the individual elements. And it is Ok if
            // the array is in an uninitialized state as all elements may be
            // uninitialized (all bit patterns are valid). Compare the
            // `MaybeUninit` docs for more information.
            let mut new_data: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init();

            // Clone all alive elements.
            for idx in self.alive.clone() {
                // The element at `idx` in the old array is alive, so we can
                // safely call `get_ref()`. We then clone it, and write the
                // clone into the new array.
                let clone = self.data.get_unchecked(idx).get_ref().clone();
                new_data.get_unchecked_mut(idx).write(clone);
            }

            Self {
                data: new_data,
                alive: self.alive.clone(),
            }
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, {N}>
where
    [T; N]: LengthAtMost32,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Only print the elements that were not yielded yet: we cannot
        // access the yielded elements anymore.
        f.debug_tuple("IntoIter")
            .field(&self.as_slice())
            .finish()
    }
}
<|endoftext|>


<commit_before>use crate::convert::From;
use crate::ops::{CoerceUnsized, DispatchFromDyn};
use crate::fmt;
use crate::marker::{PhantomData, Unsize};
use crate::mem;
use crate::ptr::NonNull;

/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
/// of this wrapper owns the referent. Useful for building abstractions like
/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
///
/// Unlike `*mut T`, `Unique<T>` behaves "as if" it were an instance of `T`.
/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies
/// the kind of strong aliasing guarantees an instance of `T` can expect:
/// the referent of the pointer should not be modified without a unique path to
/// its owning Unique.
///
/// If you're uncertain of whether it's correct to use `Unique` for your purposes,
/// consider using `NonNull`, which has weaker semantics.
///
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
/// is never dereferenced. This is so that enums may use this forbidden value
/// as a discriminant -- `Option<Unique<T>>` has the same size as `Unique<T>`.
/// However the pointer may still dangle if it isn't dereferenced.
///
/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
/// for any type which upholds Unique's aliasing requirements.
#[unstable(feature = "ptr_internals", issue = "0",
           reason = "use `NonNull` instead and consider `PhantomData<T>` \
                     (if you also use `#[may_dangle]`), `Send`, and/or `Sync`")]
#[doc(hidden)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
pub struct Unique<T: ?Sized> {
    pointer: *const T,
    // NOTE: this marker has no consequences for variance, but is necessary
    // for dropck to understand that we logically own a `T`.
    //
    // For details, see:
    // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
    _marker: PhantomData<T>,
}

/// `Unique` pointers are `Send` if `T` is `Send` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable(feature = "ptr_internals", issue = "0")]
unsafe impl<T: Send + ?Sized> Send for Unique<T> { }

/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable(feature = "ptr_internals", issue = "0")]
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: Sized> Unique<T> {
    /// Creates a new `Unique` that is dangling, but well-aligned.
    ///
    /// This is useful for initializing types which lazily allocate, like
    /// `Vec::new` does.
    ///
    /// Note that the pointer value may potentially represent a valid pointer to
    /// a `T`, which means this must not be used as a "not yet initialized"
    /// sentinel value. Types that lazily allocate must track initialization by
    /// some other means.
    // FIXME: rename to dangling() to match NonNull?
    #[inline]
    pub const fn empty() -> Self {
        unsafe {
            Unique::new_unchecked(mem::align_of::<T>() as *mut T)
        }
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> Unique<T> {
    /// Creates a new `Unique`.
    ///
    /// # Safety
    ///
    /// `ptr` must be non-null.
    #[inline]
    pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
        Unique { pointer: ptr as _, _marker: PhantomData }
    }

    /// Creates a new `Unique` if `ptr` is non-null.
    #[inline]
    pub fn new(ptr: *mut T) -> Option<Self> {
        if !ptr.is_null() {
            Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
        } else {
            None
        }
    }

    /// Acquires the underlying `*mut` pointer.
    #[inline]
    pub const fn as_ptr(self) -> *mut T {
        self.pointer as *mut T
    }

    /// Dereferences the content.
    ///
    /// The resulting lifetime is bound to self so this behaves "as if"
    /// it were actually an instance of T that is getting borrowed. If a longer
    /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
    #[inline]
    pub unsafe fn as_ref(&self) -> &T {
        &*self.as_ptr()
    }

    /// Mutably dereferences the content.
    ///
    /// The resulting lifetime is bound to self so this behaves "as if"
    /// it were actually an instance of T that is getting borrowed. If a longer
    /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
    #[inline]
    pub unsafe fn as_mut(&mut self) -> &mut T {
        &mut *self.as_ptr()
    }

    /// Casts to a pointer of another type
    #[inline]
    pub const fn cast<U>(self) -> Unique<U> {
        unsafe {
            Unique::new_unchecked(self.as_ptr() as *mut U)
        }
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> Clone for Unique<T> {
    #[inline]
    fn clone(&self) -> Self {
        *self
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> Copy for Unique<T> { }

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> { }

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> fmt::Debug for Unique<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Pointer::fmt(&self.as_ptr(), f)
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> fmt::Pointer for Unique<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Pointer::fmt(&self.as_ptr(), f)
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> From<&mut T> for Unique<T> {
    #[inline]
    fn from(reference: &mut T) -> Self {
        unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> From<&T> for Unique<T> {
    #[inline]
    fn from(reference: &T) -> Self {
        unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } }
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> From<NonNull<T>> for Unique<T> {
    #[inline]
    fn from(p: NonNull<T>) -> Self {
        unsafe { Unique::new_unchecked(p.as_ptr()) }
    }
}
<commit_msg>Doc nit<commit_after>use crate::convert::From;
use crate::ops::{CoerceUnsized, DispatchFromDyn};
use crate::fmt;
use crate::marker::{PhantomData, Unsize};
use crate::mem;
use crate::ptr::NonNull;

/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
/// of this wrapper owns the referent. Useful for building abstractions like
/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
///
/// Unlike `*mut T`, `Unique<T>` behaves "as if" it were an instance of `T`.
/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies
/// the kind of strong aliasing guarantees an instance of `T` can expect:
/// the referent of the pointer should not be modified without a unique path to
/// its owning Unique.
///
/// If you're uncertain of whether it's correct to use `Unique` for your purposes,
/// consider using `NonNull`, which has weaker semantics.
///
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
/// is never dereferenced. This is so that enums may use this forbidden value
/// as a discriminant -- `Option<Unique<T>>` has the same size as `Unique<T>`.
/// However the pointer may still dangle if it isn't dereferenced.
///
/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
/// for any type which upholds Unique's aliasing requirements.
#[unstable(feature = "ptr_internals", issue = "0",
           reason = "use `NonNull` instead and consider `PhantomData<T>` \
                     (if you also use `#[may_dangle]`), `Send`, and/or `Sync`")]
#[doc(hidden)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
pub struct Unique<T: ?Sized> {
    pointer: *const T,
    // NOTE: this marker has no consequences for variance, but is necessary
    // for dropck to understand that we logically own a `T`.
    //
    // For details, see:
    // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
    _marker: PhantomData<T>,
}

/// `Unique` pointers are `Send` if `T` is `Send` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable(feature = "ptr_internals", issue = "0")]
unsafe impl<T: Send + ?Sized> Send for Unique<T> { }

/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable(feature = "ptr_internals", issue = "0")]
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: Sized> Unique<T> {
    /// Creates a new `Unique` that is dangling, but well-aligned.
    ///
    /// This is useful for initializing types which lazily allocate, like
    /// `Vec::new` does.
    ///
    /// Note that the pointer value may potentially represent a valid pointer to
    /// a `T`, which means this must not be used as a "not yet initialized"
    /// sentinel value. Types that lazily allocate must track initialization by
    /// some other means.
    // FIXME: rename to dangling() to match NonNull?
    #[inline]
    pub const fn empty() -> Self {
        unsafe {
            Unique::new_unchecked(mem::align_of::<T>() as *mut T)
        }
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> Unique<T> {
    /// Creates a new `Unique`.
    ///
    /// # Safety
    ///
    /// `ptr` must be non-null.
    #[inline]
    pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
        Unique { pointer: ptr as _, _marker: PhantomData }
    }

    /// Creates a new `Unique` if `ptr` is non-null.
    #[inline]
    pub fn new(ptr: *mut T) -> Option<Self> {
        if !ptr.is_null() {
            Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
        } else {
            None
        }
    }

    /// Acquires the underlying `*mut` pointer.
    #[inline]
    pub const fn as_ptr(self) -> *mut T {
        self.pointer as *mut T
    }

    /// Dereferences the content.
    ///
    /// The resulting lifetime is bound to self so this behaves "as if"
    /// it were actually an instance of T that is getting borrowed. If a longer
    /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
    #[inline]
    pub unsafe fn as_ref(&self) -> &T {
        &*self.as_ptr()
    }

    /// Mutably dereferences the content.
    ///
    /// The resulting lifetime is bound to self so this behaves "as if"
    /// it were actually an instance of T that is getting borrowed. If a longer
    /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
    #[inline]
    pub unsafe fn as_mut(&mut self) -> &mut T {
        &mut *self.as_ptr()
    }

    /// Casts to a pointer of another type.
    #[inline]
    pub const fn cast<U>(self) -> Unique<U> {
        unsafe {
            Unique::new_unchecked(self.as_ptr() as *mut U)
        }
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> Clone for Unique<T> {
    #[inline]
    fn clone(&self) -> Self {
        *self
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> Copy for Unique<T> { }

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> { }

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> fmt::Debug for Unique<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Pointer::fmt(&self.as_ptr(), f)
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> fmt::Pointer for Unique<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Pointer::fmt(&self.as_ptr(), f)
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> From<&mut T> for Unique<T> {
    #[inline]
    fn from(reference: &mut T) -> Self {
        unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> From<&T> for Unique<T> {
    #[inline]
    fn from(reference: &T) -> Self {
        unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } }
    }
}

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> From<NonNull<T>> for Unique<T> {
    #[inline]
    fn from(p: NonNull<T>) -> Self {
        unsafe { Unique::new_unchecked(p.as_ptr()) }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
use regex::Regex;

//#[macro_use]
//extern crate lazy_static;
pub fn get_number<P: AsRef<Path>>(filename: P) -> io::Result<u32> {
    /*
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    */
    //let RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    let regex: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    let mut matches = match_lines(filename, &regex)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output<P: AsRef<Path>>(filename: P) -> io::Result<impl Iterator<Item = i32>> {
    let regex: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    let matches = match_lines(filename, &regex)?;
    let values = matches.map(|s|
        s.split(',').map(|v| v.parse().unwrap()).collect::<Vec<_>>().into_iter()
    ).flatten();
    Ok(values)
}

fn captured(regex: &Regex, index: usize, line: &str) -> String {
    regex.captures(&line).unwrap()[index].to_string()
}

fn match_lines<P: AsRef<Path>>(filename: P, _regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let lines = read_lines(filename)?;
    let matches = lines.filter_map(|line|
        //Some(captured(regex, &line))
        Some(captured(&Regex::new(r"NUMBER=(.*)").unwrap(), 1, &line))
    );
    Ok(matches)
}

fn read_lines<P: AsRef<Path>>(filename: P) -> io::Result<impl Iterator<Item = String>> {
    let file = File::open(filename)?;
    return Ok(io::BufReader::new(file).lines().map(|line|
        line.unwrap()
    ));
}

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

    #[test]
    fn test_captured() {
        let regex: Regex = Regex::new(r"OUTPUT:(\d+),(.*)").unwrap();
        assert_eq!(captured(&regex, 1, "OUTPUT:1231,"), "1231");
        assert_eq!(captured(&regex, 2, "OUTPUT:3234,rust"), "rust");
    }

    #[test]
    fn get_test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap() , 3);
    }
}
<commit_msg>works<commit_after>
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
use regex::Regex;

#[macro_use]
extern crate lazy_static;
pub fn get_number<P: AsRef<Path>>(filename: P) -> io::Result<u32> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output<'a, P:'a + AsRef<Path>>(filename: P) -> io::Result<impl Iterator<Item = i32> + 'a> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    let matches = match_lines(filename, &*RE)?;
    let values = matches.map(|s|
        s.split(',').map(|v| v.parse().unwrap()).collect::<Vec<_>>().into_iter()
    ).flatten();
    Ok(values)
}

fn match_lines<'a, P: 'a + AsRef<Path>>(filename: P, regex: &'a Regex) -> io::Result<impl Iterator<Item = String> + 'a> {
    let lines = read_lines(filename)?;
    let matches = lines.filter_map(move |line|  {
        if let Some(captures) = regex.captures(&line) {
            Some(captures[1].to_string())
        } else {
            None
        }
    });
    Ok(matches)
}

fn read_lines<P: AsRef<Path>>(filename: P) -> io::Result<impl Iterator<Item = String>> {
    let file = File::open(filename)?;
    return Ok(io::BufReader::new(file).lines().map(|line|
        line.unwrap()
    ));
}

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

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap() , 3);
    }

    #[test]
    fn test_output() {
        let output = [1,1,2,2,3,4,4,6,7,9,9,20,21];
        assert_eq!(get_output("../data/test.txt").unwrap().collect::<Vec<_>>(), output);
    }
}
<|endoftext|>


<commit_before>use model::prelude::*;
use chrono::{DateTime, FixedOffset};
use std::fmt::{Display, Formatter, Result as FmtResult};
use super::deserialize_sync_user;

#[cfg(all(feature = "builder", feature = "cache", feature = "model"))]
use builder::EditMember;
#[cfg(all(feature = "cache", feature = "model"))]
use internal::prelude::*;
#[cfg(feature = "model")]
use std::borrow::Cow;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use utils::Colour;
#[cfg(all(feature = "cache", feature = "model"))]
use {CACHE, http, utils};

/// A trait for allowing both u8 or &str or (u8, &str) to be passed into the `ban` methods in `Guild` and `Member`.
pub trait BanOptions {
    fn dmd(&self) -> u8 { 0 }
    fn reason(&self) -> &str { "" }
}

impl BanOptions for u8 {
    fn dmd(&self) -> u8 { *self }
}

impl BanOptions for str {
    fn reason(&self) -> &str { self }
}

impl<'a> BanOptions for &'a str {
    fn reason(&self) -> &str { self }
}

impl BanOptions for String {
    fn reason(&self) -> &str { self }
}

impl<'a> BanOptions for (u8, &'a str) {
    fn dmd(&self) -> u8 { self.0 }

    fn reason(&self) -> &str { self.1 }
}

impl BanOptions for (u8, String) {
    fn dmd(&self) -> u8 { self.0 }

    fn reason(&self) -> &str { &self.1 }
}

/// Information about a member of a guild.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Member {
    /// Indicator of whether the member can hear in voice channels.
    pub deaf: bool,
    /// The unique Id of the guild that the member is a part of.
    pub guild_id: GuildId,
    /// Timestamp representing the date when the member joined.
    pub joined_at: Option<DateTime<FixedOffset>>,
    /// Indicator of whether the member can speak in voice channels.
    pub mute: bool,
    /// The member's nickname, if present.
    ///
    /// Can't be longer than 32 characters.
    pub nick: Option<String>,
    /// Vector of Ids of [`Role`]s given to the member.
    pub roles: Vec<RoleId>,
    /// Attached User struct.
    #[serde(deserialize_with = "deserialize_sync_user",
            serialize_with = "serialize_sync_user")]
    pub user: Arc<RwLock<User>>,
}

#[cfg(feature = "model")]
impl Member {
    /// Adds a [`Role`] to the member, editing its roles in-place if the request
    /// was successful.
    ///
    /// **Note**: Requires the [Manage Roles] permission.
    ///
    /// [`Role`]: struct.Role.html
    /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
    #[cfg(feature = "cache")]
    pub fn add_role<R: Into<RoleId>>(&mut self, role_id: R) -> Result<()> {
        let role_id = role_id.into();

        if self.roles.contains(&role_id) {
            return Ok(());
        }

        match http::add_member_role(self.guild_id.0, self.user.read().id.0, role_id.0) {
            Ok(()) => {
                self.roles.push(role_id);

                Ok(())
            },
            Err(why) => Err(why),
        }
    }

    /// Adds one or multiple [`Role`]s to the member, editing
    /// its roles in-place if the request was successful.
    ///
    /// **Note**: Requires the [Manage Roles] permission.
    ///
    /// [`Role`]: struct.Role.html
    /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
    #[cfg(feature = "cache")]
    pub fn add_roles(&mut self, role_ids: &[RoleId]) -> Result<()> {
        self.roles.extend_from_slice(role_ids);

        let builder = EditMember::default().roles(&self.roles);
        let map = utils::vecmap_to_json_map(builder.0);

        match http::edit_member(self.guild_id.0, self.user.read().id.0, &map) {
            Ok(()) => Ok(()),
            Err(why) => {
                self.roles.retain(|r| !role_ids.contains(r));

                Err(why)
            },
        }
    }

    /// Ban the member from its guild, deleting the last X number of
    /// days' worth of messages.
    ///
    /// **Note**: Requires the [Ban Members] permission.
    ///
    /// # Errors
    ///
    /// Returns a [`ModelError::GuildNotFound`] if the guild could not be
    /// found.
    ///
    /// [`ModelError::GuildNotFound`]: enum.ModelError.html#variant.GuildNotFound
    ///
    /// [Ban Members]: permissions/constant.BAN_MEMBERS.html
    #[cfg(feature = "cache")]
    pub fn ban<BO: BanOptions>(&self, ban_options: &BO) -> Result<()> {
        let dmd = ban_options.dmd();
        if dmd > 7 {
            return Err(Error::Model(ModelError::DeleteMessageDaysAmount(dmd)));
        }

        let reason = ban_options.reason();

        if reason.len() > 512 {
            return Err(Error::ExceededLimit(reason.to_string(), 512));
        }

        http::ban_user(
            self.guild_id.0,
            self.user.read().id.0,
            dmd,
            &*reason,
        )
    }

    /// Determines the member's colour.
    #[cfg(all(feature = "cache", feature = "utils"))]
    pub fn colour(&self) -> Option<Colour> {
        let cache = CACHE.read();
        let guild = cache.guilds.get(&self.guild_id)?.read();

        let mut roles = self.roles
            .iter()
            .filter_map(|role_id| guild.roles.get(role_id))
            .collect::<Vec<&Role>>();
        roles.sort_by(|a, b| b.cmp(a));

        let default = Colour::default();

        roles
            .iter()
            .find(|r| r.colour.0 != default.0)
            .map(|r| r.colour)
    }

    /// Returns the "default channel" of the guild for the member.
    /// (This returns the first channel that can be read by the member, if there isn't
    /// one returns `None`)
    #[cfg(feature = "cache")]
    pub fn default_channel(&self) -> Option<Arc<RwLock<GuildChannel>>> {
        let guild = match self.guild_id.find() {
            Some(guild) => guild,
            None => return None,
        };

        let reader = guild.read();

        for (cid, channel) in &reader.channels {
            if reader.permissions_in(*cid, self.user.read().id).read_messages() {
                return Some(Arc::clone(channel));
            }
        }

        None
    }

    /// Calculates the member's display name.
    ///
    /// The nickname takes priority over the member's username if it exists.
    #[inline]
    pub fn display_name(&self) -> Cow<String> {
        self.nick
            .as_ref()
            .map(Cow::Borrowed)
            .unwrap_or_else(|| Cow::Owned(self.user.read().name.clone()))
    }

    /// Returns the DiscordTag of a Member, taking possible nickname into account.
    #[inline]
    pub fn distinct(&self) -> String {
        format!(
            "{}#{}",
            self.display_name(),
            self.user.read().discriminator
        )
    }

    /// Edits the member with the given data. See [`Guild::edit_member`] for
    /// more information.
    ///
    /// See [`EditMember`] for the permission(s) required for separate builder
    /// methods, as well as usage of this.
    ///
    /// [`Guild::edit_member`]: ../model/struct.Guild.html#method.edit_member
    /// [`EditMember`]: ../builder/struct.EditMember.html
    #[cfg(feature = "cache")]
    pub fn edit<F: FnOnce(EditMember) -> EditMember>(&self, f: F) -> Result<()> {
        let map = utils::vecmap_to_json_map(f(EditMember::default()).0);

        http::edit_member(self.guild_id.0, self.user.read().id.0, &map)
    }

    /// Kick the member from the guild.
    ///
    /// **Note**: Requires the [Kick Members] permission.
    ///
    /// # Examples
    ///
    /// Kick a member from its guild:
    ///
    /// ```rust,ignore
    /// // assuming a `member` has already been bound
    /// match member.kick() {
    ///     Ok(()) => println!("Successfully kicked member"),
    ///     Err(Error::Model(ModelError::GuildNotFound)) => {
    ///         println!("Couldn't determine guild of member");
    ///     },
    ///     Err(Error::Model(ModelError::InvalidPermissions(missing_perms))) => {
    ///         println!("Didn't have permissions; missing: {:?}", missing_perms);
    ///     },
    ///     _ => {},
    /// }
    /// ```
    ///
    /// # Errors
    ///
    /// Returns a [`ModelError::GuildNotFound`] if the Id of the member's guild
    /// could not be determined.
    ///
    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`]
    /// if the current user does not have permission to perform the kick.
    ///
    /// [`ModelError::GuildNotFound`]: enum.ModelError.html#variant.GuildNotFound
    /// [`ModelError::InvalidPermissions`]: enum.ModelError.html#variant.InvalidPermissions
    /// [Kick Members]: permissions/constant.KICK_MEMBERS.html
    pub fn kick(&self) -> Result<()> {
        #[cfg(feature = "cache")]
        {
            let req = Permissions::KICK_MEMBERS;

            let has_perms = CACHE
                .read()
                .guilds
                .get(&self.guild_id)
                .map(|guild| guild.read().has_perms(req));

            if let Some(false) = has_perms {
                return Err(Error::Model(ModelError::InvalidPermissions(req)));
            }
        }

        self.guild_id.kick(self.user.read().id)
    }

    /// Returns the guild-level permissions for the member.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// // assuming there's a `member` variable gotten from anything.
    /// println!("The permission bits for the member are: {}",
    /// member.permissions().expect("permissions").bits);
    /// ```
    ///
    /// # Errors
    ///
    /// Returns a [`ModelError::GuildNotFound`] if the guild the member's in could not be
    /// found in the cache.
    ///
    /// And/or returns [`ModelError::ItemMissing`] if the "default channel" of the guild is not
    /// found.
    ///
    /// [`ModelError::GuildNotFound`]: enum.ModelError.html#variant.GuildNotFound
    /// [`ModelError::ItemMissing`]: enum.ModelError.html#variant.ItemMissing
    #[cfg(feature = "cache")]
    pub fn permissions(&self) -> Result<Permissions> {
        let guild = match self.guild_id.find() {
            Some(guild) => guild,
            None => return Err(From::from(ModelError::GuildNotFound)),
        };

        let reader = guild.read();

        Ok(reader.member_permissions(self.user.read().id))
    }

    /// Removes a [`Role`] from the member, editing its roles in-place if the
    /// request was successful.
    ///
    /// **Note**: Requires the [Manage Roles] permission.
    ///
    /// [`Role`]: struct.Role.html
    /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
    #[cfg(feature = "cache")]
    pub fn remove_role<R: Into<RoleId>>(&mut self, role_id: R) -> Result<()> {
        let role_id = role_id.into();

        if !self.roles.contains(&role_id) {
            return Ok(());
        }

        match http::remove_member_role(self.guild_id.0, self.user.read().id.0, role_id.0) {
            Ok(()) => {
                self.roles.retain(|r| r.0 != role_id.0);

                Ok(())
            },
            Err(why) => Err(why),
        }
    }

    /// Removes one or multiple [`Role`]s from the member.
    ///
    /// **Note**: Requires the [Manage Roles] permission.
    ///
    /// [`Role`]: struct.Role.html
    /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
    #[cfg(feature = "cache")]
    pub fn remove_roles(&mut self, role_ids: &[RoleId]) -> Result<()> {
        self.roles.retain(|r| !role_ids.contains(r));

        let builder = EditMember::default().roles(&self.roles);
        let map = utils::vecmap_to_json_map(builder.0);

        match http::edit_member(self.guild_id.0, self.user.read().id.0, &map) {
            Ok(()) => Ok(()),
            Err(why) => {
                self.roles.extend_from_slice(role_ids);

                Err(why)
            },
        }
    }

    /// Retrieves the full role data for the user's roles.
    ///
    /// This is shorthand for manually searching through the CACHE.
    ///
    /// If role data can not be found for the member, then `None` is returned.
    #[cfg(feature = "cache")]
    pub fn roles(&self) -> Option<Vec<Role>> {
        self
            .guild_id
            .find()
            .map(|g| g
                .read()
                .roles
                .values()
                .filter(|role| self.roles.contains(&role.id))
                .cloned()
                .collect())
    }

    /// Unbans the [`User`] from the guild.
    ///
    /// **Note**: Requires the [Ban Members] permission.
    ///
    /// # Errors
    ///
    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`]
    /// if the current user does not have permission to perform bans.
    ///
    /// [`ModelError::InvalidPermissions`]: enum.ModelError.html#variant.InvalidPermissions
    /// [`User`]: struct.User.html
    /// [Ban Members]: permissions/constant.BAN_MEMBERS.html
    #[cfg(feature = "cache")]
    pub fn unban(&self) -> Result<()> {
        http::remove_ban(self.guild_id.0, self.user.read().id.0)
    }
}

impl Display for Member {
    /// Mentions the user so that they receive a notification.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// // assumes a `member` has already been bound
    /// println!("{} is a member!", member);
    /// ```
    ///
    // This is in the format of `<@USER_ID>`.
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        Display::fmt(&self.user.read().mention(), f)
    }
}
<commit_msg>Add Member::highest_role_info<commit_after>use model::prelude::*;
use chrono::{DateTime, FixedOffset};
use std::fmt::{Display, Formatter, Result as FmtResult};
use super::deserialize_sync_user;

#[cfg(all(feature = "builder", feature = "cache", feature = "model"))]
use builder::EditMember;
#[cfg(all(feature = "cache", feature = "model"))]
use internal::prelude::*;
#[cfg(feature = "model")]
use std::borrow::Cow;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use utils::Colour;
#[cfg(all(feature = "cache", feature = "model"))]
use {CACHE, http, utils};

/// A trait for allowing both u8 or &str or (u8, &str) to be passed into the `ban` methods in `Guild` and `Member`.
pub trait BanOptions {
    fn dmd(&self) -> u8 { 0 }
    fn reason(&self) -> &str { "" }
}

impl BanOptions for u8 {
    fn dmd(&self) -> u8 { *self }
}

impl BanOptions for str {
    fn reason(&self) -> &str { self }
}

impl<'a> BanOptions for &'a str {
    fn reason(&self) -> &str { self }
}

impl BanOptions for String {
    fn reason(&self) -> &str { self }
}

impl<'a> BanOptions for (u8, &'a str) {
    fn dmd(&self) -> u8 { self.0 }

    fn reason(&self) -> &str { self.1 }
}

impl BanOptions for (u8, String) {
    fn dmd(&self) -> u8 { self.0 }

    fn reason(&self) -> &str { &self.1 }
}

/// Information about a member of a guild.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Member {
    /// Indicator of whether the member can hear in voice channels.
    pub deaf: bool,
    /// The unique Id of the guild that the member is a part of.
    pub guild_id: GuildId,
    /// Timestamp representing the date when the member joined.
    pub joined_at: Option<DateTime<FixedOffset>>,
    /// Indicator of whether the member can speak in voice channels.
    pub mute: bool,
    /// The member's nickname, if present.
    ///
    /// Can't be longer than 32 characters.
    pub nick: Option<String>,
    /// Vector of Ids of [`Role`]s given to the member.
    pub roles: Vec<RoleId>,
    /// Attached User struct.
    #[serde(deserialize_with = "deserialize_sync_user",
            serialize_with = "serialize_sync_user")]
    pub user: Arc<RwLock<User>>,
}

#[cfg(feature = "model")]
impl Member {
    /// Adds a [`Role`] to the member, editing its roles in-place if the request
    /// was successful.
    ///
    /// **Note**: Requires the [Manage Roles] permission.
    ///
    /// [`Role`]: struct.Role.html
    /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
    #[cfg(feature = "cache")]
    pub fn add_role<R: Into<RoleId>>(&mut self, role_id: R) -> Result<()> {
        let role_id = role_id.into();

        if self.roles.contains(&role_id) {
            return Ok(());
        }

        match http::add_member_role(self.guild_id.0, self.user.read().id.0, role_id.0) {
            Ok(()) => {
                self.roles.push(role_id);

                Ok(())
            },
            Err(why) => Err(why),
        }
    }

    /// Adds one or multiple [`Role`]s to the member, editing
    /// its roles in-place if the request was successful.
    ///
    /// **Note**: Requires the [Manage Roles] permission.
    ///
    /// [`Role`]: struct.Role.html
    /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
    #[cfg(feature = "cache")]
    pub fn add_roles(&mut self, role_ids: &[RoleId]) -> Result<()> {
        self.roles.extend_from_slice(role_ids);

        let builder = EditMember::default().roles(&self.roles);
        let map = utils::vecmap_to_json_map(builder.0);

        match http::edit_member(self.guild_id.0, self.user.read().id.0, &map) {
            Ok(()) => Ok(()),
            Err(why) => {
                self.roles.retain(|r| !role_ids.contains(r));

                Err(why)
            },
        }
    }

    /// Ban the member from its guild, deleting the last X number of
    /// days' worth of messages.
    ///
    /// **Note**: Requires the [Ban Members] permission.
    ///
    /// # Errors
    ///
    /// Returns a [`ModelError::GuildNotFound`] if the guild could not be
    /// found.
    ///
    /// [`ModelError::GuildNotFound`]: enum.ModelError.html#variant.GuildNotFound
    ///
    /// [Ban Members]: permissions/constant.BAN_MEMBERS.html
    #[cfg(feature = "cache")]
    pub fn ban<BO: BanOptions>(&self, ban_options: &BO) -> Result<()> {
        let dmd = ban_options.dmd();
        if dmd > 7 {
            return Err(Error::Model(ModelError::DeleteMessageDaysAmount(dmd)));
        }

        let reason = ban_options.reason();

        if reason.len() > 512 {
            return Err(Error::ExceededLimit(reason.to_string(), 512));
        }

        http::ban_user(
            self.guild_id.0,
            self.user.read().id.0,
            dmd,
            &*reason,
        )
    }

    /// Determines the member's colour.
    #[cfg(all(feature = "cache", feature = "utils"))]
    pub fn colour(&self) -> Option<Colour> {
        let cache = CACHE.read();
        let guild = cache.guilds.get(&self.guild_id)?.read();

        let mut roles = self.roles
            .iter()
            .filter_map(|role_id| guild.roles.get(role_id))
            .collect::<Vec<&Role>>();
        roles.sort_by(|a, b| b.cmp(a));

        let default = Colour::default();

        roles
            .iter()
            .find(|r| r.colour.0 != default.0)
            .map(|r| r.colour)
    }

    /// Returns the "default channel" of the guild for the member.
    /// (This returns the first channel that can be read by the member, if there isn't
    /// one returns `None`)
    #[cfg(feature = "cache")]
    pub fn default_channel(&self) -> Option<Arc<RwLock<GuildChannel>>> {
        let guild = match self.guild_id.find() {
            Some(guild) => guild,
            None => return None,
        };

        let reader = guild.read();

        for (cid, channel) in &reader.channels {
            if reader.permissions_in(*cid, self.user.read().id).read_messages() {
                return Some(Arc::clone(channel));
            }
        }

        None
    }

    /// Calculates the member's display name.
    ///
    /// The nickname takes priority over the member's username if it exists.
    #[inline]
    pub fn display_name(&self) -> Cow<String> {
        self.nick
            .as_ref()
            .map(Cow::Borrowed)
            .unwrap_or_else(|| Cow::Owned(self.user.read().name.clone()))
    }

    /// Returns the DiscordTag of a Member, taking possible nickname into account.
    #[inline]
    pub fn distinct(&self) -> String {
        format!(
            "{}#{}",
            self.display_name(),
            self.user.read().discriminator
        )
    }

    /// Edits the member with the given data. See [`Guild::edit_member`] for
    /// more information.
    ///
    /// See [`EditMember`] for the permission(s) required for separate builder
    /// methods, as well as usage of this.
    ///
    /// [`Guild::edit_member`]: ../model/struct.Guild.html#method.edit_member
    /// [`EditMember`]: ../builder/struct.EditMember.html
    #[cfg(feature = "cache")]
    pub fn edit<F: FnOnce(EditMember) -> EditMember>(&self, f: F) -> Result<()> {
        let map = utils::vecmap_to_json_map(f(EditMember::default()).0);

        http::edit_member(self.guild_id.0, self.user.read().id.0, &map)
    }

    /// Retrieves the ID and position of the member's highest role in the
    /// hierarchy, if they have one.
    ///
    /// This _may_ return `None` if the user has roles, but they are not present
    /// in the cache for cache inconsistency reasons.
    ///
    /// The "highest role in hierarchy" is defined as the role with the highest
    /// position. If two or more roles have the same highest position, then the
    /// role with the lowest ID is the highest.
    ///
    /// # Deadlocking
    ///
    /// This function will deadlock if you have a write lock to the member's
    /// guild.
    #[cfg(feature = "cache")]
    pub fn highest_role_info(&self) -> Option<(RoleId, i64)> {
        let guild = self.guild_id.find()?;
        let reader = guild.read();

        let mut highest = None;

        for role_id in &self.roles {
            if let Some(role) = reader.roles.get(&role_id) {
                // Skip this role if this role in iteration has:
                //
                // - a position less than the recorded highest
                // - a position equal to the recorded, but a higher ID
                if let Some((id, pos)) = highest {
                    if role.position < pos || (role.position == pos && role.id > id) {
                        continue;
                    }
                }

                highest = Some((role.id, role.position));
            }
        }

        highest
    }

    /// Kick the member from the guild.
    ///
    /// **Note**: Requires the [Kick Members] permission.
    ///
    /// # Examples
    ///
    /// Kick a member from its guild:
    ///
    /// ```rust,ignore
    /// // assuming a `member` has already been bound
    /// match member.kick() {
    ///     Ok(()) => println!("Successfully kicked member"),
    ///     Err(Error::Model(ModelError::GuildNotFound)) => {
    ///         println!("Couldn't determine guild of member");
    ///     },
    ///     Err(Error::Model(ModelError::InvalidPermissions(missing_perms))) => {
    ///         println!("Didn't have permissions; missing: {:?}", missing_perms);
    ///     },
    ///     _ => {},
    /// }
    /// ```
    ///
    /// # Errors
    ///
    /// Returns a [`ModelError::GuildNotFound`] if the Id of the member's guild
    /// could not be determined.
    ///
    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`]
    /// if the current user does not have permission to perform the kick.
    ///
    /// [`ModelError::GuildNotFound`]: enum.ModelError.html#variant.GuildNotFound
    /// [`ModelError::InvalidPermissions`]: enum.ModelError.html#variant.InvalidPermissions
    /// [Kick Members]: permissions/constant.KICK_MEMBERS.html
    pub fn kick(&self) -> Result<()> {
        #[cfg(feature = "cache")]
        {
            let req = Permissions::KICK_MEMBERS;

            let has_perms = CACHE
                .read()
                .guilds
                .get(&self.guild_id)
                .map(|guild| guild.read().has_perms(req));

            if let Some(false) = has_perms {
                return Err(Error::Model(ModelError::InvalidPermissions(req)));
            }
        }

        self.guild_id.kick(self.user.read().id)
    }

    /// Returns the guild-level permissions for the member.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// // assuming there's a `member` variable gotten from anything.
    /// println!("The permission bits for the member are: {}",
    /// member.permissions().expect("permissions").bits);
    /// ```
    ///
    /// # Errors
    ///
    /// Returns a [`ModelError::GuildNotFound`] if the guild the member's in could not be
    /// found in the cache.
    ///
    /// And/or returns [`ModelError::ItemMissing`] if the "default channel" of the guild is not
    /// found.
    ///
    /// [`ModelError::GuildNotFound`]: enum.ModelError.html#variant.GuildNotFound
    /// [`ModelError::ItemMissing`]: enum.ModelError.html#variant.ItemMissing
    #[cfg(feature = "cache")]
    pub fn permissions(&self) -> Result<Permissions> {
        let guild = match self.guild_id.find() {
            Some(guild) => guild,
            None => return Err(From::from(ModelError::GuildNotFound)),
        };

        let reader = guild.read();

        Ok(reader.member_permissions(self.user.read().id))
    }

    /// Removes a [`Role`] from the member, editing its roles in-place if the
    /// request was successful.
    ///
    /// **Note**: Requires the [Manage Roles] permission.
    ///
    /// [`Role`]: struct.Role.html
    /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
    #[cfg(feature = "cache")]
    pub fn remove_role<R: Into<RoleId>>(&mut self, role_id: R) -> Result<()> {
        let role_id = role_id.into();

        if !self.roles.contains(&role_id) {
            return Ok(());
        }

        match http::remove_member_role(self.guild_id.0, self.user.read().id.0, role_id.0) {
            Ok(()) => {
                self.roles.retain(|r| r.0 != role_id.0);

                Ok(())
            },
            Err(why) => Err(why),
        }
    }

    /// Removes one or multiple [`Role`]s from the member.
    ///
    /// **Note**: Requires the [Manage Roles] permission.
    ///
    /// [`Role`]: struct.Role.html
    /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
    #[cfg(feature = "cache")]
    pub fn remove_roles(&mut self, role_ids: &[RoleId]) -> Result<()> {
        self.roles.retain(|r| !role_ids.contains(r));

        let builder = EditMember::default().roles(&self.roles);
        let map = utils::vecmap_to_json_map(builder.0);

        match http::edit_member(self.guild_id.0, self.user.read().id.0, &map) {
            Ok(()) => Ok(()),
            Err(why) => {
                self.roles.extend_from_slice(role_ids);

                Err(why)
            },
        }
    }

    /// Retrieves the full role data for the user's roles.
    ///
    /// This is shorthand for manually searching through the CACHE.
    ///
    /// If role data can not be found for the member, then `None` is returned.
    #[cfg(feature = "cache")]
    pub fn roles(&self) -> Option<Vec<Role>> {
        self
            .guild_id
            .find()
            .map(|g| g
                .read()
                .roles
                .values()
                .filter(|role| self.roles.contains(&role.id))
                .cloned()
                .collect())
    }

    /// Unbans the [`User`] from the guild.
    ///
    /// **Note**: Requires the [Ban Members] permission.
    ///
    /// # Errors
    ///
    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`]
    /// if the current user does not have permission to perform bans.
    ///
    /// [`ModelError::InvalidPermissions`]: enum.ModelError.html#variant.InvalidPermissions
    /// [`User`]: struct.User.html
    /// [Ban Members]: permissions/constant.BAN_MEMBERS.html
    #[cfg(feature = "cache")]
    pub fn unban(&self) -> Result<()> {
        http::remove_ban(self.guild_id.0, self.user.read().id.0)
    }
}

impl Display for Member {
    /// Mentions the user so that they receive a notification.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// // assumes a `member` has already been bound
    /// println!("{} is a member!", member);
    /// ```
    ///
    // This is in the format of `<@USER_ID>`.
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        Display::fmt(&self.user.read().mention(), f)
    }
}
<|endoftext|>


<commit_before>#![no_std]
#![feature(asm)]
#![feature(intrinsics)]
#![feature(lang_items)]
#[allow(dead_code)]
#[allow(non_snake_case)]
#[allow(non_camel_case_types)]
#[allow(missing_copy_implementations)]

extern crate uefi;
extern crate rlibc;

use uefi::SimpleTextOutput;

#[allow(unreachable_code)]
#[no_mangle]
pub extern "win64" fn efi_main(hdl: uefi::Handle, sys: uefi::SystemTable) -> uefi::Status {
    uefi::initialize_lib(&hdl, &sys);

    let bs = uefi::get_system_table().boot_services();
    let rs = uefi::get_system_table().runtime_services();

    uefi::get_system_table().console().write("Hello, World!\n\r");

    let (memory_map, memory_map_size, map_key, descriptor_size, descriptor_version) = uefi::lib_memory_map();

    let gop = match uefi::graphics::GraphicsOutputProtocol::new() {
        Ok(r) => r,
        Err(_) => panic!(),
    };

    for _ in 0..gop.get_max_mode() {
        uefi::get_system_table().console().write("Ya!\n\r");
    }

    let mut mode: u32 = 0;
    for i in 0..gop.get_max_mode() {
        let info = match gop.query_mode(i) {
            Ok(r) => r,
            Err(r) => return r,
        };

        if info.pixel_format != uefi::graphics::PixelFormat::RedGreenBlue
            && info.pixel_format != uefi::graphics::PixelFormat::BlueGreenRed { continue; }
        if info.horizontal_resolution > 1920 && info.vertical_resolution > 1080 { continue; }
        if info.horizontal_resolution == 1920 && info.vertical_resolution == 1080 { mode = i; break; }
        mode = i;
    };

    gop.set_mode(mode);
    gop.draw(&[uefi::graphics::Pixel::new(255, 0, 0) ; 300], 0, 300, 0, 0);

    //rs.reset_system(uefi::ResetType::Shutdown, uefi::Status::Success);

    bs.exit_boot_services(&hdl, &map_key);
    rs.set_virtual_address_map(&memory_map_size, &descriptor_size, &descriptor_version, memory_map);

    loop {
    }
    uefi::Status::Success
}

#[no_mangle]
pub fn abort() -> ! {
    loop {}
}

#[no_mangle]
pub fn breakpoint() -> ! {
    loop {}
}

#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn _Unwind_Resume() -> ! {
    loop {}
}

#[lang = "eh_personality"]
#[no_mangle]
pub extern fn rust_eh_personality() {}

#[lang = "panic_fmt"]
#[no_mangle]
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
                               _file: &'static str,
                               _line: u32) -> ! {
    loop {}
}
<commit_msg>get a ability of drawing bitmap<commit_after>#![no_std]
#![feature(asm)]
#![feature(intrinsics)]
#![feature(lang_items)]

extern crate uefi;
extern crate rlibc;

use uefi::SimpleTextOutput;

#[allow(unreachable_code)]
#[no_mangle]
pub extern "win64" fn efi_main(hdl: uefi::Handle, sys: uefi::SystemTable) -> uefi::Status {
    uefi::initialize_lib(&hdl, &sys);

    let bs = uefi::get_system_table().boot_services();
    let rs = uefi::get_system_table().runtime_services();

    uefi::get_system_table().console().write("Hello, World!\n\r");

    let (memory_map, memory_map_size, map_key, descriptor_size, descriptor_version) = uefi::lib_memory_map();

    let gop = uefi::graphics::GraphicsOutputProtocol::new().unwrap();

    let mut mode: u32 = 0;
    for i in 0..gop.get_max_mode() {
        let info = gop.query_mode(i).unwrap();

        if info.pixel_format != uefi::graphics::PixelFormat::RedGreenBlue
            && info.pixel_format != uefi::graphics::PixelFormat::BlueGreenRed { continue; }
        if info.horizontal_resolution > 1920 && info.vertical_resolution > 1080 { continue; }
        if info.horizontal_resolution == 1920 && info.vertical_resolution == 1080 { mode = i; break; }
        mode = i;
    };

    gop.set_mode(mode);
    gop.draw(&[uefi::graphics::Pixel::new(255, 0, 0) ; 90000], 300, 300, 300, 300);

    bs.exit_boot_services(&hdl, &map_key);
    rs.set_virtual_address_map(&memory_map_size, &descriptor_size, &descriptor_version, memory_map);

    loop {
    }
    uefi::Status::Success
}

#[no_mangle]
pub fn abort() -> ! {
    loop {}
}

#[no_mangle]
pub fn breakpoint() -> ! {
    loop {}
}

#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn _Unwind_Resume() -> ! {
    loop {}
}

#[lang = "eh_personality"]
#[no_mangle]
pub extern fn rust_eh_personality() {}

#[lang = "panic_fmt"]
#[no_mangle]
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
                               _file: &'static str,
                               _line: u32) -> ! {
    loop {}
}
<|endoftext|>