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

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

//! the rustc crate store interface. This also includes types that
//! are *mostly* used as a part of that interface, but these should
//! probably get a better home if someone can find one.

use hir::def;
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use hir::map as hir_map;
use hir::map::definitions::{Definitions, DefKey, DefPathTable};
use hir::svh::Svh;
use ty::{self, TyCtxt};
use session::{Session, CrateDisambiguator};
use session::search_paths::PathKind;

use std::any::Any;
use std::path::{Path, PathBuf};
use syntax::ast;
use syntax::edition::Edition;
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
use syntax_pos::Span;
use rustc_target::spec::Target;
use rustc_data_structures::sync::{self, MetadataRef, Lrc};

pub use self::NativeLibraryKind::*;

// lonely orphan structs and enums looking for a better home

#[derive(Clone, Debug, Copy)]
pub struct LinkMeta {
    pub crate_hash: Svh,
}

/// Where a crate came from on the local filesystem. One of these three options
/// must be non-None.
#[derive(PartialEq, Clone, Debug)]
pub struct CrateSource {
    pub dylib: Option<(PathBuf, PathKind)>,
    pub rlib: Option<(PathBuf, PathKind)>,
    pub rmeta: Option<(PathBuf, PathKind)>,
}

#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
pub enum DepKind {
    /// A dependency that is only used for its macros, none of which are visible from other crates.
    /// These are included in the metadata only as placeholders and are ignored when decoding.
    UnexportedMacrosOnly,
    /// A dependency that is only used for its macros.
    MacrosOnly,
    /// A dependency that is always injected into the dependency list and so
    /// doesn't need to be linked to an rlib, e.g. the injected allocator.
    Implicit,
    /// A dependency that is required by an rlib version of this crate.
    /// Ordinary `extern crate`s result in `Explicit` dependencies.
    Explicit,
}

impl DepKind {
    pub fn macros_only(self) -> bool {
        match self {
            DepKind::UnexportedMacrosOnly | DepKind::MacrosOnly => true,
            DepKind::Implicit | DepKind::Explicit => false,
        }
    }
}

#[derive(PartialEq, Clone, Debug)]
pub enum LibSource {
    Some(PathBuf),
    MetadataOnly,
    None,
}

impl LibSource {
    pub fn is_some(&self) -> bool {
        if let LibSource::Some(_) = *self {
            true
        } else {
            false
        }
    }

    pub fn option(&self) -> Option<PathBuf> {
        match *self {
            LibSource::Some(ref p) => Some(p.clone()),
            LibSource::MetadataOnly | LibSource::None => None,
        }
    }
}

#[derive(Copy, Debug, PartialEq, Clone, RustcEncodable, RustcDecodable)]
pub enum LinkagePreference {
    RequireDynamic,
    RequireStatic,
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub enum NativeLibraryKind {
    /// native static library (.a archive)
    NativeStatic,
    /// native static library, which doesn't get bundled into .rlibs
    NativeStaticNobundle,
    /// macOS-specific
    NativeFramework,
    /// default way to specify a dynamic library
    NativeUnknown,
}

#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct NativeLibrary {
    pub kind: NativeLibraryKind,
    pub name: Option<Symbol>,
    pub cfg: Option<ast::MetaItem>,
    pub foreign_module: Option<DefId>,
    pub wasm_import_module: Option<Symbol>,
}

#[derive(Clone, Hash, RustcEncodable, RustcDecodable)]
pub struct ForeignModule {
    pub foreign_items: Vec<DefId>,
    pub def_id: DefId,
}

pub enum LoadedMacro {
    MacroDef(ast::Item),
    ProcMacro(Lrc<SyntaxExtension>),
}

#[derive(Copy, Clone, Debug)]
pub struct ExternCrate {
    pub src: ExternCrateSource,

    /// span of the extern crate that caused this to be loaded
    pub span: Span,

    /// Number of links to reach the extern;
    /// used to select the extern with the shortest path
    pub path_len: usize,

    /// If true, then this crate is the crate named by the extern
    /// crate referenced above. If false, then this crate is a dep
    /// of the crate.
    pub direct: bool,
}

#[derive(Copy, Clone, Debug)]
pub enum ExternCrateSource {
    /// Crate is loaded by `extern crate`.
    Extern(
        /// def_id of the item in the current crate that caused
        /// this crate to be loaded; note that there could be multiple
        /// such ids
        DefId,
    ),
    // Crate is loaded by `use`.
    Use,
    /// Crate is implicitly loaded by an absolute or an `extern::` path.
    Path,
}

pub struct EncodedMetadata {
    pub raw_data: Vec<u8>
}

impl EncodedMetadata {
    pub fn new() -> EncodedMetadata {
        EncodedMetadata {
            raw_data: Vec::new(),
        }
    }
}

/// The backend's way to give the crate store access to the metadata in a library.
/// Note that it returns the raw metadata bytes stored in the library file, whether
/// it is compressed, uncompressed, some weird mix, etc.
/// rmeta files are backend independent and not handled here.
///
/// At the time of this writing, there is only one backend and one way to store
/// metadata in library -- this trait just serves to decouple rustc_metadata from
/// the archive reader, which depends on LLVM.
pub trait MetadataLoader {
    fn get_rlib_metadata(&self,
                         target: &Target,
                         filename: &Path)
                         -> Result<MetadataRef, String>;
    fn get_dylib_metadata(&self,
                          target: &Target,
                          filename: &Path)
                          -> Result<MetadataRef, String>;
}

/// A store of Rust crates, through with their metadata
/// can be accessed.
///
/// Note that this trait should probably not be expanding today. All new
/// functionality should be driven through queries instead!
///
/// If you find a method on this trait named `{name}_untracked` it signifies
/// that it's *not* tracked for dependency information throughout compilation
/// (it'd break incremental compilation) and should only be called pre-HIR (e.g.
/// during resolve)
pub trait CrateStore {
    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any>;

    // access to the metadata loader
    fn metadata_loader(&self) -> &dyn MetadataLoader;

    // resolve
    fn def_key(&self, def: DefId) -> DefKey;
    fn def_path(&self, def: DefId) -> hir_map::DefPath;
    fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash;
    fn def_path_table(&self, cnum: CrateNum) -> Lrc<DefPathTable>;

    // "queries" used in resolve that aren't tracked for incremental compilation
    fn visibility_untracked(&self, def: DefId) -> ty::Visibility;
    fn export_macros_untracked(&self, cnum: CrateNum);
    fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind;
    fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
    fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
    fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition;
    fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name>;
    fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export>;
    fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro;
    fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
    fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem;
    fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;

    // This is basically a 1-based range of ints, which is a little
    // silly - I may fix that.
    fn crates_untracked(&self) -> Vec<CrateNum>;

    // utility functions
    fn encode_metadata<'a, 'tcx>(&self,
                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 link_meta: &LinkMeta)
                                 -> EncodedMetadata;
    fn metadata_encoding_version(&self) -> &[u8];
}

pub type CrateStoreDyn = dyn CrateStore + sync::Sync;

/// A dummy crate store that does not support any non-local crates,
/// for test purposes.
pub struct DummyCrateStore;

#[allow(unused_variables)]
impl CrateStore for DummyCrateStore {
    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any>
        { bug!("crate_data_as_rc_any") }
    // item info
    fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics
        { bug!("item_generics_cloned") }

    // trait/impl-item info
    fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem
        { bug!("associated_item_cloned") }

    // crate metadata
    fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
    fn export_macros_untracked(&self, cnum: CrateNum) { bug!("export_macros") }
    fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") }
    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator {
        bug!("crate_disambiguator")
    }
    fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") }
    fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { bug!("crate_edition_untracked") }

    // resolve
    fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") }
    fn def_path(&self, def: DefId) -> hir_map::DefPath {
        bug!("relative_def_path")
    }
    fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash {
        bug!("def_path_hash")
    }
    fn def_path_table(&self, cnum: CrateNum) -> Lrc<DefPathTable> {
        bug!("def_path_table")
    }
    fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name> {
        bug!("struct_field_names")
    }
    fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export> {
        bug!("item_children")
    }
    fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") }

    fn crates_untracked(&self) -> Vec<CrateNum> { vec![] }

    // utility functions
    fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None }
    fn encode_metadata<'a, 'tcx>(&self,
                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 link_meta: &LinkMeta)
                                 -> EncodedMetadata {
        bug!("encode_metadata")
    }
    fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
    fn postorder_cnums_untracked(&self) -> Vec<CrateNum> { bug!("postorder_cnums_untracked") }

    // access to the metadata loader
    fn metadata_loader(&self) -> &dyn MetadataLoader { bug!("metadata_loader") }
}

pub trait CrateLoader {
    fn process_extern_crate(&mut self, item: &ast::Item, defs: &Definitions) -> CrateNum;

    fn process_path_extern(
        &mut self,
        name: Symbol,
        span: Span,
    ) -> CrateNum;

    fn process_use_extern(
        &mut self,
        name: Symbol,
        span: Span,
        id: ast::NodeId,
        defs: &Definitions,
    ) -> CrateNum;

    fn postprocess(&mut self, krate: &ast::Crate);
}

// This method is used when generating the command line to pass through to
// system linker. The linker expects undefined symbols on the left of the
// command line to be defined in libraries on the right, not the other way
// around. For more info, see some comments in the add_used_library function
// below.
//
// In order to get this left-to-right dependency ordering, we perform a
// topological sort of all crates putting the leaves at the right-most
// positions.
pub fn used_crates(tcx: TyCtxt, prefer: LinkagePreference)
    -> Vec<(CrateNum, LibSource)>
{
    let mut libs = tcx.crates()
        .iter()
        .cloned()
        .filter_map(|cnum| {
            if tcx.dep_kind(cnum).macros_only() {
                return None
            }
            let source = tcx.used_crate_source(cnum);
            let path = match prefer {
                LinkagePreference::RequireDynamic => source.dylib.clone().map(|p| p.0),
                LinkagePreference::RequireStatic => source.rlib.clone().map(|p| p.0),
            };
            let path = match path {
                Some(p) => LibSource::Some(p),
                None => {
                    if source.rmeta.is_some() {
                        LibSource::MetadataOnly
                    } else {
                        LibSource::None
                    }
                }
            };
            Some((cnum, path))
        })
        .collect::<Vec<_>>();
    let mut ordering = tcx.postorder_cnums(LOCAL_CRATE);
    Lrc::make_mut(&mut ordering).reverse();
    libs.sort_by_cached_key(|&(a, _)| {
        ordering.iter().position(|x| *x == a)
    });
    libs
}
<commit_msg>Delete dummy crate store<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

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

//! the rustc crate store interface. This also includes types that
//! are *mostly* used as a part of that interface, but these should
//! probably get a better home if someone can find one.

use hir::def;
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use hir::map as hir_map;
use hir::map::definitions::{Definitions, DefKey, DefPathTable};
use hir::svh::Svh;
use ty::{self, TyCtxt};
use session::{Session, CrateDisambiguator};
use session::search_paths::PathKind;

use std::any::Any;
use std::path::{Path, PathBuf};
use syntax::ast;
use syntax::edition::Edition;
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
use syntax_pos::Span;
use rustc_target::spec::Target;
use rustc_data_structures::sync::{self, MetadataRef, Lrc};

pub use self::NativeLibraryKind::*;

// lonely orphan structs and enums looking for a better home

#[derive(Clone, Debug, Copy)]
pub struct LinkMeta {
    pub crate_hash: Svh,
}

/// Where a crate came from on the local filesystem. One of these three options
/// must be non-None.
#[derive(PartialEq, Clone, Debug)]
pub struct CrateSource {
    pub dylib: Option<(PathBuf, PathKind)>,
    pub rlib: Option<(PathBuf, PathKind)>,
    pub rmeta: Option<(PathBuf, PathKind)>,
}

#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
pub enum DepKind {
    /// A dependency that is only used for its macros, none of which are visible from other crates.
    /// These are included in the metadata only as placeholders and are ignored when decoding.
    UnexportedMacrosOnly,
    /// A dependency that is only used for its macros.
    MacrosOnly,
    /// A dependency that is always injected into the dependency list and so
    /// doesn't need to be linked to an rlib, e.g. the injected allocator.
    Implicit,
    /// A dependency that is required by an rlib version of this crate.
    /// Ordinary `extern crate`s result in `Explicit` dependencies.
    Explicit,
}

impl DepKind {
    pub fn macros_only(self) -> bool {
        match self {
            DepKind::UnexportedMacrosOnly | DepKind::MacrosOnly => true,
            DepKind::Implicit | DepKind::Explicit => false,
        }
    }
}

#[derive(PartialEq, Clone, Debug)]
pub enum LibSource {
    Some(PathBuf),
    MetadataOnly,
    None,
}

impl LibSource {
    pub fn is_some(&self) -> bool {
        if let LibSource::Some(_) = *self {
            true
        } else {
            false
        }
    }

    pub fn option(&self) -> Option<PathBuf> {
        match *self {
            LibSource::Some(ref p) => Some(p.clone()),
            LibSource::MetadataOnly | LibSource::None => None,
        }
    }
}

#[derive(Copy, Debug, PartialEq, Clone, RustcEncodable, RustcDecodable)]
pub enum LinkagePreference {
    RequireDynamic,
    RequireStatic,
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub enum NativeLibraryKind {
    /// native static library (.a archive)
    NativeStatic,
    /// native static library, which doesn't get bundled into .rlibs
    NativeStaticNobundle,
    /// macOS-specific
    NativeFramework,
    /// default way to specify a dynamic library
    NativeUnknown,
}

#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct NativeLibrary {
    pub kind: NativeLibraryKind,
    pub name: Option<Symbol>,
    pub cfg: Option<ast::MetaItem>,
    pub foreign_module: Option<DefId>,
    pub wasm_import_module: Option<Symbol>,
}

#[derive(Clone, Hash, RustcEncodable, RustcDecodable)]
pub struct ForeignModule {
    pub foreign_items: Vec<DefId>,
    pub def_id: DefId,
}

pub enum LoadedMacro {
    MacroDef(ast::Item),
    ProcMacro(Lrc<SyntaxExtension>),
}

#[derive(Copy, Clone, Debug)]
pub struct ExternCrate {
    pub src: ExternCrateSource,

    /// span of the extern crate that caused this to be loaded
    pub span: Span,

    /// Number of links to reach the extern;
    /// used to select the extern with the shortest path
    pub path_len: usize,

    /// If true, then this crate is the crate named by the extern
    /// crate referenced above. If false, then this crate is a dep
    /// of the crate.
    pub direct: bool,
}

#[derive(Copy, Clone, Debug)]
pub enum ExternCrateSource {
    /// Crate is loaded by `extern crate`.
    Extern(
        /// def_id of the item in the current crate that caused
        /// this crate to be loaded; note that there could be multiple
        /// such ids
        DefId,
    ),
    // Crate is loaded by `use`.
    Use,
    /// Crate is implicitly loaded by an absolute or an `extern::` path.
    Path,
}

pub struct EncodedMetadata {
    pub raw_data: Vec<u8>
}

impl EncodedMetadata {
    pub fn new() -> EncodedMetadata {
        EncodedMetadata {
            raw_data: Vec::new(),
        }
    }
}

/// The backend's way to give the crate store access to the metadata in a library.
/// Note that it returns the raw metadata bytes stored in the library file, whether
/// it is compressed, uncompressed, some weird mix, etc.
/// rmeta files are backend independent and not handled here.
///
/// At the time of this writing, there is only one backend and one way to store
/// metadata in library -- this trait just serves to decouple rustc_metadata from
/// the archive reader, which depends on LLVM.
pub trait MetadataLoader {
    fn get_rlib_metadata(&self,
                         target: &Target,
                         filename: &Path)
                         -> Result<MetadataRef, String>;
    fn get_dylib_metadata(&self,
                          target: &Target,
                          filename: &Path)
                          -> Result<MetadataRef, String>;
}

/// A store of Rust crates, through with their metadata
/// can be accessed.
///
/// Note that this trait should probably not be expanding today. All new
/// functionality should be driven through queries instead!
///
/// If you find a method on this trait named `{name}_untracked` it signifies
/// that it's *not* tracked for dependency information throughout compilation
/// (it'd break incremental compilation) and should only be called pre-HIR (e.g.
/// during resolve)
pub trait CrateStore {
    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any>;

    // access to the metadata loader
    fn metadata_loader(&self) -> &dyn MetadataLoader;

    // resolve
    fn def_key(&self, def: DefId) -> DefKey;
    fn def_path(&self, def: DefId) -> hir_map::DefPath;
    fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash;
    fn def_path_table(&self, cnum: CrateNum) -> Lrc<DefPathTable>;

    // "queries" used in resolve that aren't tracked for incremental compilation
    fn visibility_untracked(&self, def: DefId) -> ty::Visibility;
    fn export_macros_untracked(&self, cnum: CrateNum);
    fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind;
    fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
    fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
    fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition;
    fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name>;
    fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export>;
    fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro;
    fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
    fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem;
    fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;

    // This is basically a 1-based range of ints, which is a little
    // silly - I may fix that.
    fn crates_untracked(&self) -> Vec<CrateNum>;

    // utility functions
    fn encode_metadata<'a, 'tcx>(&self,
                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 link_meta: &LinkMeta)
                                 -> EncodedMetadata;
    fn metadata_encoding_version(&self) -> &[u8];
}

pub type CrateStoreDyn = dyn CrateStore + sync::Sync;

pub trait CrateLoader {
    fn process_extern_crate(&mut self, item: &ast::Item, defs: &Definitions) -> CrateNum;

    fn process_path_extern(
        &mut self,
        name: Symbol,
        span: Span,
    ) -> CrateNum;

    fn process_use_extern(
        &mut self,
        name: Symbol,
        span: Span,
        id: ast::NodeId,
        defs: &Definitions,
    ) -> CrateNum;

    fn postprocess(&mut self, krate: &ast::Crate);
}

// This method is used when generating the command line to pass through to
// system linker. The linker expects undefined symbols on the left of the
// command line to be defined in libraries on the right, not the other way
// around. For more info, see some comments in the add_used_library function
// below.
//
// In order to get this left-to-right dependency ordering, we perform a
// topological sort of all crates putting the leaves at the right-most
// positions.
pub fn used_crates(tcx: TyCtxt, prefer: LinkagePreference)
    -> Vec<(CrateNum, LibSource)>
{
    let mut libs = tcx.crates()
        .iter()
        .cloned()
        .filter_map(|cnum| {
            if tcx.dep_kind(cnum).macros_only() {
                return None
            }
            let source = tcx.used_crate_source(cnum);
            let path = match prefer {
                LinkagePreference::RequireDynamic => source.dylib.clone().map(|p| p.0),
                LinkagePreference::RequireStatic => source.rlib.clone().map(|p| p.0),
            };
            let path = match path {
                Some(p) => LibSource::Some(p),
                None => {
                    if source.rmeta.is_some() {
                        LibSource::MetadataOnly
                    } else {
                        LibSource::None
                    }
                }
            };
            Some((cnum, path))
        })
        .collect::<Vec<_>>();
    let mut ordering = tcx.postorder_cnums(LOCAL_CRATE);
    Lrc::make_mut(&mut ordering).reverse();
    libs.sort_by_cached_key(|&(a, _)| {
        ordering.iter().position(|x| *x == a)
    });
    libs
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use ast::*;
use visit::{Visitor};
use std::cell::RefCell;
use ptr::*;

pub type OptionalBinding = Option<B<Binding>>;

struct ExpEvaluator{
    value : i32
}

impl ExpEvaluator{
    fn get_value(&mut self, expr : & Expr)->i32{
        match expr{
            &Expr::NumExpr(value) => value,
            _ => 1
        }
    }
}

impl<'a> Visitor<'a> for ExpEvaluator{
    fn visit_expr(&mut self, expr: &'a Expr){
        match expr{
            &Expr::AddExpr(ref left, ref right) => {
                let v1 = self.get_value(left);
                let v2 = self.get_value(right);
                self.value = v1 + v2;
            },
            _ => {}
        }
    }
}

pub struct TypeChecker{
    //block_stack : Vec<RefCell<&'a  Block>>,
    pub sym_tab : Vec<(String, OptionalBinding)>,
    //decl_cnt : u32,
    //decl_cnt_stack : Vec<u32>,
    pub ty : TType
}

impl TypeChecker{
    pub fn new()->Self{
        TypeChecker {sym_tab : Vec::new(), ty : TType::TNil}
    }

    fn get_type_for(&self){//}->&TType{
        //self.block_stack
    }
}

impl<'a> Visitor<'a> for TypeChecker{
    fn visit_expr(&mut self, expr: &'a Expr){
        match expr{
            //FIXME remove NilExpr; this is only for unit testing
            &Expr::NilExpr => self.ty = TType::TString,
            &Expr::NumExpr(_) => self.ty = TType::TInt32,
            &Expr::StringExpr(_) => self.ty = TType::TString,
            &Expr::IdExpr(ref id) =>{
                //search in the symtab for id's existence and get the type
                let mut found = false;
                for &(ref _id, ref _binding) in &self.sym_tab{ //iterator returns a ref to tuple while iterating; so &(_,_) has to be used
                    if *_id == *id{
                        found = true;
                        self.ty = match **_binding.as_ref().unwrap(){
                            Binding::TypeBinding(ref ty) |
                            Binding::VarBinding(ref ty) |
                            Binding::FuncBinding(ref ty) => ty.clone()
                        };
                        break;
                    }
                }
                if !found{
                    panic!("{} not found", id);
                }
            },
            &Expr::AddExpr(ref left, ref right) => {
                self.visit_expr(left);
                let left_ty = self.ty.clone();
                if left_ty != TType::TInt32{
                    panic!("Expected left operand of int type");
                }
                self.visit_expr(right);
                if self.ty != TType::TInt32{
                    panic!("Expected right operand of int type")
                }
            },
            &Expr::SeqExpr(ref opt_expr_list) => {
                for b_expr in opt_expr_list.as_ref().unwrap() {
                    self.visit_expr(&*b_expr);
                }
            },
            &Expr::IfThenExpr(ref conditional_expr, _) => {
                self.visit_expr(conditional_expr);
                if self.ty != TType::TInt32{
                    panic!("Expected conditional expression of int type");
                }
            },
            &Expr::LetExpr(ref decls, ref opt_expr) => {
                self.sym_tab.push(("<marker>".to_string(), None));

                for dec in decls{ //decls is a &
                    self.visit_decl(dec);
                }

                match opt_expr {
                    &Some(ref b_expr) => {
                        self.visit_expr(&*expr);
                    },
                    _ => {}
                }
                //pop till marker and then pop marker
                while self.sym_tab.last().unwrap().0 != "<marker>".to_string(){
                    self.sym_tab.pop();
                }
                self.sym_tab.pop();
            },

            _ => {}
        }
    }

    fn visit_decl(&mut self, decl : &'a Decl){
        macro_rules! store_into_sym_tab {
            ($self_ : ident, $i : ident, $p : path) => {
                $self_.sym_tab.push(($i.clone(), Some(B($p($self_.ty.clone())))));
            }
        }
        match decl{
            &Decl::VarDec(ref id, ref ty, ref expr) => {
                self.visit_expr(expr);
                if *ty != self.ty{
                    panic!("Types mismatch");
                }
                store_into_sym_tab!(self, id, Binding::VarBinding);
            },
            &Decl::FunDec(ref id, ref params, ref ret_type, ref body) => {
                self.visit_expr(&body);
                if self.ty != *ret_type{
                    panic!("Return type doesn't match with the type of the last expression.");
                }
                store_into_sym_tab!(self, id, Binding::FuncBinding);
            },
            &Decl::TypeDec(ref id, ref ty) => {
                store_into_sym_tab!(self, id, Binding::TypeBinding);
            }
        }
    }
}

struct PrettyPrintVisitor;

impl<'a> Visitor<'a> for PrettyPrintVisitor{
    fn visit_expr(&mut self, expr:&'a Expr){
        match expr{
            &Expr::LetExpr(ref v, _) => {
                println!("(let");
                for d in v{
                    println!("\t(");

                }
                println!(")");
            },
            &Expr::AddExpr(ref left, ref right) => {
                self.visit_expr(left);
                println!(" Plus ");
                self.visit_expr(right);
            },
            &Expr::NumExpr(value) => {
                println!(" Num({}) ", value);
            },
            &Expr::IdExpr(ref value) => {
                println!(" Ident({}) ", value);
            },
            _ => {}
        }
    }

    fn visit_block(&mut self, block: &'a Block){
        for s in &block.statements{
            self.visit_stmt(&*s);
        }
    }

    fn visit_stmt(&mut self, stmt : &'a Stmt){
        match stmt{
            &Stmt::VarDeclStmt(ref local) => {
                println!("(var {} type {} init ", local.ident, local.ty);
                self.visit_expr(&*local.expr);
                println!(")");
            },
            &Stmt::ExprStmt(ref expr) => {
                self.visit_expr(expr);
            }
        }
    }
}

//FIXME remove this struct
struct SymbolTableBuilder<'a>{
    block_stack : Vec<RefCell<&'a  Block>>
}

impl<'a> SymbolTableBuilder<'a>{
    fn new()->Self{
        SymbolTableBuilder {block_stack : Vec::new()}
    }
}

impl<'a> Visitor<'a> for SymbolTableBuilder<'a>{
    fn visit_block(&mut self, block : &'a Block){
        self.block_stack.push(RefCell::new(block));
        for s in &block.statements{
            self.visit_stmt(s);
        }
        self.block_stack.pop();
    }

    fn visit_stmt(&mut self, stmt : &'a Stmt){
        match stmt{
            &Stmt::VarDeclStmt(ref local) => {
                    //FIXME deduce the correct type
                    let mut block = self.block_stack.last_mut().unwrap().borrow_mut();
                    block.sym_tab.borrow_mut().insert(local.ident.clone(), TType::TInt32);
                },
            &Stmt::ExprStmt(ref expr) => {
                let b =  &**expr; //*expr is deref B which is Box<T>; **expr is deref Box<T> which is T; &**expr is therefore &T
                match b {
                    &Expr::BlockExpr(ref block) => {
                        self.visit_block(block);
                    },
                    _ => {}
                }
            }
        }
    }
}

#[test]
fn test_pp_visit_add_expr(){
    let mut p = PrettyPrintVisitor;
    p.visit_expr(&Expr::AddExpr(B(Expr::NumExpr(1)), B(Expr::NumExpr(2))));
}

#[test]
fn test_pp_visit_block(){
    let mut p = PrettyPrintVisitor;
    let mut b = Block::new();
    // let l = Local::new("a".to_string(), LuaType::LNil, B(Expr::NumExpr(1)));
    // b.statements.push(B(Stmt::VarDeclStmt(l)));
    p.visit_block(&b);
}

//#[test]
fn test_pp_visit_add(){
    let mut p = PrettyPrintVisitor;
    let mut b = Block::new();
    p.visit_block(&b);
}

#[test]
fn test_ty_set_for_num() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::NumExpr(23));
    assert_eq!(TType::TInt32, v.ty);
}

#[test]
fn test_ty_set_for_int_id() {
    let mut v = TypeChecker::new();
    v.sym_tab.push(("a".to_string(), Some(B(Binding::VarBinding(TType::TInt32)))));
    v.visit_expr(&Expr::IdExpr("a".to_string()));
    assert_eq!(TType::TInt32, v.ty);
}

#[test]
fn test_type_match_int_for_var_dec() {
    let mut v = TypeChecker::new();
    v.visit_decl(&Decl::VarDec("a".to_string(), TType::TInt32, B(Expr::NumExpr(4))));
    assert_eq!(TType::TInt32, v.ty);
    assert_eq!(v.sym_tab.len(), 1);
    assert_eq!(v.sym_tab[0].0, "a".to_string());
    //assert_eq!(v.sym_tab[0].1, TType::TInt32);
}

#[test]
fn test_type_match_string_for_var_dec() {
    let mut v = TypeChecker::new();
    v.visit_decl(&Decl::VarDec("a".to_string(), TType::TString, B(Expr::NilExpr)));
    assert_eq!(TType::TString, v.ty);
    assert_eq!(v.sym_tab.len(), 1);
    assert_eq!(v.sym_tab[0].0, "a".to_string());
    //assert_eq!(v.sym_tab[0].1, TType::TString);
}

#[test]
#[should_panic]
fn test_type_check_for_var_dec_type_mismatch() {
    let mut v = TypeChecker::new();
    v.visit_decl(&Decl::VarDec("a".to_string(), TType::TInt32, B(Expr::NilExpr)));
    assert_eq!(TType::TInt32, v.ty);
}

#[test]
fn test_correct_types_for_add_expr() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::AddExpr(B(Expr::NumExpr(4)), B(Expr::NumExpr(4))));
    assert_eq!(v.ty, TType::TInt32);
}

#[test]
#[should_panic(expected="Expected left operand of int type")]
fn test_left_type_invalid_for_add_expr() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::AddExpr(B(Expr::NilExpr), B(Expr::NumExpr(4))));
}

#[test]
#[should_panic(expected="Expected right operand of int type")]
fn test_right_type_invalid_for_add_expr() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::AddExpr(B(Expr::NumExpr(4)), B(Expr::NilExpr)));
}

#[test]
fn test_var_hiding() {
    //let mut v =
}

#[test]
fn test_func_decl_correct_return_type() {
    let mut v = TypeChecker::new();
    v.visit_decl(&Decl::FunDec(String::from("foo"), None, TType::TInt32, B(Expr::NumExpr(4))));
}

#[test]
#[should_panic(expected="Return type doesn't match with the type of the last expression.")]
fn test_func_decl_incorrect_return_type() {
    let mut v = TypeChecker::new();
    v.visit_decl(&Decl::FunDec(String::from("foo"), None, TType::TString, B(Expr::NumExpr(4))));
}

#[test]
#[should_panic(expected="Expected conditional expression of int type")]
fn test_if_expr_with_incorrect_conditional_type() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::IfThenExpr(B(Expr::StringExpr(String::from("a"))), B(Expr::StringExpr(String::from("a")))));
}

#[test]
fn test_if_expr_with_int_type() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::IfThenExpr(B(Expr::NumExpr(1)), B(Expr::StringExpr(String::from("a")))));
    assert_eq!(v.ty, TType::TInt32);
}
<commit_msg>Add preliminary type-checking for while-expr<commit_after>#![allow(dead_code)]

use ast::*;
use visit::{Visitor};
use std::cell::RefCell;
use ptr::*;

pub type OptionalBinding = Option<B<Binding>>;

struct ExpEvaluator{
    value : i32
}

impl ExpEvaluator{
    fn get_value(&mut self, expr : & Expr)->i32{
        match expr{
            &Expr::NumExpr(value) => value,
            _ => 1
        }
    }
}

impl<'a> Visitor<'a> for ExpEvaluator{
    fn visit_expr(&mut self, expr: &'a Expr){
        match expr{
            &Expr::AddExpr(ref left, ref right) => {
                let v1 = self.get_value(left);
                let v2 = self.get_value(right);
                self.value = v1 + v2;
            },
            _ => {}
        }
    }
}

pub struct TypeChecker{
    //block_stack : Vec<RefCell<&'a  Block>>,
    pub sym_tab : Vec<(String, OptionalBinding)>,
    //decl_cnt : u32,
    //decl_cnt_stack : Vec<u32>,
    pub ty : TType
}

impl TypeChecker{
    pub fn new()->Self{
        TypeChecker {sym_tab : Vec::new(), ty : TType::TNil}
    }

    fn get_type_for(&self){//}->&TType{
        //self.block_stack
    }
}

impl<'a> Visitor<'a> for TypeChecker{
    fn visit_expr(&mut self, expr: &'a Expr){
        match expr{
            //FIXME remove NilExpr; this is only for unit testing
            &Expr::NilExpr => self.ty = TType::TString,
            &Expr::NumExpr(_) => self.ty = TType::TInt32,
            &Expr::StringExpr(_) => self.ty = TType::TString,
            &Expr::IdExpr(ref id) =>{
                //search in the symtab for id's existence and get the type
                let mut found = false;
                for &(ref _id, ref _binding) in &self.sym_tab{ //iterator returns a ref to tuple while iterating; so &(_,_) has to be used
                    if *_id == *id{
                        found = true;
                        self.ty = match **_binding.as_ref().unwrap(){
                            Binding::TypeBinding(ref ty) |
                            Binding::VarBinding(ref ty) |
                            Binding::FuncBinding(ref ty) => ty.clone()
                        };
                        break;
                    }
                }
                if !found{
                    panic!("{} not found", id);
                }
            },
            &Expr::AddExpr(ref left, ref right) => {
                self.visit_expr(left);
                let left_ty = self.ty.clone();
                if left_ty != TType::TInt32{
                    panic!("Expected left operand of int type");
                }
                self.visit_expr(right);
                if self.ty != TType::TInt32{
                    panic!("Expected right operand of int type")
                }
            },
            &Expr::SeqExpr(ref opt_expr_list) => {
                for b_expr in opt_expr_list.as_ref().unwrap() {
                    self.visit_expr(&*b_expr);
                }
            },
            &Expr::IfThenExpr(ref conditional_expr, _) => {
                self.visit_expr(conditional_expr);
                if self.ty != TType::TInt32{
                    panic!("Expected conditional expression of int type");
                }
            },
            &Expr::WhileExpr(ref conditional_expr, _) => {
                self.visit_expr(conditional_expr);
                if self.ty != TType::TInt32{
                    panic!("Expected conditional expression of int type");
                }
            },
            &Expr::LetExpr(ref decls, ref opt_expr) => {
                self.sym_tab.push(("<marker>".to_string(), None));

                for dec in decls{ //decls is a &
                    self.visit_decl(dec);
                }

                match opt_expr {
                    &Some(ref b_expr) => {
                        self.visit_expr(&*expr);
                    },
                    _ => {}
                }
                //pop till marker and then pop marker
                while self.sym_tab.last().unwrap().0 != "<marker>".to_string(){
                    self.sym_tab.pop();
                }
                self.sym_tab.pop();
            },

            _ => {}
        }
    }

    fn visit_decl(&mut self, decl : &'a Decl){
        macro_rules! store_into_sym_tab {
            ($self_ : ident, $i : ident, $p : path) => {
                $self_.sym_tab.push(($i.clone(), Some(B($p($self_.ty.clone())))));
            }
        }
        match decl{
            &Decl::VarDec(ref id, ref ty, ref expr) => {
                self.visit_expr(expr);
                if *ty != self.ty{
                    panic!("Types mismatch");
                }
                store_into_sym_tab!(self, id, Binding::VarBinding);
            },
            &Decl::FunDec(ref id, ref params, ref ret_type, ref body) => {
                self.visit_expr(&body);
                if self.ty != *ret_type{
                    panic!("Return type doesn't match with the type of the last expression.");
                }
                store_into_sym_tab!(self, id, Binding::FuncBinding);
            },
            &Decl::TypeDec(ref id, ref ty) => {
                store_into_sym_tab!(self, id, Binding::TypeBinding);
            }
        }
    }
}

struct PrettyPrintVisitor;

impl<'a> Visitor<'a> for PrettyPrintVisitor{
    fn visit_expr(&mut self, expr:&'a Expr){
        match expr{
            &Expr::LetExpr(ref v, _) => {
                println!("(let");
                for d in v{
                    println!("\t(");

                }
                println!(")");
            },
            &Expr::AddExpr(ref left, ref right) => {
                self.visit_expr(left);
                println!(" Plus ");
                self.visit_expr(right);
            },
            &Expr::NumExpr(value) => {
                println!(" Num({}) ", value);
            },
            &Expr::IdExpr(ref value) => {
                println!(" Ident({}) ", value);
            },
            _ => {}
        }
    }

    fn visit_block(&mut self, block: &'a Block){
        for s in &block.statements{
            self.visit_stmt(&*s);
        }
    }

    fn visit_stmt(&mut self, stmt : &'a Stmt){
        match stmt{
            &Stmt::VarDeclStmt(ref local) => {
                println!("(var {} type {} init ", local.ident, local.ty);
                self.visit_expr(&*local.expr);
                println!(")");
            },
            &Stmt::ExprStmt(ref expr) => {
                self.visit_expr(expr);
            }
        }
    }
}

//FIXME remove this struct
struct SymbolTableBuilder<'a>{
    block_stack : Vec<RefCell<&'a  Block>>
}

impl<'a> SymbolTableBuilder<'a>{
    fn new()->Self{
        SymbolTableBuilder {block_stack : Vec::new()}
    }
}

impl<'a> Visitor<'a> for SymbolTableBuilder<'a>{
    fn visit_block(&mut self, block : &'a Block){
        self.block_stack.push(RefCell::new(block));
        for s in &block.statements{
            self.visit_stmt(s);
        }
        self.block_stack.pop();
    }

    fn visit_stmt(&mut self, stmt : &'a Stmt){
        match stmt{
            &Stmt::VarDeclStmt(ref local) => {
                    //FIXME deduce the correct type
                    let mut block = self.block_stack.last_mut().unwrap().borrow_mut();
                    block.sym_tab.borrow_mut().insert(local.ident.clone(), TType::TInt32);
                },
            &Stmt::ExprStmt(ref expr) => {
                let b =  &**expr; //*expr is deref B which is Box<T>; **expr is deref Box<T> which is T; &**expr is therefore &T
                match b {
                    &Expr::BlockExpr(ref block) => {
                        self.visit_block(block);
                    },
                    _ => {}
                }
            }
        }
    }
}

#[test]
fn test_pp_visit_add_expr(){
    let mut p = PrettyPrintVisitor;
    p.visit_expr(&Expr::AddExpr(B(Expr::NumExpr(1)), B(Expr::NumExpr(2))));
}

#[test]
fn test_pp_visit_block(){
    let mut p = PrettyPrintVisitor;
    let mut b = Block::new();
    // let l = Local::new("a".to_string(), LuaType::LNil, B(Expr::NumExpr(1)));
    // b.statements.push(B(Stmt::VarDeclStmt(l)));
    p.visit_block(&b);
}

//#[test]
fn test_pp_visit_add(){
    let mut p = PrettyPrintVisitor;
    let mut b = Block::new();
    p.visit_block(&b);
}

#[test]
fn test_ty_set_for_num() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::NumExpr(23));
    assert_eq!(TType::TInt32, v.ty);
}

#[test]
fn test_ty_set_for_int_id() {
    let mut v = TypeChecker::new();
    v.sym_tab.push(("a".to_string(), Some(B(Binding::VarBinding(TType::TInt32)))));
    v.visit_expr(&Expr::IdExpr("a".to_string()));
    assert_eq!(TType::TInt32, v.ty);
}

#[test]
fn test_type_match_int_for_var_dec() {
    let mut v = TypeChecker::new();
    v.visit_decl(&Decl::VarDec("a".to_string(), TType::TInt32, B(Expr::NumExpr(4))));
    assert_eq!(TType::TInt32, v.ty);
    assert_eq!(v.sym_tab.len(), 1);
    assert_eq!(v.sym_tab[0].0, "a".to_string());
    //assert_eq!(v.sym_tab[0].1, TType::TInt32);
}

#[test]
fn test_type_match_string_for_var_dec() {
    let mut v = TypeChecker::new();
    v.visit_decl(&Decl::VarDec("a".to_string(), TType::TString, B(Expr::NilExpr)));
    assert_eq!(TType::TString, v.ty);
    assert_eq!(v.sym_tab.len(), 1);
    assert_eq!(v.sym_tab[0].0, "a".to_string());
    //assert_eq!(v.sym_tab[0].1, TType::TString);
}

#[test]
#[should_panic]
fn test_type_check_for_var_dec_type_mismatch() {
    let mut v = TypeChecker::new();
    v.visit_decl(&Decl::VarDec("a".to_string(), TType::TInt32, B(Expr::NilExpr)));
    assert_eq!(TType::TInt32, v.ty);
}

#[test]
fn test_correct_types_for_add_expr() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::AddExpr(B(Expr::NumExpr(4)), B(Expr::NumExpr(4))));
    assert_eq!(v.ty, TType::TInt32);
}

#[test]
#[should_panic(expected="Expected left operand of int type")]
fn test_left_type_invalid_for_add_expr() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::AddExpr(B(Expr::NilExpr), B(Expr::NumExpr(4))));
}

#[test]
#[should_panic(expected="Expected right operand of int type")]
fn test_right_type_invalid_for_add_expr() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::AddExpr(B(Expr::NumExpr(4)), B(Expr::NilExpr)));
}

#[test]
fn test_var_hiding() {
    //let mut v =
}

#[test]
fn test_func_decl_correct_return_type() {
    let mut v = TypeChecker::new();
    v.visit_decl(&Decl::FunDec(String::from("foo"), None, TType::TInt32, B(Expr::NumExpr(4))));
}

#[test]
#[should_panic(expected="Return type doesn't match with the type of the last expression.")]
fn test_func_decl_incorrect_return_type() {
    let mut v = TypeChecker::new();
    v.visit_decl(&Decl::FunDec(String::from("foo"), None, TType::TString, B(Expr::NumExpr(4))));
}

#[test]
#[should_panic(expected="Expected conditional expression of int type")]
fn test_if_expr_with_incorrect_conditional_type() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::IfThenExpr(B(Expr::StringExpr(String::from("a"))), B(Expr::StringExpr(String::from("a")))));
}

#[test]
fn test_if_expr_with_int_type() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::IfThenExpr(B(Expr::NumExpr(1)), B(Expr::StringExpr(String::from("a")))));
    assert_eq!(v.ty, TType::TInt32);
}

#[test]
#[should_panic(expected="Expected conditional expression of int type")]
fn test_while_expr_with_incorrect_conditional_type() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::Expr(B(Expr::StringExpr(String::from("a"))), B(Expr::StringExpr(String::from("a")))));
}

#[test]
fn test_while_expr_with_int_type() {
    let mut v = TypeChecker::new();
    v.visit_expr(&Expr::WhileExpr(B(Expr::NumExpr(1)), B(Expr::StringExpr(String::from("a")))));
    assert_eq!(v.ty, TType::TInt32);
}
<|endoftext|>


<commit_before>extern crate secp256k1;
extern crate rand;
extern crate sha3;
extern crate sha2;
extern crate byteorder;
extern crate crypto;
extern crate etcommon_bigint as bigint;
extern crate etcommon_crypto as hash;
extern crate etcommon_rlp as rlp;
extern crate etcommon_util;
extern crate bytes;
#[macro_use]
extern crate futures;
extern crate tokio_io;
extern crate tokio_core;

mod util;
pub mod ecies;
mod peer;
mod mac;
mod errors;

pub use peer::{PeerStream, CapabilityInfo};

use bigint::H512;
use util::pk2id;
use hash::SECP256K1;
use secp256k1::key::{PublicKey, SecretKey};
use futures::future;
use futures::{Poll, Async, StartSend, AsyncSink, Future, Stream, Sink};
use std::io;
use std::net::SocketAddr;
use tokio_core::reactor::Handle;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Framed, Encoder, Decoder};

pub struct RLPxStream {
    streams: Vec<PeerStream>,
    futures: Vec<Box<Future<Item = PeerStream, Error = io::Error>>>,
    secret_key: SecretKey,
    protocol_version: usize,
    client_version: String,
    capabilities: Vec<CapabilityInfo>,
    port: usize,
}

impl RLPxStream {
    pub fn new(secret_key: SecretKey, protocol_version: usize,
               client_version: String, capabilities: Vec<CapabilityInfo>,
               port: usize) -> RLPxStream {
        RLPxStream {
            streams: Vec::new(),
            futures: Vec::new(),
            secret_key, protocol_version, client_version,
            capabilities, port,
        }
    }

    pub fn add_peer(
        &mut self, addr: &SocketAddr, handle: &Handle, remote_id: H512
    ) {
        let future = PeerStream::connect(addr, handle, self.secret_key.clone(),
                                         remote_id, self.protocol_version,
                                         self.client_version.clone(),
                                         self.capabilities.clone(), self.port);
        self.futures.push(future);
    }
}

fn retain_mut<T, F>(vec: &mut Vec<T>, mut f: F)
    where F: FnMut(&mut T) -> bool
{
    let len = vec.len();
    let mut del = 0;
    {
        let v = &mut **vec;

        for i in 0..len {
            if !f(&mut v[i]) {
                del += 1;
            } else if del > 0 {
                v.swap(i - del, i);
            }
        }
    }
    if del > 0 {
        vec.truncate(len - del);
    }
}

impl Stream for RLPxStream {
    type Item = (CapabilityInfo, usize, Vec<u8>);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let ref mut futures = self.futures;
        let ref mut streams = self.streams;

        retain_mut(futures, |ref mut future| {
            match future.poll() {
                Ok(Async::NotReady) => true,
                Ok(Async::Ready(peer)) => {
                    streams.push(peer);
                    false
                },
                Err(e) => false,
            }
        });

        let mut ret: Option<Self::Item> = None;
        retain_mut(streams, |ref mut peer| {
            if ret.is_some() {
                return true;
            }

            match peer.poll() {
                Ok(Async::NotReady) => true,
                Ok(Async::Ready(None)) => false,
                Ok(Async::Ready(Some(val))) => {
                    ret = Some(val);
                    true
                },
                Err(e) => false,
            }
        });

        if ret.is_some() {
            Ok(Async::Ready(ret))
        } else {
            Ok(Async::NotReady)
        }
    }
}

impl Sink for RLPxStream {
    type SinkItem = (CapabilityInfo, usize, Vec<u8>);
    type SinkError = io::Error;

    fn start_send(&mut self, (cap, id, data): (CapabilityInfo, usize, Vec<u8>)) -> StartSend<Self::SinkItem, Self::SinkError> {
        let ref mut futures = self.futures;
        let ref mut streams = self.streams;

        retain_mut(futures, |ref mut future| {
            match future.poll() {
                Ok(Async::NotReady) => true,
                Ok(Async::Ready(peer)) => {
                    streams.push(peer);
                    false
                },
                Err(e) => false,
            }
        });

        let mut any_ready = false;

        retain_mut(streams, |ref mut peer| {
            match peer.start_send((cap.clone(), id, data.clone())) {
                Ok(AsyncSink::Ready) => {
                    any_ready = true;
                    true
                },
                Ok(AsyncSink::NotReady(_)) => true,
                Err(e) => false,
            }
        });

        if any_ready {
            Ok(AsyncSink::Ready)
        } else {
            Ok(AsyncSink::NotReady((cap, id, data)))
        }
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        let ref mut streams = self.streams;

        let mut all_ready = true;

        retain_mut(streams, |ref mut peer| {
            match peer.poll_complete() {
                Ok(Async::Ready(())) => true,
                Ok(Async::NotReady) => {
                    all_ready = false;
                    true
                },
                Err(e) => false,
            }
        });

        if all_ready {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::NotReady)
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>rlpx: RLPxStream::poll_new_peers<commit_after>extern crate secp256k1;
extern crate rand;
extern crate sha3;
extern crate sha2;
extern crate byteorder;
extern crate crypto;
extern crate etcommon_bigint as bigint;
extern crate etcommon_crypto as hash;
extern crate etcommon_rlp as rlp;
extern crate etcommon_util;
extern crate bytes;
#[macro_use]
extern crate futures;
extern crate tokio_io;
extern crate tokio_core;

mod util;
pub mod ecies;
mod peer;
mod mac;
mod errors;

pub use peer::{PeerStream, CapabilityInfo};

use bigint::H512;
use util::pk2id;
use hash::SECP256K1;
use secp256k1::key::{PublicKey, SecretKey};
use futures::future;
use futures::{Poll, Async, StartSend, AsyncSink, Future, Stream, Sink};
use std::io;
use std::net::SocketAddr;
use tokio_core::reactor::Handle;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Framed, Encoder, Decoder};

pub struct RLPxStream {
    streams: Vec<PeerStream>,
    futures: Vec<Box<Future<Item = PeerStream, Error = io::Error>>>,
    secret_key: SecretKey,
    protocol_version: usize,
    client_version: String,
    capabilities: Vec<CapabilityInfo>,
    port: usize,
}

impl RLPxStream {
    pub fn new(secret_key: SecretKey, protocol_version: usize,
               client_version: String, capabilities: Vec<CapabilityInfo>,
               port: usize) -> RLPxStream {
        RLPxStream {
            streams: Vec::new(),
            futures: Vec::new(),
            secret_key, protocol_version, client_version,
            capabilities, port,
        }
    }

    pub fn add_peer(
        &mut self, addr: &SocketAddr, handle: &Handle, remote_id: H512
    ) {
        let future = PeerStream::connect(addr, handle, self.secret_key.clone(),
                                         remote_id, self.protocol_version,
                                         self.client_version.clone(),
                                         self.capabilities.clone(), self.port);
        self.futures.push(future);
    }

    pub fn poll_new_peers(&mut self) -> Poll<(), io::Error> {
        let ref mut futures = self.futures;
        let ref mut streams = self.streams;

        let mut all_ready = true;

        retain_mut(futures, |ref mut future| {
            match future.poll() {
                Ok(Async::NotReady) => {
                    all_ready = false;
                    true
                },
                Ok(Async::Ready(peer)) => {
                    streams.push(peer);
                    false
                },
                Err(e) => false,
            }
        });

        if all_ready {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::NotReady)
        }
    }
}

fn retain_mut<T, F>(vec: &mut Vec<T>, mut f: F)
    where F: FnMut(&mut T) -> bool
{
    let len = vec.len();
    let mut del = 0;
    {
        let v = &mut **vec;

        for i in 0..len {
            if !f(&mut v[i]) {
                del += 1;
            } else if del > 0 {
                v.swap(i - del, i);
            }
        }
    }
    if del > 0 {
        vec.truncate(len - del);
    }
}

impl Stream for RLPxStream {
    type Item = (CapabilityInfo, usize, Vec<u8>);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.poll_new_peers();

        let ref mut streams = self.streams;

        let mut ret: Option<Self::Item> = None;
        retain_mut(streams, |ref mut peer| {
            if ret.is_some() {
                return true;
            }

            match peer.poll() {
                Ok(Async::NotReady) => true,
                Ok(Async::Ready(None)) => false,
                Ok(Async::Ready(Some(val))) => {
                    ret = Some(val);
                    true
                },
                Err(e) => false,
            }
        });

        if ret.is_some() {
            Ok(Async::Ready(ret))
        } else {
            Ok(Async::NotReady)
        }
    }
}

impl Sink for RLPxStream {
    type SinkItem = (CapabilityInfo, usize, Vec<u8>);
    type SinkError = io::Error;

    fn start_send(&mut self, (cap, id, data): (CapabilityInfo, usize, Vec<u8>)) -> StartSend<Self::SinkItem, Self::SinkError> {
        self.poll_new_peers();

        let ref mut streams = self.streams;

        let mut any_ready = false;

        retain_mut(streams, |ref mut peer| {
            match peer.start_send((cap.clone(), id, data.clone())) {
                Ok(AsyncSink::Ready) => {
                    any_ready = true;
                    true
                },
                Ok(AsyncSink::NotReady(_)) => true,
                Err(e) => false,
            }
        });

        if any_ready {
            Ok(AsyncSink::Ready)
        } else {
            Ok(AsyncSink::NotReady((cap, id, data)))
        }
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        let ref mut streams = self.streams;

        let mut all_ready = true;

        retain_mut(streams, |ref mut peer| {
            match peer.poll_complete() {
                Ok(Async::Ready(())) => true,
                Ok(Async::NotReady) => {
                    all_ready = false;
                    true
                },
                Err(e) => false,
            }
        });

        if all_ready {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::NotReady)
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashSet, VecDeque};
use std::env;
use std::ffi::{OsStr, OsString};
use std::iter::Filter;
use std::path::PathBuf;

use nix::NixPath;

pub struct UniquePath {
    vec: VecDeque<PathBuf>,
}

pub struct Iter<'a, T: Iterator<Item=&'a PathBuf>> {
    filter: Filter<T, fn(&&PathBuf) -> bool>,
    set: HashSet<&'a PathBuf>,
}

impl<'a, T: Iterator<Item=&'a PathBuf>> From<T> for Iter<'a, T> {
    fn from(iter: T) -> Self {
        Self {
            filter: iter.filter(|p: &&PathBuf| p.len() > 0),
            set: HashSet::new(),
        }
    }
}

impl<'a, T: Iterator<Item=&'a PathBuf>> Iterator for Iter<'a, T> {
    type Item = &'a PathBuf;

    fn next(&mut self) -> Option<Self::Item> {
        let set = &self.set;
        self.filter
            .find(|&x| !set.contains(x))
            .map(|x| {
                self.set.insert(x);
                x
            })
    }
}

impl UniquePath {
    pub fn make(&self) -> OsString {
        return env::join_paths(self.unique()).expect("join unique path error");
    }

    pub fn unique(&self) -> impl Iterator<Item=&PathBuf> {
        Iter::from(self.vec.iter())
    }

    pub fn push_front<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_front(path.into())
    }

    pub fn push_back<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_back(path.into())
    }

    pub fn parse<T: AsRef<OsStr>>(input: T) -> Self {
        let mut vec = VecDeque::new();
        for s in env::split_paths(input.as_ref()) {
            vec.push_back(s);
        }
        Self { vec }
    }

    pub fn new() -> Self {
        Self {
            vec: VecDeque::new(),
        }
    }
}

#[cfg(test)]
mod tests {
    // Note this useful idiom: importing names from outer (for mod tests) scope.
    use super::*;

    const FOO: &str = "/foo";
    const BAR: &str = "/bar";

    #[test]
    fn test() {
        // no item
        let ps = UniquePath::parse(OsString::from(""));
        let actual = ps.make();
        assert_eq!(actual, "");

        // no item add one to front
        let mut ps = UniquePath::parse(OsString::from(""));
        ps.push_front(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add one to back
        let mut ps = UniquePath::parse(OsString::from(""));
        ps.push_back(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // one item
        let ps = UniquePath::parse(OsString::from(FOO));
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // two items
        let input = OsString::from(format!("{}:{}", FOO, BAR));
        let ps = UniquePath::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, input);

        // move order correctly
        let input = OsString::from("/a:/b:/c");
        let mut ps = UniquePath::parse(&input);
        ps.push_front("/c".to_string());
        let actual = ps.make();
        let expect = OsString::from("/c:/a:/b");
        assert_eq!(actual, expect);
    }
}
<commit_msg>nmk.rs: clearer generic type bound<commit_after>use std::collections::{HashSet, VecDeque};
use std::env;
use std::ffi::{OsStr, OsString};
use std::iter::Filter;
use std::path::PathBuf;

use nix::NixPath;

pub struct UniquePath {
    vec: VecDeque<PathBuf>,
}

pub struct Iter<'a, T> {
    filter: Filter<T, fn(&&PathBuf) -> bool>,
    set: HashSet<&'a PathBuf>,
}

impl<'a, T> From<T> for Iter<'a, T> where
    T: Iterator<Item=&'a PathBuf> {
    fn from(iter: T) -> Self {
        Self {
            filter: iter.filter(|p: &&PathBuf| p.len() > 0),
            set: HashSet::new(),
        }
    }
}

impl<'a, T> Iterator for Iter<'a, T>
    where T: Iterator<Item=&'a PathBuf> {
    type Item = &'a PathBuf;

    fn next(&mut self) -> Option<Self::Item> {
        let set = &self.set;
        self.filter
            .find(|&x| !set.contains(x))
            .map(|x| {
                self.set.insert(x);
                x
            })
    }
}

impl UniquePath {
    pub fn make(&self) -> OsString {
        return env::join_paths(self.unique()).expect("join unique path error");
    }

    pub fn unique(&self) -> impl Iterator<Item=&PathBuf> {
        Iter::from(self.vec.iter())
    }

    pub fn push_front<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_front(path.into())
    }

    pub fn push_back<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_back(path.into())
    }

    pub fn parse<T: AsRef<OsStr>>(input: T) -> Self {
        let mut vec = VecDeque::new();
        for s in env::split_paths(input.as_ref()) {
            vec.push_back(s);
        }
        Self { vec }
    }

    pub fn new() -> Self {
        Self {
            vec: VecDeque::new(),
        }
    }
}

#[cfg(test)]
mod tests {
    // Note this useful idiom: importing names from outer (for mod tests) scope.
    use super::*;

    const FOO: &str = "/foo";
    const BAR: &str = "/bar";

    #[test]
    fn test() {
        // no item
        let ps = UniquePath::parse(OsString::from(""));
        let actual = ps.make();
        assert_eq!(actual, "");

        // no item add one to front
        let mut ps = UniquePath::parse(OsString::from(""));
        ps.push_front(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add one to back
        let mut ps = UniquePath::parse(OsString::from(""));
        ps.push_back(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // one item
        let ps = UniquePath::parse(OsString::from(FOO));
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // two items
        let input = OsString::from(format!("{}:{}", FOO, BAR));
        let ps = UniquePath::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, input);

        // move order correctly
        let input = OsString::from("/a:/b:/c");
        let mut ps = UniquePath::parse(&input);
        ps.push_front("/c".to_string());
        let actual = ps.make();
        let expect = OsString::from("/c:/a:/b");
        assert_eq!(actual, expect);
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::env;
use std::ffi::{OsStr, OsString};
use std::path::PathBuf;

use indexmap::IndexSet;
use nix::NixPath;

pub struct PathVec {
    vec: VecDeque<PathBuf>,
}

impl PathVec {
    pub fn make(&self) -> OsString {
        return env::join_paths(self.unique()).expect("join unique path error");
    }

    pub fn iter(&self) -> impl Iterator<Item=&PathBuf> {
        self.vec.iter()
    }

    pub fn unique(&self) -> Self {
        let vec = self.vec.iter().map(|x| x.to_owned())
            .collect::<IndexSet<_>>()
            .into_iter().filter(|x| x.len() > 0)
            .collect::<VecDeque<_>>();
        Self {
            vec
        }
    }

    pub fn no_version_managers(&self) -> Self {
        let vec = self.vec.clone().into_iter().filter(|x| {
            !x.ends_with(".pyenv/shims") && !x.ends_with(".rbenv/shims")
        }).collect::<VecDeque<_>>();
        Self {
            vec
        }
    }

    pub fn push_front<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_front(path.into())
    }

    #[allow(dead_code)]
    pub fn push_back<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_back(path.into())
    }

    pub fn parse<T: AsRef<OsStr>>(input: T) -> Self {
        let mut vec = VecDeque::new();
        for s in env::split_paths(input.as_ref()) {
            vec.push_back(s);
        }
        Self { vec }
    }

    pub fn new() -> Self {
        Self {
            vec: VecDeque::new(),
        }
    }
}

impl IntoIterator for PathVec {
    type Item = PathBuf;
    type IntoIter = std::collections::vec_deque::IntoIter<PathBuf>;

    fn into_iter(self) -> Self::IntoIter {
        self.vec.into_iter()
    }
}

#[cfg(test)]
mod tests {
    // Note this useful idiom: importing names from outer (for mod tests) scope.
    use super::*;

    const FOO: &str = "/foo";
    const BAR: &str = "/bar";

    #[test]
    fn test() {
        // no item
        let ps = PathVec::parse(OsString::from(""));
        let actual = ps.make();
        assert_eq!(actual, "");

        // no item add one to front
        let mut ps = PathVec::parse(OsString::from(""));
        ps.push_front(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add one to back
        let mut ps = PathVec::parse(OsString::from(""));
        ps.push_back(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // one item
        let ps = PathVec::parse(OsString::from(FOO));
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // two items
        let input = OsString::from(format!("{}:{}", FOO, BAR));
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, input);

        // move order correctly
        let input = OsString::from("/a:/b:/c");
        let mut ps = PathVec::parse(&input);
        ps.push_front("/c".to_string());
        let actual = ps.make();
        let expect = OsString::from("/c:/a:/b");
        assert_eq!(actual, expect);

        // remove pyenv, rbenv, and node path
        let input = OsString::from("/a:/home/.pyenv/shims:/home/.rbenv/shims");
        let mut ps = PathVec::parse(&input).no_version_managers();
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a"))
    }
}
<commit_msg>nmk.rs: cosmetic changes<commit_after>use std::collections::VecDeque;
use std::env;
use std::ffi::{OsStr, OsString};
use std::path::PathBuf;

use indexmap::IndexSet;
use nix::NixPath;

pub struct PathVec {
    vec: VecDeque<PathBuf>,
}

impl PathVec {
    pub fn make(&self) -> OsString {
        return env::join_paths(self.unique()).expect("join path error");
    }

    pub fn iter(&self) -> impl Iterator<Item=&PathBuf> {
        self.vec.iter()
    }

    pub fn unique(&self) -> Self {
        let vec = self.vec.iter().map(|x| x.to_owned())
            .collect::<IndexSet<_>>()
            .into_iter().filter(|x| x.len() > 0)
            .collect::<VecDeque<_>>();
        Self {
            vec
        }
    }

    pub fn no_version_managers(&self) -> Self {
        let vec = self.vec.clone().into_iter().filter(|x| {
            !x.ends_with(".pyenv/shims") && !x.ends_with(".rbenv/shims")
        }).collect();
        Self {
            vec
        }
    }

    pub fn push_front<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_front(path.into())
    }

    #[allow(dead_code)]
    pub fn push_back<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_back(path.into())
    }

    pub fn parse<T: AsRef<OsStr>>(input: T) -> Self {
        let mut vec = VecDeque::new();
        for s in env::split_paths(input.as_ref()) {
            vec.push_back(s);
        }
        Self { vec }
    }

    pub fn new() -> Self {
        Self {
            vec: VecDeque::new(),
        }
    }
}

impl IntoIterator for PathVec {
    type Item = PathBuf;
    type IntoIter = std::collections::vec_deque::IntoIter<PathBuf>;

    fn into_iter(self) -> Self::IntoIter {
        self.vec.into_iter()
    }
}

#[cfg(test)]
mod tests {
    // Note this useful idiom: importing names from outer (for mod tests) scope.
    use super::*;

    const FOO: &str = "/foo";
    const BAR: &str = "/bar";

    #[test]
    fn test() {
        // no item
        let ps = PathVec::parse(OsString::from(""));
        let actual = ps.make();
        assert_eq!(actual, "");

        // no item add one to front
        let mut ps = PathVec::parse(OsString::from(""));
        ps.push_front(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add one to back
        let mut ps = PathVec::parse(OsString::from(""));
        ps.push_back(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // one item
        let ps = PathVec::parse(OsString::from(FOO));
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // two items
        let input = OsString::from(format!("{}:{}", FOO, BAR));
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, input);

        // move order correctly
        let input = OsString::from("/a:/b:/c");
        let mut ps = PathVec::parse(&input);
        ps.push_front("/c".to_string());
        let actual = ps.make();
        let expect = OsString::from("/c:/a:/b");
        assert_eq!(actual, expect);

        // remove pyenv, rbenv, and node path
        let input = OsString::from("/a:/home/.pyenv/shims:/home/.rbenv/shims");
        let mut ps = PathVec::parse(&input).no_version_managers();
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a"))
    }
}
<|endoftext|>


<commit_before>pub mod application_command;
pub mod autocomplete;
pub mod message_component;
pub mod modal;
pub mod ping;

use application_command::ApplicationCommandInteraction;
use autocomplete::AutocompleteInteraction;
use message_component::MessageComponentInteraction;
use modal::ModalSubmitInteraction;
use ping::PingInteraction;
use serde::de::{Deserialize, Deserializer, Error as DeError};
use serde::ser::{Serialize, Serializer};

use super::prelude::*;
use crate::internal::prelude::*;
use crate::json::{from_value, Value};

#[derive(Clone, Debug)]
pub enum Interaction {
    Ping(PingInteraction),
    ApplicationCommand(ApplicationCommandInteraction),
    MessageComponent(MessageComponentInteraction),
    Autocomplete(AutocompleteInteraction),
    ModalSubmit(ModalSubmitInteraction),
}

impl Interaction {
    /// Gets the interaction Id.
    pub fn id(&self) -> InteractionId {
        match self {
            Interaction::Ping(i) => i.id,
            Interaction::ApplicationCommand(i) => i.id,
            Interaction::MessageComponent(i) => i.id,
            Interaction::Autocomplete(i) => i.id,
            Interaction::ModalSubmit(i) => i.id,
        }
    }

    /// Gets the interaction type
    pub fn kind(&self) -> InteractionType {
        match self {
            Interaction::Ping(_) => InteractionType::Ping,
            Interaction::ApplicationCommand(_) => InteractionType::ApplicationCommand,
            Interaction::MessageComponent(_) => InteractionType::MessageComponent,
            Interaction::Autocomplete(_) => InteractionType::Autocomplete,
            Interaction::ModalSubmit(_) => InteractionType::ModalSubmit,
        }
    }

    /// Gets the interaction application Id
    pub fn application_id(&self) -> ApplicationId {
        match self {
            Interaction::Ping(i) => i.application_id,
            Interaction::ApplicationCommand(i) => i.application_id,
            Interaction::MessageComponent(i) => i.application_id,
            Interaction::Autocomplete(i) => i.application_id,
            Interaction::ModalSubmit(i) => i.application_id,
        }
    }

    /// Gets the interaction token.
    pub fn token(&self) -> &str {
        match self {
            Interaction::Ping(ref i) => i.token.as_str(),
            Interaction::ApplicationCommand(i) => i.token.as_str(),
            Interaction::MessageComponent(i) => i.token.as_str(),
            Interaction::Autocomplete(i) => i.token.as_str(),
            Interaction::ModalSubmit(i) => i.token.as_str(),
        }
    }

    /// Gets the invoked guild locale.
    pub fn guild_locale(&self) -> Option<&str> {
        match self {
            Interaction::Ping(i) => i.guild_locale.as_deref(),
            Interaction::ApplicationCommand(i) => i.guild_locale.as_deref(),
            Interaction::MessageComponent(i) => i.guild_locale.as_deref(),
            Interaction::Autocomplete(i) => i.guild_locale.as_deref(),
            Interaction::ModalSubmit(i) => i.guild_locale.as_deref(),
        }
    }

    /// Converts this to a [`PingInteraction`]
    pub fn ping(self) -> Option<PingInteraction> {
        match self {
            Interaction::Ping(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to an [`ApplicationCommandInteraction`]
    pub fn application_command(self) -> Option<ApplicationCommandInteraction> {
        match self {
            Interaction::ApplicationCommand(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to a [`MessageComponentInteraction`]
    pub fn message_component(self) -> Option<MessageComponentInteraction> {
        match self {
            Interaction::MessageComponent(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to a [`AutocompleteInteraction`]
    pub fn autocomplete(self) -> Option<AutocompleteInteraction> {
        match self {
            Interaction::Autocomplete(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to a [`ModalSubmitInteraction`]
    pub fn modal_submit(self) -> Option<ModalSubmitInteraction> {
        match self {
            Interaction::ModalSubmit(i) => Some(i),
            _ => None,
        }
    }
}

impl<'de> Deserialize<'de> for Interaction {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
        let map = JsonMap::deserialize(deserializer)?;

        let kind = map
            .get("type")
            .ok_or_else(|| DeError::custom("expected type"))
            .and_then(InteractionType::deserialize)
            .map_err(DeError::custom)?;

        match kind {
            InteractionType::Ping => from_value::<PingInteraction>(Value::from(map))
                .map(Interaction::Ping)
                .map_err(DeError::custom),
            InteractionType::ApplicationCommand => {
                from_value::<ApplicationCommandInteraction>(Value::from(map))
                    .map(Interaction::ApplicationCommand)
                    .map_err(DeError::custom)
            },
            InteractionType::MessageComponent => {
                from_value::<MessageComponentInteraction>(Value::from(map))
                    .map(Interaction::MessageComponent)
                    .map_err(DeError::custom)
            },
            InteractionType::Autocomplete => {
                from_value::<AutocompleteInteraction>(Value::from(map))
                    .map(Interaction::Autocomplete)
                    .map_err(DeError::custom)
            },
            InteractionType::ModalSubmit => from_value::<ModalSubmitInteraction>(Value::from(map))
                .map(Interaction::ModalSubmit)
                .map_err(DeError::custom),
            InteractionType::Unknown => Err(DeError::custom("Unknown interaction type")),
        }
    }
}

impl Serialize for Interaction {
    fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Interaction::Ping(i) => PingInteraction::serialize(i, serializer),
            Interaction::ApplicationCommand(i) => {
                ApplicationCommandInteraction::serialize(i, serializer)
            },
            Interaction::MessageComponent(i) => {
                MessageComponentInteraction::serialize(i, serializer)
            },
            Interaction::Autocomplete(i) => AutocompleteInteraction::serialize(i, serializer),
            Interaction::ModalSubmit(i) => ModalSubmitInteraction::serialize(i, serializer),
        }
    }
}

/// The type of an Interaction.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
#[repr(u8)]
pub enum InteractionType {
    Ping = 1,
    ApplicationCommand = 2,
    MessageComponent = 3,
    Autocomplete = 4,
    ModalSubmit = 5,
    Unknown = !0,
}

enum_number!(InteractionType {
    Ping,
    MessageComponent,
    ApplicationCommand,
    Autocomplete,
    ModalSubmit
});

bitflags! {
    /// The flags for an interaction response.
    #[derive(Default)]
    pub struct InteractionApplicationCommandCallbackDataFlags: u64 {
        /// Interaction message will only be visible to sender and will
        /// be quickly deleted.
        const EPHEMERAL = 1 << 6;
    }
}

/// Sent when a [`Message`] is a response to an [`Interaction`].
///
/// [`Message`]: crate::model::channel::Message
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MessageInteraction {
    /// The id of the interaction.
    pub id: InteractionId,
    /// The type of the interaction.
    #[serde(rename = "type")]
    pub kind: InteractionType,
    /// The name of the [`ApplicationCommand`].
    ///
    /// [`ApplicationCommand`]: crate::model::interactions::application_command::ApplicationCommand
    pub name: String,
    /// The user who invoked the interaction.
    pub user: User,
}

/// The available responses types for an interaction response.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
#[repr(u8)]
pub enum InteractionResponseType {
    Pong = 1,
    ChannelMessageWithSource = 4,
    DeferredChannelMessageWithSource = 5,
    DeferredUpdateMessage = 6,
    UpdateMessage = 7,
    Autocomplete = 8,
    Modal = 9,
}
<commit_msg>Add `SUPPRESS_EMBEDS` flag for interaction response messages (#1873)<commit_after>pub mod application_command;
pub mod autocomplete;
pub mod message_component;
pub mod modal;
pub mod ping;

use application_command::ApplicationCommandInteraction;
use autocomplete::AutocompleteInteraction;
use message_component::MessageComponentInteraction;
use modal::ModalSubmitInteraction;
use ping::PingInteraction;
use serde::de::{Deserialize, Deserializer, Error as DeError};
use serde::ser::{Serialize, Serializer};

use super::prelude::*;
use crate::internal::prelude::*;
use crate::json::{from_value, Value};

#[derive(Clone, Debug)]
pub enum Interaction {
    Ping(PingInteraction),
    ApplicationCommand(ApplicationCommandInteraction),
    MessageComponent(MessageComponentInteraction),
    Autocomplete(AutocompleteInteraction),
    ModalSubmit(ModalSubmitInteraction),
}

impl Interaction {
    /// Gets the interaction Id.
    pub fn id(&self) -> InteractionId {
        match self {
            Interaction::Ping(i) => i.id,
            Interaction::ApplicationCommand(i) => i.id,
            Interaction::MessageComponent(i) => i.id,
            Interaction::Autocomplete(i) => i.id,
            Interaction::ModalSubmit(i) => i.id,
        }
    }

    /// Gets the interaction type
    pub fn kind(&self) -> InteractionType {
        match self {
            Interaction::Ping(_) => InteractionType::Ping,
            Interaction::ApplicationCommand(_) => InteractionType::ApplicationCommand,
            Interaction::MessageComponent(_) => InteractionType::MessageComponent,
            Interaction::Autocomplete(_) => InteractionType::Autocomplete,
            Interaction::ModalSubmit(_) => InteractionType::ModalSubmit,
        }
    }

    /// Gets the interaction application Id
    pub fn application_id(&self) -> ApplicationId {
        match self {
            Interaction::Ping(i) => i.application_id,
            Interaction::ApplicationCommand(i) => i.application_id,
            Interaction::MessageComponent(i) => i.application_id,
            Interaction::Autocomplete(i) => i.application_id,
            Interaction::ModalSubmit(i) => i.application_id,
        }
    }

    /// Gets the interaction token.
    pub fn token(&self) -> &str {
        match self {
            Interaction::Ping(ref i) => i.token.as_str(),
            Interaction::ApplicationCommand(i) => i.token.as_str(),
            Interaction::MessageComponent(i) => i.token.as_str(),
            Interaction::Autocomplete(i) => i.token.as_str(),
            Interaction::ModalSubmit(i) => i.token.as_str(),
        }
    }

    /// Gets the invoked guild locale.
    pub fn guild_locale(&self) -> Option<&str> {
        match self {
            Interaction::Ping(i) => i.guild_locale.as_deref(),
            Interaction::ApplicationCommand(i) => i.guild_locale.as_deref(),
            Interaction::MessageComponent(i) => i.guild_locale.as_deref(),
            Interaction::Autocomplete(i) => i.guild_locale.as_deref(),
            Interaction::ModalSubmit(i) => i.guild_locale.as_deref(),
        }
    }

    /// Converts this to a [`PingInteraction`]
    pub fn ping(self) -> Option<PingInteraction> {
        match self {
            Interaction::Ping(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to an [`ApplicationCommandInteraction`]
    pub fn application_command(self) -> Option<ApplicationCommandInteraction> {
        match self {
            Interaction::ApplicationCommand(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to a [`MessageComponentInteraction`]
    pub fn message_component(self) -> Option<MessageComponentInteraction> {
        match self {
            Interaction::MessageComponent(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to a [`AutocompleteInteraction`]
    pub fn autocomplete(self) -> Option<AutocompleteInteraction> {
        match self {
            Interaction::Autocomplete(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to a [`ModalSubmitInteraction`]
    pub fn modal_submit(self) -> Option<ModalSubmitInteraction> {
        match self {
            Interaction::ModalSubmit(i) => Some(i),
            _ => None,
        }
    }
}

impl<'de> Deserialize<'de> for Interaction {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
        let map = JsonMap::deserialize(deserializer)?;

        let kind = map
            .get("type")
            .ok_or_else(|| DeError::custom("expected type"))
            .and_then(InteractionType::deserialize)
            .map_err(DeError::custom)?;

        match kind {
            InteractionType::Ping => from_value::<PingInteraction>(Value::from(map))
                .map(Interaction::Ping)
                .map_err(DeError::custom),
            InteractionType::ApplicationCommand => {
                from_value::<ApplicationCommandInteraction>(Value::from(map))
                    .map(Interaction::ApplicationCommand)
                    .map_err(DeError::custom)
            },
            InteractionType::MessageComponent => {
                from_value::<MessageComponentInteraction>(Value::from(map))
                    .map(Interaction::MessageComponent)
                    .map_err(DeError::custom)
            },
            InteractionType::Autocomplete => {
                from_value::<AutocompleteInteraction>(Value::from(map))
                    .map(Interaction::Autocomplete)
                    .map_err(DeError::custom)
            },
            InteractionType::ModalSubmit => from_value::<ModalSubmitInteraction>(Value::from(map))
                .map(Interaction::ModalSubmit)
                .map_err(DeError::custom),
            InteractionType::Unknown => Err(DeError::custom("Unknown interaction type")),
        }
    }
}

impl Serialize for Interaction {
    fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Interaction::Ping(i) => PingInteraction::serialize(i, serializer),
            Interaction::ApplicationCommand(i) => {
                ApplicationCommandInteraction::serialize(i, serializer)
            },
            Interaction::MessageComponent(i) => {
                MessageComponentInteraction::serialize(i, serializer)
            },
            Interaction::Autocomplete(i) => AutocompleteInteraction::serialize(i, serializer),
            Interaction::ModalSubmit(i) => ModalSubmitInteraction::serialize(i, serializer),
        }
    }
}

/// The type of an Interaction.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
#[repr(u8)]
pub enum InteractionType {
    Ping = 1,
    ApplicationCommand = 2,
    MessageComponent = 3,
    Autocomplete = 4,
    ModalSubmit = 5,
    Unknown = !0,
}

enum_number!(InteractionType {
    Ping,
    MessageComponent,
    ApplicationCommand,
    Autocomplete,
    ModalSubmit
});

bitflags! {
    /// The flags for an interaction response.
    #[derive(Default)]
    pub struct InteractionApplicationCommandCallbackDataFlags: u64 {
        /// Do not include any embeds when serializing this message.
        const SUPPRESS_EMBEDS = 1 << 2;
        /// Interaction message will only be visible to sender and will
        /// be quickly deleted.
        const EPHEMERAL = 1 << 6;
    }
}

/// Sent when a [`Message`] is a response to an [`Interaction`].
///
/// [`Message`]: crate::model::channel::Message
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MessageInteraction {
    /// The id of the interaction.
    pub id: InteractionId,
    /// The type of the interaction.
    #[serde(rename = "type")]
    pub kind: InteractionType,
    /// The name of the [`ApplicationCommand`].
    ///
    /// [`ApplicationCommand`]: crate::model::interactions::application_command::ApplicationCommand
    pub name: String,
    /// The user who invoked the interaction.
    pub user: User,
}

/// The available responses types for an interaction response.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
#[repr(u8)]
pub enum InteractionResponseType {
    Pong = 1,
    ChannelMessageWithSource = 4,
    DeferredChannelMessageWithSource = 5,
    DeferredUpdateMessage = 6,
    UpdateMessage = 7,
    Autocomplete = 8,
    Modal = 9,
}
<|endoftext|>


<commit_before>use crate::{TokenTree, Subtree, Leaf};

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct EntryId(usize);

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct EntryPtr(EntryId, usize);

/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
#[derive(Debug)]
enum Entry {
    // Mimicking types from proc-macro.
    Subtree(Subtree, EntryId),
    Leaf(Leaf),
    // End entries contain a pointer to the entry from the containing
    // token tree, or None if this is the outermost level.
    End(Option<EntryPtr>),
}

/// A token tree buffer
/// The safe version of `syn` [`TokenBuffer`](https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L41)
#[derive(Debug)]
pub struct TokenBuffer {
    buffers: Vec<Box<[Entry]>>,
}

impl TokenBuffer {
    pub fn new(tokens: &[TokenTree]) -> TokenBuffer {
        let mut buffers = vec![];

        let idx = TokenBuffer::new_inner(tokens, &mut buffers, None);
        assert_eq!(idx, 0);

        TokenBuffer { buffers }
    }

    fn new_inner(
        tokens: &[TokenTree],
        buffers: &mut Vec<Box<[Entry]>>,
        next: Option<EntryPtr>,
    ) -> usize {
        let mut entries = vec![];
        let mut children = vec![];

        for (idx, tt) in tokens.iter().cloned().enumerate() {
            match tt {
                TokenTree::Leaf(leaf) => {
                    entries.push(Entry::Leaf(leaf));
                }
                TokenTree::Subtree(subtree) => {
                    entries.push(Entry::End(None));
                    children.push((idx, subtree));
                }
            }
        }

        entries.push(Entry::End(next));
        let res = buffers.len();
        buffers.push(entries.into_boxed_slice());

        for (child_idx, subtree) in children {
            let idx = TokenBuffer::new_inner(
                &subtree.token_trees,
                buffers,
                Some(EntryPtr(EntryId(res), child_idx + 1)),
            );
            buffers[res].as_mut()[child_idx] = Entry::Subtree(subtree, EntryId(idx));
        }

        res
    }

    /// Creates a cursor referencing the first token in the buffer and able to
    /// traverse until the end of the buffer.
    pub fn begin(&self) -> Cursor {
        Cursor::create(self, EntryPtr(EntryId(0), 0))
    }

    fn entry(&self, ptr: &EntryPtr) -> Option<&Entry> {
        let id = ptr.0;
        self.buffers[id.0].get(ptr.1)
    }
}

/// A safe version of `Cursor` from `syn` crate https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L125
#[derive(Copy, Clone, Debug)]
pub struct Cursor<'a> {
    buffer: &'a TokenBuffer,
    ptr: EntryPtr,
}

impl<'a> PartialEq for Cursor<'a> {
    fn eq(&self, other: &Cursor) -> bool {
        self.ptr == other.ptr && std::ptr::eq(self.buffer, other.buffer)
    }
}

impl<'a> Eq for Cursor<'a> {}

impl<'a> Cursor<'a> {
    /// Check whether it is eof
    pub fn eof(self) -> bool {
        match self.buffer.entry(&self.ptr) {
            None | Some(Entry::End(None)) => true,
            _ => false,
        }
    }

    /// If the cursor is pointing at the end of a subtree, returns
    /// the parent subtree
    pub fn end(self) -> Option<(&'a Subtree)> {
        match self.entry() {
            Some(Entry::End(Some(ptr))) => {
                let idx = ptr.1;
                if let Some(Entry::Subtree(subtree, _)) =
                    self.buffer.entry(&EntryPtr(ptr.0, idx - 1))
                {
                    return Some(subtree);
                }

                None
            }
            _ => None,
        }
    }

    fn entry(self) -> Option<(&'a Entry)> {
        self.buffer.entry(&self.ptr)
    }

    /// If the cursor is pointing at a `Subtree`, returns
    /// a cursor into that subtree
    pub fn subtree(self) -> Option<Cursor<'a>> {
        match self.entry() {
            Some(Entry::Subtree(_, entry_id)) => {
                Some(Cursor::create(self.buffer, EntryPtr(*entry_id, 0)))
            }
            _ => None,
        }
    }

    /// If the cursor is pointing at a `TokenTree`, returns it
    pub fn token_tree(self) -> Option<(TokenTree)> {
        match self.entry() {
            Some(Entry::Leaf(leaf)) => Some(leaf.clone().into()),
            Some(Entry::Subtree(subtree, _)) => Some(subtree.clone().into()),
            Some(Entry::End(_)) => None,
            None => None,
        }
    }

    fn create(buffer: &'a TokenBuffer, ptr: EntryPtr) -> Cursor<'a> {
        Cursor { buffer, ptr }
    }

    /// Bump the cursor
    pub fn bump(self) -> Cursor<'a> {
        if let Some(Entry::End(exit)) = self.buffer.entry(&self.ptr) {
            if let Some(exit) = exit {
                Cursor::create(self.buffer, *exit)
            } else {
                self
            }
        } else {
            Cursor::create(self.buffer, EntryPtr(self.ptr.0, self.ptr.1 + 1))
        }
    }
}
<commit_msg>Add more helper func in Cursor<commit_after>use crate::{TokenTree, Subtree, Leaf};

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct EntryId(usize);

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct EntryPtr(EntryId, usize);

/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
#[derive(Debug)]
enum Entry {
    // Mimicking types from proc-macro.
    Subtree(Subtree, EntryId),
    Leaf(Leaf),
    // End entries contain a pointer to the entry from the containing
    // token tree, or None if this is the outermost level.
    End(Option<EntryPtr>),
}

/// A token tree buffer
/// The safe version of `syn` [`TokenBuffer`](https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L41)
#[derive(Debug)]
pub struct TokenBuffer {
    buffers: Vec<Box<[Entry]>>,
}

impl TokenBuffer {
    pub fn new(tokens: &[TokenTree]) -> TokenBuffer {
        let mut buffers = vec![];

        let idx = TokenBuffer::new_inner(tokens, &mut buffers, None);
        assert_eq!(idx, 0);

        TokenBuffer { buffers }
    }

    fn new_inner(
        tokens: &[TokenTree],
        buffers: &mut Vec<Box<[Entry]>>,
        next: Option<EntryPtr>,
    ) -> usize {
        let mut entries = vec![];
        let mut children = vec![];

        for (idx, tt) in tokens.iter().cloned().enumerate() {
            match tt {
                TokenTree::Leaf(leaf) => {
                    entries.push(Entry::Leaf(leaf));
                }
                TokenTree::Subtree(subtree) => {
                    entries.push(Entry::End(None));
                    children.push((idx, subtree));
                }
            }
        }

        entries.push(Entry::End(next));
        let res = buffers.len();
        buffers.push(entries.into_boxed_slice());

        for (child_idx, subtree) in children {
            let idx = TokenBuffer::new_inner(
                &subtree.token_trees,
                buffers,
                Some(EntryPtr(EntryId(res), child_idx + 1)),
            );
            buffers[res].as_mut()[child_idx] = Entry::Subtree(subtree, EntryId(idx));
        }

        res
    }

    /// Creates a cursor referencing the first token in the buffer and able to
    /// traverse until the end of the buffer.
    pub fn begin(&self) -> Cursor {
        Cursor::create(self, EntryPtr(EntryId(0), 0))
    }

    fn entry(&self, ptr: &EntryPtr) -> Option<&Entry> {
        let id = ptr.0;
        self.buffers[id.0].get(ptr.1)
    }
}

/// A safe version of `Cursor` from `syn` crate https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L125
#[derive(Copy, Clone, Debug)]
pub struct Cursor<'a> {
    buffer: &'a TokenBuffer,
    ptr: EntryPtr,
}

impl<'a> PartialEq for Cursor<'a> {
    fn eq(&self, other: &Cursor) -> bool {
        self.ptr == other.ptr && std::ptr::eq(self.buffer, other.buffer)
    }
}

impl<'a> Eq for Cursor<'a> {}

impl<'a> Cursor<'a> {
    /// Check whether it is eof
    pub fn eof(self) -> bool {
        match self.buffer.entry(&self.ptr) {
            None | Some(Entry::End(None)) => true,
            _ => false,
        }
    }

    /// If the cursor is pointing at the end of a subtree, returns
    /// the parent subtree
    pub fn end(self) -> Option<(&'a Subtree)> {
        match self.entry() {
            Some(Entry::End(Some(ptr))) => {
                let idx = ptr.1;
                if let Some(Entry::Subtree(subtree, _)) =
                    self.buffer.entry(&EntryPtr(ptr.0, idx - 1))
                {
                    return Some(subtree);
                }

                None
            }
            _ => None,
        }
    }

    fn entry(self) -> Option<(&'a Entry)> {
        self.buffer.entry(&self.ptr)
    }

    /// If the cursor is pointing at a `Subtree`, returns
    /// a cursor into that subtree
    pub fn subtree(self) -> Option<Cursor<'a>> {
        match self.entry() {
            Some(Entry::Subtree(_, entry_id)) => {
                Some(Cursor::create(self.buffer, EntryPtr(*entry_id, 0)))
            }
            _ => None,
        }
    }

    /// If the cursor is pointing at a `TokenTree`, returns it
    pub fn token_tree(self) -> Option<(TokenTree)> {
        match self.entry() {
            Some(Entry::Leaf(leaf)) => Some(leaf.clone().into()),
            Some(Entry::Subtree(subtree, _)) => Some(subtree.clone().into()),
            Some(Entry::End(_)) => None,
            None => None,
        }
    }

    fn create(buffer: &'a TokenBuffer, ptr: EntryPtr) -> Cursor<'a> {
        Cursor { buffer, ptr }
    }

    /// Bump the cursor
    pub fn bump(self) -> Cursor<'a> {
        if let Some(Entry::End(exit)) = self.buffer.entry(&self.ptr) {
            if let Some(exit) = exit {
                Cursor::create(self.buffer, *exit)
            } else {
                self
            }
        } else {
            Cursor::create(self.buffer, EntryPtr(self.ptr.0, self.ptr.1 + 1))
        }
    }

    /// Bump the cursor, if it is a subtree, returns
    /// a cursor into that subtree
    pub fn bump_subtree(self) -> Cursor<'a> {
        match self.entry() {
            Some(Entry::Subtree(_, _)) => self.subtree().unwrap(),
            _ => self.bump(),
        }
    }

    /// Check whether it is a top level
    pub fn is_root(&self) -> bool {
        let entry_id = self.ptr.0;
        return entry_id.0 == 0;
    }
}
<|endoftext|>