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

use dom::bindings::codegen::Bindings::DOMExceptionBinding;
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionConstants;
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods;
use dom::bindings::error::Error;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use util::str::DOMString;

use std::borrow::ToOwned;

#[repr(uint)]
#[derive(Copy, Debug)]
#[jstraceable]
pub enum DOMErrorName {
    IndexSizeError = DOMExceptionConstants::INDEX_SIZE_ERR as uint,
    HierarchyRequestError = DOMExceptionConstants::HIERARCHY_REQUEST_ERR as uint,
    WrongDocumentError = DOMExceptionConstants::WRONG_DOCUMENT_ERR as uint,
    InvalidCharacterError = DOMExceptionConstants::INVALID_CHARACTER_ERR as uint,
    NoModificationAllowedError = DOMExceptionConstants::NO_MODIFICATION_ALLOWED_ERR as uint,
    NotFoundError = DOMExceptionConstants::NOT_FOUND_ERR as uint,
    NotSupportedError = DOMExceptionConstants::NOT_SUPPORTED_ERR as uint,
    InvalidStateError = DOMExceptionConstants::INVALID_STATE_ERR as uint,
    SyntaxError = DOMExceptionConstants::SYNTAX_ERR as uint,
    InvalidModificationError = DOMExceptionConstants::INVALID_MODIFICATION_ERR as uint,
    NamespaceError = DOMExceptionConstants::NAMESPACE_ERR as uint,
    InvalidAccessError = DOMExceptionConstants::INVALID_ACCESS_ERR as uint,
    SecurityError = DOMExceptionConstants::SECURITY_ERR as uint,
    NetworkError = DOMExceptionConstants::NETWORK_ERR as uint,
    AbortError = DOMExceptionConstants::ABORT_ERR as uint,
    URLMismatchError = DOMExceptionConstants::URL_MISMATCH_ERR as uint,
    QuotaExceededError = DOMExceptionConstants::QUOTA_EXCEEDED_ERR as uint,
    TimeoutError = DOMExceptionConstants::TIMEOUT_ERR as uint,
    InvalidNodeTypeError = DOMExceptionConstants::INVALID_NODE_TYPE_ERR as uint,
    DataCloneError = DOMExceptionConstants::DATA_CLONE_ERR as uint,
    EncodingError
}

impl DOMErrorName {
    fn from_error(error: Error) -> DOMErrorName {
        match error {
            Error::IndexSize => DOMErrorName::IndexSizeError,
            Error::NotFound => DOMErrorName::NotFoundError,
            Error::HierarchyRequest => DOMErrorName::HierarchyRequestError,
            Error::InvalidCharacter => DOMErrorName::InvalidCharacterError,
            Error::NotSupported => DOMErrorName::NotSupportedError,
            Error::InvalidState => DOMErrorName::InvalidStateError,
            Error::Syntax => DOMErrorName::SyntaxError,
            Error::NamespaceError => DOMErrorName::NamespaceError,
            Error::InvalidAccess => DOMErrorName::InvalidAccessError,
            Error::Security => DOMErrorName::SecurityError,
            Error::Network => DOMErrorName::NetworkError,
            Error::Abort => DOMErrorName::AbortError,
            Error::Timeout => DOMErrorName::TimeoutError,
            Error::DataClone => DOMErrorName::DataCloneError,
            Error::NoModificationAllowedError => DOMErrorName::NoModificationAllowedError,
            Error::FailureUnknown => panic!(),
        }
    }
}

#[dom_struct]
pub struct DOMException {
    reflector_: Reflector,
    code: DOMErrorName,
}

impl DOMException {
    fn new_inherited(code: DOMErrorName) -> DOMException {
        DOMException {
            reflector_: Reflector::new(),
            code: code,
        }
    }

    pub fn new(global: GlobalRef, code: DOMErrorName) -> Temporary<DOMException> {
        reflect_dom_object(box DOMException::new_inherited(code), global, DOMExceptionBinding::Wrap)
    }

    pub fn new_from_error(global: GlobalRef, code: Error) -> Temporary<DOMException> {
        DOMException::new(global, DOMErrorName::from_error(code))
    }
}

impl<'a> DOMExceptionMethods for JSRef<'a, DOMException> {
    // http://dom.spec.whatwg.org/#dom-domexception-code
    fn Code(self) -> u16 {
        match self.code {
            // http://dom.spec.whatwg.org/#concept-throw
            DOMErrorName::EncodingError => 0,
            code => code as u16
        }
    }

    // http://dom.spec.whatwg.org/#error-names-0
    fn Name(self) -> DOMString {
        format!("{:?}", self.code)
    }

    // http://dom.spec.whatwg.org/#error-names-0
    fn Message(self) -> DOMString {
        let message = match self.code {
            DOMErrorName::IndexSizeError => "The index is not in the allowed range.",
            DOMErrorName::HierarchyRequestError => "The operation would yield an incorrect node tree.",
            DOMErrorName::WrongDocumentError => "The object is in the wrong document.",
            DOMErrorName::InvalidCharacterError => "The string contains invalid characters.",
            DOMErrorName::NoModificationAllowedError => "The object can not be modified.",
            DOMErrorName::NotFoundError => "The object can not be found here.",
            DOMErrorName::NotSupportedError => "The operation is not supported.",
            DOMErrorName::InvalidStateError => "The object is in an invalid state.",
            DOMErrorName::SyntaxError => "The string did not match the expected pattern.",
            DOMErrorName::InvalidModificationError => "The object can not be modified in this way.",
            DOMErrorName::NamespaceError => "The operation is not allowed by Namespaces in XML.",
            DOMErrorName::InvalidAccessError => "The object does not support the operation or argument.",
            DOMErrorName::SecurityError => "The operation is insecure.",
            DOMErrorName::NetworkError => "A network error occurred.",
            DOMErrorName::AbortError => "The operation was aborted.",
            DOMErrorName::URLMismatchError => "The given URL does not match another URL.",
            DOMErrorName::QuotaExceededError => "The quota has been exceeded.",
            DOMErrorName::TimeoutError => "The operation timed out.",
            DOMErrorName::InvalidNodeTypeError => "The supplied node is incorrect or has an incorrect ancestor for this operation.",
            DOMErrorName::DataCloneError => "The object can not be cloned.",
            DOMErrorName::EncodingError => "The encoding operation (either encoded or decoding) failed."
        };

        message.to_owned()
    }
}
<commit_msg>Change the representation of DOMErrorName to u16.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::DOMExceptionBinding;
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionConstants;
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods;
use dom::bindings::error::Error;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use util::str::DOMString;

use std::borrow::ToOwned;

#[repr(u16)]
#[derive(Copy, Debug)]
#[jstraceable]
pub enum DOMErrorName {
    IndexSizeError = DOMExceptionConstants::INDEX_SIZE_ERR,
    HierarchyRequestError = DOMExceptionConstants::HIERARCHY_REQUEST_ERR,
    WrongDocumentError = DOMExceptionConstants::WRONG_DOCUMENT_ERR,
    InvalidCharacterError = DOMExceptionConstants::INVALID_CHARACTER_ERR,
    NoModificationAllowedError = DOMExceptionConstants::NO_MODIFICATION_ALLOWED_ERR,
    NotFoundError = DOMExceptionConstants::NOT_FOUND_ERR,
    NotSupportedError = DOMExceptionConstants::NOT_SUPPORTED_ERR,
    InvalidStateError = DOMExceptionConstants::INVALID_STATE_ERR,
    SyntaxError = DOMExceptionConstants::SYNTAX_ERR,
    InvalidModificationError = DOMExceptionConstants::INVALID_MODIFICATION_ERR,
    NamespaceError = DOMExceptionConstants::NAMESPACE_ERR,
    InvalidAccessError = DOMExceptionConstants::INVALID_ACCESS_ERR,
    SecurityError = DOMExceptionConstants::SECURITY_ERR,
    NetworkError = DOMExceptionConstants::NETWORK_ERR,
    AbortError = DOMExceptionConstants::ABORT_ERR,
    URLMismatchError = DOMExceptionConstants::URL_MISMATCH_ERR,
    QuotaExceededError = DOMExceptionConstants::QUOTA_EXCEEDED_ERR,
    TimeoutError = DOMExceptionConstants::TIMEOUT_ERR,
    InvalidNodeTypeError = DOMExceptionConstants::INVALID_NODE_TYPE_ERR,
    DataCloneError = DOMExceptionConstants::DATA_CLONE_ERR,
    EncodingError
}

impl DOMErrorName {
    fn from_error(error: Error) -> DOMErrorName {
        match error {
            Error::IndexSize => DOMErrorName::IndexSizeError,
            Error::NotFound => DOMErrorName::NotFoundError,
            Error::HierarchyRequest => DOMErrorName::HierarchyRequestError,
            Error::InvalidCharacter => DOMErrorName::InvalidCharacterError,
            Error::NotSupported => DOMErrorName::NotSupportedError,
            Error::InvalidState => DOMErrorName::InvalidStateError,
            Error::Syntax => DOMErrorName::SyntaxError,
            Error::NamespaceError => DOMErrorName::NamespaceError,
            Error::InvalidAccess => DOMErrorName::InvalidAccessError,
            Error::Security => DOMErrorName::SecurityError,
            Error::Network => DOMErrorName::NetworkError,
            Error::Abort => DOMErrorName::AbortError,
            Error::Timeout => DOMErrorName::TimeoutError,
            Error::DataClone => DOMErrorName::DataCloneError,
            Error::NoModificationAllowedError => DOMErrorName::NoModificationAllowedError,
            Error::FailureUnknown => panic!(),
        }
    }
}

#[dom_struct]
pub struct DOMException {
    reflector_: Reflector,
    code: DOMErrorName,
}

impl DOMException {
    fn new_inherited(code: DOMErrorName) -> DOMException {
        DOMException {
            reflector_: Reflector::new(),
            code: code,
        }
    }

    pub fn new(global: GlobalRef, code: DOMErrorName) -> Temporary<DOMException> {
        reflect_dom_object(box DOMException::new_inherited(code), global, DOMExceptionBinding::Wrap)
    }

    pub fn new_from_error(global: GlobalRef, code: Error) -> Temporary<DOMException> {
        DOMException::new(global, DOMErrorName::from_error(code))
    }
}

impl<'a> DOMExceptionMethods for JSRef<'a, DOMException> {
    // http://dom.spec.whatwg.org/#dom-domexception-code
    fn Code(self) -> u16 {
        match self.code {
            // http://dom.spec.whatwg.org/#concept-throw
            DOMErrorName::EncodingError => 0,
            code => code as u16
        }
    }

    // http://dom.spec.whatwg.org/#error-names-0
    fn Name(self) -> DOMString {
        format!("{:?}", self.code)
    }

    // http://dom.spec.whatwg.org/#error-names-0
    fn Message(self) -> DOMString {
        let message = match self.code {
            DOMErrorName::IndexSizeError => "The index is not in the allowed range.",
            DOMErrorName::HierarchyRequestError => "The operation would yield an incorrect node tree.",
            DOMErrorName::WrongDocumentError => "The object is in the wrong document.",
            DOMErrorName::InvalidCharacterError => "The string contains invalid characters.",
            DOMErrorName::NoModificationAllowedError => "The object can not be modified.",
            DOMErrorName::NotFoundError => "The object can not be found here.",
            DOMErrorName::NotSupportedError => "The operation is not supported.",
            DOMErrorName::InvalidStateError => "The object is in an invalid state.",
            DOMErrorName::SyntaxError => "The string did not match the expected pattern.",
            DOMErrorName::InvalidModificationError => "The object can not be modified in this way.",
            DOMErrorName::NamespaceError => "The operation is not allowed by Namespaces in XML.",
            DOMErrorName::InvalidAccessError => "The object does not support the operation or argument.",
            DOMErrorName::SecurityError => "The operation is insecure.",
            DOMErrorName::NetworkError => "A network error occurred.",
            DOMErrorName::AbortError => "The operation was aborted.",
            DOMErrorName::URLMismatchError => "The given URL does not match another URL.",
            DOMErrorName::QuotaExceededError => "The quota has been exceeded.",
            DOMErrorName::TimeoutError => "The operation timed out.",
            DOMErrorName::InvalidNodeTypeError => "The supplied node is incorrect or has an incorrect ancestor for this operation.",
            DOMErrorName::DataCloneError => "The object can not be cloned.",
            DOMErrorName::EncodingError => "The encoding operation (either encoded or decoding) failed."
        };

        message.to_owned()
    }
}
<|endoftext|>


<commit_before>use hir::{AsAssocItem, Impl, Semantics};
use ide_db::{
    defs::{Definition, NameClass, NameRefClass},
    RootDatabase,
};
use syntax::{ast, AstNode};

use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};

// Feature: Go to Implementation
//
// Navigates to the impl block of structs, enums or traits. Also implemented as a code lens.
//
// |===
// | Editor  | Shortcut
//
// | VS Code | kbd:[Ctrl+F12]
// |===
//
// image::https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif[]
pub(crate) fn goto_implementation(
    db: &RootDatabase,
    position: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
    let sema = Semantics::new(db);
    let source_file = sema.parse(position.file_id);
    let syntax = source_file.syntax().clone();

    let node = sema.find_node_at_offset_with_descend(&syntax, position.offset)?;
    let def = match &node {
        ast::NameLike::Name(name) => {
            NameClass::classify(&sema, name).map(|class| class.referenced_or_defined(sema.db))
        }
        ast::NameLike::NameRef(name_ref) => {
            NameRefClass::classify(&sema, name_ref).map(|class| class.referenced(sema.db))
        }
        ast::NameLike::Lifetime(_) => None,
    }?;

    let def = match def {
        Definition::ModuleDef(def) => def,
        _ => return None,
    };
    let navs = match def {
        hir::ModuleDef::Trait(trait_) => impls_for_trait(&sema, trait_),
        hir::ModuleDef::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
        hir::ModuleDef::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
        hir::ModuleDef::BuiltinType(builtin) => {
            let module = sema.to_module_def(position.file_id)?;
            impls_for_ty(&sema, builtin.ty(sema.db, module))
        }
        hir::ModuleDef::Function(f) => {
            let assoc = f.as_assoc_item(sema.db)?;
            let name = assoc.name(sema.db)?;
            let trait_ = assoc.containing_trait(sema.db)?;
            impls_for_trait_fn(&sema, trait_, name)
        }
        _ => return None,
    };
    Some(RangeInfo { range: node.syntax().text_range(), info: navs })
}

fn impls_for_ty(sema: &Semantics<RootDatabase>, ty: hir::Type) -> Vec<NavigationTarget> {
    Impl::all_for_type(sema.db, ty).into_iter().filter_map(|imp| imp.try_to_nav(sema.db)).collect()
}

fn impls_for_trait(sema: &Semantics<RootDatabase>, trait_: hir::Trait) -> Vec<NavigationTarget> {
    Impl::all_for_trait(sema.db, trait_)
        .into_iter()
        .filter_map(|imp| imp.try_to_nav(sema.db))
        .collect()
}

fn impls_for_trait_fn(
    sema: &Semantics<RootDatabase>,
    trait_: hir::Trait,
    fun_name: hir::Name,
) -> Vec<NavigationTarget> {
    Impl::all_for_trait(sema.db, trait_)
        .into_iter()
        .filter_map(|imp| {
            let item = imp.items(sema.db).iter().find_map(|itm| {
                let itm_name = itm.name(sema.db)?;
                (itm_name == fun_name).then(|| itm.clone())
            })?;
            item.try_to_nav(sema.db)
        })
        .collect()
}

#[cfg(test)]
mod tests {
    use ide_db::base_db::FileRange;

    use crate::fixture;

    fn check(ra_fixture: &str) {
        let (analysis, position, annotations) = fixture::annotations(ra_fixture);

        let navs = analysis.goto_implementation(position).unwrap().unwrap().info;

        let key = |frange: &FileRange| (frange.file_id, frange.range.start());

        let mut expected = annotations
            .into_iter()
            .map(|(range, data)| {
                assert!(data.is_empty());
                range
            })
            .collect::<Vec<_>>();
        expected.sort_by_key(key);

        let mut actual = navs
            .into_iter()
            .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() })
            .collect::<Vec<_>>();
        actual.sort_by_key(key);

        assert_eq!(expected, actual);
    }

    #[test]
    fn goto_implementation_works() {
        check(
            r#"
struct Foo$0;
impl Foo {}
   //^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_works_multiple_blocks() {
        check(
            r#"
struct Foo$0;
impl Foo {}
   //^^^
impl Foo {}
   //^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_works_multiple_mods() {
        check(
            r#"
struct Foo$0;
mod a {
    impl super::Foo {}
       //^^^^^^^^^^
}
mod b {
    impl super::Foo {}
       //^^^^^^^^^^
}
"#,
        );
    }

    #[test]
    fn goto_implementation_works_multiple_files() {
        check(
            r#"
//- /lib.rs
struct Foo$0;
mod a;
mod b;
//- /a.rs
impl crate::Foo {}
   //^^^^^^^^^^
//- /b.rs
impl crate::Foo {}
   //^^^^^^^^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_for_trait() {
        check(
            r#"
trait T$0 {}
struct Foo;
impl T for Foo {}
         //^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_for_trait_multiple_files() {
        check(
            r#"
//- /lib.rs
trait T$0 {};
struct Foo;
mod a;
mod b;
//- /a.rs
impl crate::T for crate::Foo {}
                //^^^^^^^^^^
//- /b.rs
impl crate::T for crate::Foo {}
                //^^^^^^^^^^
            "#,
        );
    }

    #[test]
    fn goto_implementation_all_impls() {
        check(
            r#"
//- /lib.rs
trait T {}
struct Foo$0;
impl Foo {}
   //^^^
impl T for Foo {}
         //^^^
impl T for &Foo {}
         //^^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_to_builtin_derive() {
        check(
            r#"
  #[derive(Copy)]
//^^^^^^^^^^^^^^^
struct Foo$0;

mod marker {
    trait Copy {}
}
#[rustc_builtin_macro]
macro Copy {}
"#,
        );
    }

    #[test]
    fn goto_implementation_type_alias() {
        check(
            r#"
struct Foo;

type Bar$0 = Foo;

impl Foo {}
   //^^^
impl Bar {}
   //^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_adt_generic() {
        check(
            r#"
struct Foo$0<T>;

impl<T> Foo<T> {}
      //^^^^^^
impl Foo<str> {}
   //^^^^^^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_builtin() {
        check(
            r#"
//- /lib.rs crate:main deps:core
fn foo(_: bool$0) {{}}
//- /libcore.rs crate:core
#[lang = "bool"]
impl bool {}
   //^^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_trait_functions() {
        check(
            r#"
trait Tr {
    fn f$0();
}

struct S;

impl Tr for S {
    fn f() {
     //^
        println!("Hello, world!");
    }
}
"#,
        );
    }
}
<commit_msg>Also do goto implementation on assoc consts<commit_after>use hir::{AsAssocItem, Impl, Semantics};
use ide_db::{
    defs::{Definition, NameClass, NameRefClass},
    RootDatabase,
};
use syntax::{ast, AstNode};

use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};

// Feature: Go to Implementation
//
// Navigates to the impl block of structs, enums or traits. Also implemented as a code lens.
//
// |===
// | Editor  | Shortcut
//
// | VS Code | kbd:[Ctrl+F12]
// |===
//
// image::https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif[]
pub(crate) fn goto_implementation(
    db: &RootDatabase,
    position: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
    let sema = Semantics::new(db);
    let source_file = sema.parse(position.file_id);
    let syntax = source_file.syntax().clone();

    let node = sema.find_node_at_offset_with_descend(&syntax, position.offset)?;
    let def = match &node {
        ast::NameLike::Name(name) => {
            NameClass::classify(&sema, name).map(|class| class.referenced_or_defined(sema.db))
        }
        ast::NameLike::NameRef(name_ref) => {
            NameRefClass::classify(&sema, name_ref).map(|class| class.referenced(sema.db))
        }
        ast::NameLike::Lifetime(_) => None,
    }?;

    let def = match def {
        Definition::ModuleDef(def) => def,
        _ => return None,
    };
    let navs = match def {
        hir::ModuleDef::Trait(trait_) => impls_for_trait(&sema, trait_),
        hir::ModuleDef::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
        hir::ModuleDef::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
        hir::ModuleDef::BuiltinType(builtin) => {
            let module = sema.to_module_def(position.file_id)?;
            impls_for_ty(&sema, builtin.ty(sema.db, module))
        }
        hir::ModuleDef::Function(f) => {
            let assoc = f.as_assoc_item(sema.db)?;
            let name = assoc.name(sema.db)?;
            let trait_ = assoc.containing_trait(sema.db)?;
            impls_for_trait_item(&sema, trait_, name)
        }
        hir::ModuleDef::Const(c) => {
            let assoc = c.as_assoc_item(sema.db)?;
            let name = assoc.name(sema.db)?;
            let trait_ = assoc.containing_trait(sema.db)?;
            impls_for_trait_item(&sema, trait_, name)
        }
        _ => return None,
    };
    Some(RangeInfo { range: node.syntax().text_range(), info: navs })
}

fn impls_for_ty(sema: &Semantics<RootDatabase>, ty: hir::Type) -> Vec<NavigationTarget> {
    Impl::all_for_type(sema.db, ty).into_iter().filter_map(|imp| imp.try_to_nav(sema.db)).collect()
}

fn impls_for_trait(sema: &Semantics<RootDatabase>, trait_: hir::Trait) -> Vec<NavigationTarget> {
    Impl::all_for_trait(sema.db, trait_)
        .into_iter()
        .filter_map(|imp| imp.try_to_nav(sema.db))
        .collect()
}

fn impls_for_trait_item(
    sema: &Semantics<RootDatabase>,
    trait_: hir::Trait,
    fun_name: hir::Name,
) -> Vec<NavigationTarget> {
    Impl::all_for_trait(sema.db, trait_)
        .into_iter()
        .filter_map(|imp| {
            let item = imp.items(sema.db).iter().find_map(|itm| {
                let itm_name = itm.name(sema.db)?;
                (itm_name == fun_name).then(|| itm.clone())
            })?;
            item.try_to_nav(sema.db)
        })
        .collect()
}

#[cfg(test)]
mod tests {
    use ide_db::base_db::FileRange;

    use crate::fixture;

    fn check(ra_fixture: &str) {
        let (analysis, position, annotations) = fixture::annotations(ra_fixture);

        let navs = analysis.goto_implementation(position).unwrap().unwrap().info;

        let key = |frange: &FileRange| (frange.file_id, frange.range.start());

        let mut expected = annotations
            .into_iter()
            .map(|(range, data)| {
                assert!(data.is_empty());
                range
            })
            .collect::<Vec<_>>();
        expected.sort_by_key(key);

        let mut actual = navs
            .into_iter()
            .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() })
            .collect::<Vec<_>>();
        actual.sort_by_key(key);

        assert_eq!(expected, actual);
    }

    #[test]
    fn goto_implementation_works() {
        check(
            r#"
struct Foo$0;
impl Foo {}
   //^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_works_multiple_blocks() {
        check(
            r#"
struct Foo$0;
impl Foo {}
   //^^^
impl Foo {}
   //^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_works_multiple_mods() {
        check(
            r#"
struct Foo$0;
mod a {
    impl super::Foo {}
       //^^^^^^^^^^
}
mod b {
    impl super::Foo {}
       //^^^^^^^^^^
}
"#,
        );
    }

    #[test]
    fn goto_implementation_works_multiple_files() {
        check(
            r#"
//- /lib.rs
struct Foo$0;
mod a;
mod b;
//- /a.rs
impl crate::Foo {}
   //^^^^^^^^^^
//- /b.rs
impl crate::Foo {}
   //^^^^^^^^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_for_trait() {
        check(
            r#"
trait T$0 {}
struct Foo;
impl T for Foo {}
         //^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_for_trait_multiple_files() {
        check(
            r#"
//- /lib.rs
trait T$0 {};
struct Foo;
mod a;
mod b;
//- /a.rs
impl crate::T for crate::Foo {}
                //^^^^^^^^^^
//- /b.rs
impl crate::T for crate::Foo {}
                //^^^^^^^^^^
            "#,
        );
    }

    #[test]
    fn goto_implementation_all_impls() {
        check(
            r#"
//- /lib.rs
trait T {}
struct Foo$0;
impl Foo {}
   //^^^
impl T for Foo {}
         //^^^
impl T for &Foo {}
         //^^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_to_builtin_derive() {
        check(
            r#"
  #[derive(Copy)]
//^^^^^^^^^^^^^^^
struct Foo$0;

mod marker {
    trait Copy {}
}
#[rustc_builtin_macro]
macro Copy {}
"#,
        );
    }

    #[test]
    fn goto_implementation_type_alias() {
        check(
            r#"
struct Foo;

type Bar$0 = Foo;

impl Foo {}
   //^^^
impl Bar {}
   //^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_adt_generic() {
        check(
            r#"
struct Foo$0<T>;

impl<T> Foo<T> {}
      //^^^^^^
impl Foo<str> {}
   //^^^^^^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_builtin() {
        check(
            r#"
//- /lib.rs crate:main deps:core
fn foo(_: bool$0) {{}}
//- /libcore.rs crate:core
#[lang = "bool"]
impl bool {}
   //^^^^
"#,
        );
    }

    #[test]
    fn goto_implementation_trait_functions() {
        check(
            r#"
trait Tr {
    fn f$0();
}

struct S;

impl Tr for S {
    fn f() {
     //^
        println!("Hello, world!");
    }
}
"#,
        );
    }

    #[test]
    fn goto_implementation_trait_assoc_const() {
        check(
            r#"
trait Tr {
    const C$0: usize;
}

struct S;

impl Tr for S {
    const C: usize = 4;
        //^
}
"#,
        );
    }
}
<|endoftext|>


<commit_before>/// Declares an item with a doc attribute computed by some macro expression.
/// This allows documentation to be dynamically generated based on input.
/// Necessary to work around <https://github.com/rust-lang/rust/issues/52607>.
macro_rules! doc_concat {
    ( $( #[doc = $doc:expr] $( $thing:tt )* )* ) => ( $( #[doc = $doc] $( $thing )* )* );
}

macro_rules! partial_eq_string {
    ($id:ty $([$( $g:ident ),*])?) => {
        partial_eq_string!(@imp $(<$($g),*>)?, $id, str);
        partial_eq_string!(@imp $(<$($g),*>)?, $id, &str);
        partial_eq_string!(@imp $(<$($g),*>)?, $id, String);
        partial_eq_string!(@imp $(<$($g),*>)?, str, $id);
        partial_eq_string!(@imp $(<$($g),*>)?, &str, $id);
        partial_eq_string!(@imp $(<$($g),*>)?, String, $id);
    };
    (@imp $(<$( $g:ident ),*>)?, $l:ty, $r:ty) => {
        impl $(<$($g),*>)? PartialEq<$r> for $l {
            fn eq(&self, other: &$r) -> bool {
                AsRef::<str>::as_ref(self)
                    == AsRef::<str>::as_ref(other)
            }
        }
    }
}

macro_rules! as_str_based_impls {
    ($id:ty) => {
        impl AsRef<str> for $id {
            fn as_ref(&self) -> &str {
                self.as_str()
            }
        }

        impl std::fmt::Display for $id {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(f, "{}", self.as_str())
            }
        }

        impl PartialEq for $id {
            fn eq(&self, other: &Self) -> bool {
                self.as_str() == other.as_str()
            }
        }

        impl std::cmp::Eq for $id {}

        impl std::cmp::PartialOrd for $id {
            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
                std::cmp::PartialOrd::partial_cmp(self.as_str(), other.as_str())
            }
        }

        impl std::cmp::Ord for $id {
            fn cmp(&self, other: &Self) -> std::cmp::Ordering {
                std::cmp::Ord::cmp(self.as_str(), other.as_str())
            }
        }

        impl std::hash::Hash for $id {
            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
                self.as_str().hash(state);
            }
        }

        #[cfg(feature = "serde")]
        impl serde::Serialize for $id {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: serde::Serializer,
            {
                serializer.serialize_str(self.as_str())
            }
        }
    };
}

macro_rules! common_impls {
    ($id:ty, $try_from:ident, $desc:literal) => {
        impl $id {
            doc_concat! {
                #[doc = concat!("Creates a string slice from this `", stringify!($id), "`")]
                pub fn as_str(&self) -> &str {
                    &self.full_id
                }
            }

            doc_concat! {
                #[doc = concat!("Creates a byte slice from this `", stringify!($id), "`")]
                pub fn as_bytes(&self) -> &[u8] {
                    self.full_id.as_bytes()
                }
            }

            doc_concat! {
                #[doc = concat!("Converts this `", stringify!($id), "` into a `String`")]
                pub fn into_string(self) -> String {
                    self.full_id.into()
                }
            }

            doc_concat! {
                #[doc = concat!("Converts this `", stringify!($id), "` into a `Vec<u8>`")]
                pub fn into_bytes(self) -> Vec<u8> {
                    Box::<[u8]>::from(self.full_id).into()
                }
            }
        }

        impl From<$id> for String {
            fn from(id: $id) -> Self {
                id.into_string()
            }
        }

        impl From<$id> for Vec<u8> {
            fn from(id: $id) -> Self {
                id.into_bytes()
            }
        }

        impl std::str::FromStr for $id {
            type Err = crate::Error;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                $try_from(s)
            }
        }

        impl std::convert::TryFrom<&str> for $id {
            type Error = crate::Error;

            fn try_from(s: &str) -> Result<Self, Self::Error> {
                $try_from(s)
            }
        }

        impl std::convert::TryFrom<String> for $id {
            type Error = crate::Error;

            fn try_from(s: String) -> Result<Self, Self::Error> {
                $try_from(s)
            }
        }

        #[cfg(feature = "serde")]
        impl<'de> serde::Deserialize<'de> for $id {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                crate::deserialize_id(deserializer, $desc)
            }
        }

        as_str_based_impls!($id);
        partial_eq_string!($id);
    };
}

macro_rules! opaque_identifier {
    (
        $( #[doc = $docs:literal] )*
        $vis:vis type $id:ident;
    ) => {
        $( #[doc = $docs] )*
        #[repr(transparent)]
        pub struct $id(str);

        paste::paste! {
            doc_concat! {
                #[doc = concat!("An owned [", stringify!($id), "].")]
                pub type [<$id Box>] = Box<$id>;
            }
        }

        impl $id {
            #[allow(clippy::transmute_ptr_to_ptr)]
            fn from_borrowed(s: &str) -> &Self {
                unsafe { std::mem::transmute(s) }
            }

            pub(super) fn from_owned(s: Box<str>) -> Box<Self> {
                unsafe { Box::from_raw(Box::into_raw(s) as _) }
            }

            fn into_owned(self: Box<Self>) -> Box<str> {
                unsafe { Box::from_raw(Box::into_raw(self) as _) }
            }

            doc_concat! {
                #[doc = concat!("Creates a string slice from this `", stringify!($id), "`.")]
                pub fn as_str(&self) -> &str {
                    &self.0
                }
            }

            doc_concat! {
                #[doc = concat!("Creates a byte slice from this `", stringify!($id), "`.")]
                pub fn as_bytes(&self) -> &[u8] {
                    self.0.as_bytes()
                }
            }
        }

        impl std::fmt::Debug for $id {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                f.write_str(self.as_ref())
            }
        }

        impl Clone for Box<$id> {
            fn clone(&self) -> Self {
                (**self).to_owned()
            }
        }

        impl ToOwned for $id {
            type Owned = Box<$id>;

            fn to_owned(&self) -> Self::Owned {
                Self::from_owned(self.0.to_owned().into_boxed_str())
            }
        }

        impl From<&$id> for Box<$id> {
            fn from(id: &$id) -> Self {
                id.to_owned()
            }
        }

        impl AsRef<str> for Box<$id> {
            fn as_ref(&self) -> &str {
                self.as_str()
            }
        }

        impl<'a> From<&'a str> for &'a $id {
            fn from(s: &'a str) -> Self {
                $id::from_borrowed(s)
            }
        }

        impl From<&str> for Box<$id> {
            fn from(s: &str) -> Self {
                $id::from_owned(s.into())
            }
        }

        impl From<String> for Box<$id> {
            fn from(s: String) -> Self {
                $id::from_owned(s.into())
            }
        }

        impl From<Box<$id>> for String {
            fn from(id: Box<$id>) -> Self {
                id.into_owned().into()
            }
        }

        #[cfg(feature = "serde")]
        impl<'de> serde::Deserialize<'de> for Box<$id> {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                Box::<str>::deserialize(deserializer).map($id::from_owned)
            }
        }

        as_str_based_impls!($id);
        partial_eq_string!($id);
        partial_eq_string!(Box<$id>);
    };
}
<commit_msg>identifiers: Fix unnecessary qualification<commit_after>/// Declares an item with a doc attribute computed by some macro expression.
/// This allows documentation to be dynamically generated based on input.
/// Necessary to work around <https://github.com/rust-lang/rust/issues/52607>.
macro_rules! doc_concat {
    ( $( #[doc = $doc:expr] $( $thing:tt )* )* ) => ( $( #[doc = $doc] $( $thing )* )* );
}

macro_rules! partial_eq_string {
    ($id:ty $([$( $g:ident ),*])?) => {
        partial_eq_string!(@imp $(<$($g),*>)?, $id, str);
        partial_eq_string!(@imp $(<$($g),*>)?, $id, &str);
        partial_eq_string!(@imp $(<$($g),*>)?, $id, String);
        partial_eq_string!(@imp $(<$($g),*>)?, str, $id);
        partial_eq_string!(@imp $(<$($g),*>)?, &str, $id);
        partial_eq_string!(@imp $(<$($g),*>)?, String, $id);
    };
    (@imp $(<$( $g:ident ),*>)?, $l:ty, $r:ty) => {
        impl $(<$($g),*>)? PartialEq<$r> for $l {
            fn eq(&self, other: &$r) -> bool {
                AsRef::<str>::as_ref(self)
                    == AsRef::<str>::as_ref(other)
            }
        }
    }
}

macro_rules! as_str_based_impls {
    ($id:ty) => {
        impl AsRef<str> for $id {
            fn as_ref(&self) -> &str {
                self.as_str()
            }
        }

        impl std::fmt::Display for $id {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(f, "{}", self.as_str())
            }
        }

        impl PartialEq for $id {
            fn eq(&self, other: &Self) -> bool {
                self.as_str() == other.as_str()
            }
        }

        impl Eq for $id {}

        impl PartialOrd for $id {
            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
                PartialOrd::partial_cmp(self.as_str(), other.as_str())
            }
        }

        impl Ord for $id {
            fn cmp(&self, other: &Self) -> std::cmp::Ordering {
                Ord::cmp(self.as_str(), other.as_str())
            }
        }

        impl std::hash::Hash for $id {
            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
                self.as_str().hash(state);
            }
        }

        #[cfg(feature = "serde")]
        impl serde::Serialize for $id {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: serde::Serializer,
            {
                serializer.serialize_str(self.as_str())
            }
        }
    };
}

macro_rules! common_impls {
    ($id:ty, $try_from:ident, $desc:literal) => {
        impl $id {
            doc_concat! {
                #[doc = concat!("Creates a string slice from this `", stringify!($id), "`")]
                pub fn as_str(&self) -> &str {
                    &self.full_id
                }
            }

            doc_concat! {
                #[doc = concat!("Creates a byte slice from this `", stringify!($id), "`")]
                pub fn as_bytes(&self) -> &[u8] {
                    self.full_id.as_bytes()
                }
            }

            doc_concat! {
                #[doc = concat!("Converts this `", stringify!($id), "` into a `String`")]
                pub fn into_string(self) -> String {
                    self.full_id.into()
                }
            }

            doc_concat! {
                #[doc = concat!("Converts this `", stringify!($id), "` into a `Vec<u8>`")]
                pub fn into_bytes(self) -> Vec<u8> {
                    Box::<[u8]>::from(self.full_id).into()
                }
            }
        }

        impl From<$id> for String {
            fn from(id: $id) -> Self {
                id.into_string()
            }
        }

        impl From<$id> for Vec<u8> {
            fn from(id: $id) -> Self {
                id.into_bytes()
            }
        }

        impl std::str::FromStr for $id {
            type Err = crate::Error;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                $try_from(s)
            }
        }

        impl std::convert::TryFrom<&str> for $id {
            type Error = crate::Error;

            fn try_from(s: &str) -> Result<Self, Self::Error> {
                $try_from(s)
            }
        }

        impl std::convert::TryFrom<String> for $id {
            type Error = crate::Error;

            fn try_from(s: String) -> Result<Self, Self::Error> {
                $try_from(s)
            }
        }

        #[cfg(feature = "serde")]
        impl<'de> serde::Deserialize<'de> for $id {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                crate::deserialize_id(deserializer, $desc)
            }
        }

        as_str_based_impls!($id);
        partial_eq_string!($id);
    };
}

macro_rules! opaque_identifier {
    (
        $( #[doc = $docs:literal] )*
        $vis:vis type $id:ident;
    ) => {
        $( #[doc = $docs] )*
        #[repr(transparent)]
        pub struct $id(str);

        paste::paste! {
            doc_concat! {
                #[doc = concat!("An owned [", stringify!($id), "].")]
                pub type [<$id Box>] = Box<$id>;
            }
        }

        impl $id {
            #[allow(clippy::transmute_ptr_to_ptr)]
            fn from_borrowed(s: &str) -> &Self {
                unsafe { std::mem::transmute(s) }
            }

            pub(super) fn from_owned(s: Box<str>) -> Box<Self> {
                unsafe { Box::from_raw(Box::into_raw(s) as _) }
            }

            fn into_owned(self: Box<Self>) -> Box<str> {
                unsafe { Box::from_raw(Box::into_raw(self) as _) }
            }

            doc_concat! {
                #[doc = concat!("Creates a string slice from this `", stringify!($id), "`.")]
                pub fn as_str(&self) -> &str {
                    &self.0
                }
            }

            doc_concat! {
                #[doc = concat!("Creates a byte slice from this `", stringify!($id), "`.")]
                pub fn as_bytes(&self) -> &[u8] {
                    self.0.as_bytes()
                }
            }
        }

        impl std::fmt::Debug for $id {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                f.write_str(self.as_ref())
            }
        }

        impl Clone for Box<$id> {
            fn clone(&self) -> Self {
                (**self).to_owned()
            }
        }

        impl ToOwned for $id {
            type Owned = Box<$id>;

            fn to_owned(&self) -> Self::Owned {
                Self::from_owned(self.0.to_owned().into_boxed_str())
            }
        }

        impl From<&$id> for Box<$id> {
            fn from(id: &$id) -> Self {
                id.to_owned()
            }
        }

        impl AsRef<str> for Box<$id> {
            fn as_ref(&self) -> &str {
                self.as_str()
            }
        }

        impl<'a> From<&'a str> for &'a $id {
            fn from(s: &'a str) -> Self {
                $id::from_borrowed(s)
            }
        }

        impl From<&str> for Box<$id> {
            fn from(s: &str) -> Self {
                $id::from_owned(s.into())
            }
        }

        impl From<String> for Box<$id> {
            fn from(s: String) -> Self {
                $id::from_owned(s.into())
            }
        }

        impl From<Box<$id>> for String {
            fn from(id: Box<$id>) -> Self {
                id.into_owned().into()
            }
        }

        #[cfg(feature = "serde")]
        impl<'de> serde::Deserialize<'de> for Box<$id> {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                Box::<str>::deserialize(deserializer).map($id::from_owned)
            }
        }

        as_str_based_impls!($id);
        partial_eq_string!($id);
        partial_eq_string!(Box<$id>);
    };
}
<|endoftext|>


<commit_before>use neb::server::*;
use neb::ram::schema::*;
use neb::server::transactions;
use neb::ram::types::*;
use neb::server::transactions::*;
use std::rc::Rc;
use neb::ram::cell::*;
use super::*;

#[test]
pub fn workspace_wr() {
    let server_addr = String::from("127.0.0.1:5200");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    server.meta.schemas.new_schema(&mut schema);
    let txn = transactions::new_client(&server_addr).unwrap();
    let txn_id = txn.begin().unwrap().unwrap();
    let mut data_map = Map::<String, Value>::new();
    data_map.insert(String::from("id"), Value::I64(100));
    data_map.insert(String::from("score"), Value::U64(70));
    data_map.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map.clone());
    let cell_1_w_res = txn.write(&txn_id, &cell_1).unwrap().unwrap();
    match cell_1_w_res {
        TransactionExecResult::Accepted(()) => {},
        _ => {panic!("write cell 1 not accepted {:?}", cell_1_w_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TransactionExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("id").unwrap().I64().unwrap(), 100);
            assert_eq!(cell.data.Map().unwrap().get("name").unwrap().String().unwrap(), "Jack");
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 70);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_w_res)}
    }
    data_map.insert(String::from("score"), Value::U64(90));
    let cell_1_w2 = Cell::new(schema.id, &cell_1.id(), data_map.clone());
    let cell_1_w_res = txn.write(&txn_id, &cell_1_w2).unwrap().unwrap();
    match cell_1_w_res {
        TransactionExecResult::Accepted(()) => {panic!("Write existed cell should fail")}
        TransactionExecResult::Error(WriteError::CellAlreadyExisted) => {}
        _ => {panic!("Wrong feedback {:?}", cell_1_w_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TransactionExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 70);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_w_res)}
    }
    let cell_1_u_res = txn.update(&txn_id, &cell_1_w2).unwrap().unwrap();
    match cell_1_u_res {
        TransactionExecResult::Accepted(()) => {},
        _ => {panic!("update cell 1 not accepted")}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TransactionExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 90);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_w_res)}
    }
    let cell_1_rm_res = txn.remove(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_rm_res {
        TransactionExecResult::Accepted(()) => {},
        _ => {panic!("remove cell 1 not accepted {:?}", cell_1_rm_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TransactionExecResult::Error(ReadError::CellDoesNotExisted) => {},
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_w_res)}
    }
}
<commit_msg>scaffolding data site wr test, bifrost failed<commit_after>use neb::server::*;
use neb::ram::schema::*;
use neb::server::transactions;
use neb::ram::types::*;
use neb::server::transactions::*;
use std::rc::Rc;
use neb::ram::cell::*;
use super::*;

#[test]
pub fn workspace_wr() {
    let server_addr = String::from("127.0.0.1:5200");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    server.meta.schemas.new_schema(&mut schema);
    let txn = transactions::new_client(&server_addr).unwrap();
    let txn_id = txn.begin().unwrap().unwrap();
    let mut data_map = Map::<String, Value>::new();
    data_map.insert(String::from("id"), Value::I64(100));
    data_map.insert(String::from("score"), Value::U64(70));
    data_map.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map.clone());
    let cell_1_w_res = txn.write(&txn_id, &cell_1).unwrap().unwrap();
    match cell_1_w_res {
        TransactionExecResult::Accepted(()) => {},
        _ => {panic!("write cell 1 not accepted {:?}", cell_1_w_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TransactionExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("id").unwrap().I64().unwrap(), 100);
            assert_eq!(cell.data.Map().unwrap().get("name").unwrap().String().unwrap(), "Jack");
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 70);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_w_res)}
    }
    data_map.insert(String::from("score"), Value::U64(90));
    let cell_1_w2 = Cell::new(schema.id, &cell_1.id(), data_map.clone());
    let cell_1_w_res = txn.write(&txn_id, &cell_1_w2).unwrap().unwrap();
    match cell_1_w_res {
        TransactionExecResult::Accepted(()) => {panic!("Write existed cell should fail")}
        TransactionExecResult::Error(WriteError::CellAlreadyExisted) => {}
        _ => {panic!("Wrong feedback {:?}", cell_1_w_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TransactionExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 70);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_w_res)}
    }
    let cell_1_u_res = txn.update(&txn_id, &cell_1_w2).unwrap().unwrap();
    match cell_1_u_res {
        TransactionExecResult::Accepted(()) => {},
        _ => {panic!("update cell 1 not accepted")}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TransactionExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 90);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_w_res)}
    }
    let cell_1_rm_res = txn.remove(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_rm_res {
        TransactionExecResult::Accepted(()) => {},
        _ => {panic!("remove cell 1 not accepted {:?}", cell_1_rm_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TransactionExecResult::Error(ReadError::CellDoesNotExisted) => {},
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_w_res)}
    }
}

#[test]
pub fn data_site_wr() {
    let server_addr = String::from("127.0.0.1:5201");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    server.meta.schemas.new_schema(&mut schema);
    let txn = transactions::new_client(&server_addr).unwrap();
    let txn_id = txn.begin().unwrap().unwrap();
    let mut data_map = Map::<String, Value>::new();
    data_map.insert(String::from("id"), Value::I64(100));
    data_map.insert(String::from("score"), Value::U64(70));
    data_map.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map.clone());
    let cell_1_non_exists_read = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
}<|endoftext|>


<commit_before>#![feature(test)]
#![feature(box_patterns, box_syntax)]
extern crate test;
extern crate french_press;
extern crate jsrs_common;

use std::cell::RefCell;
use std::rc::Rc;

use test::Bencher;
use french_press::*;
use french_press::alloc::AllocBox;
use jsrs_common::ast::{Exp, Stmt};
use jsrs_common::backend::Backend;
use jsrs_common::types::js_fn::JsFnStruct;
use jsrs_common::types::js_obj::JsObjStruct;
use jsrs_common::types::js_str::JsStrStruct;
use jsrs_common::types::js_var::{JsKey, JsPtrEnum, JsPtrTag, JsType, JsVar};

fn make_num(i: f64) -> JsVar {
    JsVar::new(JsType::JsNum(i))
}

fn make_str(s: &str) -> (JsVar, JsPtrEnum) {
    let var = JsVar::new(JsType::JsPtr(JsPtrTag::JsStr));
    (var, JsPtrEnum::JsStr(JsStrStruct::new(s)))
}

fn make_obj(kvs: Vec<(JsKey, JsVar, Option<JsPtrEnum>)>, heap: Rc<RefCell<AllocBox>>) -> (JsVar, JsPtrEnum) {
    let var = JsVar::new(JsType::JsPtr(JsPtrTag::JsObj));
    (var, JsPtrEnum::JsObj(JsObjStruct::new(None, "test", kvs, &mut *heap.borrow_mut())))
}

//#[bench]
fn small_no_gc(b: &mut Bencher) {
    b.iter(|| {
        let mut mgr = init_gc();
        mgr.alloc(make_num(0.), None).unwrap();
        mgr.alloc(make_num(1.), None).unwrap();
        mgr.alloc(make_num(2.), None).unwrap();
        mgr.pop_scope(None, false).unwrap();
    });
}

//#[bench]
fn deep_lookup(b: &mut Bencher) {
    let mut mgr = init_gc();
    mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
    let var = make_num(0.);
    let bnd = var.binding.clone();
    mgr.alloc(var, None).unwrap();
    for _ in 0..1000 {
        mgr.push_scope(&Exp::Undefined);
    }
    b.iter(|| {
        mgr.load(&bnd).unwrap();
    });
}

#[bench]
fn leak_many(b: &mut Bencher) {
    let mut mgr = init_gc();
    for _ in 0..100 {
        mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));

        let (var, ptr) = make_str("test");
        let key = JsKey::JsSym("true".to_string());
        let kvs = vec![(key.clone(), var, Some(ptr))];

        let (var, ptr) = make_obj(kvs, mgr.alloc_box.clone());
        let bnd = var.binding.clone();
        mgr.alloc(var, Some(ptr)).unwrap();

        let copy = mgr.load(&bnd);
        let (mut var, mut ptr) = copy.unwrap();

        for _ in 0..1000 {
            let (leak_var, leak_ptr) = make_str("test");
            match *&mut ptr {
                Some(JsPtrEnum::JsObj(ref mut obj)) => {
                    obj.add_key(key.clone(), leak_var, Some(leak_ptr), &mut *(mgr.alloc_box.borrow_mut()));
                },
                _ => unreachable!()
            }
        }
        mgr.store(var, ptr).unwrap();
    }
    let f = || { mgr.pop_scope(None, true).unwrap(); };
    b.iter(f);
}
<commit_msg>Add more benchmarks<commit_after>#![feature(test)]
#![feature(box_patterns, box_syntax)]
extern crate test;
extern crate french_press;
extern crate jsrs_common;

use std::cell::RefCell;
use std::rc::Rc;

use test::Bencher;
use french_press::*;
use french_press::alloc::AllocBox;
use jsrs_common::ast::{Exp, Stmt};
use jsrs_common::backend::Backend;
use jsrs_common::types::js_fn::JsFnStruct;
use jsrs_common::types::js_obj::JsObjStruct;
use jsrs_common::types::js_str::JsStrStruct;
use jsrs_common::types::js_var::{JsKey, JsPtrEnum, JsPtrTag, JsType, JsVar};

fn make_num(i: f64) -> JsVar {
    JsVar::new(JsType::JsNum(i))
}

fn make_str(s: &str) -> (JsVar, JsPtrEnum) {
    let var = JsVar::new(JsType::JsPtr(JsPtrTag::JsStr));
    (var, JsPtrEnum::JsStr(JsStrStruct::new(s)))
}

fn make_obj(kvs: Vec<(JsKey, JsVar, Option<JsPtrEnum>)>, heap: Rc<RefCell<AllocBox>>) -> (JsVar, JsPtrEnum) {
    let var = JsVar::new(JsType::JsPtr(JsPtrTag::JsObj));
    (var, JsPtrEnum::JsObj(JsObjStruct::new(None, "test", kvs, &mut *heap.borrow_mut())))
}

#[bench]
fn init_only(b: &mut Bencher) {
    b.iter(|| {
        init_gc();
    });
}

#[bench]
fn push_scope(b: &mut Bencher) {
    let mut mgr = init_gc();
    let exp = Exp::Undefined;
    b.iter(|| {
        mgr.push_scope(&exp);
    });
}

#[bench]
fn push_pop_no_gc(b: &mut Bencher) {
    let mut mgr = init_gc();
    let exp = Exp::Undefined;
    b.iter(|| {
        mgr.push_scope(&exp);
        mgr.pop_scope(None, false);
    });
}

#[bench]
fn push_pop_gc(b: &mut Bencher) {
    let mut mgr = init_gc();
    let exp = Exp::Undefined;
    b.iter(|| {
        mgr.push_scope(&exp);
        mgr.pop_scope(None, true);
    });
}

#[bench]
fn small_stack_alloc_no_gc(b: &mut Bencher) {
    let mut mgr = init_gc();
    b.iter(|| {
        mgr.alloc(make_num(0.), None).unwrap();
    });
}

#[bench]
fn small_heap_alloc_no_gc(b: &mut Bencher) {
    let mut mgr = init_gc();
    b.iter(|| {
        let (var, ptr) = make_str("");
        mgr.alloc(var, Some(ptr)).unwrap();
    });
}
#[bench]
fn small_heap_alloc_no_gc_2(b: &mut Bencher) {
    let mut mgr = init_gc();
    b.iter(|| {
        let (var, ptr) = make_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
        mgr.alloc(var, Some(ptr)).unwrap();
    });
}

#[bench]
fn large_alloc_no_gc_flat_obj(b: &mut Bencher) {
    let mut mgr = init_gc();
    let kvs = vec![(JsKey::JsSym("0".to_string()), make_num(0.), None),
                   (JsKey::JsSym("1".to_string()), make_num(1.), None),
                   (JsKey::JsSym("2".to_string()), make_num(2.), None),
                   (JsKey::JsSym("3".to_string()), make_num(3.), None),
                   (JsKey::JsSym("4".to_string()), make_num(4.), None),
                   (JsKey::JsSym("5".to_string()), make_num(5.), None),
                   (JsKey::JsSym("6".to_string()), make_num(6.), None),
                   (JsKey::JsSym("7".to_string()), make_num(7.), None),
                   (JsKey::JsSym("8".to_string()), make_num(8.), None),
                   (JsKey::JsSym("9".to_string()), make_num(9.), None),
                   (JsKey::JsSym("10".to_string()), make_num(10.), None)];
    b.iter(|| {
        for _ in 0..100 {
            let (var, ptr) = make_obj(kvs.clone(), mgr.alloc_box.clone());
            mgr.alloc(var, Some(ptr)).unwrap();
        }
    });
}

#[bench]
fn small_local_store(b: &mut Bencher) {
    let mut mgr = init_gc();
    mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
    let var = make_num(0.);
    let (bnd, unique) = (var.binding.clone(), var.unique.clone());
    mgr.alloc(var.clone(), None).unwrap();
    b.iter(|| {
        mgr.store(var.clone(), None).unwrap();
    });
}

#[bench]
fn shallow_load(b: &mut Bencher) {
    let mut mgr = init_gc();
    mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
    let var = make_num(0.);
    let bnd = var.binding.clone();
    mgr.alloc(var, None).unwrap();
    b.iter(|| {
        mgr.load(&bnd).unwrap();
    });
}

#[bench]
fn deep_load(b: &mut Bencher) {
    let mut mgr = init_gc();
    mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
    let var = make_num(0.);
    let bnd = var.binding.clone();
    mgr.alloc(var, None).unwrap();
    for _ in 0..100 {
        mgr.push_scope(&Exp::Undefined);
    }
    b.iter(|| {
        mgr.load(&bnd).unwrap();
    });
}

#[bench]
fn small_alloc_gc(b: &mut Bencher) {
    let mut mgr = init_gc();
    let kvs = vec![(JsKey::JsSym("0".to_string()), make_num(0.), None)];
    let exp = &Exp::Call(box Exp::Undefined, vec![]);
    b.iter(|| {
        mgr.push_scope(&exp);
        let (var, ptr) = make_obj(kvs.clone(), mgr.alloc_box.clone());
        mgr.alloc(var, Some(ptr)).unwrap();
        mgr.pop_scope(None, true).unwrap();
    });
}

#[bench]
fn small_flat_heap_alloc_gc(b: &mut Bencher) {
    let mut mgr = init_gc();
    let kvs = vec![(JsKey::JsSym("0".to_string()), make_num(0.), None),
                   (JsKey::JsSym("1".to_string()), make_num(1.), None),
                   (JsKey::JsSym("2".to_string()), make_num(2.), None),
                   (JsKey::JsSym("3".to_string()), make_num(3.), None),
                   (JsKey::JsSym("4".to_string()), make_num(4.), None),
                   (JsKey::JsSym("5".to_string()), make_num(5.), None),
                   (JsKey::JsSym("6".to_string()), make_num(6.), None),
                   (JsKey::JsSym("7".to_string()), make_num(7.), None),
                   (JsKey::JsSym("8".to_string()), make_num(8.), None),
                   (JsKey::JsSym("9".to_string()), make_num(9.), None),
                   (JsKey::JsSym("10".to_string()), make_num(10.), None)];
    let exp = Exp::Call(box Exp::Undefined, vec![]);
    b.iter(|| {
        mgr.push_scope(&exp);
        let (var, ptr) = make_obj(kvs.clone(), mgr.alloc_box.clone());
        mgr.alloc(var, Some(ptr)).unwrap();
        mgr.pop_scope(None, true).unwrap();
    });
}

#[bench]
fn large_flat_alloc_gc(b: &mut Bencher) {
    let mut mgr = init_gc();
    let kvs = vec![(JsKey::JsSym("0".to_string()), make_num(0.), None),
                   (JsKey::JsSym("1".to_string()), make_num(1.), None),
                   (JsKey::JsSym("2".to_string()), make_num(2.), None),
                   (JsKey::JsSym("3".to_string()), make_num(3.), None),
                   (JsKey::JsSym("4".to_string()), make_num(4.), None),
                   (JsKey::JsSym("5".to_string()), make_num(5.), None),
                   (JsKey::JsSym("6".to_string()), make_num(6.), None),
                   (JsKey::JsSym("7".to_string()), make_num(7.), None),
                   (JsKey::JsSym("8".to_string()), make_num(8.), None),
                   (JsKey::JsSym("9".to_string()), make_num(9.), None),
                   (JsKey::JsSym("10".to_string()), make_num(10.), None)];
    b.iter(|| {
        mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
        for _ in 0..100 {
            let (var, ptr) = make_obj(kvs.clone(), mgr.alloc_box.clone());
            mgr.alloc(var, Some(ptr)).unwrap();
        }
        mgr.pop_scope(None, true).unwrap();
    });
}

#[bench]
fn leak_many(b: &mut Bencher) {
    let mut mgr = init_gc();

    let (var, ptr) = make_str("test");
    let key = JsKey::JsSym("true".to_string());
    let kvs = vec![(key.clone(), var, Some(ptr))];

    b.iter(|| {
        mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
        let (var, ptr) = make_obj(kvs.clone(), mgr.alloc_box.clone());
        let bnd = var.binding.clone();
        mgr.alloc(var.clone(), Some(ptr.clone())).unwrap();

        let copy = mgr.load(&bnd);
        let (mut var, mut ptr) = copy.unwrap();

        for _ in 0..1000 {
            let (leak_var, leak_ptr) = make_str("test");
            match *&mut ptr {
                Some(JsPtrEnum::JsObj(ref mut obj)) => {
                    obj.add_key(key.clone(), leak_var, Some(leak_ptr), &mut *(mgr.alloc_box.borrow_mut()));
                },
                _ => unreachable!()
            }
        }
        mgr.store(var, ptr).unwrap();
        mgr.pop_scope(None, true).unwrap();
    });
}
<|endoftext|>


<commit_before>use std::fmt;
use memory::Memory;
use super::Size;
use PC;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Operand {
    DataRegisterDirect(u8),
    AddressRegisterDirect(u8),
    AddressRegisterIndirect(u8),
    AddressRegisterIndirectWithPredecrement(u8),
    AddressRegisterIndirectWithPostincrement(u8),
    AddressRegisterIndirectWithDisplacement(u8, i16),
    AddressRegisterIndirectWithIndex(u8, u8, i8),
    PcWithDisplacement(i16),
    PcWithIndex(u8, i8),
    AbsoluteWord(u16),
    AbsoluteLong(u32),
    Immediate(Size, u32),
    StatusRegister(Size),
    Displacement(Size, u32),
    Number(Size, u32),
}

fn encode_extension_word(xreg_ndx_size: u8, displacement: i8) -> u16 {
    // top four bits = (D/A RRR) matches our register array layout
    (((xreg_ndx_size as u16) << 12) | (displacement as u8 as u16)) as u16
}

impl Operand {
    pub fn extension_words(&self) -> u32 {
        match *self {
            Operand::DataRegisterDirect(_) => 0,
            Operand::AddressRegisterDirect(_) => 0,
            Operand::AddressRegisterIndirect(_) => 0,
            Operand::AddressRegisterIndirectWithPredecrement(_) => 0,
            Operand::AddressRegisterIndirectWithPostincrement(_) => 0,
            Operand::AddressRegisterIndirectWithDisplacement(_, _) => 1,
            Operand::AddressRegisterIndirectWithIndex(_, _, _) => 1,
            Operand::AbsoluteWord(_) => 1,
            Operand::AbsoluteLong(_) => 2,
            Operand::Displacement(Size::Byte, _) => 0,
            Operand::Displacement(Size::Word, _) => 1,
            Operand::Displacement(Size::Long, _) => 2,
            Operand::Displacement(Size::Unsized, _) => panic!("unsized {:?}", self),
            Operand::Number(_, _) => panic!("unsized {:?}", self),
            Operand::PcWithDisplacement(_) => 1,
            Operand::PcWithIndex(_, _) => 1,
            Operand::Immediate(Size::Byte, _) => 1,
            Operand::Immediate(Size::Word, _) => 1,
            Operand::Immediate(Size::Long, _) => 2,
            Operand::Immediate(Size::Unsized, _) => panic!("unsized {:?}", self),
            Operand::StatusRegister(_) => 0,
        }
    }

    pub fn add_extension_words(&self, pc: PC, mem: &mut Memory) -> PC {
        match *self {
            Operand::DataRegisterDirect(_) => pc,
            Operand::AddressRegisterDirect(_) => pc,
            Operand::AddressRegisterIndirect(_) => pc,
            Operand::AddressRegisterIndirectWithPredecrement(_) => pc,
            Operand::AddressRegisterIndirectWithPostincrement(_) => pc,
            Operand::AddressRegisterIndirectWithDisplacement(_, displacement) =>
                mem.write_word(pc, displacement as u16),
            Operand::AddressRegisterIndirectWithIndex(_, indexinfo, displacement) =>
                mem.write_word(pc, encode_extension_word(indexinfo, displacement)),
            Operand::AbsoluteWord(val) => mem.write_word(pc, val as u16),
            Operand::AbsoluteLong(val) => {
                mem.write_word(pc, (val >> 16) as u16);
                mem.write_word(pc + 2, val as u16)
            },
            Operand::Displacement(Size::Byte, _) => pc,
            Operand::Displacement(Size::Word, val) => mem.write_word(pc, val as u16),
            Operand::Displacement(Size::Long, val) => {
                mem.write_word(pc, (val >> 16) as u16);
                mem.write_word(pc + 2, val as u16)
            },
            Operand::Displacement(Size::Unsized, _) => panic!("unsized {:?}", self),
            Operand::Number(_, _) => panic!("unsized {:?}", self),
            Operand::PcWithDisplacement(displacement) => mem.write_word(pc, displacement as u16),
            Operand::PcWithIndex(indexinfo, displacement) => mem.write_word(pc, encode_extension_word(indexinfo, displacement)),
            Operand::Immediate(Size::Byte, val) => mem.write_word(pc, (val & 0xff) as u16),
            Operand::Immediate(Size::Word, val) => mem.write_word(pc, val as u16),
            Operand::Immediate(Size::Long, val) => {
                mem.write_word(pc, (val >> 16) as u16);
                mem.write_word(pc + 2, val as u16)
            }
            Operand::Immediate(Size::Unsized, _) => panic!("unsized {:?}", self),
            Operand::StatusRegister(_) => pc,
        }
    }
}

impl fmt::Display for Operand {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Operand::DataRegisterDirect(reg) => write!(f, "D{}", reg),
            Operand::AddressRegisterDirect(reg) => write!(f, "A{}", reg),
            Operand::AddressRegisterIndirect(reg) => write!(f, "(A{})", reg),
            Operand::AddressRegisterIndirectWithPredecrement(reg) => write!(f, "-(A{})", reg),
            Operand::AddressRegisterIndirectWithPostincrement(reg) => write!(f, "(A{})+", reg),
            Operand::AddressRegisterIndirectWithDisplacement(reg, dis) => write!(f, "{}(A{})", dis, reg),
            Operand::AddressRegisterIndirectWithIndex(reg, ireg, dis) => write!(f, "{}(A{},{})", dis, reg, xreg(ireg)),
            Operand::PcWithDisplacement(dis) => write!(f, "{}(PC)", dis),
            Operand::PcWithIndex(ireg, dis) => write!(f, "{}(PC,{})", dis, xreg(ireg)),
            Operand::AbsoluteWord(val) => write!(f, "${:04X}", val),
            Operand::AbsoluteLong(val) => write!(f, "${:08X}", val),
            Operand::Number(Size::Byte, val) => write!(f, "${:02X}", val),
            Operand::Number(Size::Word, val) => write!(f, "${:04X}", val),
            Operand::Number(Size::Long, val) => write!(f, "${:08X}", val),
            Operand::Number(Size::Unsized, val) => write!(f, "${:08X}.?", val),
            Operand::Displacement(Size::Byte, val) => write!(f, "${:02X}", val),
            Operand::Displacement(Size::Word, val) => write!(f, "${:04X}", val),
            Operand::Displacement(Size::Long, val) => write!(f, "${:08X}", val),
            Operand::Displacement(Size::Unsized, val) => write!(f, "${:08X}.?", val),
            Operand::Immediate(Size::Byte, val) => write!(f, "#${:02X}", val),
            Operand::Immediate(Size::Word, val) => write!(f, "#${:04X}", val),
            Operand::Immediate(Size::Long, val) => write!(f, "#${:08X}", val),
            Operand::Immediate(Size::Unsized, val) => write!(f, "#${:08X}.?", val),
            Operand::StatusRegister(Size::Byte) => write!(f, "CCR"),
            Operand::StatusRegister(_) => write!(f, "SR"),
         }
    }
}

fn xreg(xreg: u8) -> Operand {
    if xreg & 8 > 0 {
        Operand::AddressRegisterDirect(xreg & 7)
    } else {
        Operand::DataRegisterDirect(xreg & 7)
    }
}

<commit_msg>Registers operand Displays correctly<commit_after>use std::fmt;
use memory::Memory;
use super::Size;
use PC;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Operand {
    DataRegisterDirect(u8),
    AddressRegisterDirect(u8),
    AddressRegisterIndirect(u8),
    AddressRegisterIndirectWithPredecrement(u8),
    AddressRegisterIndirectWithPostincrement(u8),
    AddressRegisterIndirectWithDisplacement(u8, i16),
    AddressRegisterIndirectWithIndex(u8, u8, i8),
    PcWithDisplacement(i16),
    PcWithIndex(u8, i8),
    AbsoluteWord(u16),
    AbsoluteLong(u32),
    Immediate(Size, u32),
    StatusRegister(Size),
    Displacement(Size, u32),
    Number(Size, u32),
    Registers(u16, bool), // reglist, reversed
}

fn encode_extension_word(xreg_ndx_size: u8, displacement: i8) -> u16 {
    // top four bits = (D/A RRR) matches our register array layout
    (((xreg_ndx_size as u16) << 12) | (displacement as u8 as u16)) as u16
}

impl Operand {
    pub fn extension_words(&self) -> u32 {
        match *self {
            Operand::DataRegisterDirect(_) => 0,
            Operand::AddressRegisterDirect(_) => 0,
            Operand::AddressRegisterIndirect(_) => 0,
            Operand::AddressRegisterIndirectWithPredecrement(_) => 0,
            Operand::AddressRegisterIndirectWithPostincrement(_) => 0,
            Operand::AddressRegisterIndirectWithDisplacement(_, _) => 1,
            Operand::AddressRegisterIndirectWithIndex(_, _, _) => 1,
            Operand::AbsoluteWord(_) => 1,
            Operand::AbsoluteLong(_) => 2,
            Operand::Displacement(Size::Byte, _) => 0,
            Operand::Displacement(Size::Word, _) => 1,
            Operand::Displacement(Size::Long, _) => 2,
            Operand::Displacement(Size::Unsized, _) => panic!("unsized {:?}", self),
            Operand::Number(_, _) => panic!("unsized {:?}", self),
            Operand::PcWithDisplacement(_) => 1,
            Operand::PcWithIndex(_, _) => 1,
            Operand::Immediate(Size::Byte, _) => 1,
            Operand::Immediate(Size::Word, _) => 1,
            Operand::Immediate(Size::Long, _) => 2,
            Operand::Immediate(Size::Unsized, _) => panic!("unsized {:?}", self),
            Operand::StatusRegister(_) => 0,
            Operand::Registers(_, _) => 1,
        }
    }

    pub fn add_extension_words(&self, pc: PC, mem: &mut Memory) -> PC {
        match *self {
            Operand::DataRegisterDirect(_) => pc,
            Operand::AddressRegisterDirect(_) => pc,
            Operand::AddressRegisterIndirect(_) => pc,
            Operand::AddressRegisterIndirectWithPredecrement(_) => pc,
            Operand::AddressRegisterIndirectWithPostincrement(_) => pc,
            Operand::AddressRegisterIndirectWithDisplacement(_, displacement) =>
                mem.write_word(pc, displacement as u16),
            Operand::AddressRegisterIndirectWithIndex(_, indexinfo, displacement) =>
                mem.write_word(pc, encode_extension_word(indexinfo, displacement)),
            Operand::AbsoluteWord(val) => mem.write_word(pc, val as u16),
            Operand::AbsoluteLong(val) => {
                mem.write_word(pc, (val >> 16) as u16);
                mem.write_word(pc + 2, val as u16)
            },
            Operand::Displacement(Size::Byte, _) => pc,
            Operand::Displacement(Size::Word, val) => mem.write_word(pc, val as u16),
            Operand::Displacement(Size::Long, val) => {
                mem.write_word(pc, (val >> 16) as u16);
                mem.write_word(pc + 2, val as u16)
            },
            Operand::Displacement(Size::Unsized, _) => panic!("unsized {:?}", self),
            Operand::Number(_, _) => panic!("unsized {:?}", self),
            Operand::PcWithDisplacement(displacement) => mem.write_word(pc, displacement as u16),
            Operand::PcWithIndex(indexinfo, displacement) => mem.write_word(pc, encode_extension_word(indexinfo, displacement)),
            Operand::Immediate(Size::Byte, val) => mem.write_word(pc, (val & 0xff) as u16),
            Operand::Immediate(Size::Word, val) => mem.write_word(pc, val as u16),
            Operand::Immediate(Size::Long, val) => {
                mem.write_word(pc, (val >> 16) as u16);
                mem.write_word(pc + 2, val as u16)
            }
            Operand::Immediate(Size::Unsized, _) => panic!("unsized {:?}", self),
            Operand::StatusRegister(_) => pc,
            Operand::Registers(reglist, false) => mem.write_word(pc, reglist),
            Operand::Registers(reglist, true) => mem.write_word(pc, bit_reverse(reglist)),
        }
    }
}

fn bit_reverse(x: u16) -> u16 {
    let x = (x & 0b1010_1010_1010_1010) >> 1 | (x & 0b0101_0101_0101_0101) << 1;
    let x = (x & 0b1100_1100_1100_1100) >> 2 | (x & 0b0011_0011_0011_0011) << 2;
    let x = (x & 0b1111_0000_1111_0000) >> 4 | (x & 0b0000_1111_0000_1111) << 4;
    (x >> 8 | x << 8)
}

impl fmt::Display for Operand {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fn write_registers(f: &mut fmt::Formatter, reglist: u16) -> fmt::Result {
            let mut result: fmt::Result = Ok(());
            let mut reglist = reglist;
            let mut first = true;
            for bit in 0..16u16 {
                if (1 << bit) & reglist != 0 {
                    let mut span = bit;
                    let span = loop {
                        if span < 16 {
                            let spanbit = (1 << span);
                            if spanbit & reglist != 0 {
                                reglist &= !spanbit;
                                span += 1;
                                continue;
                            }
                        }
                        break span - 1;
                    };
                    if !first {
                        result = write!(f, "/");
                    };
                    first = false;
                    if span == bit {
                        if bit > 7 {
                            result = write!(f, "A{}", bit-8);
                        } else {
                            result = write!(f, "D{}", bit);
                        }
                    } else {
                        if bit > 7 {
                            result = write!(f, "A{}-", bit-8);
                        } else {
                            result = write!(f, "D{}-", bit);
                        }
                        if span > 7 {
                            result = write!(f, "A{}", span-8);
                        } else {
                            result = write!(f, "D{}", span);
                        }
                    }
                }
            };
            result
        };
        match *self {
            Operand::DataRegisterDirect(reg) => write!(f, "D{}", reg),
            Operand::AddressRegisterDirect(reg) => write!(f, "A{}", reg),
            Operand::AddressRegisterIndirect(reg) => write!(f, "(A{})", reg),
            Operand::AddressRegisterIndirectWithPredecrement(reg) => write!(f, "-(A{})", reg),
            Operand::AddressRegisterIndirectWithPostincrement(reg) => write!(f, "(A{})+", reg),
            Operand::AddressRegisterIndirectWithDisplacement(reg, dis) => write!(f, "{}(A{})", dis, reg),
            Operand::AddressRegisterIndirectWithIndex(reg, ireg, dis) => write!(f, "{}(A{},{})", dis, reg, xreg(ireg)),
            Operand::PcWithDisplacement(dis) => write!(f, "{}(PC)", dis),
            Operand::PcWithIndex(ireg, dis) => write!(f, "{}(PC,{})", dis, xreg(ireg)),
            Operand::AbsoluteWord(val) => write!(f, "${:04X}", val),
            Operand::AbsoluteLong(val) => write!(f, "${:08X}", val),
            Operand::Number(Size::Byte, val) => write!(f, "${:02X}", val),
            Operand::Number(Size::Word, val) => write!(f, "${:04X}", val),
            Operand::Number(Size::Long, val) => write!(f, "${:08X}", val),
            Operand::Number(Size::Unsized, val) => write!(f, "${:08X}.?", val),
            Operand::Displacement(Size::Byte, val) => write!(f, "${:02X}", val),
            Operand::Displacement(Size::Word, val) => write!(f, "${:04X}", val),
            Operand::Displacement(Size::Long, val) => write!(f, "${:08X}", val),
            Operand::Displacement(Size::Unsized, val) => write!(f, "${:08X}.?", val),
            Operand::Immediate(Size::Byte, val) => write!(f, "#${:02X}", val),
            Operand::Immediate(Size::Word, val) => write!(f, "#${:04X}", val),
            Operand::Immediate(Size::Long, val) => write!(f, "#${:08X}", val),
            Operand::Immediate(Size::Unsized, val) => write!(f, "#${:08X}.?", val),
            Operand::StatusRegister(Size::Byte) => write!(f, "CCR"),
            Operand::StatusRegister(_) => write!(f, "SR"),
            Operand::Registers(reglist, false) => write_registers(f, reglist),
            Operand::Registers(reglist, true) => write_registers(f, bit_reverse(reglist)),
         }
    }
}

fn xreg(xreg: u8) -> Operand {
    if xreg & 8 > 0 {
        Operand::AddressRegisterDirect(xreg & 7)
    } else {
        Operand::DataRegisterDirect(xreg & 7)
    }
}

#[cfg(test)]
mod tests {
    use operand::bit_reverse;
    extern crate rand;
    use self::rand::Rng;
    use operand::Operand;

    #[test]
    fn simple_bit_reversal() {
        assert_eq!(0b1101_0011_1010_0001, bit_reverse(0b1000_0101_1100_1011));
    }

    #[test]
    fn bit_reversal() {
        let mut r = rand::thread_rng();
        for _ in 0..1000 {
            let v = r.gen();
            assert_eq!(v, bit_reverse(bit_reverse(v)));
        }
    }

    #[test]
    fn single_bit_registers_operand() {
        for bit in 0..16 {
            let expected = if bit < 8 {
                format!("D{}", bit)
            } else {
                format!("A{}", bit-8)
            };
            assert_eq!(expected, format!("{}", Operand::Registers(1 << bit, false)));
        }
    }
    #[test]
    fn separate_registers_operand() {
        assert_eq!("A1/A4", format!("{}", Operand::Registers(0b0001_0010_0000_0000, false)));
        assert_eq!("D5/A2", format!("{}", Operand::Registers(0b0000_0100_0010_0000, false)));
    }
    #[test]
    fn spanning_registers_operand() {
        assert_eq!("A1-A4", format!("{}", Operand::Registers(0b0001_1110_0000_0000, false)));
        assert_eq!("D5-A2", format!("{}", Operand::Registers(0b0000_0111_1110_0000, false)));
    }
    #[test]
    fn combined_registers_operand() {
        assert_eq!("D4/A1-A4", format!("{}", Operand::Registers(0b0001_1110_0001_0000, false)));
        assert_eq!("D5-A2/A5", format!("{}", Operand::Registers(0b0010_0111_1110_0000, false)));
    }
}<|endoftext|>


<commit_before>extern crate pretty;

use pretty::{
    BoxAllocator,
    DocAllocator,
    DocBuilder,
};
use std::io;
use std::str;

#[derive(Clone, Debug)]
pub struct Forest<'a>(&'a [Tree<'a>]);

impl<'a> Forest<'a> {
    fn forest(forest: &'a [Tree<'a>]) -> Forest<'a> {
        Forest(forest)
    }

    fn nil() -> Forest<'a> {
        Forest(&[])
    }

    fn bracket<'b, A>(&'b self, allocator: &'b A) -> DocBuilder<'b, A>
    where A: DocAllocator<'b>
    {
        if (self.0).len() == 0 {
            allocator.nil()
        } else {
            allocator.text("[")
                .append(
                    allocator.newline()
                        .append(self.pretty(allocator))
                        .nest(2))
                .append(allocator.newline())
                .append(allocator.text("]"))
        }
    }

    fn pretty<'b, A>(&'b self, allocator: &'b A) -> DocBuilder<'b, A>
    where A: DocAllocator<'b>
    {
        let forest = self.0;
        let mut doc = allocator.nil();
        let mut i = 0;
        let k = forest.len() - 1;
        loop {
            if i < k {
                doc = doc
                    .append(forest[i].pretty(allocator)
                        .append(allocator.text(","))
                        .append(allocator.newline()));
            }
            else if i == k {
                doc = doc
                    .append(forest[i].pretty(allocator));
                break
            }
            i += 1;
        }
        doc
    }
}

#[derive(Clone, Debug)]
pub struct Tree<'a> {
    node: String,
    forest: Forest<'a>,
}

impl<'a> Tree<'a> {
    pub fn node(node: &str) -> Tree<'a> {
        Tree {
            node: node.to_string(),
            forest: Forest::nil(),
        }
    }

    pub fn node_with_forest(node: &str, forest: &'a [Tree<'a>]) -> Tree<'a> {
        Tree {
            node: node.to_string(),
            forest: Forest::forest(forest),
        }
    }

    pub fn pretty<'b, A>(&'b self, allocator: &'b A) -> DocBuilder<'b, A>
    where A: DocAllocator<'b>
    {
        allocator.text(&self.node[..])
            .append((self.forest).bracket(allocator))
            .group()
    }
}

#[allow(dead_code)]
pub fn main() {
    let allocator = BoxAllocator;
    let bbbbbbs = [
        Tree::node("ccc"),
        Tree::node("dd"),
    ];
    let ffffs = [
        Tree::node("gg"),
        Tree::node("hhh"),
        Tree::node("ii"),
    ];
    let aaas = [
        Tree::node_with_forest("bbbbbb", &bbbbbbs),
        Tree::node("eee"),
        Tree::node_with_forest("ffff", &ffffs),
    ];
    let example = Tree::node_with_forest("aaaa", &aaas);

    let err_msg = "<buffer is not a utf-8 encoded string>";

    // try writing to stdout
    {
        print!("\nwriting to stdout directly:\n");
        let mut out = io::stdout();
        example
            .pretty(&allocator)
            .1
            .render(70, &mut out)
    // try writing to memory
    }.and_then(|()| {
        print!("\nwriting to string then printing:\n");
        let mut mem = Vec::new();
        example
            .pretty(&allocator)
            .1
            .render(70, &mut mem)
            // print to console from memory
            .map(|()| {
                let res = str::from_utf8(&mem).unwrap_or(err_msg);
                println!("{}", res)
            })
    // print an error if anything failed
    }).unwrap_or_else(|err| {
        println!("error: {}", err)
    });
}
<commit_msg>Post: Use `intersperse` in example code.<commit_after>extern crate pretty;

use pretty::{
    BoxAllocator,
    DocAllocator,
    DocBuilder,
};
use std::io;
use std::str;

#[derive(Clone, Debug)]
pub struct Forest<'a>(&'a [Tree<'a>]);

impl<'a> Forest<'a> {
    fn forest(forest: &'a [Tree<'a>]) -> Forest<'a> {
        Forest(forest)
    }

    fn nil() -> Forest<'a> {
        Forest(&[])
    }

    fn bracket<'b, A>(&'b self, allocator: &'b A) -> DocBuilder<'b, A>
    where A: DocAllocator<'b>
    {
        if (self.0).len() == 0 {
            allocator.nil()
        } else {
            allocator.text("[")
                .append(
                    allocator.newline()
                        .append(self.pretty(allocator))
                        .nest(2))
                .append(allocator.newline())
                .append(allocator.text("]"))
        }
    }

    fn pretty<'b, A>(&'b self, allocator: &'b A) -> DocBuilder<'b, A>
    where A: DocAllocator<'b>
    {
        let forest = self.0;
        let separator = allocator.text(",").append(allocator.newline());
        allocator.intersperse(forest.into_iter().map(|tree| tree.pretty(allocator)), separator)
    }
}

#[derive(Clone, Debug)]
pub struct Tree<'a> {
    node: String,
    forest: Forest<'a>,
}

impl<'a> Tree<'a> {
    pub fn node(node: &str) -> Tree<'a> {
        Tree {
            node: node.to_string(),
            forest: Forest::nil(),
        }
    }

    pub fn node_with_forest(node: &str, forest: &'a [Tree<'a>]) -> Tree<'a> {
        Tree {
            node: node.to_string(),
            forest: Forest::forest(forest),
        }
    }

    pub fn pretty<'b, A>(&'b self, allocator: &'b A) -> DocBuilder<'b, A>
    where A: DocAllocator<'b>
    {
        allocator.text(&self.node[..])
            .append((self.forest).bracket(allocator))
            .group()
    }
}

#[allow(dead_code)]
pub fn main() {
    let allocator = BoxAllocator;
    let bbbbbbs = [
        Tree::node("ccc"),
        Tree::node("dd"),
    ];
    let ffffs = [
        Tree::node("gg"),
        Tree::node("hhh"),
        Tree::node("ii"),
    ];
    let aaas = [
        Tree::node_with_forest("bbbbbb", &bbbbbbs),
        Tree::node("eee"),
        Tree::node_with_forest("ffff", &ffffs),
    ];
    let example = Tree::node_with_forest("aaaa", &aaas);

    let err_msg = "<buffer is not a utf-8 encoded string>";

    // try writing to stdout
    {
        print!("\nwriting to stdout directly:\n");
        let mut out = io::stdout();
        example
            .pretty(&allocator)
            .1
            .render(70, &mut out)
    // try writing to memory
    }.and_then(|()| {
        print!("\nwriting to string then printing:\n");
        let mut mem = Vec::new();
        example
            .pretty(&allocator)
            .1
            .render(70, &mut mem)
            // print to console from memory
            .map(|()| {
                let res = str::from_utf8(&mem).unwrap_or(err_msg);
                println!("{}", res)
            })
    // print an error if anything failed
    }).unwrap_or_else(|err| {
        println!("error: {}", err)
    });
}
<|endoftext|>


<commit_before>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

extern crate twitter_api as twitter;
extern crate rustc_serialize as rustc_serialize;
extern crate oauth_client as oauth;

use std::io;
use std::io::prelude::*;
use std::env;
use std::fs::{File, OpenOptions};
use std::path::Path;
use std::path::PathBuf;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};
use oauth::Token;

const TWITTER_CONF_FILENAME: &'static str = ".twitter.conf";

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Config {
    pub consumer_key: String,
    pub consumer_secret: String,
    pub access_key: String,
    pub access_secret: String
}

impl Config {
    pub fn read() -> Option<Config> {
        let path = Path::new(PATH);
        let mut file = match File::open(&path) {
            Ok(f) => f,
            Err(_) => return None
        };
        let conf = Json::from_reader(&mut file).unwrap();
        Decodable::decode(&mut json::Decoder::new(conf)).ok()
    }

    pub fn write(&self) {
        let path = Path::new(PATH);
        let mut file = match OpenOptions::new().write(true).open(&path) {
            Ok(f) => f,
            Err(e) => panic!("{}", e)
        };
        let _ = write!(&mut file, "{}\n", &json::encode(self).unwrap());
    }
}

fn console_input(prompt: &str) -> String {
    print!("{}\n\t", prompt);
    let mut line = String::new();
    let _ = io::stdin().read_line(&mut line).unwrap();
    line.trim().to_string()
}

fn main() {
    let conf = match Config::read() {
        Some(c) => c,
        None => {
            let consumer_key    = console_input("input your consumer key:");
            let consumer_secret = console_input("input your consumer secret:");
            let consumer = Token::new(consumer_key, consumer_secret);

            let request = twitter::get_request_token(&consumer);
            println!("open the following url:");
            println!("\t{}", twitter::get_authorize_url(&request));
            let pin = console_input("input pin:");
            let access = twitter::get_access_token(&consumer, &request, &pin);

            let c = Config {
                consumer_key: consumer.key.to_string(),
                consumer_secret: consumer.secret.to_string(),
                access_key: access.key.to_string(),
                access_secret: access.secret.to_string()
            };
            c.write();
            c
        }
    };

    let consumer = Token::new(conf.consumer_key, conf.consumer_secret);
    let access = Token::new(conf.access_key, conf.access_secret);

    let status = console_input("What's happening?");
    twitter::tweet(&consumer, &access, &status);
}

<commit_msg>examples/tweet.rs : Function to get the home dir<commit_after>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

extern crate twitter_api as twitter;
extern crate rustc_serialize as rustc_serialize;
extern crate oauth_client as oauth;

use std::io;
use std::io::prelude::*;
use std::env;
use std::fs::{File, OpenOptions};
use std::path::Path;
use std::path::PathBuf;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};
use oauth::Token;

const TWITTER_CONF_FILENAME: &'static str = ".twitter.conf";

fn get_home_dir() -> PathBuf{
    match env::home_dir() {
        Some(p) => p,
        None => {
            panic!("Impossible to get your home dir!");
        }
    }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Config {
    pub consumer_key: String,
    pub consumer_secret: String,
    pub access_key: String,
    pub access_secret: String
}

impl Config {
    pub fn read() -> Option<Config> {
        let path = Path::new(PATH);
        let mut file = match File::open(&path) {
            Ok(f) => f,
            Err(_) => return None
        };
        let conf = Json::from_reader(&mut file).unwrap();
        Decodable::decode(&mut json::Decoder::new(conf)).ok()
    }

    pub fn write(&self) {
        let path = Path::new(PATH);
        let mut file = match OpenOptions::new().write(true).open(&path) {
            Ok(f) => f,
            Err(e) => panic!("{}", e)
        };
        let _ = write!(&mut file, "{}\n", &json::encode(self).unwrap());
    }
}

fn console_input(prompt: &str) -> String {
    print!("{}\n\t", prompt);
    let mut line = String::new();
    let _ = io::stdin().read_line(&mut line).unwrap();
    line.trim().to_string()
}

fn main() {
    let conf = match Config::read() {
        Some(c) => c,
        None => {
            let consumer_key    = console_input("input your consumer key:");
            let consumer_secret = console_input("input your consumer secret:");
            let consumer = Token::new(consumer_key, consumer_secret);

            let request = twitter::get_request_token(&consumer);
            println!("open the following url:");
            println!("\t{}", twitter::get_authorize_url(&request));
            let pin = console_input("input pin:");
            let access = twitter::get_access_token(&consumer, &request, &pin);

            let c = Config {
                consumer_key: consumer.key.to_string(),
                consumer_secret: consumer.secret.to_string(),
                access_key: access.key.to_string(),
                access_secret: access.secret.to_string()
            };
            c.write();
            c
        }
    };

    let consumer = Token::new(conf.consumer_key, conf.consumer_secret);
    let access = Token::new(conf.access_key, conf.access_secret);

    let status = console_input("What's happening?");
    twitter::tweet(&consumer, &access, &status);
}

<|endoftext|>


<commit_before>extern crate futures;
extern crate ldap3;
extern crate tokio_core;

use std::io;
use std::result::Result;

use futures::{Future, IntoFuture, Stream};
use ldap3::{LdapConnAsync, LdapResult, Scope};
use tokio_core::reactor::Core;

const ENTRIES_BEFORE_ABANDON: usize = 1;

fn main() {
    match do_abandon() {
        Ok(r) => println!("{:?}", r),
        Err(e) => println!("{:?}", e),
    }
}

fn do_abandon() -> Result<LdapResult, io::Error> {
    let mut core = Core::new()?;
    let handle = core.handle();
    let ldap = LdapConnAsync::new("ldap://localhost:2389", &handle)?;
    let srch = ldap
        .and_then(|ldap| {
            ldap.streaming_search(
                "ou=Places,dc=example,dc=org",
                Scope::Subtree,
                "objectClass=locality",
                vec!["l"]
        )})
        .and_then(|mut strm| {
            let mut count = 0;
            let rx = strm.get_result_rx().into_future();
            let a_chan = strm.get_abandon_channel().into_future();
            a_chan.and_then(move |a_chan| rx.and_then(move |rx|
                rx.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
                    .join(strm.for_each(move |_tag|
                        if count == ENTRIES_BEFORE_ABANDON {
                            a_chan.send(())
                                .map_err(|_e| io::Error::new(io::ErrorKind::Other, "a_chan send"))
                        } else {
                            count += 1;
                            Ok(())
                        }
                ))
            ))
        })
        .map(|(res, _)| res);
    core.run(srch)
}
<commit_msg>Update example not to use deprecated API<commit_after>extern crate futures;
extern crate ldap3;
extern crate tokio_core;

use std::io;
use std::result::Result;

use futures::{Future, IntoFuture, Stream};
use ldap3::{LdapConnAsync, LdapResult, Scope};
use tokio_core::reactor::Core;

const ENTRIES_BEFORE_ABANDON: usize = 1;

fn main() {
    match do_abandon() {
        Ok(r) => println!("{:?}", r),
        Err(e) => println!("{:?}", e),
    }
}

fn do_abandon() -> Result<LdapResult, io::Error> {
    let mut core = Core::new()?;
    let handle = core.handle();
    let ldap = LdapConnAsync::new("ldap://localhost:2389", &handle)?;
    let srch = ldap
        .and_then(|ldap| {
            ldap.streaming_search(
                "ou=Places,dc=example,dc=org",
                Scope::Subtree,
                "objectClass=locality",
                vec!["l"]
        )})
        .and_then(|mut strm| {
            let mut count = 0;
            let rx = strm.get_result_rx().into_future();
            let a_chan = strm.get_abandon_channel().into_future();
            a_chan.and_then(move |a_chan| rx.and_then(move |rx|
                rx.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
                    .join(strm.for_each(move |_tag|
                        if count == ENTRIES_BEFORE_ABANDON {
                            a_chan.unbounded_send(())
                                .map_err(|_e| io::Error::new(io::ErrorKind::Other, "a_chan send"))
                        } else {
                            count += 1;
                            Ok(())
                        }
                ))
            ))
        })
        .map(|(res, _)| res);
    core.run(srch)
}
<|endoftext|>