<commit_before>extern crate indy;

// Workaround to share some utils code based on indy sdk types between tests and indy sdk
use indy::api as api;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;

#[macro_use]
mod utils;

#[cfg(feature = "local_nodes_pool")]
use indy::api::ErrorCode;

use utils::environment::EnvironmentUtils;
use utils::pool::PoolUtils;
use utils::test::TestUtils;

mod high_cases {
    use super::*;

    mod create {
        use super::*;

        #[test]
        fn create_pool_ledger_config_works() {
            TestUtils::cleanup_storage();

            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool("pool_create", None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config("pool_create", Some(pool_config.as_str())).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn create_pool_ledger_config_works_for_empty_name() {
            TestUtils::cleanup_storage();

            let pool_name = "";
            let res = PoolUtils::create_pool_ledger_config(pool_name, None);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonInvalidParam2);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn create_pool_ledger_config_works_for_config_json() {
            TestUtils::cleanup_storage();

            let pool_name = "create_pool_ledger_config_works_for_config_json";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());

            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn create_pool_ledger_config_works_for_specific_config() {
            TestUtils::cleanup_storage();

            let pool_name = "create_pool_ledger_config_works_for_specific_config";
            let txn_file_path = EnvironmentUtils::tmp_file_path("specific_filename.txn");
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, Some(txn_file_path.as_path()));
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());

            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod open {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works() {
            TestUtils::cleanup_storage();

            let pool_name = "pool_open";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            PoolUtils::open_pool_ledger(pool_name, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")] //TODO Not implemented yet
        fn open_pool_ledger_works_for_config() {
            TestUtils::cleanup_storage();

            let pool_name = "open_pool_ledger_works_for_config";
            let config = r#"{"refreshOnOpen": true}"#;

            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            PoolUtils::open_pool_ledger(pool_name, Some(config)).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_twice() {
            TestUtils::cleanup_storage();

            let pool_name = "pool_open_twice";
            PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();

            let res = PoolUtils::open_pool_ledger(pool_name, None);
            assert_match!(Err(ErrorCode::PoolLedgerInvalidPoolHandle), res);

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_two_nodes() {
            TestUtils::cleanup_storage();

            let pool_name = "open_pool_ledger_works_for_two_nodes";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, Some(2), None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            PoolUtils::open_pool_ledger(pool_name, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_three_nodes() {
            TestUtils::cleanup_storage();

            let pool_name = "open_pool_ledger_works_for_three_nodes";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, Some(3), None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            PoolUtils::open_pool_ledger(pool_name, None).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod refresh {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_refresh_pool_ledger_works() {
            TestUtils::cleanup_storage();

            let pool_handle = PoolUtils::create_and_open_pool_ledger("indy_refresh_pool_ledger_works").unwrap();

            PoolUtils::refresh(pool_handle).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod close {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_close_pool_ledger_works() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_close_pool_ledger_works";
            let pool_handle = PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();

            PoolUtils::close(pool_handle).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_close_pool_ledger_works_for_twice() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_close_pool_ledger_works_twice";
            let pool_handle = PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();

            PoolUtils::close(pool_handle).unwrap();
            assert_eq!(PoolUtils::close(pool_handle).unwrap_err(), ErrorCode::PoolLedgerInvalidPoolHandle);

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_close_pool_ledger_works_for_reopen_after_close() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_close_pool_ledger_works";
            let pool_handle = PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();

            PoolUtils::close(pool_handle).unwrap();
            PoolUtils::open_pool_ledger(pool_name, None).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod delete {
        use super::*;

        #[test]
        fn indy_delete_pool_ledger_config_works() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_remove_pool_ledger_config_works";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            PoolUtils::delete(pool_name).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_delete_pool_ledger_config_works_for_opened() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_remove_pool_ledger_config_works_for_opened";
            PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();

            assert_eq!(PoolUtils::delete(pool_name).unwrap_err(), ErrorCode::CommonInvalidState);

            TestUtils::cleanup_storage();
        }
    }
}

mod medium_cases {
    use super::*;

    mod create {
        use super::*;

        #[test]
        fn create_pool_ledger_config_works_for_invalid_config_json() {
            TestUtils::cleanup_storage();

            let pool_name = "create_pool_ledger_config_works_for_invalid_config";
            let config = r#"{}"#.to_string();

            let res = PoolUtils::create_pool_ledger_config(pool_name, Some(config.as_str()));
            assert_eq!(res.unwrap_err(), ErrorCode::CommonInvalidStructure);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn create_pool_ledger_config_works_for_invalid_genesis_txn_path() {
            TestUtils::cleanup_storage();

            let pool_name = "create_pool_ledger_config_works_for_invalid_genesis_txn_path";
            let config = r#"{"genesis_txn": "path"}"#.to_string();

            let res = PoolUtils::create_pool_ledger_config(pool_name, Some(config.as_str()));
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn create_pool_ledger_config_works_for_twice() {
            TestUtils::cleanup_storage();

            let pool_name = "pool_create";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());

            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();
            let res = PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str()));

            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerConfigAlreadyExistsError);

            TestUtils::cleanup_storage();
        }
    }

    mod open {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_invalid_name() {
            TestUtils::cleanup_storage();
            let pool_name = "open_pool_ledger_works_for_invalid_name";

            let res = PoolUtils::open_pool_ledger(pool_name, None);
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerTerminated);//TODO change it on IOError

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_invalid_nodes_file() {
            TestUtils::cleanup_storage();

            let pool_name = "open_pool_ledger_works_for_invalid_nodes_file";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool_with_invalid_nodes(pool_name, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            let res = PoolUtils::open_pool_ledger(pool_name, Some(pool_config.as_str()));
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerTerminated);//TODO Replace on InvalidState Error

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_wrong_alias() {
            TestUtils::cleanup_storage();

            let pool_name = "open_pool_ledger_works_for_wrong_alias";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool_with_wrong_alias(pool_name, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            let res = PoolUtils::open_pool_ledger(pool_name, None);
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerTerminated);//TODO Replace on InvalidState Error

            TestUtils::cleanup_storage();
        }

        #[test]
        #[ignore]
        #[cfg(feature = "local_nodes_pool")] //TODO Not implemented yet
        fn open_pool_ledger_works_for_invalid_config() {
            TestUtils::cleanup_storage();
            let name = "pool_open";
            let config = r#"{"refreshOnOpen": "true"}"#;

            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(name, Some(pool_config.as_str())).unwrap();

            let res = PoolUtils::open_pool_ledger(name, Some(config));
            assert_eq!(res.unwrap_err(), ErrorCode::CommonInvalidStructure);

            TestUtils::cleanup_storage();
        }
    }
}<commit_msg>Added medium cases tests for Pool Api<commit_after>extern crate indy;

// Workaround to share some utils code based on indy sdk types between tests and indy sdk
use indy::api as api;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;

#[macro_use]
mod utils;

#[cfg(feature = "local_nodes_pool")]
use indy::api::ErrorCode;

use utils::environment::EnvironmentUtils;
use utils::pool::PoolUtils;
use utils::test::TestUtils;

mod high_cases {
    use super::*;

    mod create {
        use super::*;

        #[test]
        fn create_pool_ledger_config_works() {
            TestUtils::cleanup_storage();

            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool("pool_create", None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config("pool_create", Some(pool_config.as_str())).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn create_pool_ledger_config_works_for_empty_name() {
            TestUtils::cleanup_storage();

            let pool_name = "";
            let res = PoolUtils::create_pool_ledger_config(pool_name, None);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonInvalidParam2);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn create_pool_ledger_config_works_for_config_json() {
            TestUtils::cleanup_storage();

            let pool_name = "create_pool_ledger_config_works_for_config_json";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());

            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn create_pool_ledger_config_works_for_specific_config() {
            TestUtils::cleanup_storage();

            let pool_name = "create_pool_ledger_config_works_for_specific_config";
            let txn_file_path = EnvironmentUtils::tmp_file_path("specific_filename.txn");
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, Some(txn_file_path.as_path()));
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());

            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod open {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works() {
            TestUtils::cleanup_storage();

            let pool_name = "pool_open";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            PoolUtils::open_pool_ledger(pool_name, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")] //TODO Not implemented yet
        fn open_pool_ledger_works_for_config() {
            TestUtils::cleanup_storage();

            let pool_name = "open_pool_ledger_works_for_config";
            let config = r#"{"refreshOnOpen": true}"#;

            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            PoolUtils::open_pool_ledger(pool_name, Some(config)).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_twice() {
            TestUtils::cleanup_storage();

            let pool_name = "pool_open_twice";
            PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();

            let res = PoolUtils::open_pool_ledger(pool_name, None);
            assert_match!(Err(ErrorCode::PoolLedgerInvalidPoolHandle), res);

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_two_nodes() {
            TestUtils::cleanup_storage();

            let pool_name = "open_pool_ledger_works_for_two_nodes";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, Some(2), None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            PoolUtils::open_pool_ledger(pool_name, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_three_nodes() {
            TestUtils::cleanup_storage();

            let pool_name = "open_pool_ledger_works_for_three_nodes";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, Some(3), None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            PoolUtils::open_pool_ledger(pool_name, None).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod refresh {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_refresh_pool_ledger_works() {
            TestUtils::cleanup_storage();

            let pool_handle = PoolUtils::create_and_open_pool_ledger("indy_refresh_pool_ledger_works").unwrap();

            PoolUtils::refresh(pool_handle).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod close {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_close_pool_ledger_works() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_close_pool_ledger_works";
            let pool_handle = PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();

            PoolUtils::close(pool_handle).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_close_pool_ledger_works_for_twice() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_close_pool_ledger_works_twice";
            let pool_handle = PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();

            PoolUtils::close(pool_handle).unwrap();
            assert_eq!(PoolUtils::close(pool_handle).unwrap_err(), ErrorCode::PoolLedgerInvalidPoolHandle);

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_close_pool_ledger_works_for_reopen_after_close() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_close_pool_ledger_works";
            let pool_handle = PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();

            PoolUtils::close(pool_handle).unwrap();
            PoolUtils::open_pool_ledger(pool_name, None).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod delete {
        use super::*;

        #[test]
        fn indy_delete_pool_ledger_config_works() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_remove_pool_ledger_config_works";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            PoolUtils::delete(pool_name).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_delete_pool_ledger_config_works_for_opened() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_remove_pool_ledger_config_works_for_opened";
            PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();

            assert_eq!(PoolUtils::delete(pool_name).unwrap_err(), ErrorCode::CommonInvalidState);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn indy_delete_pool_ledger_config_works_for_closed() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_delete_pool_ledger_config_works_for_closed";
            let pool_handle = PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();
            PoolUtils::close(pool_handle).unwrap();
            PoolUtils::delete(pool_name).unwrap();

            TestUtils::cleanup_storage();
        }
    }
}

mod medium_cases {
    use super::*;

    mod create {
        use super::*;

        #[test]
        fn create_pool_ledger_config_works_for_invalid_config_json() {
            TestUtils::cleanup_storage();

            let pool_name = "create_pool_ledger_config_works_for_invalid_config";
            let config = r#"{}"#.to_string();

            let res = PoolUtils::create_pool_ledger_config(pool_name, Some(config.as_str()));
            assert_eq!(res.unwrap_err(), ErrorCode::CommonInvalidStructure);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn create_pool_ledger_config_works_for_invalid_genesis_txn_path() {
            TestUtils::cleanup_storage();

            let pool_name = "create_pool_ledger_config_works_for_invalid_genesis_txn_path";
            let config = r#"{"genesis_txn": "path"}"#.to_string();

            let res = PoolUtils::create_pool_ledger_config(pool_name, Some(config.as_str()));
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn create_pool_ledger_config_works_for_twice() {
            TestUtils::cleanup_storage();

            let pool_name = "pool_create";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(pool_name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());

            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();
            let res = PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str()));

            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerConfigAlreadyExistsError);

            TestUtils::cleanup_storage();
        }
    }

    mod open {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_invalid_name() {
            TestUtils::cleanup_storage();
            let pool_name = "open_pool_ledger_works_for_invalid_name";

            let res = PoolUtils::open_pool_ledger(pool_name, None);
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerTerminated);//TODO change it on IOError

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_invalid_nodes_file() {
            TestUtils::cleanup_storage();

            let pool_name = "open_pool_ledger_works_for_invalid_nodes_file";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool_with_invalid_nodes(pool_name, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            let res = PoolUtils::open_pool_ledger(pool_name, Some(pool_config.as_str()));
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerTerminated);//TODO Replace on InvalidState Error

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_wrong_alias() {
            TestUtils::cleanup_storage();

            let pool_name = "open_pool_ledger_works_for_wrong_alias";
            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool_with_wrong_alias(pool_name, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(pool_name, Some(pool_config.as_str())).unwrap();

            let res = PoolUtils::open_pool_ledger(pool_name, None);
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerTerminated);//TODO Replace on InvalidState Error

            TestUtils::cleanup_storage();
        }

        #[test]
        #[ignore]
        #[cfg(feature = "local_nodes_pool")] //TODO Not implemented yet
        fn open_pool_ledger_works_for_invalid_config() {
            TestUtils::cleanup_storage();
            let name = "pool_open";
            let config = r#"{"refreshOnOpen": "true"}"#;

            let txn_file_path = PoolUtils::create_genesis_txn_file_for_test_pool(name, None, None);
            let pool_config = PoolUtils::pool_config_json(txn_file_path.as_path());
            PoolUtils::create_pool_ledger_config(name, Some(pool_config.as_str())).unwrap();

            let res = PoolUtils::open_pool_ledger(name, Some(config));
            assert_eq!(res.unwrap_err(), ErrorCode::CommonInvalidStructure);

            TestUtils::cleanup_storage();
        }
    }

    mod close {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_close_pool_ledger_works_for_invalid_handle() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_close_pool_ledger_works_for_invalid_handle";
            let pool_handle = PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();

            let pool_handle = pool_handle + 1;
            let res = PoolUtils::close(pool_handle);
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerInvalidPoolHandle);

            TestUtils::cleanup_storage();
        }
    }

    mod delete {
        use super::*;

        #[test]
        fn indy_delete_pool_ledger_config_works_for_not_created() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_delete_pool_ledger_config_works_for_invalid_name";
            let res = PoolUtils::delete(pool_name);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn indy_delete_pool_ledger_config_works_for_twice() {
            TestUtils::cleanup_storage();

            let pool_name = "indy_delete_pool_ledger_config_works_for_twice";
            let pool_handle = PoolUtils::create_and_open_pool_ledger(pool_name).unwrap();
            PoolUtils::close(pool_handle).unwrap();
            PoolUtils::delete(pool_name).unwrap();
            let res = PoolUtils::delete(pool_name);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }
    }

    mod refresh {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn indy_refresh_pool_ledger_works_for_invalid_handle() {
            TestUtils::cleanup_storage();

            let pool_handle = PoolUtils::create_and_open_pool_ledger("indy_refresh_pool_ledger_works_for_invalid_handle").unwrap();

            let pool_handle = pool_handle + 1;
            let res = PoolUtils::refresh(pool_handle);
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerInvalidPoolHandle);

            TestUtils::cleanup_storage();
        }
    }
}<|endoftext|>


<commit_before>extern crate curl;

use std::str;
use std::time::Duration;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
    })
}

use curl::easy::{Easy, Form};

use server::Server;
mod server;

fn handle() -> Easy {
    let mut e = Easy::new();
    t!(e.timeout(Duration::new(20, 0)));
    return e
}

#[test]
fn custom() {
    let s = Server::new();
    s.receive("\
POST / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
Content-Length: 142\r\n\
Content-Type: multipart/form-data; boundary=--[..]\r\n\
\r\n\
--[..]\r\n\
Content-Disposition: form-data; name=\"foo\"\r\n\
\r\n\
1234\r\n\
--[..]\r\n");
    s.send("HTTP/1.1 200 OK\r\n\r\n");

    let mut handle = handle();
    let mut form = Form::new();
    t!(form.part("foo").contents(b"1234").add());
    t!(handle.url(&s.url("/")));
    t!(handle.httppost(form));
    t!(handle.perform());
}

#[test]
fn buffer() {
    let s = Server::new();
    s.receive("\
POST / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
Content-Length: 181\r\n\
Content-Type: multipart/form-data; boundary=--[..]\r\n\
\r\n\
--[..]\r\n\
Content-Disposition: form-data; name=\"foo\"; filename=\"bar\"\r\n\
Content-Type: foo/bar\r\n\
\r\n\
1234\r\n\
--[..]\r\n");
    s.send("HTTP/1.1 200 OK\r\n\r\n");

    let mut handle = handle();
    let mut form = Form::new();
    t!(form.part("foo")
           .buffer("bar", b"1234".to_vec())
           .content_type("foo/bar")
           .add());
    t!(handle.url(&s.url("/")));
    t!(handle.httppost(form));
    t!(handle.perform());
}

#[test]
fn file() {
    let s = Server::new();
    let formdata = include_str!("formdata");
    s.receive(format!("\
POST / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
Content-Length: {}\r\n\
Content-Type: multipart/form-data; boundary=--[..]\r\n\
\r\n\
--[..]\r\n\
Content-Disposition: form-data; name=\"foo\"; filename=\"formdata\"\r\n\
Content-Type: application/octet-stream\r\n\
\r\n\
{}\
\r\n\
--[..]\r\n", 199 + formdata.len(), formdata).as_str());
    s.send("HTTP/1.1 200 OK\r\n\r\n");

    let mut handle = handle();
    let mut form = Form::new();
    t!(form.part("foo")
           .file("tests/formdata")
           .add());
    t!(handle.url(&s.url("/")));
    t!(handle.httppost(form));
    t!(handle.perform());
}
<commit_msg>Manually disable `Expect` header in POST tests<commit_after>extern crate curl;

use std::time::Duration;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
    })
}

use curl::easy::{Easy, List, Form};

use server::Server;
mod server;

fn handle() -> Easy {
    let mut e = Easy::new();
    t!(e.timeout(Duration::new(20, 0)));
    let mut list = List::new();
    t!(list.append("Expect:"));
    t!(e.http_headers(list));
    return e
}

#[test]
fn custom() {
    let s = Server::new();
    s.receive("\
POST / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
Content-Length: 142\r\n\
Content-Type: multipart/form-data; boundary=--[..]\r\n\
\r\n\
--[..]\r\n\
Content-Disposition: form-data; name=\"foo\"\r\n\
\r\n\
1234\r\n\
--[..]\r\n");
    s.send("HTTP/1.1 200 OK\r\n\r\n");

    let mut handle = handle();
    let mut form = Form::new();
    t!(form.part("foo").contents(b"1234").add());
    t!(handle.url(&s.url("/")));
    t!(handle.httppost(form));
    t!(handle.perform());
}

#[test]
fn buffer() {
    let s = Server::new();
    s.receive("\
POST / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
Content-Length: 181\r\n\
Content-Type: multipart/form-data; boundary=--[..]\r\n\
\r\n\
--[..]\r\n\
Content-Disposition: form-data; name=\"foo\"; filename=\"bar\"\r\n\
Content-Type: foo/bar\r\n\
\r\n\
1234\r\n\
--[..]\r\n");
    s.send("HTTP/1.1 200 OK\r\n\r\n");

    let mut handle = handle();
    let mut form = Form::new();
    t!(form.part("foo")
           .buffer("bar", b"1234".to_vec())
           .content_type("foo/bar")
           .add());
    t!(handle.url(&s.url("/")));
    t!(handle.httppost(form));
    t!(handle.perform());
}

#[test]
fn file() {
    let s = Server::new();
    let formdata = include_str!("formdata");
    s.receive(format!("\
POST / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
Content-Length: {}\r\n\
Content-Type: multipart/form-data; boundary=--[..]\r\n\
\r\n\
--[..]\r\n\
Content-Disposition: form-data; name=\"foo\"; filename=\"formdata\"\r\n\
Content-Type: application/octet-stream\r\n\
\r\n\
{}\
\r\n\
--[..]\r\n", 199 + formdata.len(), formdata).as_str());
    s.send("HTTP/1.1 200 OK\r\n\r\n");

    let mut handle = handle();
    let mut form = Form::new();
    t!(form.part("foo")
           .file("tests/formdata")
           .add());
    t!(handle.url(&s.url("/")));
    t!(handle.httppost(form));
    t!(handle.perform());
}
<|endoftext|>


<commit_before>use beacon_chain::{BeaconChain, BeaconChainTypes};
use bls::PublicKey;
use futures::Future;
use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink};
use protos::services::{ActiveValidator, GetDutiesRequest, GetDutiesResponse, ValidatorDuty};
use protos::services_grpc::ValidatorService;
use slog::{trace, warn};
use ssz::Decode;
use std::sync::Arc;
use types::{Epoch, EthSpec, RelativeEpoch};

#[derive(Clone)]
pub struct ValidatorServiceInstance<T: BeaconChainTypes> {
    pub chain: Arc<BeaconChain<T>>,
    pub log: slog::Logger,
}

impl<T: BeaconChainTypes> ValidatorService for ValidatorServiceInstance<T> {
    /// For a list of validator public keys, this function returns the slot at which each
    /// validator must propose a block, attest to a shard, their shard committee and the shard they
    /// need to attest to.
    fn get_validator_duties(
        &mut self,
        ctx: RpcContext,
        req: GetDutiesRequest,
        sink: UnarySink<GetDutiesResponse>,
    ) {
        let validators = req.get_validators();
        trace!(self.log, "RPC request"; "endpoint" => "GetValidatorDuties", "epoch" => req.get_epoch());

        let slot = if let Ok(slot) = self.chain.slot() {
            slot
        } else {
            let log_clone = self.log.clone();
            let f = sink
                .fail(RpcStatus::new(
                    RpcStatusCode::FailedPrecondition,
                    Some("No slot for chain".to_string()),
                ))
                .map_err(move |e| warn!(log_clone, "failed to reply {:?}: {:?}", req, e));
            return ctx.spawn(f);
        };
        let mut state = if let Ok(state) = self.chain.state_at_slot(slot) {
            state.as_ref().clone()
        } else {
            let log_clone = self.log.clone();
            let f = sink
                .fail(RpcStatus::new(
                    RpcStatusCode::FailedPrecondition,
                    Some("No state".to_string()),
                ))
                .map_err(move |e| warn!(log_clone, "failed to reply {:?}: {:?}", req, e));
            return ctx.spawn(f);
        };

        let _ = state.build_all_caches(&self.chain.spec);

        let epoch = Epoch::from(req.get_epoch());
        let mut resp = GetDutiesResponse::new();
        let resp_validators = resp.mut_active_validators();

        let validator_proposers: Result<Vec<usize>, _> = epoch
            .slot_iter(T::EthSpec::slots_per_epoch())
            .map(|slot| self.chain.block_proposer(slot))
            .collect();
        let validator_proposers = match validator_proposers {
            Ok(v) => v,
            Err(e) => {
                // could not get the validator proposer index
                let log_clone = self.log.clone();
                let f = sink
                    .fail(RpcStatus::new(
                        RpcStatusCode::FailedPrecondition,
                        Some(format!("Could not find beacon proposers: {:?}", e)),
                    ))
                    .map_err(move |e| warn!(log_clone, "failed to reply {:?} : {:?}", req, e));
                return ctx.spawn(f);
            }
        };

        // get the duties for each validator
        for validator_pk in validators.get_public_keys() {
            let mut active_validator = ActiveValidator::new();

            let public_key = match PublicKey::from_ssz_bytes(validator_pk) {
                Ok(v) => v,
                Err(_) => {
                    let log_clone = self.log.clone();
                    let f = sink
                        .fail(RpcStatus::new(
                            RpcStatusCode::InvalidArgument,
                            Some("Invalid public_key".to_string()),
                        ))
                        .map_err(move |_| warn!(log_clone, "failed to reply {:?}", req));
                    return ctx.spawn(f);
                }
            };

            // get the validator index
            let val_index = match state.get_validator_index(&public_key) {
                Ok(Some(index)) => index,
                Ok(None) => {
                    // index not present in registry, set the duties for this key to None
                    warn!(
                        self.log,
                        "RPC requested a public key that is not in the registry: {:?}", public_key
                    );
                    active_validator.set_none(false);
                    resp_validators.push(active_validator);
                    continue;
                }
                // the cache is not built, throw an error
                Err(e) => {
                    let log_clone = self.log.clone();
                    let f = sink
                        .fail(RpcStatus::new(
                            RpcStatusCode::FailedPrecondition,
                            Some(format!("Beacon state error {:?}", e)),
                        ))
                        .map_err(move |e| warn!(log_clone, "Failed to reply {:?}: {:?}", req, e));
                    return ctx.spawn(f);
                }
            };

            // get attestation duties and check if validator is active
            let attestation_duties = match state
                .get_attestation_duties(val_index, RelativeEpoch::Current)
            {
                Ok(Some(v)) => v,
                Ok(_) => {
                    // validator is inactive, go to the next validator
                    warn!(
                        self.log,
                        "RPC requested an inactive validator key: {:?}", public_key
                    );
                    active_validator.set_none(false);
                    resp_validators.push(active_validator);
                    continue;
                }
                // the cache is not built, throw an error
                Err(e) => {
                    let log_clone = self.log.clone();
                    let f = sink
                        .fail(RpcStatus::new(
                            RpcStatusCode::FailedPrecondition,
                            Some(format!("Beacon state error {:?}", e)),
                        ))
                        .map_err(move |e| warn!(log_clone, "Failed to reply {:?}: {:?}", req, e));
                    return ctx.spawn(f);
                }
            };

            // we have an active validator, set its duties
            let mut duty = ValidatorDuty::new();

            // check if the validator needs to propose a block
            if let Some(slot) = validator_proposers.iter().position(|&v| val_index == v) {
                duty.set_block_production_slot(
                    epoch.start_slot(T::EthSpec::slots_per_epoch()).as_u64() + slot as u64,
                );
            } else {
                // no blocks to propose this epoch
                duty.set_none(false)
            }

            duty.set_committee_index(attestation_duties.committee_index as u64);
            duty.set_attestation_slot(attestation_duties.slot.as_u64());
            duty.set_attestation_shard(attestation_duties.shard);
            duty.set_committee_len(attestation_duties.committee_len as u64);

            active_validator.set_duty(duty);
            resp_validators.push(active_validator);
        }

        let f = sink
            .success(resp)
            .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e));
        ctx.spawn(f)
    }
}
<commit_msg>Modify RPC duties endpoint<commit_after>use beacon_chain::{BeaconChain, BeaconChainTypes};
use bls::PublicKey;
use futures::Future;
use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink};
use protos::services::{ActiveValidator, GetDutiesRequest, GetDutiesResponse, ValidatorDuty};
use protos::services_grpc::ValidatorService;
use slog::{trace, warn};
use ssz::Decode;
use std::sync::Arc;
use types::{Epoch, EthSpec, RelativeEpoch};

#[derive(Clone)]
pub struct ValidatorServiceInstance<T: BeaconChainTypes> {
    pub chain: Arc<BeaconChain<T>>,
    pub log: slog::Logger,
}

impl<T: BeaconChainTypes> ValidatorService for ValidatorServiceInstance<T> {
    /// For a list of validator public keys, this function returns the slot at which each
    /// validator must propose a block, attest to a shard, their shard committee and the shard they
    /// need to attest to.
    fn get_validator_duties(
        &mut self,
        ctx: RpcContext,
        req: GetDutiesRequest,
        sink: UnarySink<GetDutiesResponse>,
    ) {
        let validators = req.get_validators();
        trace!(self.log, "RPC request"; "endpoint" => "GetValidatorDuties", "epoch" => req.get_epoch());

        let epoch = Epoch::from(req.get_epoch());
        let slot = epoch.start_slot(T::EthSpec::slots_per_epoch());

        let mut state = if let Ok(state) = self.chain.state_at_slot(slot) {
            state.as_ref().clone()
        } else {
            let log_clone = self.log.clone();
            let f = sink
                .fail(RpcStatus::new(
                    RpcStatusCode::FailedPrecondition,
                    Some("No state".to_string()),
                ))
                .map_err(move |e| warn!(log_clone, "failed to reply {:?}: {:?}", req, e));
            return ctx.spawn(f);
        };

        let _ = state.build_all_caches(&self.chain.spec);

        let mut resp = GetDutiesResponse::new();
        let resp_validators = resp.mut_active_validators();

        let validator_proposers: Result<Vec<usize>, _> = epoch
            .slot_iter(T::EthSpec::slots_per_epoch())
            .map(|slot| self.chain.block_proposer(slot))
            .collect();
        let validator_proposers = match validator_proposers {
            Ok(v) => v,
            Err(e) => {
                // could not get the validator proposer index
                let log_clone = self.log.clone();
                let f = sink
                    .fail(RpcStatus::new(
                        RpcStatusCode::FailedPrecondition,
                        Some(format!("Could not find beacon proposers: {:?}", e)),
                    ))
                    .map_err(move |e| warn!(log_clone, "failed to reply {:?} : {:?}", req, e));
                return ctx.spawn(f);
            }
        };

        // get the duties for each validator
        for validator_pk in validators.get_public_keys() {
            let mut active_validator = ActiveValidator::new();

            let public_key = match PublicKey::from_ssz_bytes(validator_pk) {
                Ok(v) => v,
                Err(_) => {
                    let log_clone = self.log.clone();
                    let f = sink
                        .fail(RpcStatus::new(
                            RpcStatusCode::InvalidArgument,
                            Some("Invalid public_key".to_string()),
                        ))
                        .map_err(move |_| warn!(log_clone, "failed to reply {:?}", req));
                    return ctx.spawn(f);
                }
            };

            // get the validator index
            let val_index = match state.get_validator_index(&public_key) {
                Ok(Some(index)) => index,
                Ok(None) => {
                    // index not present in registry, set the duties for this key to None
                    warn!(
                        self.log,
                        "RPC requested a public key that is not in the registry: {:?}", public_key
                    );
                    active_validator.set_none(false);
                    resp_validators.push(active_validator);
                    continue;
                }
                // the cache is not built, throw an error
                Err(e) => {
                    let log_clone = self.log.clone();
                    let f = sink
                        .fail(RpcStatus::new(
                            RpcStatusCode::FailedPrecondition,
                            Some(format!("Beacon state error {:?}", e)),
                        ))
                        .map_err(move |e| warn!(log_clone, "Failed to reply {:?}: {:?}", req, e));
                    return ctx.spawn(f);
                }
            };

            // get attestation duties and check if validator is active
            let attestation_duties = match state
                .get_attestation_duties(val_index, RelativeEpoch::Current)
            {
                Ok(Some(v)) => v,
                Ok(_) => {
                    // validator is inactive, go to the next validator
                    warn!(
                        self.log,
                        "RPC requested an inactive validator key: {:?}", public_key
                    );
                    active_validator.set_none(false);
                    resp_validators.push(active_validator);
                    continue;
                }
                // the cache is not built, throw an error
                Err(e) => {
                    let log_clone = self.log.clone();
                    let f = sink
                        .fail(RpcStatus::new(
                            RpcStatusCode::FailedPrecondition,
                            Some(format!("Beacon state error {:?}", e)),
                        ))
                        .map_err(move |e| warn!(log_clone, "Failed to reply {:?}: {:?}", req, e));
                    return ctx.spawn(f);
                }
            };

            // we have an active validator, set its duties
            let mut duty = ValidatorDuty::new();

            // check if the validator needs to propose a block
            if let Some(slot) = validator_proposers.iter().position(|&v| val_index == v) {
                duty.set_block_production_slot(
                    epoch.start_slot(T::EthSpec::slots_per_epoch()).as_u64() + slot as u64,
                );
            } else {
                // no blocks to propose this epoch
                duty.set_none(false)
            }

            duty.set_committee_index(attestation_duties.committee_index as u64);
            duty.set_attestation_slot(attestation_duties.slot.as_u64());
            duty.set_attestation_shard(attestation_duties.shard);
            duty.set_committee_len(attestation_duties.committee_len as u64);

            active_validator.set_duty(duty);
            resp_validators.push(active_validator);
        }

        let f = sink
            .success(resp)
            .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e));
        ctx.spawn(f)
    }
}
<|endoftext|>


<commit_before>#[cfg(target_arch = "aarch64")]
use aarch64::regs::*;
use std::env;
use std::f64::consts::{E, PI};
use std::fs::File;
use std::hint::black_box;
use std::io::Read;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::thread;
use std::time::Instant;
use std::vec;
#[cfg(target_os = "linux")]
use syscalls::SYS_getpid;

const NR_RUNS: usize = 1000;

#[cfg(target_arch = "x86_64")]
#[inline]
fn get_timestamp() -> u64 {
	unsafe {
		let mut _aux = 0;
		let value = core::arch::x86_64::__rdtscp(&mut _aux);
		core::arch::x86_64::_mm_lfence();
		value
	}
}

#[cfg(target_arch = "aarch64")]
#[inline]
fn get_timestamp() -> u64 {
	CNTPCT_EL0.get()
}

extern "C" {
	#[cfg(target_os = "hermit")]
	fn sys_getpid() -> u32;
}

pub fn bench_syscall() -> Result<(), ()> {
	let n = 1000000;

	let ticks = unsafe {
		// cache warmup
		#[cfg(target_os = "hermit")]
		let _ = sys_getpid();
		#[cfg(target_os = "linux")]
		let _ = syscall!(SYS_getpid);
		let _ = get_timestamp();

		let start = get_timestamp();
		for _ in 0..n {
			#[cfg(target_os = "hermit")]
			let _ = sys_getpid();
			#[cfg(target_os = "linux")]
			let _ = syscall!(SYS_getpid);
		}
		get_timestamp() - start
	};

	println!("Time {} for a system call (in ticks)", ticks / n);

	Ok(())
}

pub fn bench_sched_one_thread() -> Result<(), ()> {
	let n = 1000000;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp();

	let start = get_timestamp();
	for _ in 0..n {
		thread::yield_now();
	}
	let ticks = get_timestamp() - start;

	println!("Scheduling time {} ticks (1 thread)", ticks / n);

	Ok(())
}

pub fn bench_sched_two_threads() -> Result<(), ()> {
	let n = 1000000;
	let nthreads = 2;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp();

	let start = get_timestamp();
	let threads: Vec<_> = (0..nthreads - 1)
		.map(|_| {
			thread::spawn(move || {
				for _ in 0..n {
					thread::yield_now();
				}
			})
		})
		.collect();

	for _ in 0..n {
		thread::yield_now();
	}

	let ticks = get_timestamp() - start;

	for t in threads {
		t.join().unwrap();
	}

	println!(
		"Scheduling time {} ticks (2 threads)",
		ticks / (nthreads * n)
	);

	Ok(())
}

fn memcpy_builtin(n: usize) {
	let v1 = vec![1u8; n];
	let mut v2 = vec![0u8; n];

	let now = Instant::now();
	for _i in 0..NR_RUNS {
		let src: &[u8] = black_box(&v1);
		let dst: &mut [u8] = black_box(&mut v2);
		dst.copy_from_slice(src);
	}

	println!(
		"memcpy_builtin:  {} block size, {} MByte/s",
		n,
		((NR_RUNS * n) >> 20) as f64 / now.elapsed().as_secs_f64()
	);
}

fn memset_builtin(n: usize) {
	let mut v1 = vec![0u8; n];
	let now = Instant::now();
	for _i in 0..NR_RUNS {
		let dst: &mut [u8] = black_box(&mut v1);
		let val: u8 = black_box(27);
		for b in dst {
			*b = val;
		}
	}

	println!(
		"memset_builtin:  {} block, {} MByte/s",
		n,
		((NR_RUNS * n) >> 20) as f64 / now.elapsed().as_secs_f64()
	);
}

pub fn bench_mem() -> Result<(), ()> {
	memcpy_builtin(4096);
	memcpy_builtin(1048576);
	memset_builtin(4096);
	memset_builtin(1048576);

	Ok(())
}
<commit_msg>fix calculation of the bandwidth<commit_after>#[cfg(target_arch = "aarch64")]
use aarch64::regs::*;
use std::env;
use std::f64::consts::{E, PI};
use std::fs::File;
use std::hint::black_box;
use std::io::Read;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::thread;
use std::time::Instant;
use std::vec;
#[cfg(target_os = "linux")]
use syscalls::SYS_getpid;

const NR_RUNS: usize = 1000;

#[cfg(target_arch = "x86_64")]
#[inline]
fn get_timestamp() -> u64 {
	unsafe {
		let mut _aux = 0;
		let value = core::arch::x86_64::__rdtscp(&mut _aux);
		core::arch::x86_64::_mm_lfence();
		value
	}
}

#[cfg(target_arch = "aarch64")]
#[inline]
fn get_timestamp() -> u64 {
	CNTPCT_EL0.get()
}

extern "C" {
	#[cfg(target_os = "hermit")]
	fn sys_getpid() -> u32;
}

pub fn bench_syscall() -> Result<(), ()> {
	let n = 1000000;

	let ticks = unsafe {
		// cache warmup
		#[cfg(target_os = "hermit")]
		let _ = sys_getpid();
		#[cfg(target_os = "linux")]
		let _ = syscall!(SYS_getpid);
		let _ = get_timestamp();

		let start = get_timestamp();
		for _ in 0..n {
			#[cfg(target_os = "hermit")]
			let _ = sys_getpid();
			#[cfg(target_os = "linux")]
			let _ = syscall!(SYS_getpid);
		}
		get_timestamp() - start
	};

	println!("Time {} for a system call (in ticks)", ticks / n);

	Ok(())
}

pub fn bench_sched_one_thread() -> Result<(), ()> {
	let n = 1000000;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp();

	let start = get_timestamp();
	for _ in 0..n {
		thread::yield_now();
	}
	let ticks = get_timestamp() - start;

	println!("Scheduling time {} ticks (1 thread)", ticks / n);

	Ok(())
}

pub fn bench_sched_two_threads() -> Result<(), ()> {
	let n = 1000000;
	let nthreads = 2;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp();

	let start = get_timestamp();
	let threads: Vec<_> = (0..nthreads - 1)
		.map(|_| {
			thread::spawn(move || {
				for _ in 0..n {
					thread::yield_now();
				}
			})
		})
		.collect();

	for _ in 0..n {
		thread::yield_now();
	}

	let ticks = get_timestamp() - start;

	for t in threads {
		t.join().unwrap();
	}

	println!(
		"Scheduling time {} ticks (2 threads)",
		ticks / (nthreads * n)
	);

	Ok(())
}

fn memcpy_builtin(n: usize) {
	let v1 = vec![1u8; n];
	let mut v2 = vec![0u8; n];

	let now = Instant::now();
	for _i in 0..NR_RUNS {
		let src: &[u8] = black_box(&v1);
		let dst: &mut [u8] = black_box(&mut v2);
		dst.copy_from_slice(src);
	}

	println!(
		"memcpy_builtin:  {} block size, {} MByte/s",
		n,
		(NR_RUNS * n) as f64 / (1024.0 * 1024.0 * now.elapsed().as_secs_f64())
	);
}

fn memset_builtin(n: usize) {
	let mut v1 = vec![0u8; n];
	let now = Instant::now();
	for _i in 0..NR_RUNS {
		let dst: &mut [u8] = black_box(&mut v1);
		let val: u8 = black_box(27);
		for b in dst {
			*b = val;
		}
	}

	println!(
		"memset_builtin:  {} block, {} MByte/s",
		n,
		((NR_RUNS * n) >> 20) as f64 / now.elapsed().as_secs_f64()
	);
}

pub fn bench_mem() -> Result<(), ()> {
	memcpy_builtin(4096);
	memcpy_builtin(1048576);
	memset_builtin(4096);
	memset_builtin(1048576);

	Ok(())
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;

fn read_line( text: &str ) -> String {
    let stdin = io::stdin();
    let mut buffer = String::new();
    print!( "{}", text );
    io::stdout().flush().ok().expect( "Не удалось очистить stdout!");
    stdin.lock().read_line( &mut buffer ).ok().expect( "Невозможно прочитать строку!" );
    buffer.trim_right().to_string()
}

fn read_file( filename: String ) -> Vec<u8> {
    let mut code: Vec<u8> = Vec::new();
    let path = Path::new( &filename );
    let mut file = match File::open( path ) {
        Ok( file ) => file,
        Err( error ) => panic!( "[ошибка]: {}", error )
    };
    let result = file.read_to_end( &mut code ).unwrap();
    code
}

fn main() {
    let filename = read_line( "Исполняемый файл: " );
    let code: Vec<u8> = read_file( filename );
    let mem_size: usize = 64;
    let mut code_index: usize = 0;
    let mut cell_index: usize = 0;
    let mut func_index: Vec<usize> = Vec::new();
    let mut memory: Vec<i64> = ( 0 .. mem_size ).map( |_| 0 ).collect();
    while code_index < code.len() {
        match code[code_index] as char {
            '+' => memory[cell_index] += 1,
            '-' => memory[cell_index] -= 1,
            '>' => cell_index += if cell_index < mem_size { 1 } else { 0 },
            '<' => cell_index -= if cell_index > 0 { 1 } else { 0 },
            '.' => print!( "{}", ( memory[cell_index] as u8 ) as char ),
            ',' => {
                let stdin = io::stdin();
                memory[cell_index] = stdin.lock().bytes().next().unwrap().unwrap() as i64;
            },
            '[' => func_index.push( code_index ),
            ']' => {
                if memory[cell_index] > 0 {
                    code_index = func_index.pop().unwrap();
                    continue;
                } else {
                    func_index.pop();
                }
            },
            _ => {}
        }
        code_index += 1;
    }
}<commit_msg>[upd] cell count, code formating<commit_after>use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;

fn read_line( text: &str ) -> String {
    let mut buffer = String::new();
    print!( "{}", text );
    io::stdout().flush()
        .ok()
        .expect( "Не удалось очистить stdout!");
    io::stdin().read_line( &mut buffer )
        .ok()
        .expect( "Невозможно прочитать строку!" );
    buffer.trim_right().to_string()
}

fn read_file( filename: String ) -> Vec< u8 > {
    let mut code: Vec< u8 > = Vec::new();
    let path = Path::new( &filename );
    let mut file = match File::open( path ) {
        Ok( file )   => file,
        Err( error ) => panic!( "[ошибка]: {}", error )
    };
    file.read_to_end( &mut code )
        .ok()
        .expect( "Невозможно прочитать файл!" );
    code
}

fn main() {
    let filename = read_line( "Исполняемый файл: " );
    let code: Vec< u8 > = read_file( filename );
    let mem_size: usize = 256;
    let mut code_index: usize = 0;
    let mut cell_index: usize = 0;
    let mut func_index: Vec< usize > = Vec::new();
    let mut memory: Vec< i64 > = ( 0 .. mem_size ).map( |_| 0 ).collect();
    while code_index < code.len() {
        match code[code_index] as char {
            '+' => memory[cell_index] += 1,
            '-' => memory[cell_index] -= 1,
            '>' => cell_index += if cell_index < mem_size { 1 } else { 0 },
            '<' => cell_index -= if cell_index > 0 { 1 } else { 0 },
            '.' => print!( "{}", ( memory[cell_index] as u8 ) as char ),
            ',' => memory[cell_index] = io::stdin().bytes().next().unwrap().unwrap() as i64,
            '[' => func_index.push( code_index ),
            ']' => {
                if memory[cell_index] > 0 {
                    code_index = func_index.pop().unwrap();
                    continue;
                } else {
                    func_index.pop();
                }
            },
            _ => {}
        }
        code_index += 1;
    }
}<|endoftext|>


<commit_before>#![cfg(target_os = "windows")]

use Api;
use ContextError;
use CreationError;
use PixelFormat;
use PixelFormatRequirements;
use GlAttributes;

use winit;

use api::egl::ffi::egl::Egl;
use api::egl;
use api::egl::Context as EglContext;

use std::ffi::CString;
use std::ops::{Deref, DerefMut};
use kernel32;

mod context;

/// Stupid wrapper because `*const libc::c_void` doesn't implement `Sync`.
struct EglWrapper(Egl);
unsafe impl Sync for EglWrapper {}

lazy_static! {
    // An EGL implementation available on the system.
    static ref EGL: Option<EglWrapper> = {
        // the ATI drivers provide an EGL implementation in their DLLs
        let ati_dll_name = if cfg!(target_pointer_width = "64") {
            b"atio6axx.dll\0"
        } else {
            b"atioglxx.dll\0"
        };

        for dll_name in &[b"libEGL.dll\0" as &[u8], ati_dll_name] {
            let dll = unsafe { kernel32::LoadLibraryA(dll_name.as_ptr() as *const _) };
            if dll.is_null() {
                continue;
            }

            let egl = Egl::load_with(|name| {
                let name = CString::new(name).unwrap();
                unsafe { kernel32::GetProcAddress(dll, name.as_ptr()) as *const _ }
            });

            return Some(EglWrapper(egl))
        }

        None
    };
}

// #[derive(Clone, Default)]
// pub struct PlatformSpecificWindowBuilderAttributes;
#[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes;

/// The Win32 implementation of the main `Context` object.
pub struct Context(context::Context);

impl Context {
    /// See the docs in the crate root file.
    #[inline]
    pub fn new(
        window_builder: winit::WindowBuilder,
        events_loop: &winit::EventsLoop,
        pf_reqs: &PixelFormatRequirements,
        opengl: &GlAttributes<&Self>,
    ) -> Result<(winit::Window, Self), CreationError> {
        context::Context::new(
            window_builder,
            events_loop,
            pf_reqs,
            &opengl.clone().map_sharing(|w| &w.0),
            EGL.as_ref().map(|w| &w.0),
        ).map(|(w, c)| (w, Context(c)))
    }
}

impl Deref for Context {
    type Target = context::Context;

    #[inline]
    fn deref(&self) -> &context::Context {
        &self.0
    }
}

impl DerefMut for Context {
    #[inline]
    fn deref_mut(&mut self) -> &mut context::Context {
        &mut self.0
    }
}

///
pub enum HeadlessContext {
    /// A regular window, but invisible.
    HiddenWindow(winit::EventsLoop, winit::Window, context::Context),
    /// An EGL pbuffer.
    EglPbuffer(EglContext),
}

impl HeadlessContext {
    pub fn new(
        dimensions: (u32, u32),
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Self>,
        _: &PlatformSpecificHeadlessBuilderAttributes,
    ) -> Result<Self, CreationError>
    {
        // if EGL is available, we try using EGL first
        // if EGL returns an error, we try the hidden window method
        if let &Some(ref egl) = &*EGL {
            let gl_attr = &gl_attr.clone().map_sharing(|_| unimplemented!()); // TODO
            let native_display = egl::NativeDisplay::Other(None);
            let context = EglContext::new(egl.0.clone(), pf_reqs, &gl_attr, native_display)
                .and_then(|prototype| prototype.finish_pbuffer(dimensions))
                .map(|ctxt| HeadlessContext::EglPbuffer(ctxt));
            if let Ok(context) = context {
                return Ok(context);
            }
        }
        let events_loop = winit::EventsLoop::new();
        let window_builder = winit::WindowBuilder::new().with_visibility(false);
        let gl_attr = &gl_attr.clone().map_sharing(|_| unimplemented!());
        let egl = EGL.as_ref().map(|w| &w.0);
        context::Context::new(window_builder, &events_loop, pf_reqs, gl_attr, egl)
            .map(|(window, context)| HeadlessContext::HiddenWindow(events_loop, window, context))
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.make_current(),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.make_current(),
        }
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.is_current(),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.is_current(),
        }
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.get_proc_address(addr),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.get_proc_address(addr),
        }
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.swap_buffers(),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.swap_buffers(),
        }
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.get_api(),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.get_api(),
        }
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.get_pixel_format(),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.get_pixel_format(),
        }
    }
}
<commit_msg>Remove commented code in windows backend<commit_after>#![cfg(target_os = "windows")]

use Api;
use ContextError;
use CreationError;
use PixelFormat;
use PixelFormatRequirements;
use GlAttributes;

use winit;

use api::egl::ffi::egl::Egl;
use api::egl;
use api::egl::Context as EglContext;

use std::ffi::CString;
use std::ops::{Deref, DerefMut};
use kernel32;

mod context;

/// Stupid wrapper because `*const libc::c_void` doesn't implement `Sync`.
struct EglWrapper(Egl);
unsafe impl Sync for EglWrapper {}

lazy_static! {
    // An EGL implementation available on the system.
    static ref EGL: Option<EglWrapper> = {
        // the ATI drivers provide an EGL implementation in their DLLs
        let ati_dll_name = if cfg!(target_pointer_width = "64") {
            b"atio6axx.dll\0"
        } else {
            b"atioglxx.dll\0"
        };

        for dll_name in &[b"libEGL.dll\0" as &[u8], ati_dll_name] {
            let dll = unsafe { kernel32::LoadLibraryA(dll_name.as_ptr() as *const _) };
            if dll.is_null() {
                continue;
            }

            let egl = Egl::load_with(|name| {
                let name = CString::new(name).unwrap();
                unsafe { kernel32::GetProcAddress(dll, name.as_ptr()) as *const _ }
            });

            return Some(EglWrapper(egl))
        }

        None
    };
}

#[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes;

/// The Win32 implementation of the main `Context` object.
pub struct Context(context::Context);

impl Context {
    /// See the docs in the crate root file.
    #[inline]
    pub fn new(
        window_builder: winit::WindowBuilder,
        events_loop: &winit::EventsLoop,
        pf_reqs: &PixelFormatRequirements,
        opengl: &GlAttributes<&Self>,
    ) -> Result<(winit::Window, Self), CreationError> {
        context::Context::new(
            window_builder,
            events_loop,
            pf_reqs,
            &opengl.clone().map_sharing(|w| &w.0),
            EGL.as_ref().map(|w| &w.0),
        ).map(|(w, c)| (w, Context(c)))
    }
}

impl Deref for Context {
    type Target = context::Context;

    #[inline]
    fn deref(&self) -> &context::Context {
        &self.0
    }
}

impl DerefMut for Context {
    #[inline]
    fn deref_mut(&mut self) -> &mut context::Context {
        &mut self.0
    }
}

///
pub enum HeadlessContext {
    /// A regular window, but invisible.
    HiddenWindow(winit::EventsLoop, winit::Window, context::Context),
    /// An EGL pbuffer.
    EglPbuffer(EglContext),
}

impl HeadlessContext {
    pub fn new(
        dimensions: (u32, u32),
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Self>,
        _: &PlatformSpecificHeadlessBuilderAttributes,
    ) -> Result<Self, CreationError>
    {
        // if EGL is available, we try using EGL first
        // if EGL returns an error, we try the hidden window method
        if let &Some(ref egl) = &*EGL {
            let gl_attr = &gl_attr.clone().map_sharing(|_| unimplemented!()); // TODO
            let native_display = egl::NativeDisplay::Other(None);
            let context = EglContext::new(egl.0.clone(), pf_reqs, &gl_attr, native_display)
                .and_then(|prototype| prototype.finish_pbuffer(dimensions))
                .map(|ctxt| HeadlessContext::EglPbuffer(ctxt));
            if let Ok(context) = context {
                return Ok(context);
            }
        }
        let events_loop = winit::EventsLoop::new();
        let window_builder = winit::WindowBuilder::new().with_visibility(false);
        let gl_attr = &gl_attr.clone().map_sharing(|_| unimplemented!());
        let egl = EGL.as_ref().map(|w| &w.0);
        context::Context::new(window_builder, &events_loop, pf_reqs, gl_attr, egl)
            .map(|(window, context)| HeadlessContext::HiddenWindow(events_loop, window, context))
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.make_current(),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.make_current(),
        }
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.is_current(),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.is_current(),
        }
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.get_proc_address(addr),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.get_proc_address(addr),
        }
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.swap_buffers(),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.swap_buffers(),
        }
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.get_api(),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.get_api(),
        }
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        match self {
            &HeadlessContext::HiddenWindow(_, _, ref ctxt) => ctxt.get_pixel_format(),
            &HeadlessContext::EglPbuffer(ref ctxt) => ctxt.get_pixel_format(),
        }
    }
}
<|endoftext|>


<commit_before>// TODO: This will panic on certain opcodes. The ideas I have for cpu_lang
// will probably fix it; we'll see. For now tho, I'm gonna leave it as-is;
// I can imagine fixing it trivially might lead to performance problems.
// I'll deal with it after the port is finished.

// TODO: This is a placeholder before I start generalizing traits
// from the old code.
use super::apu::Apu;

pub struct Smp<'a> {
    emulator: &'a mut Apu,

    reg_pc: u16,
    reg_a: u8,
    reg_x: u8,
    reg_y: u8,
    reg_sp: u8,

    psw_c: bool,
    psw_z: bool,
    psw_h: bool,
    psw_p: bool,
    psw_v: bool,
    psw_n: bool,
    // TODO: Look up some more behavior for I and B. Can't seem to find much
    // but some instructions DO set them.
    psw_i: bool,
    psw_b: bool,

    cycle_count: i32
}

impl<'a> Smp<'a> {
    pub fn new(emulator: &'a mut Apu) -> Smp<'a> {
        let mut ret = Smp {
            emulator: emulator,

            reg_pc: 0,
            reg_a: 0,
            reg_x: 0,
            reg_y: 0,
            reg_sp: 0,

            psw_c: false,
            psw_z: false,
            psw_h: false,
            psw_p: false,
            psw_v: false,
            psw_n: false,
            psw_i: false,
            psw_b: false,

            cycle_count: 0
        };
        ret.reset();
        ret
    }

    pub fn reset(&mut self) {
        self.reg_pc = 0xffc0;
        self.reg_a = 0;
        self.reg_x = 0;
        self.reg_y = 0;
        self.reg_sp = 0xef;
        self.set_psw(0x02);
    }

    pub fn set_reg_ya(&mut self, value: u16) {
        self.reg_a = (value & 0xff) as u8;
        self.reg_y = ((value >> 8) & 0xff) as u8;
    }

    pub fn get_reg_ya(&self) -> u16 {
        ((self.reg_y as u16) << 8) | (self.reg_a as u16)
    }

    pub fn set_psw(&mut self, value: u8) {
        self.psw_c = (value & 0x01) != 0;
        self.psw_z = (value & 0x02) != 0;
        self.psw_h = (value & 0x08) != 0;
        self.psw_p = (value & 0x20) != 0;
        self.psw_v = (value & 0x40) != 0;
        self.psw_n = (value & 0x80) != 0;
    }

    pub fn get_psw(&self) -> u8 {
        ((if self.psw_n { 1 } else { 0 }) << 7) |
        ((if self.psw_v { 1 } else { 0 }) << 6) |
        ((if self.psw_p { 1 } else { 0 }) << 5) |
        ((if self.psw_h { 1 } else { 0 }) << 3) |
        ((if self.psw_z { 1 } else { 0 }) << 1) |
        (if self.psw_c { 1 } else { 0 })
    }

    fn is_negative(value: u32) -> bool {
        (value & 0x80) != 0
    }

    fn cycles(&mut self, num_cycles: i32) {
        self.emulator.cpu_cycles_callback(num_cycles);
        self.cycle_count += num_cycles;
    }

    fn read_op(&mut self, addr: u16) -> u8 {
        self.cycles(1);
        self.emulator.read_byte(addr as u32)
    }

    fn write_op(&mut self, addr: u16, value: u8) {
        self.cycles(1);
        self.emulator.write_byte(addr as u32, value);
    }

    fn read_pc_op(&mut self) -> u8 {
        let addr = self.reg_pc;
        self.reg_pc += 1;
        let ret = self.read_op(addr);
        ret
    }

    fn read_sp_op(&mut self) -> u8 {
        self.reg_sp += 1;
        let addr = 0x0100 | (self.reg_sp as u16);
        self.read_op(addr)
    }

    fn write_sp_op(&mut self, value: u8) {
        let addr = 0x0100 | (self.reg_sp as u16);
        self.reg_sp -= 1;
        self.write_op(addr, value);
    }

    fn read_dp_op(&mut self, addr: u8) -> u8 {
        let addr = (if self.psw_p { 0x0100 } else { 0 }) | (addr as u16);
        self.read_op(addr)
    }

    fn write_dp_op(&mut self, addr: u8, value: u8) {
        let addr = (if self.psw_p { 0x0100 } else { 0 }) | (addr as u16);
        self.write_op(addr, value);
    }

    fn set_psw_n_z_op(&mut self, x: u32) {
        self.psw_n = Smp::is_negative(x);
        self.psw_z = x == 0;
    }

    fn adc_op(&mut self, x: u8, y: u8) -> u8 {
        let x = x as u32;
        let y = y as u32;
        let r = x + y + (if self.psw_c { 1 } else { 0 });
        self.psw_n = Smp::is_negative(r);
        self.psw_v = (!(x ^ y) & (x ^ r) & 0x80) != 0;
        self.psw_h = ((x ^ y ^ r) & 0x10) != 0;
        self.psw_z = (r & 0xff) == 0;
        self.psw_c = r > 0xff;
        (r & 0xff) as u8
    }

    fn and_op(&mut self, x: u8, y: u8) -> u8 {
        let ret = x & y;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn asl_op(&mut self, x: u8) -> u8 {
        self.psw_c = Smp::is_negative(x as u32);
        let ret = x << 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn cmp_op(&mut self, x: u8, y: u8) -> u8 {
        let r = (x as i32) - (y as i32);
        self.psw_n = (r & 0x80) != 0;
        self.psw_z = (r & 0xff) == 0;
        self.psw_c = r >= 0;
        x
    }

    fn dec_op(&mut self, x: u8) -> u8 {
        let ret = x - 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn eor_op(&mut self, x: u8, y: u8) -> u8 {
        let ret = x ^ y;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn inc_op(&mut self, x: u8) -> u8 {
        let ret = x + 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn ld_op(&mut self, _: u8, y: u8) -> u8 {
        self.set_psw_n_z_op(y as u32);
        y
    }

    fn lsr_op(&mut self, x: u8) -> u8 {
        self.psw_c = (x & 0x01) != 0;
        let ret = x >> 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn or_op(&mut self, x: u8, y: u8) -> u8 {
        let ret = x | y;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn rol_op(&mut self, x: u8) -> u8 {
        let carry = if self.psw_c { 1 } else { 0 };
        self.psw_c = (x & 0x80) != 0;
        let ret = (x << 1) | carry;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn ror_op(&mut self, x: u8) -> u8 {
        let carry = if self.psw_c { 0x80 } else { 0 };
        self.psw_c = (x & 0x01) != 0;
        let ret = carry | (x >> 1);
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn sbc_op(&mut self, x: u8, y: u8) -> u8 {
        self.adc_op(x, !y)
    }

    fn st_op(&mut self, _: u8, y: u8) -> u8 {
        y
    }

    fn adw_op(&mut self, x: u16, y: u16) -> u16 {
        self.psw_c = false;
        let mut ret = self.adc_op(x as u8, y as u8) as u16;
        ret |= (self.adc_op((x >> 8) as u8, (y >> 8) as u8) as u16) << 8;
        self.psw_z = ret == 0;
        ret
    }

    fn run(&mut self, target_cycles: i32) -> i32 {
        0 // TODO
    }
}
<commit_msg>implemented some more ops<commit_after>// TODO: This will panic on certain opcodes. The ideas I have for cpu_lang
// will probably fix it; we'll see. For now tho, I'm gonna leave it as-is;
// I can imagine fixing it trivially might lead to performance problems.
// I'll deal with it after the port is finished.

// TODO: This is a placeholder before I start generalizing traits
// from the old code.
use super::apu::Apu;

pub struct Smp<'a> {
    emulator: &'a mut Apu,

    reg_pc: u16,
    reg_a: u8,
    reg_x: u8,
    reg_y: u8,
    reg_sp: u8,

    psw_c: bool,
    psw_z: bool,
    psw_h: bool,
    psw_p: bool,
    psw_v: bool,
    psw_n: bool,
    // TODO: Look up some more behavior for I and B. Can't seem to find much
    // but some instructions DO set them.
    psw_i: bool,
    psw_b: bool,

    cycle_count: i32
}

impl<'a> Smp<'a> {
    pub fn new(emulator: &'a mut Apu) -> Smp<'a> {
        let mut ret = Smp {
            emulator: emulator,

            reg_pc: 0,
            reg_a: 0,
            reg_x: 0,
            reg_y: 0,
            reg_sp: 0,

            psw_c: false,
            psw_z: false,
            psw_h: false,
            psw_p: false,
            psw_v: false,
            psw_n: false,
            psw_i: false,
            psw_b: false,

            cycle_count: 0
        };
        ret.reset();
        ret
    }

    pub fn reset(&mut self) {
        self.reg_pc = 0xffc0;
        self.reg_a = 0;
        self.reg_x = 0;
        self.reg_y = 0;
        self.reg_sp = 0xef;
        self.set_psw(0x02);
    }

    pub fn set_reg_ya(&mut self, value: u16) {
        self.reg_a = (value & 0xff) as u8;
        self.reg_y = ((value >> 8) & 0xff) as u8;
    }

    pub fn get_reg_ya(&self) -> u16 {
        ((self.reg_y as u16) << 8) | (self.reg_a as u16)
    }

    pub fn set_psw(&mut self, value: u8) {
        self.psw_c = (value & 0x01) != 0;
        self.psw_z = (value & 0x02) != 0;
        self.psw_h = (value & 0x08) != 0;
        self.psw_p = (value & 0x20) != 0;
        self.psw_v = (value & 0x40) != 0;
        self.psw_n = (value & 0x80) != 0;
    }

    pub fn get_psw(&self) -> u8 {
        ((if self.psw_n { 1 } else { 0 }) << 7) |
        ((if self.psw_v { 1 } else { 0 }) << 6) |
        ((if self.psw_p { 1 } else { 0 }) << 5) |
        ((if self.psw_h { 1 } else { 0 }) << 3) |
        ((if self.psw_z { 1 } else { 0 }) << 1) |
        (if self.psw_c { 1 } else { 0 })
    }

    fn is_negative(value: u32) -> bool {
        (value & 0x80) != 0
    }

    fn cycles(&mut self, num_cycles: i32) {
        self.emulator.cpu_cycles_callback(num_cycles);
        self.cycle_count += num_cycles;
    }

    fn read_op(&mut self, addr: u16) -> u8 {
        self.cycles(1);
        self.emulator.read_byte(addr as u32)
    }

    fn write_op(&mut self, addr: u16, value: u8) {
        self.cycles(1);
        self.emulator.write_byte(addr as u32, value);
    }

    fn read_pc_op(&mut self) -> u8 {
        let addr = self.reg_pc;
        self.reg_pc += 1;
        let ret = self.read_op(addr);
        ret
    }

    fn read_sp_op(&mut self) -> u8 {
        self.reg_sp += 1;
        let addr = 0x0100 | (self.reg_sp as u16);
        self.read_op(addr)
    }

    fn write_sp_op(&mut self, value: u8) {
        let addr = 0x0100 | (self.reg_sp as u16);
        self.reg_sp -= 1;
        self.write_op(addr, value);
    }

    fn read_dp_op(&mut self, addr: u8) -> u8 {
        let addr = (if self.psw_p { 0x0100 } else { 0 }) | (addr as u16);
        self.read_op(addr)
    }

    fn write_dp_op(&mut self, addr: u8, value: u8) {
        let addr = (if self.psw_p { 0x0100 } else { 0 }) | (addr as u16);
        self.write_op(addr, value);
    }

    fn set_psw_n_z_op(&mut self, x: u32) {
        self.psw_n = Smp::is_negative(x);
        self.psw_z = x == 0;
    }

    fn adc_op(&mut self, x: u8, y: u8) -> u8 {
        let x = x as u32;
        let y = y as u32;
        let r = x + y + (if self.psw_c { 1 } else { 0 });
        self.psw_n = Smp::is_negative(r);
        self.psw_v = (!(x ^ y) & (x ^ r) & 0x80) != 0;
        self.psw_h = ((x ^ y ^ r) & 0x10) != 0;
        self.psw_z = (r & 0xff) == 0;
        self.psw_c = r > 0xff;
        (r & 0xff) as u8
    }

    fn and_op(&mut self, x: u8, y: u8) -> u8 {
        let ret = x & y;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn asl_op(&mut self, x: u8) -> u8 {
        self.psw_c = Smp::is_negative(x as u32);
        let ret = x << 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn cmp_op(&mut self, x: u8, y: u8) -> u8 {
        let r = (x as i32) - (y as i32);
        self.psw_n = (r & 0x80) != 0;
        self.psw_z = (r & 0xff) == 0;
        self.psw_c = r >= 0;
        x
    }

    fn dec_op(&mut self, x: u8) -> u8 {
        let ret = x - 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn eor_op(&mut self, x: u8, y: u8) -> u8 {
        let ret = x ^ y;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn inc_op(&mut self, x: u8) -> u8 {
        let ret = x + 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn ld_op(&mut self, _: u8, y: u8) -> u8 {
        self.set_psw_n_z_op(y as u32);
        y
    }

    fn lsr_op(&mut self, x: u8) -> u8 {
        self.psw_c = (x & 0x01) != 0;
        let ret = x >> 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn or_op(&mut self, x: u8, y: u8) -> u8 {
        let ret = x | y;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn rol_op(&mut self, x: u8) -> u8 {
        let carry = if self.psw_c { 1 } else { 0 };
        self.psw_c = (x & 0x80) != 0;
        let ret = (x << 1) | carry;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn ror_op(&mut self, x: u8) -> u8 {
        let carry = if self.psw_c { 0x80 } else { 0 };
        self.psw_c = (x & 0x01) != 0;
        let ret = carry | (x >> 1);
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn sbc_op(&mut self, x: u8, y: u8) -> u8 {
        self.adc_op(x, !y)
    }

    fn st_op(&self, _: u8, y: u8) -> u8 {
        y
    }

    fn adw_op(&mut self, x: u16, y: u16) -> u16 {
        self.psw_c = false;
        let mut ret = self.adc_op(x as u8, y as u8) as u16;
        ret |= (self.adc_op((x >> 8) as u8, (y >> 8) as u8) as u16) << 8;
        self.psw_z = ret == 0;
        ret
    }

    fn cpw_op(&mut self, x: u16, y: u16) -> u16 {
        let ret = (x as i32) - (y as i32);
        self.psw_n = (ret & 0x8000) != 0;
        self.psw_z = (ret as u16) == 0;
        self.psw_c = ret >= 0;
        ret as u16
    }

    fn ldw_op(&mut self, _: u16, y: u16) -> u16 {
        self.psw_n = (y & 0x8000) != 0;
        self.psw_z = y == 0;
        y
    }

    fn sbw_op(&mut self, x: u16, y: u16) -> u16 {
        self.psw_c = true;
        let mut ret = self.sbc_op(x as u8, y as u8) as u16;
        ret |= (self.sbc_op((x >> 8) as u8, (y >> 8) as u8) as u16) << 8;
        self.psw_z = ret == 0;
        ret
    }

    fn run(&mut self, target_cycles: i32) -> i32 {
        0 // TODO
    }
}
<|endoftext|>


<commit_before>
use hamt::HamtMap;
use itertools::*;

use std::error::Error;
use std::fmt::{self, Display, Debug, Formatter};
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

pub struct SymbolTable {
    ident_map: HamtMap<String, u32>,
    id_map: HamtMap<u32, Record>,
}

impl SymbolTable {
    pub fn empty() -> Self {
        SymbolTable {
            ident_map: Default::default(),
            id_map: Default::default(),
        }
    }

    pub fn add_ident<T: Into<String>>(&mut self, ident: T) -> Result<&Record, Box<Error>> {
        let ident = ident.into();

        if let Some(record) = self.lookup_ident(&*ident) {
            let msg = format!("Error adding identifier {} to {:?}, that record already exists: \
                               {:#?}",
                              ident,
                              self,
                              record);
            return Err(msg.into());
        }

        let id = next_id();
        let record = Record {
            id: id,
            ident: ident.clone(),
        };

        self.ident_map = self.ident_map.clone().plus(ident, id);
        self.id_map = self.id_map.clone().plus(id, record);

        Ok(self.lookup_id(id).unwrap())
    }

    pub fn lookup_ident<T: Into<String>>(&self, ident: T) -> Option<&Record> {
        self.ident_map.find(&ident.into()).and_then(|&id| self.lookup_id(id))
    }

    pub fn lookup_id(&self, id: u32) -> Option<&Record> {
        self.id_map.find(&id)
    }

    // TODO tree api
    // probably leave it until it's needed (and thus requirements are known)
}

#[derive(Debug)]
pub struct Record {
    ident: String,
    id: u32,
}

impl Record {
    pub fn id(&self) -> u32 {
        self.id
    }

    pub fn ident(&self) -> &str {
        &*self.ident
    }
}

fn next_id() -> u32 {
    static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;

    COUNTER.fetch_add(1, Ordering::SeqCst) as u32
}

impl Debug for SymbolTable {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use std::cmp;

        let mut records = self.id_map.iter().map(|kv| kv.1).collect::<Vec<_>>();
        records.sort_by(|a, b| a.id().cmp(&b.id()));

        let id_size = cmp::max("id".len(),
                               records.last().map_or(0, |r| r.id().to_string().len()));
        let ident_size = cmp::max("ident".len(),
                                  records.iter().map(|r| r.ident().len()).max().unwrap_or(0));

        let fmt_record = |a: &Display, b: &Display| -> String {
            format!("| {:>2$} | {:>3$} |", a, b, id_size, ident_size)
        };

        let header = format!("| {:>2$} | {:>3$} |", "id", "ident", id_size, ident_size);
        let sep = format!("|-{0:->1$}-|-{0:->2$}-|", "", id_size, ident_size);

        try!(writeln!(f, "SymbolTable:"));
        try!(writeln!(f, "{}", header));
        try!(writeln!(f, "{}", sep));

        for r in records {
            try!(writeln!(f, "{}", fmt_record(&r.id(), &r.ident())))
        }

        Ok(())
    }
}
<commit_msg>Preliminary VarKind in symbol table<commit_after>
use hamt::HamtMap;
use itertools::*;

use std::error::Error;
use std::fmt::{self, Display, Debug, Formatter};
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

pub struct SymbolTable {
    ident_map: HamtMap<String, u32>,
    id_map: HamtMap<u32, Record>,
}

impl SymbolTable {
    pub fn empty() -> Self {
        SymbolTable {
            ident_map: Default::default(),
            id_map: Default::default(),
        }
    }

    pub fn add_ident<T: Into<String>>(&mut self, ident: T) -> Result<&Record, Box<Error>> {
        let ident = ident.into();

        if let Some(record) = self.lookup_ident(&*ident) {
            let msg = format!("Error adding identifier {} to {:?}, that record already exists: \
                               {:#?}",
                              ident,
                              self,
                              record);
            return Err(msg.into());
        }

        let id = next_id();
        let record = Record {
            id: id,
            ident: ident.clone(),
            kind: VarKind::Normal, // TODO
        };

        self.ident_map = self.ident_map.clone().plus(ident, id);
        self.id_map = self.id_map.clone().plus(id, record);

        Ok(self.lookup_id(id).unwrap())
    }

    pub fn lookup_ident<T: Into<String>>(&self, ident: T) -> Option<&Record> {
        self.ident_map.find(&ident.into()).and_then(|&id| self.lookup_id(id))
    }

    pub fn lookup_id(&self, id: u32) -> Option<&Record> {
        self.id_map.find(&id)
    }

    // TODO tree api
    // probably leave it until it's needed (and thus requirements are known)
}

#[derive(Debug)]
pub struct Record {
    ident: String,
    kind: VarKind,
    id: u32,
}

impl Record {
    pub fn id(&self) -> u32 {
        self.id
    }

    pub fn ident(&self) -> &str {
        &*self.ident
    }
}

#[derive(Debug)]
enum VarKind {
    // builtins
    Special,
    // user-defined
    Normal,
}

fn next_id() -> u32 {
    static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;

    COUNTER.fetch_add(1, Ordering::SeqCst) as u32
}

impl Debug for SymbolTable {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use std::cmp;

        let mut records = self.id_map.iter().map(|kv| kv.1).collect::<Vec<_>>();
        records.sort_by(|a, b| a.id().cmp(&b.id()));

        let id_size = cmp::max("id".len(),
                               records.last().map_or(0, |r| r.id().to_string().len()));

        let ident_size = cmp::max("ident".len(),
                                  records.iter().map(|r| r.ident().len()).max().unwrap_or(0));

        let var_kind_size = "special".len();

        let header = format!("| {:>3$} | {:>4$} | {:>5$} |",
                             "id",
                             "ident",
                             "kind",
                             id_size,
                             ident_size,
                             var_kind_size);

        let sep = format!("|-{0:->1$}-|-{0:->2$}-|-{0:->3$}-|",
                          "",
                          id_size,
                          ident_size,
                          var_kind_size);

        try!(writeln!(f, "SymbolTable:"));
        try!(writeln!(f, "{}", header));
        try!(writeln!(f, "{}", sep));

        for r in records {
            let r_kind = match r.kind {
                VarKind::Normal => "normal",
                VarKind::Special => "special",
            };

            let out = format!("| {:>3$} | {:>4$} | {:>5$} |",
                              r.id(),
                              r.ident(),
                              r_kind,
                              id_size,
                              ident_size,
                              var_kind_size);

            try!(writeln!(f, "{}", out))
        }

        Ok(())
    }
}
<|endoftext|>


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

use std::io;
use std::mem;
use std::net::{TcpListener, TcpStream, UdpSocket};
use std::os::unix::io::FromRawFd;
use libc::{self, c_int, ioctl, FIOCLEX};

mod impls;

pub use libc as c;

pub struct Socket {
    fd: c_int,
}

impl Socket {
    pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
        unsafe {
            let fd = try!(::cvt(libc::socket(family, ty, 0)));
            ioctl(fd, FIOCLEX);
            Ok(Socket { fd: fd })
        }
    }

    pub fn raw(&self) -> c_int { self.fd }

    fn into_fd(self) -> c_int {
        let fd = self.fd;
        mem::forget(self);
        fd
    }

    pub fn into_tcp_listener(self) -> TcpListener {
        unsafe { TcpListener::from_raw_fd(self.into_fd()) }
    }

    pub fn into_tcp_stream(self) -> TcpStream {
        unsafe { TcpStream::from_raw_fd(self.into_fd()) }
    }

    pub fn into_udp_socket(self) -> UdpSocket {
        unsafe { UdpSocket::from_raw_fd(self.into_fd()) }
    }
}

impl ::FromInner for Socket {
    type Inner = c_int;
    fn from_inner(fd: c_int) -> Socket {
        Socket { fd: fd }
    }
}

impl Drop for Socket {
    fn drop(&mut self) {
        unsafe {
            let _ = libc::close(self.fd);
        }
    }
}
<commit_msg>Fix a compile error on nightly<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::io;
use std::mem;
use std::net::{TcpListener, TcpStream, UdpSocket};
use std::os::unix::io::FromRawFd;
use libc::{self, c_int, ioctl, FIOCLEX};

mod impls;

pub mod c {
    pub use libc::*;
}

pub struct Socket {
    fd: c_int,
}

impl Socket {
    pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
        unsafe {
            let fd = try!(::cvt(libc::socket(family, ty, 0)));
            ioctl(fd, FIOCLEX);
            Ok(Socket { fd: fd })
        }
    }

    pub fn raw(&self) -> c_int { self.fd }

    fn into_fd(self) -> c_int {
        let fd = self.fd;
        mem::forget(self);
        fd
    }

    pub fn into_tcp_listener(self) -> TcpListener {
        unsafe { TcpListener::from_raw_fd(self.into_fd()) }
    }

    pub fn into_tcp_stream(self) -> TcpStream {
        unsafe { TcpStream::from_raw_fd(self.into_fd()) }
    }

    pub fn into_udp_socket(self) -> UdpSocket {
        unsafe { UdpSocket::from_raw_fd(self.into_fd()) }
    }
}

impl ::FromInner for Socket {
    type Inner = c_int;
    fn from_inner(fd: c_int) -> Socket {
        Socket { fd: fd }
    }
}

impl Drop for Socket {
    fn drop(&mut self) {
        unsafe {
            let _ = libc::close(self.fd);
        }
    }
}
<|endoftext|>


<commit_before>//! Support for the DMABuf type

use wlroots_sys::{wl_display, wlr_linux_dmabuf_v1, wlr_linux_dmabuf_v1_create,
                wlr_linux_dmabuf_v1_destroy};
use {compositor::Compositor,
    render::GenericRenderer};

#[derive(Debug)]
pub struct Dmabuf {
    dmabuf: *mut wlr_linux_dmabuf_v1
}

impl Dmabuf {
    pub fn new(compositor: &Compositor) -> Option<Self> {
        unsafe {
            // Get the renderer from compositor
            let renderer: Option<GenericRenderer> = compositor.renderer;
            // Unwrap it and check if it's null
            let renderer_raw = renderer.unwrap().as_ptr();
            if !renderer_raw.is_null() {
                // We found a renderer
                let dmabuf_raw = wlr_linux_dmabuf_v1_create(compositor.display as *mut wl_display, renderer_raw);
                if !dmabuf_raw.is_null() {
                    Some(Dmabuf { dmabuf: dmabuf_raw })
                } else {
                    None
                }
            }
            else {
                 // No renderer found so return none
                None
            }
        }
    }
    // TODO wrap rest of dmabuf
}

impl Drop for Dmabuf {
    fn drop(&mut self) {
        unsafe { wlr_linux_dmabuf_v1_destroy(self.dmabuf) }
    }
}
<commit_msg>address review comments<commit_after>//! Support for the DMABuf type

use wlroots_sys::{wl_display, wlr_linux_dmabuf_v1, wlr_linux_dmabuf_v1_create,
                wlr_linux_dmabuf_v1_destroy};
use {crate::compositor::Compositor,
    crate::render::GenericRenderer};

#[derive(Debug)]
pub struct Dmabuf {
    dmabuf: *mut wlr_linux_dmabuf_v1
}

impl Dmabuf {
    pub fn new(compositor: &Compositor) -> Option<Self> {
        unsafe {
            // Get the renderer from compositor
            let renderer: Option<&GenericRenderer> = compositor.renderer.as_ref();
            let dmabuf_raw = wlr_linux_dmabuf_v1_create(compositor.display as *mut wl_display, renderer.unwrap().as_ptr());
            if !dmabuf_raw.is_null() {
                Some(Dmabuf { dmabuf: dmabuf_raw })
            } else {
                None
            }
        }
    }
    // TODO wrap rest of dmabuf
}

impl Drop for Dmabuf {
    fn drop(&mut self) {
        unsafe { wlr_linux_dmabuf_v1_destroy(self.dmabuf) }
    }
}
<|endoftext|>