<commit_before>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website <https://serde.rs/> for additional documentation and
//! usage examples.
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
//!   markup language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [JSON5], a superset of JSON including some productions from ES5.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [URL] query strings, in the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//! - [S-expressions], the textual representation of code and data used by the
//!   Lisp language family.
//! - [D-Bus]'s binary wire format.
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
//! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to
//!   and from DynamoDB.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/bincode-org/bincode
//! [CBOR]: https://github.com/enarx/ciborium
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/mongodb/bson-rust
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html
//! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.137")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
        unnested_or_patterns,
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
        semicolon_if_nothing_returned,
        // not available in our oldest supported compiler
        empty_enum,
        type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        option_if_let_else,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // correctly used
        derive_partial_eq_without_eq,
        enum_glob_use,
        let_underscore_drop,
        map_err_ignore,
        result_unit_err,
        wildcard_imports,
        // not practical
        needless_pass_by_value,
        similar_names,
        too_many_lines,
        // preference
        doc_markdown,
        unseparated_literal_suffix,
        // false positive
        needless_doctest_main,
        // noisy
        missing_errors_doc,
        must_use_candidate,
    )
)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::num::Wrapping;
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::{String, ToString};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
    pub use std::collections::Bound;

    #[cfg(not(no_core_reverse))]
    pub use self::core::cmp::Reverse;

    #[cfg(not(no_ops_bound))]
    pub use self::core::ops::Bound;

    #[cfg(not(no_range_inclusive))]
    pub use self::core::ops::RangeInclusive;

    #[cfg(all(feature = "std", not(no_std_atomic)))]
    pub use std::sync::atomic::{
        AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
        AtomicUsize, Ordering,
    };
    #[cfg(all(feature = "std", not(no_std_atomic64)))]
    pub use std::sync::atomic::{AtomicI64, AtomicU64};

    #[cfg(any(feature = "std", not(no_core_duration)))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Used by generated code and doc tests. Not public API.
#[doc(hidden)]
#[path = "private/mod.rs"]
pub mod __private;

#[allow(unused_imports)]
use self::__private as export;
#[allow(unused_imports)]
use self::__private as private;

#[path = "de/seed.rs"]
mod seed;

#[cfg(not(feature = "std"))]
mod std_error;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;

#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
mod actually_private {
    pub struct T;
}
<commit_msg>Ignore explicit_auto_deref clippy lint<commit_after>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website <https://serde.rs/> for additional documentation and
//! usage examples.
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
//!   markup language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [JSON5], a superset of JSON including some productions from ES5.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [URL] query strings, in the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//! - [S-expressions], the textual representation of code and data used by the
//!   Lisp language family.
//! - [D-Bus]'s binary wire format.
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
//! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to
//!   and from DynamoDB.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/bincode-org/bincode
//! [CBOR]: https://github.com/enarx/ciborium
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/mongodb/bson-rust
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html
//! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.137")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
        unnested_or_patterns,
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
        semicolon_if_nothing_returned,
        // not available in our oldest supported compiler
        empty_enum,
        type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        option_if_let_else,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // correctly used
        derive_partial_eq_without_eq,
        enum_glob_use,
        explicit_auto_deref,
        let_underscore_drop,
        map_err_ignore,
        result_unit_err,
        wildcard_imports,
        // not practical
        needless_pass_by_value,
        similar_names,
        too_many_lines,
        // preference
        doc_markdown,
        unseparated_literal_suffix,
        // false positive
        needless_doctest_main,
        // noisy
        missing_errors_doc,
        must_use_candidate,
    )
)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::num::Wrapping;
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::{String, ToString};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
    pub use std::collections::Bound;

    #[cfg(not(no_core_reverse))]
    pub use self::core::cmp::Reverse;

    #[cfg(not(no_ops_bound))]
    pub use self::core::ops::Bound;

    #[cfg(not(no_range_inclusive))]
    pub use self::core::ops::RangeInclusive;

    #[cfg(all(feature = "std", not(no_std_atomic)))]
    pub use std::sync::atomic::{
        AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
        AtomicUsize, Ordering,
    };
    #[cfg(all(feature = "std", not(no_std_atomic64)))]
    pub use std::sync::atomic::{AtomicI64, AtomicU64};

    #[cfg(any(feature = "std", not(no_core_duration)))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Used by generated code and doc tests. Not public API.
#[doc(hidden)]
#[path = "private/mod.rs"]
pub mod __private;

#[allow(unused_imports)]
use self::__private as export;
#[allow(unused_imports)]
use self::__private as private;

#[path = "de/seed.rs"]
mod seed;

#[cfg(not(feature = "std"))]
mod std_error;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;

#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
mod actually_private {
    pub struct T;
}
<|endoftext|>


<commit_before>extern crate stratis_shared as shared;
extern crate stratis;

extern crate rand;

use stratis::{Server,Client};
use shared::opcode;
use shared::events::Event;

use std::thread;
use std::time::Duration;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::Receiver;

use rand::distributions::{IndependentSample,Range};

fn assert_opcode (rx: &Receiver<Event>, op: u8) -> Event {
    match rx.try_recv() {
        Ok(ev) => {
            assert_eq!(ev.0,op);
            return ev
        },
        _ => { panic!("no events received"); }
    }
}

fn assert_client () -> (Arc<Mutex<Client>>,Receiver<Event>) {
    let btw = Range::new(25000,64000);
    let mut rng = rand::thread_rng();

    let v = btw.ind_sample(&mut rng);
    println!("{:?}",v);

    let host = "127.0.0.1:".to_owned() + stringify!(btw.ind_sample(&mut rng));
    let host_ = host.clone();
    let _handle = thread::spawn(move || {
        let mut _server = Server::new(&host_);
    });
    let (mut client, rx) = Client::default();
    client.connect(&host);
    client.register();

    let client = Arc::new(Mutex::new(client));
    Client::login(&client);

    assert!(client.lock().unwrap().stream.is_some());

    (client,rx)
}

#[test]
fn client () {
    let (_client, rx) = assert_client();

    thread::sleep(Duration::from_millis(100));

    // we recv player twice
    // once for our own login
    // and again for each player that's connected
    assert_opcode(&rx,opcode::PLAYER);
    assert_opcode(&rx,opcode::PLAYER);
}

#[test]
fn client_chat () {
    let (client, rx) = assert_client();

    thread::sleep(Duration::from_millis(100));
    let text = "test";
    client.lock().unwrap().chat(text);

    assert_opcode(&rx,opcode::PLAYER);
    assert_opcode(&rx,opcode::PLAYER);
    let id = assert_opcode(&rx,opcode::CHAT).1;
    let text_ = client.lock().unwrap()
        .msg_cache.get_mut(&id).unwrap()
        .remove(0);

    assert_eq!(text,text_);
}
<commit_msg>fix test<commit_after>extern crate stratis_shared as shared;
extern crate stratis;

extern crate rand;

use stratis::{Server,Client};
use shared::opcode;
use shared::events::Event;

use std::thread;
use std::time::Duration;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::Receiver;

use rand::distributions::{IndependentSample,Range};

fn assert_opcode (rx: &Receiver<Event>, op: u8) -> Event {
    match rx.try_recv() {
        Ok(ev) => {
            assert_eq!(ev.0,op);
            return ev
        },
        _ => { panic!("no events received"); }
    }
}

fn assert_client () -> (Arc<Mutex<Client>>,Receiver<Event>) {
    let btw = Range::new(25000,64000);
    let mut rng = rand::thread_rng();
    let port = btw.ind_sample(&mut rng).to_string();

    let host = "127.0.0.1:".to_owned() + &port;
    let host_ = host.clone();
    let _handle = thread::spawn(move || {
        let mut _server = Server::new(&host_);
    });

    let (mut client, rx) = Client::default();
    client.connect(&host);
    client.register();

    let client = Arc::new(Mutex::new(client));
    Client::login(&client);

    assert!(client.lock().unwrap().stream.is_some());

    (client,rx)
}

#[test]
fn client () {
    let (_client, rx) = assert_client();

    thread::sleep(Duration::from_millis(100));

    // we recv player twice
    // once for our own login
    // and again for each player that's connected
    assert_opcode(&rx,opcode::PLAYER);
    assert_opcode(&rx,opcode::PLAYER);
}

#[test]
fn client_chat () {
    let (client, rx) = assert_client();

    thread::sleep(Duration::from_millis(100));
    let text = "test";
    client.lock().unwrap().chat(text);

    assert_opcode(&rx,opcode::PLAYER);
    assert_opcode(&rx,opcode::PLAYER);

    thread::sleep(Duration::from_millis(10));
    let id = assert_opcode(&rx,opcode::CHAT).1;
    let text_ = client.lock().unwrap()
        .msg_cache.get_mut(&id).unwrap()
        .remove(0);

    assert_eq!(text,text_);
}
<|endoftext|>


<commit_before>extern crate ncurses;

use std::option::Option;
use std::iter::FromIterator;
use self::ncurses::*;
use cpu::ExecState;
use instruction;

struct CodeWin {
    wtext:  WINDOW,
    lines:  Vec<String>,
    line:   Option<u8>,
}

impl CodeWin {
    fn new(win: WINDOW, s: &str) -> Self {
        let wtext = derwin(win, TEXT_LINES, TEXT_COLS, 0, 0);
        wbkgd(wtext, '?' as u64);

        let mut codewin = CodeWin {
            wtext: wtext,
            lines: Self::code_vec(s),
            line:  None,
        };

        codewin.set_line(Some(1));
        codewin.draw_all_lines();
        codewin
    }

    fn code_vec(s: &str) -> Vec<String> {
        s.lines().map(str::to_string).collect()
    }

    fn set_code(&mut self, s: &str) {
        self.lines = Self::code_vec(s);
        self.draw_all_lines();
    }

    fn draw_all_lines(&mut self) {
        for i in (0..self.lines.len() as u8) {
            self.draw_line(i);
        }
    }

    fn draw_line(&mut self, line: u8) {
        let mut max_x: i32 = 0;
        let mut max_y: i32 = 0;
        getmaxyx(self.wtext, &mut max_y, &mut max_x);

        if self.line == Some(line) {
            wattr_on(self.wtext, A_STANDOUT());
        }

        let line = line as i32;
        assert!(line < max_y);

        wmove(self.wtext, line, 0);
        wclrtoeol(self.wtext);
        wmove(self.wtext, line, 0);
        if let Some(s) = self.lines.get(line as usize) {
            mvwprintw(self.wtext, line, 0, s);
            let pad: usize = TEXT_COLS as usize - s.len();
            wprintw(self.wtext, &String::from_iter([' '].iter().cloned().cycle().take(pad)));
        }
        wattr_off(self.wtext, A_STANDOUT());
        wrefresh(self.wtext);
    }

    /// Sets the active (highlighted) line
    fn set_line(&mut self, newline: Option<u8>) {
        let oldline = self.line;
        self.line = newline;

        if let Some(old) = oldline {
            self.draw_line(old);
        }

        if let Some(new) = newline {
            self.draw_line(new);
        }
    }
}

impl Drop for CodeWin {
    fn drop(&mut self) {
        delwin(self.wtext);
    }
}

struct CpuWin {
    win:        WINDOW,
    winner:     WINDOW,
    wsidebar:   WINDOW,
    codewin:    CodeWin,
}

const SIDEBAR_CELL_HEIGHT: i32 = 2;
const SIDEBAR_WIDTH: i32 = 6;
const CPUWIN_HEIGHT: i32 = (SIDEBAR_CELL_HEIGHT + 1) * 4 + 1;
const CPUWIN_WIDTH: i32 = CPUWIN_HEIGHT*2 + SIDEBAR_WIDTH;
const SIDEBAR_X: i32 = CPUWIN_WIDTH - 1 - SIDEBAR_WIDTH - 1;

const TEXT_LINES: i32 = CPUWIN_HEIGHT - 2;
const TEXT_COLS: i32 = CPUWIN_WIDTH - SIDEBAR_WIDTH - 3;

impl CpuWin {
    fn new(posx: i32, posy: i32) -> CpuWin {

        let win = newwin(CPUWIN_HEIGHT, CPUWIN_WIDTH, posy, posx);
        let winner = derwin(win, CPUWIN_HEIGHT-2, CPUWIN_WIDTH-2, 1, 1);
        let wsidebar = derwin(winner, CPUWIN_HEIGHT-2, SIDEBAR_WIDTH, 0, SIDEBAR_X);

        /* Border */
        box_(win, 0, 0);

        /* Left size of sidebar */
        mvwaddch(win, 0, SIDEBAR_X, ACS_TTEE());
        mvwvline(win, 1, SIDEBAR_X, ACS_VLINE(), CPUWIN_HEIGHT - 2);
        mvwaddch(win, CPUWIN_HEIGHT-1, SIDEBAR_X, ACS_BTEE());

        let mut cpuwin = CpuWin {
            win:        win,
            winner:     winner,
            wsidebar:   wsidebar,
            codewin:    CodeWin::new(winner, "line1\nline2\n\nline4"),
        };
        cpuwin.cell_label(0, "ACC");
        cpuwin.cell_label(1, "BAK");
        cpuwin.cell_label(2, "LAST");
        cpuwin.cell_label(3, "MODE");

        cpuwin.cell_divider(1);
        cpuwin.cell_divider(2);
        cpuwin.cell_divider(3);

        cpuwin.set_values(0, 10, None, ExecState::EXEC);

        cpuwin
    }

    fn cell_label(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell), 1, l);
    }

    fn cell_val(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell)+1, 1, l);
    }

    fn cell_divider(&mut self, cell: i32) {
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X, ACS_LTEE());
        mvwhline(self.win, Self::cell_y(cell), SIDEBAR_X+1, ACS_HLINE(), SIDEBAR_WIDTH);
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X+SIDEBAR_WIDTH+1, ACS_RTEE());
    }

    fn cell_y(cell: i32) -> i32 {
        (SIDEBAR_CELL_HEIGHT + 1) * cell
    }

    fn refresh(&mut self) {
        wrefresh(self.win);
    }

    fn set_values(&mut self, acc: i32, bak: i32, last: Option<instruction::Port>, mode: ExecState) {
        let acc = format!("{:^4}", acc);
        let bak = format!("{:^4}", bak);
        let last = last.map_or_else(|| "N/A".to_string(), |p| p.to_string());
        let mode = mode.to_string();
        self.cell_val(0, &acc);
        self.cell_val(1, &bak);
        self.cell_val(2, &last);
        self.cell_val(3, &mode);
    }

    fn set_code(&mut self, s: &str) {
        self.codewin.set_code(s)
    }

    fn set_line(&mut self, newline: Option<u8>) {
        self.codewin.set_line(newline)
    }
}

impl Drop for CpuWin {
    fn drop(&mut self) {
        delwin(self.wsidebar);
        delwin(self.winner);
        wclear(self.win);
        //wrefresh(self.win);
        delwin(self.win);
    }
}

fn create_cpu_wins() -> Vec<Vec<CpuWin>> {
    let left_margin = 10;
    let inner_margin = 4;

    let mut cpuwins: Vec<Vec<CpuWin>> = (0..4).map(|x| {
        (0..3).map(|y| (x, y)).map(|(x, y)| {
            CpuWin::new(x*(CPUWIN_WIDTH + inner_margin) + left_margin,
                        y*(CPUWIN_HEIGHT + inner_margin/2) + left_margin/2)
        }).collect::<Vec<_>>()
    }).collect();

    for y in cpuwins.iter_mut() {
        for cpu in y.iter_mut() {
            cpu.refresh();
        }
    }

    cpuwins
}

pub fn gui() {
    initscr();
    refresh();

    let mut cpuwins = create_cpu_wins();

    loop {
        let c = getch();
        if c == b'q' as i32 {
            break;
        } else if c == KEY_RESIZE {
            drop(cpuwins);
            clear();
            refresh();
            cpuwins = create_cpu_wins();
        } else {
            cpuwins[0][0].set_code("whoo");
            refresh();
        }
    }

    drop(cpuwins);
    endwin();
}
<commit_msg>gui_ncurses: redraw full text box<commit_after>extern crate ncurses;

use std::option::Option;
use std::iter::FromIterator;
use self::ncurses::*;
use cpu::ExecState;
use instruction;

struct CodeWin {
    wtext:  WINDOW,
    lines:  Vec<String>,
    line:   Option<u8>,
}

impl CodeWin {
    fn new(win: WINDOW, s: &str) -> Self {
        let wtext = derwin(win, TEXT_LINES, TEXT_COLS, 0, 0);
        wbkgd(wtext, '?' as u64);

        let mut codewin = CodeWin {
            wtext: wtext,
            lines: Self::code_vec(s),
            line:  None,
        };

        codewin.set_line(Some(1));
        codewin.draw_all_lines();
        codewin
    }

    fn code_vec(s: &str) -> Vec<String> {
        s.lines().take(TEXT_LINES as usize).map(str::to_string).collect()
    }

    fn set_code(&mut self, s: &str) {
        self.lines = Self::code_vec(s);
        self.draw_all_lines();
    }

    fn draw_all_lines(&mut self) {
        for i in (0..TEXT_LINES as u8) {
            self.draw_line(i);
        }
    }

    fn draw_line(&mut self, line: u8) {
        let mut max_x: i32 = 0;
        let mut max_y: i32 = 0;
        getmaxyx(self.wtext, &mut max_y, &mut max_x);

        if self.line == Some(line) {
            wattr_on(self.wtext, A_STANDOUT());
        }

        let line = line as i32;
        assert!(line < max_y);

        wmove(self.wtext, line, 0);
        wclrtoeol(self.wtext);
        wmove(self.wtext, line, 0);
        if let Some(s) = self.lines.get(line as usize) {
            mvwprintw(self.wtext, line, 0, s);
            let pad: usize = TEXT_COLS as usize - s.len();
            wprintw(self.wtext, &String::from_iter([' '].iter().cloned().cycle().take(pad)));
        }
        wattr_off(self.wtext, A_STANDOUT());
        wrefresh(self.wtext);
    }

    /// Sets the active (highlighted) line
    fn set_line(&mut self, newline: Option<u8>) {
        let oldline = self.line;
        self.line = newline;

        if let Some(old) = oldline {
            self.draw_line(old);
        }

        if let Some(new) = newline {
            self.draw_line(new);
        }
    }
}

impl Drop for CodeWin {
    fn drop(&mut self) {
        delwin(self.wtext);
    }
}

struct CpuWin {
    win:        WINDOW,
    winner:     WINDOW,
    wsidebar:   WINDOW,
    codewin:    CodeWin,
}

const SIDEBAR_CELL_HEIGHT: i32 = 2;
const SIDEBAR_WIDTH: i32 = 6;
const CPUWIN_HEIGHT: i32 = (SIDEBAR_CELL_HEIGHT + 1) * 4 + 1;
const CPUWIN_WIDTH: i32 = CPUWIN_HEIGHT*2 + SIDEBAR_WIDTH;
const SIDEBAR_X: i32 = CPUWIN_WIDTH - 1 - SIDEBAR_WIDTH - 1;

const TEXT_LINES: i32 = CPUWIN_HEIGHT - 2;
const TEXT_COLS: i32 = CPUWIN_WIDTH - SIDEBAR_WIDTH - 3;

impl CpuWin {
    fn new(posx: i32, posy: i32) -> CpuWin {

        let win = newwin(CPUWIN_HEIGHT, CPUWIN_WIDTH, posy, posx);
        let winner = derwin(win, CPUWIN_HEIGHT-2, CPUWIN_WIDTH-2, 1, 1);
        let wsidebar = derwin(winner, CPUWIN_HEIGHT-2, SIDEBAR_WIDTH, 0, SIDEBAR_X);

        /* Border */
        box_(win, 0, 0);

        /* Left size of sidebar */
        mvwaddch(win, 0, SIDEBAR_X, ACS_TTEE());
        mvwvline(win, 1, SIDEBAR_X, ACS_VLINE(), CPUWIN_HEIGHT - 2);
        mvwaddch(win, CPUWIN_HEIGHT-1, SIDEBAR_X, ACS_BTEE());

        let mut cpuwin = CpuWin {
            win:        win,
            winner:     winner,
            wsidebar:   wsidebar,
            codewin:    CodeWin::new(winner, "line1\nline2\n\nline4"),
        };
        cpuwin.cell_label(0, "ACC");
        cpuwin.cell_label(1, "BAK");
        cpuwin.cell_label(2, "LAST");
        cpuwin.cell_label(3, "MODE");

        cpuwin.cell_divider(1);
        cpuwin.cell_divider(2);
        cpuwin.cell_divider(3);

        cpuwin.set_values(0, 10, None, ExecState::EXEC);

        cpuwin
    }

    fn cell_label(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell), 1, l);
    }

    fn cell_val(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell)+1, 1, l);
    }

    fn cell_divider(&mut self, cell: i32) {
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X, ACS_LTEE());
        mvwhline(self.win, Self::cell_y(cell), SIDEBAR_X+1, ACS_HLINE(), SIDEBAR_WIDTH);
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X+SIDEBAR_WIDTH+1, ACS_RTEE());
    }

    fn cell_y(cell: i32) -> i32 {
        (SIDEBAR_CELL_HEIGHT + 1) * cell
    }

    fn refresh(&mut self) {
        wrefresh(self.win);
    }

    fn set_values(&mut self, acc: i32, bak: i32, last: Option<instruction::Port>, mode: ExecState) {
        let acc = format!("{:^4}", acc);
        let bak = format!("{:^4}", bak);
        let last = last.map_or_else(|| "N/A".to_string(), |p| p.to_string());
        let mode = mode.to_string();
        self.cell_val(0, &acc);
        self.cell_val(1, &bak);
        self.cell_val(2, &last);
        self.cell_val(3, &mode);
    }

    fn set_code(&mut self, s: &str) {
        self.codewin.set_code(s)
    }

    fn set_line(&mut self, newline: Option<u8>) {
        self.codewin.set_line(newline)
    }
}

impl Drop for CpuWin {
    fn drop(&mut self) {
        delwin(self.wsidebar);
        delwin(self.winner);
        wclear(self.win);
        //wrefresh(self.win);
        delwin(self.win);
    }
}

fn create_cpu_wins() -> Vec<Vec<CpuWin>> {
    let left_margin = 10;
    let inner_margin = 4;

    let mut cpuwins: Vec<Vec<CpuWin>> = (0..4).map(|x| {
        (0..3).map(|y| (x, y)).map(|(x, y)| {
            CpuWin::new(x*(CPUWIN_WIDTH + inner_margin) + left_margin,
                        y*(CPUWIN_HEIGHT + inner_margin/2) + left_margin/2)
        }).collect::<Vec<_>>()
    }).collect();

    for y in cpuwins.iter_mut() {
        for cpu in y.iter_mut() {
            cpu.refresh();
        }
    }

    cpuwins
}

pub fn gui() {
    initscr();
    refresh();

    let mut cpuwins = create_cpu_wins();
    let codes = ["woo", "one\ntwo\nthree"];
    let mut codes_iter = codes.iter();

    loop {
        let c = getch();
        if c == b'q' as i32 {
            break;
        } else if c == KEY_RESIZE {
            drop(cpuwins);
            clear();
            refresh();
            cpuwins = create_cpu_wins();
        } else {
            cpuwins[0][0].set_code(codes_iter.next().unwrap_or(&""));
        }
    }

    drop(cpuwins);
    endwin();
}
<|endoftext|>


<commit_before>use std::cmp::Eq;

use ::symbol_table;

/// Internal edge identifier.
///
/// This type is not exported by the crate because it does not identify the
/// graph that it belongs to, which makes it only slightly less dangerous than a
/// pointer with no lifetime.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct EdgeId(pub usize);

impl EdgeId {
    /// Converts an `EdgeId` to a usize that is guaranteed to be unique within a
    /// graph.
    pub fn as_usize(self) -> usize {
        let EdgeId(x) = self;
        x
    }
}

/// Internal vertex identifier.
///
/// For a given graph, distinct `VertexId`s are associated with distinct game
/// states. This type is not exported by the crate because it does not identify
/// the graph that it belongs to, which makes it only slightly less dangerous
/// than a pointer with no lifetime.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct VertexId(pub usize);

impl Default for VertexId {
    fn default() -> Self { VertexId(0) }
}

impl symbol_table::SymbolId for VertexId {
    fn next(&self) -> Self { VertexId(self.0 + 1) }
    fn as_usize(&self) -> usize { self.0 }
}

    // /// Changes associations between states and `VertexId`s.
    // ///
    // /// `(T, VertexId)` associations for which `f` returns `Some(new_id)` will be
    // /// remapped to use `new_id`.
    // ///
    // /// `(T, VertexId)` associations for which `f` returns `None` will be dropped.
    // ///
    // /// It is the responsibility of the caller to ensure that states map to
    // /// unique `VertexId`s.
    // pub fn remap<F>(&mut self, mut f: F) where F: FnMut(&T, VertexId) -> Option<VertexId> {
    //     let mut new_state_to_id = HashMap::with_capacity(self.state_to_id.len());
    //     for (state, old_state_id) in self.state_to_id.drain() {
    //         if let Some(new_state_id) = f(&state, old_state_id) {
    //             new_state_to_id.insert(state.clone(), new_state_id);
    //             self.id_to_state[new_state_id.as_usize()] = state;
    //         }
    //     }
    //     new_state_to_id.shrink_to_fit();
    //     self.state_to_id = new_state_to_id;
    //     self.id_to_state.truncate(self.state_to_id.len());
    // }

    // /// Transforms this namespace mapping to a hashtable. This is intended for
    // /// testing purposes only.
    // #[cfg(test)]
    // pub fn to_hash_map(self) -> HashMap<Rc<T>, VertexId> {
    //     self.state_to_id
    // }

    // pub fn get_state(&self, id: usize) -> Option<&T> {
    //     self.id_to_state.get(id).map(|x| &**x)
    // }

/// Internal type for graph edges.
///
/// The Hash, Ord, and Eq implementations will conflate parallel edges with
/// identical statistics.
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct RawEdge<A> {
    /// Edge data.
    pub data: A,
    /// Source vertex.
    pub source: VertexId,
    /// Target vertex.
    pub target: VertexId,
}

/// Internal type for graph vertices.
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct RawVertex<S> {
    /// Vertex data.
    pub data: S,
    /// Parent edges pointing into this vertex.
    pub parents: Vec<EdgeId>,
    /// Child edges pointing out of this vertex.
    pub children: Vec<EdgeId>,
}
<commit_msg>Remove dead code.<commit_after>use std::cmp::Eq;

use ::symbol_table;

/// Internal edge identifier.
///
/// This type is not exported by the crate because it does not identify the
/// graph that it belongs to, which makes it only slightly less dangerous than a
/// pointer with no lifetime.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct EdgeId(pub usize);

impl EdgeId {
    /// Converts an `EdgeId` to a usize that is guaranteed to be unique within a
    /// graph.
    pub fn as_usize(self) -> usize {
        let EdgeId(x) = self;
        x
    }
}

/// Internal vertex identifier.
///
/// For a given graph, distinct `VertexId`s are associated with distinct game
/// states. This type is not exported by the crate because it does not identify
/// the graph that it belongs to, which makes it only slightly less dangerous
/// than a pointer with no lifetime.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct VertexId(pub usize);

impl Default for VertexId {
    fn default() -> Self { VertexId(0) }
}

impl symbol_table::SymbolId for VertexId {
    fn next(&self) -> Self { VertexId(self.0 + 1) }
    fn as_usize(&self) -> usize { self.0 }
}

/// Internal type for graph edges.
///
/// The Hash, Ord, and Eq implementations will conflate parallel edges with
/// identical statistics.
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct RawEdge<A> {
    /// Edge data.
    pub data: A,
    /// Source vertex.
    pub source: VertexId,
    /// Target vertex.
    pub target: VertexId,
}

/// Internal type for graph vertices.
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct RawVertex<S> {
    /// Vertex data.
    pub data: S,
    /// Parent edges pointing into this vertex.
    pub parents: Vec<EdgeId>,
    /// Child edges pointing out of this vertex.
    pub children: Vec<EdgeId>,
}
<|endoftext|>


<commit_before>// Copyright 2017 Rich Lane <lanerl@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
// the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! This module parses eBPF assembly language source code.

use combine::char::{alpha_num, char, digit, hex_digit, spaces, string};
use combine::{between, eof, many, many1, one_of, optional, Parser, ParseError, ParseResult, parser,
              sep_by, try, State, Stream};
use combine::primitives::{Error, Info};

/// Operand of an instruction.
#[derive(Debug, PartialEq)]
pub enum Operand {
    /// Register number.
    Register(i64),
    /// Jump offset or immediate.
    Integer(i64),
    /// Register number and offset.
    Memory(i64, i64),
}

/// Parsed instruction.
#[derive(Debug, PartialEq)]
pub struct Instruction {
    /// Instruction name.
    pub name: String,
    /// Operands.
    pub operands: Vec<Operand>,
}

fn ident<I>(input: I) -> ParseResult<String, I>
    where I: Stream<Item = char>
{
    many1(alpha_num()).parse_stream(input)
}

fn integer<I>(input: I) -> ParseResult<i64, I>
    where I: Stream<Item = char>
{
    let sign = optional(one_of("-+".chars())).map(|x| match x {
        Some('-') => -1,
        _ => 1,
    });
    let hex =
        string("0x").with(many1(hex_digit())).map(|x: String| i64::from_str_radix(&x, 16).unwrap());
    let dec = many1(digit()).map(|x: String| i64::from_str_radix(&x, 10).unwrap());
    (sign, try(hex).or(dec)).map(|(s, x)| s * x).parse_stream(input)
}

fn register<I>(input: I) -> ParseResult<i64, I>
    where I: Stream<Item = char>
{
    char('r')
        .with(many1(digit()))
        .map(|x: String| i64::from_str_radix(&x, 10).unwrap())
        .parse_stream(input)
}

fn operand<I>(input: I) -> ParseResult<Operand, I>
    where I: Stream<Item = char>
{
    let register_operand = parser(register).map(|x: i64| Operand::Register(x));
    let immediate = parser(integer).map(|x: i64| Operand::Integer(x));
    let memory = between(char('['),
                         char(']'),
                         (parser(register), optional(parser(integer))))
        .map(|t| Operand::Memory(t.0, t.1.unwrap_or(0)));
    register_operand.or(immediate).or(memory).parse_stream(input)
}

fn instruction<I>(input: I) -> ParseResult<Instruction, I>
    where I: Stream<Item = char>
{
    let operands = sep_by(parser(operand), char(',').skip(spaces()));
    (parser(ident).skip(spaces()), operands, spaces())
        .map(|t| {
            Instruction {
                name: t.0,
                operands: t.1,
            }
        })
        .parse_stream(input)
}

fn format_info(info: &Info<char, &str>) -> String {
    match *info {
        Info::Token(x) => format!("{:?}", x),
        Info::Range(ref x) => format!("{:?}", x),
        Info::Owned(ref x) => x.clone(),
        Info::Borrowed(ref x) => x.to_string(),
    }
}

fn format_error(error: &Error<char, &str>) -> String {
    match *error {
        Error::Unexpected(ref x) => format!("unexpected {}", format_info(x)),
        Error::Expected(ref x) => format!("expected {}", format_info(x)),
        Error::Message(ref x) => format_info(x),
        Error::Other(ref x) => format!("{:?}", x),
    }
}

fn format_parse_error(parse_error: ParseError<State<&str>>) -> String {
    format!("Parse error at line {} column {}: {}",
            parse_error.position.line,
            parse_error.position.column,
            parse_error.errors.iter().map(format_error).collect::<Vec<String>>().join(", "))
}

/// Parse a string into a list of instructions.
///
/// The instructions are not validated and may have invalid names and operand types.
pub fn parse(input: &str) -> Result<Vec<Instruction>, String> {
    match many(parser(instruction)).skip(eof()).parse(State::new(input)) {
        Ok((insts, _)) => Ok(insts),
        Err(err) => Err(format_parse_error(err)),
    }
}

#[cfg(test)]
mod tests {
    use combine::{Parser, parser};
    use super::{ident, integer, register, operand, instruction, Operand, Instruction};

    #[test]
    fn test_ident() {
        assert_eq!(parser(ident).parse("nop"), Ok(("nop".to_string(), "")));
        assert_eq!(parser(ident).parse("add32"), Ok(("add32".to_string(), "")));
        assert_eq!(parser(ident).parse("add32*"),
                   Ok(("add32".to_string(), "*")));
    }

    #[test]
    fn test_integer() {
        assert_eq!(parser(integer).parse("0"), Ok((0, "")));
        assert_eq!(parser(integer).parse("42"), Ok((42, "")));
        assert_eq!(parser(integer).parse("+42"), Ok((42, "")));
        assert_eq!(parser(integer).parse("-42"), Ok((-42, "")));
        assert_eq!(parser(integer).parse("0x0"), Ok((0, "")));
        assert_eq!(parser(integer).parse("0x123456789abcdef0"),
                   Ok((0x123456789abcdef0, "")));
        assert_eq!(parser(integer).parse("-0x1f"), Ok((-31, "")));
    }

    #[test]
    fn test_register() {
        assert_eq!(parser(register).parse("r0"), Ok((0, "")));
        assert_eq!(parser(register).parse("r15"), Ok((15, "")));
    }

    #[test]
    fn test_operand() {
        assert_eq!(parser(operand).parse("r0"), Ok((Operand::Register(0), "")));
        assert_eq!(parser(operand).parse("r15"),
                   Ok((Operand::Register(15), "")));
        assert_eq!(parser(operand).parse("0"), Ok((Operand::Integer(0), "")));
        assert_eq!(parser(operand).parse("42"), Ok((Operand::Integer(42), "")));
        assert_eq!(parser(operand).parse("[r1]"),
                   Ok((Operand::Memory(1, 0), "")));
        assert_eq!(parser(operand).parse("[r3+5]"),
                   Ok((Operand::Memory(3, 5), "")));
        assert_eq!(parser(operand).parse("[r3+0x1f]"),
                   Ok((Operand::Memory(3, 31), "")));
        assert_eq!(parser(operand).parse("[r3-0x1f]"),
                   Ok((Operand::Memory(3, -31), "")));
    }

    #[test]
    fn test_instruction() {
        assert_eq!(parser(instruction).parse("exit"),
                   Ok((Instruction {
                           name: "exit".to_string(),
                           operands: vec![],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("call 2"),
                   Ok((Instruction {
                           name: "call".to_string(),
                           operands: vec![Operand::Integer(2)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("addi r1, 2"),
                   Ok((Instruction {
                           name: "addi".to_string(),
                           operands: vec![Operand::Register(1), Operand::Integer(2)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("ldxb r2, [r1+12]"),
                   Ok((Instruction {
                           name: "ldxb".to_string(),
                           operands: vec![Operand::Register(2), Operand::Memory(1, 12)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("lsh r3, 0x8"),
                   Ok((Instruction {
                           name: "lsh".to_string(),
                           operands: vec![Operand::Register(3), Operand::Integer(8)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("jne r3, 0x8, +37"),
                   Ok((Instruction {
                           name: "jne".to_string(),
                           operands: vec![Operand::Register(3),
                                          Operand::Integer(8),
                                          Operand::Integer(37)],
                       },
                       "")));

        // Whitespace between operands is optional.
        assert_eq!(parser(instruction).parse("jne r3,0x8,+37"),
                   Ok((Instruction {
                           name: "jne".to_string(),
                           operands: vec![Operand::Register(3),
                                          Operand::Integer(8),
                                          Operand::Integer(37)],
                       },
                       "")));
    }

}
<commit_msg>src/asm_parser.rs: remove unnecessary closures<commit_after>// Copyright 2017 Rich Lane <lanerl@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
// the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! This module parses eBPF assembly language source code.

use combine::char::{alpha_num, char, digit, hex_digit, spaces, string};
use combine::{between, eof, many, many1, one_of, optional, Parser, ParseError, ParseResult, parser,
              sep_by, try, State, Stream};
use combine::primitives::{Error, Info};

/// Operand of an instruction.
#[derive(Debug, PartialEq)]
pub enum Operand {
    /// Register number.
    Register(i64),
    /// Jump offset or immediate.
    Integer(i64),
    /// Register number and offset.
    Memory(i64, i64),
}

/// Parsed instruction.
#[derive(Debug, PartialEq)]
pub struct Instruction {
    /// Instruction name.
    pub name: String,
    /// Operands.
    pub operands: Vec<Operand>,
}

fn ident<I>(input: I) -> ParseResult<String, I>
    where I: Stream<Item = char>
{
    many1(alpha_num()).parse_stream(input)
}

fn integer<I>(input: I) -> ParseResult<i64, I>
    where I: Stream<Item = char>
{
    let sign = optional(one_of("-+".chars())).map(|x| match x {
        Some('-') => -1,
        _ => 1,
    });
    let hex =
        string("0x").with(many1(hex_digit())).map(|x: String| i64::from_str_radix(&x, 16).unwrap());
    let dec = many1(digit()).map(|x: String| i64::from_str_radix(&x, 10).unwrap());
    (sign, try(hex).or(dec)).map(|(s, x)| s * x).parse_stream(input)
}

fn register<I>(input: I) -> ParseResult<i64, I>
    where I: Stream<Item = char>
{
    char('r')
        .with(many1(digit()))
        .map(|x: String| i64::from_str_radix(&x, 10).unwrap())
        .parse_stream(input)
}

fn operand<I>(input: I) -> ParseResult<Operand, I>
    where I: Stream<Item = char>
{
    let register_operand = parser(register).map(Operand::Register);
    let immediate = parser(integer).map(Operand::Integer);
    let memory = between(char('['),
                         char(']'),
                         (parser(register), optional(parser(integer))))
        .map(|t| Operand::Memory(t.0, t.1.unwrap_or(0)));
    register_operand.or(immediate).or(memory).parse_stream(input)
}

fn instruction<I>(input: I) -> ParseResult<Instruction, I>
    where I: Stream<Item = char>
{
    let operands = sep_by(parser(operand), char(',').skip(spaces()));
    (parser(ident).skip(spaces()), operands, spaces())
        .map(|t| {
            Instruction {
                name: t.0,
                operands: t.1,
            }
        })
        .parse_stream(input)
}

fn format_info(info: &Info<char, &str>) -> String {
    match *info {
        Info::Token(x) => format!("{:?}", x),
        Info::Range(ref x) => format!("{:?}", x),
        Info::Owned(ref x) => x.clone(),
        Info::Borrowed(ref x) => x.to_string(),
    }
}

fn format_error(error: &Error<char, &str>) -> String {
    match *error {
        Error::Unexpected(ref x) => format!("unexpected {}", format_info(x)),
        Error::Expected(ref x) => format!("expected {}", format_info(x)),
        Error::Message(ref x) => format_info(x),
        Error::Other(ref x) => format!("{:?}", x),
    }
}

fn format_parse_error(parse_error: ParseError<State<&str>>) -> String {
    format!("Parse error at line {} column {}: {}",
            parse_error.position.line,
            parse_error.position.column,
            parse_error.errors.iter().map(format_error).collect::<Vec<String>>().join(", "))
}

/// Parse a string into a list of instructions.
///
/// The instructions are not validated and may have invalid names and operand types.
pub fn parse(input: &str) -> Result<Vec<Instruction>, String> {
    match many(parser(instruction)).skip(eof()).parse(State::new(input)) {
        Ok((insts, _)) => Ok(insts),
        Err(err) => Err(format_parse_error(err)),
    }
}

#[cfg(test)]
mod tests {
    use combine::{Parser, parser};
    use super::{ident, integer, register, operand, instruction, Operand, Instruction};

    #[test]
    fn test_ident() {
        assert_eq!(parser(ident).parse("nop"), Ok(("nop".to_string(), "")));
        assert_eq!(parser(ident).parse("add32"), Ok(("add32".to_string(), "")));
        assert_eq!(parser(ident).parse("add32*"),
                   Ok(("add32".to_string(), "*")));
    }

    #[test]
    fn test_integer() {
        assert_eq!(parser(integer).parse("0"), Ok((0, "")));
        assert_eq!(parser(integer).parse("42"), Ok((42, "")));
        assert_eq!(parser(integer).parse("+42"), Ok((42, "")));
        assert_eq!(parser(integer).parse("-42"), Ok((-42, "")));
        assert_eq!(parser(integer).parse("0x0"), Ok((0, "")));
        assert_eq!(parser(integer).parse("0x123456789abcdef0"),
                   Ok((0x123456789abcdef0, "")));
        assert_eq!(parser(integer).parse("-0x1f"), Ok((-31, "")));
    }

    #[test]
    fn test_register() {
        assert_eq!(parser(register).parse("r0"), Ok((0, "")));
        assert_eq!(parser(register).parse("r15"), Ok((15, "")));
    }

    #[test]
    fn test_operand() {
        assert_eq!(parser(operand).parse("r0"), Ok((Operand::Register(0), "")));
        assert_eq!(parser(operand).parse("r15"),
                   Ok((Operand::Register(15), "")));
        assert_eq!(parser(operand).parse("0"), Ok((Operand::Integer(0), "")));
        assert_eq!(parser(operand).parse("42"), Ok((Operand::Integer(42), "")));
        assert_eq!(parser(operand).parse("[r1]"),
                   Ok((Operand::Memory(1, 0), "")));
        assert_eq!(parser(operand).parse("[r3+5]"),
                   Ok((Operand::Memory(3, 5), "")));
        assert_eq!(parser(operand).parse("[r3+0x1f]"),
                   Ok((Operand::Memory(3, 31), "")));
        assert_eq!(parser(operand).parse("[r3-0x1f]"),
                   Ok((Operand::Memory(3, -31), "")));
    }

    #[test]
    fn test_instruction() {
        assert_eq!(parser(instruction).parse("exit"),
                   Ok((Instruction {
                           name: "exit".to_string(),
                           operands: vec![],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("call 2"),
                   Ok((Instruction {
                           name: "call".to_string(),
                           operands: vec![Operand::Integer(2)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("addi r1, 2"),
                   Ok((Instruction {
                           name: "addi".to_string(),
                           operands: vec![Operand::Register(1), Operand::Integer(2)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("ldxb r2, [r1+12]"),
                   Ok((Instruction {
                           name: "ldxb".to_string(),
                           operands: vec![Operand::Register(2), Operand::Memory(1, 12)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("lsh r3, 0x8"),
                   Ok((Instruction {
                           name: "lsh".to_string(),
                           operands: vec![Operand::Register(3), Operand::Integer(8)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("jne r3, 0x8, +37"),
                   Ok((Instruction {
                           name: "jne".to_string(),
                           operands: vec![Operand::Register(3),
                                          Operand::Integer(8),
                                          Operand::Integer(37)],
                       },
                       "")));

        // Whitespace between operands is optional.
        assert_eq!(parser(instruction).parse("jne r3,0x8,+37"),
                   Ok((Instruction {
                           name: "jne".to_string(),
                           operands: vec![Operand::Register(3),
                                          Operand::Integer(8),
                                          Operand::Integer(37)],
                       },
                       "")));
    }

}
<|endoftext|>


<commit_before>use std::fmt;
use crate::decoders::basics::*;

const DECODE_CACHE_BITS: u32 = 11;

pub struct HuffTable {
  // These two fields directly represent the contents of a JPEG DHT marker
  pub bits: [u32;17],
  pub huffval: [u32;256],

  // Represent the weird shifts that are needed for some NEF files
  pub shiftval: [u32;256],

  // Enable the workaround for 16 bit decodes in DNG that need to consume those
  // bits instead of the value being implied
  pub dng_bug: bool,

  // In CRW we only use the len code so the cache is not needed
  pub disable_cache: bool,

  // The remaining fields are computed from the above to allow more
  // efficient coding and decoding and thus private

  // The max number of bits in a huffman code and the table that converts those
  // bits into how many bits to consume and the decoded length and shift
  nbits: u32,
  hufftable: Vec<(u8,u8,u8)>,

  // A pregenerated table that goes straight to decoding a diff without first
  // finding a length, fetching bits, and sign extending them. The table is
  // sized by DECODE_CACHE_BITS and can have 97%+ hit rate with 11 bits
  decodecache: [Option<(u8,i32)>; 1<< DECODE_CACHE_BITS],

  initialized: bool,
}

struct MockPump {
  bits: u64,
  nbits: u32,
}

impl MockPump {
  pub fn empty() -> Self {
    MockPump {
      bits: 0,
      nbits: 0,
    }
  }

  pub fn set(&mut self, bits: u32, nbits: u32) {
    self.bits = (bits as u64) << 32;
    self.nbits = nbits + 32;
  }

  pub fn validbits(&self) -> i32 {
    self.nbits as i32 - 32
  }
}

impl BitPump for MockPump {
  fn peek_bits(&mut self, num: u32) -> u32 {
    (self.bits >> (self.nbits-num)) as u32
  }

  fn consume_bits(&mut self, num: u32) {
    self.nbits -= num;
    self.bits &= (1 << self.nbits) - 1;
  }
}

impl HuffTable {
  pub fn empty() -> HuffTable {
    HuffTable {
      bits: [0;17],
      huffval: [0;256],
      shiftval: [0;256],
      dng_bug: false,
      disable_cache: false,

      nbits: 0,
      hufftable: Vec::new(),
      decodecache: [None; 1 << DECODE_CACHE_BITS],
      initialized: false,
    }
  }

  pub fn new(bits: [u32;17], huffval: [u32;256], dng_bug: bool) -> Result<HuffTable,String> {
    let mut tbl = HuffTable {
      bits: bits,
      huffval: huffval,
      shiftval: [0;256],
      dng_bug: dng_bug,
      disable_cache: false,

      nbits: 0,
      hufftable: Vec::new(),
      decodecache: [None; 1 << DECODE_CACHE_BITS],
      initialized: false,
    };
    tbl.initialize()?;
    Ok(tbl)
  }

  pub fn initialize(&mut self) -> Result<(), String> {
    // Find out the max code length and allocate a table with that size
    self.nbits = 16;
    for i in 0..16 {
      if self.bits[16-i] != 0 {
        break;
      }
      self.nbits -= 1;
    }
    self.hufftable = vec![(0,0,0); 1 << self.nbits];

    // Fill in the table itself
    let mut h = 0;
    let mut pos = 0;
    for len in 0..self.nbits {
      for _ in 0..self.bits[len as usize + 1] {
        for _ in 0..(1 << (self.nbits-len-1)) {
          self.hufftable[h] = (len as u8 + 1, self.huffval[pos] as u8, self.shiftval[pos] as u8);
          h += 1;
        }
        pos += 1;
      }
    }

    // Create the decode cache by running the slow code over all the possible
    // values DECODE_CACHE_BITS wide
    if !self.disable_cache {
      let mut pump = MockPump::empty();
      let mut i = 0;
      loop {
        pump.set(i, DECODE_CACHE_BITS);
        let decode = self.huff_decode_slow(&mut pump);
        if pump.validbits() >= 0 {
          self.decodecache[i as usize] = Some(decode);
        }
        i += 1;
        if i >= 1 << DECODE_CACHE_BITS {
          break;
        }
      }
    }

    self.initialized = true;
    Ok(())
  }

  pub fn huff_decode(&self, pump: &mut dyn BitPump) -> Result<i32,String> {
    let code = pump.peek_bits(DECODE_CACHE_BITS) as usize;
    if let Some((bits,decode)) = self.decodecache[code] {
      pump.consume_bits(bits as u32);
      Ok(decode)
    } else {
      let decode = self.huff_decode_slow(pump);
      Ok(decode.1)
    }
  }

  pub fn huff_decode_slow(&self, pump: &mut dyn BitPump) -> (u8,i32) {
    let len = self.huff_len(pump);
    (len.0+len.1, self.huff_diff(pump, len))
  }

  pub fn huff_len(&self, pump: &mut dyn BitPump) -> (u8,u8,u8) {
    let code = pump.peek_bits(self.nbits) as usize;
    let (bits, len, shift) = self.hufftable[code];
    pump.consume_bits(bits as u32);
    (bits, len, shift)
  }

  pub fn huff_get_bits(&self, pump: &mut dyn BitPump) -> u32 {
    let code = pump.peek_bits(self.nbits) as usize;
    let (bits, len, _) = self.hufftable[code];
    pump.consume_bits(bits as u32);
    len as u32
  }

  pub fn huff_diff(&self, pump: &mut dyn BitPump, input: (u8,u8,u8)) -> i32 {
    let (_, len, shift) = input;

    match len {
      0 => 0,
      16 => {
        if self.dng_bug {
          pump.get_bits(16); // consume can fail because we haven't peeked yet
        }
        -32768
      },
      len => {
        // decode the difference and extend sign bit
        let fulllen: i32 = len as i32 + shift as i32;
        let shift: i32 = shift as i32;
        let bits = pump.get_bits(len as u32) as i32;
        let mut diff: i32 = ((bits << 1) + 1) << shift >> 1;
        if (diff & (1 << (fulllen - 1))) == 0 {
          diff -= (1 << fulllen) - ((shift == 0) as i32);
        }
        diff
      },
    }
  }
}

impl fmt::Debug for HuffTable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    if self.initialized {
      write!(f, "HuffTable {{ bits: {:?} huffval: {:?} }}", self.bits, &self.huffval[..])
    } else {
      write!(f, "HuffTable {{ uninitialized }}")
    }
  }
}
<commit_msg>Make the huffman decode cache denser and larger<commit_after>use std::fmt;
use crate::decoders::basics::*;

const DECODE_CACHE_BITS: u32 = 13;

pub struct HuffTable {
  // These two fields directly represent the contents of a JPEG DHT marker
  pub bits: [u32;17],
  pub huffval: [u32;256],

  // Represent the weird shifts that are needed for some NEF files
  pub shiftval: [u32;256],

  // Enable the workaround for 16 bit decodes in DNG that need to consume those
  // bits instead of the value being implied
  pub dng_bug: bool,

  // In CRW we only use the len code so the cache is not needed
  pub disable_cache: bool,

  // The remaining fields are computed from the above to allow more
  // efficient coding and decoding and thus private

  // The max number of bits in a huffman code and the table that converts those
  // bits into how many bits to consume and the decoded length and shift
  nbits: u32,
  hufftable: Vec<(u8,u8,u8)>,

  // A pregenerated table that goes straight to decoding a diff without first
  // finding a length, fetching bits, and sign extending them. The table is
  // sized by DECODE_CACHE_BITS and can have 99%+ hit rate with 13 bits
  decodecache: [Option<(u8,i16)>; 1<< DECODE_CACHE_BITS],

  initialized: bool,
}

struct MockPump {
  bits: u64,
  nbits: u32,
}

impl MockPump {
  pub fn empty() -> Self {
    MockPump {
      bits: 0,
      nbits: 0,
    }
  }

  pub fn set(&mut self, bits: u32, nbits: u32) {
    self.bits = (bits as u64) << 32;
    self.nbits = nbits + 32;
  }

  pub fn validbits(&self) -> i32 {
    self.nbits as i32 - 32
  }
}

impl BitPump for MockPump {
  fn peek_bits(&mut self, num: u32) -> u32 {
    (self.bits >> (self.nbits-num)) as u32
  }

  fn consume_bits(&mut self, num: u32) {
    self.nbits -= num;
    self.bits &= (1 << self.nbits) - 1;
  }
}

impl HuffTable {
  pub fn empty() -> HuffTable {
    HuffTable {
      bits: [0;17],
      huffval: [0;256],
      shiftval: [0;256],
      dng_bug: false,
      disable_cache: false,

      nbits: 0,
      hufftable: Vec::new(),
      decodecache: [None; 1 << DECODE_CACHE_BITS],
      initialized: false,
    }
  }

  pub fn new(bits: [u32;17], huffval: [u32;256], dng_bug: bool) -> Result<HuffTable,String> {
    let mut tbl = HuffTable {
      bits: bits,
      huffval: huffval,
      shiftval: [0;256],
      dng_bug: dng_bug,
      disable_cache: false,

      nbits: 0,
      hufftable: Vec::new(),
      decodecache: [None; 1 << DECODE_CACHE_BITS],
      initialized: false,
    };
    tbl.initialize()?;
    Ok(tbl)
  }

  pub fn initialize(&mut self) -> Result<(), String> {
    // Find out the max code length and allocate a table with that size
    self.nbits = 16;
    for i in 0..16 {
      if self.bits[16-i] != 0 {
        break;
      }
      self.nbits -= 1;
    }
    self.hufftable = vec![(0,0,0); 1 << self.nbits];

    // Fill in the table itself
    let mut h = 0;
    let mut pos = 0;
    for len in 0..self.nbits {
      for _ in 0..self.bits[len as usize + 1] {
        for _ in 0..(1 << (self.nbits-len-1)) {
          self.hufftable[h] = (len as u8 + 1, self.huffval[pos] as u8, self.shiftval[pos] as u8);
          h += 1;
        }
        pos += 1;
      }
    }

    // Create the decode cache by running the slow code over all the possible
    // values DECODE_CACHE_BITS wide
    if !self.disable_cache {
      let mut pump = MockPump::empty();
      let mut i = 0;
      loop {
        pump.set(i, DECODE_CACHE_BITS);
        let (bits, decode) = self.huff_decode_slow(&mut pump);
        if pump.validbits() >= 0 {
          self.decodecache[i as usize] = Some((bits, decode as i16));
        }
        i += 1;
        if i >= 1 << DECODE_CACHE_BITS {
          break;
        }
      }
    }

    self.initialized = true;
    Ok(())
  }

  pub fn huff_decode(&self, pump: &mut dyn BitPump) -> Result<i32,String> {
    let code = pump.peek_bits(DECODE_CACHE_BITS) as usize;
    if let Some((bits,decode)) = self.decodecache[code] {
      pump.consume_bits(bits as u32);
      Ok(decode as i32)
    } else {
      let decode = self.huff_decode_slow(pump);
      Ok(decode.1)
    }
  }

  pub fn huff_decode_slow(&self, pump: &mut dyn BitPump) -> (u8,i32) {
    let len = self.huff_len(pump);
    (len.0+len.1, self.huff_diff(pump, len))
  }

  pub fn huff_len(&self, pump: &mut dyn BitPump) -> (u8,u8,u8) {
    let code = pump.peek_bits(self.nbits) as usize;
    let (bits, len, shift) = self.hufftable[code];
    pump.consume_bits(bits as u32);
    (bits, len, shift)
  }

  pub fn huff_get_bits(&self, pump: &mut dyn BitPump) -> u32 {
    let code = pump.peek_bits(self.nbits) as usize;
    let (bits, len, _) = self.hufftable[code];
    pump.consume_bits(bits as u32);
    len as u32
  }

  pub fn huff_diff(&self, pump: &mut dyn BitPump, input: (u8,u8,u8)) -> i32 {
    let (_, len, shift) = input;

    match len {
      0 => 0,
      16 => {
        if self.dng_bug {
          pump.get_bits(16); // consume can fail because we haven't peeked yet
        }
        -32768
      },
      len => {
        // decode the difference and extend sign bit
        let fulllen: i32 = len as i32 + shift as i32;
        let shift: i32 = shift as i32;
        let bits = pump.get_bits(len as u32) as i32;
        let mut diff: i32 = ((bits << 1) + 1) << shift >> 1;
        if (diff & (1 << (fulllen - 1))) == 0 {
          diff -= (1 << fulllen) - ((shift == 0) as i32);
        }
        diff
      },
    }
  }
}

impl fmt::Debug for HuffTable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    if self.initialized {
      write!(f, "HuffTable {{ bits: {:?} huffval: {:?} }}", self.bits, &self.huffval[..])
    } else {
      write!(f, "HuffTable {{ uninitialized }}")
    }
  }
}
<|endoftext|>


<commit_before>// 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 address::Address;
use instruction::Instruction;
use petgraph::EdgeDirection;

/// When is this edge taken? Conditionally or unconditionally?
#[derive(Clone,Copy,Debug,Eq,PartialEq)]
pub enum EdgeType {
    /// This edge is when a conditional is taken.
    ConditionalTaken,
    /// This edge is when a conditional falls through to the next instruction.
    ConditionalFallthrough,
    /// This is edge is always taken.
    Unconditional,
}

/// A [basic block] is a sequence of instructions with no inward-bound
/// branches except to the entry point and no outward-bound branches
/// except at the exit.
///
/// [basic block]: https://en.wikipedia.org/wiki/Basic_block
#[derive(Debug)]
pub struct BasicBlock<'f> {
    /// The name of the basic block. Not all blocks have meaningful names.
    pub name: Option<String>,
    /// The address of the first instruction in the basic block.
    pub address: Address,
    /// The instructions within this basic block.
    pub instructions: Vec<&'f Box<Instruction>>,
}

impl<'f> BasicBlock<'f> {
    /// Construct a new `BasicBlock`.
    pub fn new(name: Option<&str>, address: Address) -> Self {
        BasicBlock {
            name: name.map(|s| s.to_owned()),
            address: address,
            instructions: vec![],
        }
    }
}

/// Information about an edge between 2 [basic blocks].
///
/// This represents a branch, jump or other form of control flow
/// transfer within the control flow graph.
///
/// [basic blocks]: struct.BasicBlock.html
#[derive(Debug)]
pub struct BasicBlockEdge {
    /// Is this edge taken [conditionally or unconditionally]?
    ///
    /// [conditionally or unconditionally]: enum.EdgeType.html
    pub edge_type: EdgeType,
    /// Is this an inbound or outbound edge?
    pub direction: EdgeDirection,
}
<commit_msg>Remove EdgeDirection usage from BasicBlockEdge.<commit_after>// 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 address::Address;
use instruction::Instruction;

/// When is this edge taken? Conditionally or unconditionally?
#[derive(Clone,Copy,Debug,Eq,PartialEq)]
pub enum EdgeType {
    /// This edge is when a conditional is taken.
    ConditionalTaken,
    /// This edge is when a conditional falls through to the next instruction.
    ConditionalFallthrough,
    /// This is edge is always taken.
    Unconditional,
}

/// A [basic block] is a sequence of instructions with no inward-bound
/// branches except to the entry point and no outward-bound branches
/// except at the exit.
///
/// [basic block]: https://en.wikipedia.org/wiki/Basic_block
#[derive(Debug)]
pub struct BasicBlock<'f> {
    /// The name of the basic block. Not all blocks have meaningful names.
    pub name: Option<String>,
    /// The address of the first instruction in the basic block.
    pub address: Address,
    /// The instructions within this basic block.
    pub instructions: Vec<&'f Box<Instruction>>,
}

impl<'f> BasicBlock<'f> {
    /// Construct a new `BasicBlock`.
    pub fn new(name: Option<&str>, address: Address) -> Self {
        BasicBlock {
            name: name.map(|s| s.to_owned()),
            address: address,
            instructions: vec![],
        }
    }
}

/// Information about an edge between 2 [basic blocks].
///
/// This represents a branch, jump or other form of control flow
/// transfer within the control flow graph.
///
/// [basic blocks]: struct.BasicBlock.html
#[derive(Debug)]
pub struct BasicBlockEdge {
    /// Is this edge taken [conditionally or unconditionally]?
    ///
    /// [conditionally or unconditionally]: enum.EdgeType.html
    pub edge_type: EdgeType,
}
<|endoftext|>