<commit_before>//! The `message` module provides all functionality to deal with messages.

use std::collections::HashMap;
use serde::{Serialize, Deserialize};
use serde_json::Value;
use maplit::*;
use super::*;
use super::body_from_json;

/// Struct that defines a message.
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Eq)]
pub struct Message {
    /// Description of this message interaction. This needs to be unique in the pact file.
    pub description: String,
    /// Optional provider state for the interaction.
    /// See https://docs.pact.io/getting_started/provider_states for more info on provider states.
    pub provider_state: Option<String>,
    /// The contents of the message
    pub contents: OptionalBody,
    /// Metadata associated with this message.
    pub metadata: HashMap<String, String>,
    /// Matching rules
    pub matching_rules: matchingrules::MatchingRules
}

impl Message {
    /// Returns a default message
    pub fn default() -> Message {
        Message {
            description: s!("message"),
            provider_state: None,
            contents: OptionalBody::Missing,
            metadata: hashmap!{},
            matching_rules: matchingrules::MatchingRules::default()
        }
    }

    /// Constructs a `Message` from the `Json` struct.
    pub fn from_json(index: usize, json: &Value, spec_version: &PactSpecification) -> Result<Message, String> {
        match spec_version {
            &PactSpecification::V3 => {
                let description = match json.get("description") {
                    Some(v) => match *v {
                        Value::String(ref s) => s.clone(),
                        _ => v.to_string()
                    },
                    None => format!("Message {}", index)
                };
                let provider_state = match json.get("providerState") {
                    Some(v) => match *v {
                        Value::String(ref s) => if s.is_empty() {
                            None
                        } else {
                            Some(s.clone())
                        },
                        Value::Null => None,
                        _ => Some(v.to_string())
                    },
                    None => None
                };
                let metadata = match json.get("metadata") {
                    Some(&Value::Object(ref v)) => v.iter().map(|(k, v)| {
                        (k.clone(), match v {
                            &Value::String(ref s) => s.clone(),
                            _ => v.to_string()
                        })
                    }).collect(),
                    _ => hashmap!{}
                };
                Ok(Message {
                     description: description,
                     provider_state: provider_state,
                     contents: body_from_json(json, "contents", &None),
                     matching_rules: matchingrules::matchers_from_json(json, &None),
                     metadata: metadata
                })
            },
            _ => Err(s!("Messages require Pact Specification version 3 or later"))
        }
    }

    /// Determins the content type of the message
    pub fn mimetype(&self) -> String {
        match self.metadata.get("contentType") {
            Some(v) => v.clone(),
            None => s!("application/json")
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use expectest::prelude::*;
    use expectest::expect;
    use serde_json;

    #[test]
    fn loading_message_from_json() {
        let message_json = r#"{
            "description": "String",
            "providerState": "provider state",
            "matchingRules": {}
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.description).to(be_equal_to("String"));
        expect!(message.provider_state).to(be_some().value("provider state"));
        expect!(message.matching_rules.rules.iter()).to(be_empty());
    }

    #[test]
    fn defaults_to_number_if_no_description() {
        let message_json = r#"{
            "providerState": "provider state"
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.description).to(be_equal_to("Message 0"));
    }

    #[test]
    fn defaults_to_none_if_no_provider_state() {
        let message_json = r#"{
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.provider_state).to(be_none());
        expect!(message.matching_rules.rules.iter()).to(be_empty());
    }

    #[test]
    fn defaults_to_none_if_provider_state_null() {
        let message_json = r#"{
            "providerState": null
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.provider_state).to(be_none());
    }

    #[test]
    fn returns_an_error_if_the_spec_version_is_less_than_three() {
        let message_json = r#"{
            "description": "String",
            "providerState": "provider state"
        }"#;
        let result = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V1);
        expect!(result).to(be_err());
    }

    #[test]
    fn message_with_json_body() {
        let message_json = r#"{
            "contents": {
                "hello": "world"
            },
            "metadata": {
                "contentType": "application/json"
            }
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.contents.str_value()).to(be_equal_to("{\"hello\":\"world\"}"));
    }

    #[test]
    fn message_with_non_json_body() {
        let message_json = r#"{
            "contents": "hello world",
            "metadata": {
                "contentType": "text/plain"
            }
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.contents.str_value()).to(be_equal_to("hello world"));
    }

    #[test]
    fn message_with_empty_body() {
        let message_json = r#"{
            "contents": "",
            "metadata": {
                "contentType": "text/plain"
            }
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.contents.str_value()).to(be_equal_to(""));
    }

    #[test]
    fn message_with_missing_body() {
        let message_json = r#"{
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.contents).to(be_equal_to(OptionalBody::Missing));
    }

    #[test]
    fn message_with_null_body() {
        let message_json = r#"{
            "contents": null,
            "metadata": {
                "contentType": "text/plain"
            }
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.contents).to(be_equal_to(OptionalBody::Null));
    }

    #[test]
    fn message_mimetype_is_based_on_the_metadata() {
        let message = Message {
            metadata: hashmap!{ s!("contentType") => s!("text/plain") },
            .. Message::default()
        };
        expect!(message.mimetype()).to(be_equal_to("text/plain"));
    }

    #[test]
    fn message_mimetype_defaults_to_json() {
        let message = Message::default();
        expect!(message.mimetype()).to(be_equal_to("application/json"));
    }
}
<commit_msg>Made `Message` understand `providerStates`.<commit_after>//! The `message` module provides all functionality to deal with messages.

use std::collections::HashMap;
use serde::{Serialize, Deserialize};
use serde_json::Value;
use maplit::*;
use crate::models::provider_states::ProviderState;
use super::*;
use super::body_from_json;

/// Struct that defines a message.
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Eq)]
pub struct Message {
    /// Description of this message interaction. This needs to be unique in the pact file.
    pub description: String,
    /// Optional provider state for the interaction.
    /// See https://docs.pact.io/getting_started/provider_states for more info on provider states.
    pub provider_states: Vec<ProviderState>,
    /// The contents of the message
    pub contents: OptionalBody,
    /// Metadata associated with this message.
    pub metadata: HashMap<String, String>,
    /// Matching rules
    pub matching_rules: matchingrules::MatchingRules
}

impl Message {
    /// Returns a default message
    pub fn default() -> Message {
        Message {
            description: s!("message"),
            provider_states: vec![],
            contents: OptionalBody::Missing,
            metadata: hashmap!{},
            matching_rules: matchingrules::MatchingRules::default()
        }
    }

    /// Constructs a `Message` from the `Json` struct.
    pub fn from_json(index: usize, json: &Value, spec_version: &PactSpecification) -> Result<Message, String> {
        match spec_version {
            &PactSpecification::V3 => {
                let description = match json.get("description") {
                    Some(v) => match *v {
                        Value::String(ref s) => s.clone(),
                        _ => v.to_string()
                    },
                    None => format!("Message {}", index)
                };
                let provider_states = ProviderState::from_json(json);
                let metadata = match json.get("metadata") {
                    Some(&Value::Object(ref v)) => v.iter().map(|(k, v)| {
                        (k.clone(), match v {
                            &Value::String(ref s) => s.clone(),
                            _ => v.to_string()
                        })
                    }).collect(),
                    _ => hashmap!{}
                };
                Ok(Message {
                     description,
                     provider_states,
                     contents: body_from_json(json, "contents", &None),
                     matching_rules: matchingrules::matchers_from_json(json, &None),
                     metadata
                })
            },
            _ => Err(s!("Messages require Pact Specification version 3 or later"))
        }
    }

    /// Determins the content type of the message
    pub fn mimetype(&self) -> String {
        match self.metadata.get("contentType") {
            Some(v) => v.clone(),
            None => s!("application/json")
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use expectest::prelude::*;
    use expectest::expect;
    use serde_json;

    #[test]
    fn loading_message_from_json() {
        let message_json = r#"{
            "description": "String",
            "providerState": "provider state",
            "matchingRules": {}
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.description).to(be_equal_to("String"));
        expect!(message.provider_state).to(be_some().value("provider state"));
        expect!(message.matching_rules.rules.iter()).to(be_empty());
    }

    #[test]
    fn defaults_to_number_if_no_description() {
        let message_json = r#"{
            "providerState": "provider state"
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.description).to(be_equal_to("Message 0"));
    }

    #[test]
    fn defaults_to_none_if_no_provider_state() {
        let message_json = r#"{
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.provider_state).to(be_none());
        expect!(message.matching_rules.rules.iter()).to(be_empty());
    }

    #[test]
    fn defaults_to_none_if_provider_state_null() {
        let message_json = r#"{
            "providerState": null
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.provider_state).to(be_none());
    }

    #[test]
    fn returns_an_error_if_the_spec_version_is_less_than_three() {
        let message_json = r#"{
            "description": "String",
            "providerState": "provider state"
        }"#;
        let result = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V1);
        expect!(result).to(be_err());
    }

    #[test]
    fn message_with_json_body() {
        let message_json = r#"{
            "contents": {
                "hello": "world"
            },
            "metadata": {
                "contentType": "application/json"
            }
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.contents.str_value()).to(be_equal_to("{\"hello\":\"world\"}"));
    }

    #[test]
    fn message_with_non_json_body() {
        let message_json = r#"{
            "contents": "hello world",
            "metadata": {
                "contentType": "text/plain"
            }
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.contents.str_value()).to(be_equal_to("hello world"));
    }

    #[test]
    fn message_with_empty_body() {
        let message_json = r#"{
            "contents": "",
            "metadata": {
                "contentType": "text/plain"
            }
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.contents.str_value()).to(be_equal_to(""));
    }

    #[test]
    fn message_with_missing_body() {
        let message_json = r#"{
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.contents).to(be_equal_to(OptionalBody::Missing));
    }

    #[test]
    fn message_with_null_body() {
        let message_json = r#"{
            "contents": null,
            "metadata": {
                "contentType": "text/plain"
            }
        }"#;
        let message = Message::from_json(0, &serde_json::from_str(message_json).unwrap(), &PactSpecification::V3).unwrap();
        expect!(message.contents).to(be_equal_to(OptionalBody::Null));
    }

    #[test]
    fn message_mimetype_is_based_on_the_metadata() {
        let message = Message {
            metadata: hashmap!{ s!("contentType") => s!("text/plain") },
            .. Message::default()
        };
        expect!(message.mimetype()).to(be_equal_to("text/plain"));
    }

    #[test]
    fn message_mimetype_defaults_to_json() {
        let message = Message::default();
        expect!(message.mimetype()).to(be_equal_to("application/json"));
    }
}
<|endoftext|>


<commit_before>use autograd::Function;
use tensor::Tensor;
use std::ops::{AddAssign, Index};
use ::*;

pub type VarList<T> = Vec<Variable<T>>;

pub enum SavedVarKind {
    FloatVariable(SavedVariable<f32>),
    LongVariable(SavedVariable<i64>),
}
pub enum VarKind {
    FloatVariable(Variable<f32>),
    LongVariable(Variable<i64>),
}

impl Clone for VarKind {
    fn clone(&self) -> Self {
        unimplemented!()
    }
}

pub struct VariableImpl<T> {
    data: Tensor<T>,
    // AKA Creator
    grad_fn: OptRcMut<Function>,
    grad: OptRcMut<Variable<T>>,
    // version_counter etc ...
    volatile: bool,
    requires_grad: bool,
}

impl<T> VariableImpl<T> {
    fn new(data: Tensor<T>) -> Self {
        VariableImpl {
            data: data,
            grad_fn: None,
            grad: None,
            // XXX
            volatile: false,
            requires_grad: false,
        }
    }
    fn new_args(data: Tensor<T>, args: VariableArgs) -> Self {

        let grad_fn = match args.creator {
            Some(creator) => Some(RcMutNew(creator)),
            _ => None,
        };

        VariableImpl {
            data: data,
            grad_fn: grad_fn,
            grad: None,
            volatile: args.volatile,
            requires_grad: args.requires_grad,
        }
    }
}

pub struct Variable<T> {
    value: RcMut<VariableImpl<T>>,
}

impl<T> Clone for Variable<T> {
    fn clone(&self) -> Self {
        Variable { value: self.value.clone() }
    }
}

pub struct SavedVariable<T> {
    data: Box<Tensor<T>>,
    grad_fn: OptRcMut<Function>,
    grad: OptRcMut<Variable<T>>,
	// version_counter etc ...
}

#[derive(Default, Clone)]
pub struct BackwardArgs {}

pub struct VariableArgs {
    pub creator: Option<Function>,
    pub volatile: bool,
    pub requires_grad: bool,
}

impl Default for VariableArgs {
    fn default() -> Self {
        VariableArgs {
            creator: None,
            volatile: false,
            requires_grad: true,
        }
    }
}

impl<T> Variable<T> {
    pub fn new(data: Tensor<T>) -> Self {
        Variable::new_args(data, VariableArgs::default())
    }
    pub fn new_args(data: Tensor<T>, args: VariableArgs) -> Self {
        Variable { value: RcMutNew(VariableImpl::new(data)) }
    }
    pub fn apply(&mut self, callback: fn(&mut Tensor<T>)) {
        let mut v = self.value.borrow_mut();
        callback(&mut v.data);
    }
    // XXX FIXME
    pub fn data(&mut self) -> RefMut<Tensor<T>> {
        RefMut::map(self.value.borrow_mut(), |v| &mut v.data)
    }
    pub fn view(&self, dims: &[i32]) -> Self {
        unimplemented!()
    }
    // Computes the gradient of current variable w.r.t. graph leaves
    pub fn backward(&mut self, args: &BackwardArgs) {
        unimplemented!()
    }
    // Detach from graph
    pub fn detach_(&mut self) {
        unimplemented!()
    }
    // return a new variable detached from graph
    pub fn detach(&self) -> Variable<T> {
        unimplemented!()
    }
}

impl<T> Default for Variable<T> {
    fn default() -> Self {
        let v = VariableImpl {
            data: Tensor::new(),
            grad_fn: None,
            grad: None,
            // XXX
            volatile: false,
            requires_grad: false,
        };
        Variable { value: RcMutNew(v) }
    }
}

impl<T: Copy> Index<isize> for Variable<T> {
    type Output = T;

    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}

impl AddAssign<Variable<f32>> for f32 {
    fn add_assign(&mut self, rhs: Variable<f32>) {
        *self = *self + rhs[0]
    }
}
<commit_msg>flesh out a bit further<commit_after>use autograd::{Function, ExecutionEngine};
use tensor::Tensor;
use std::ops::{AddAssign, Index};
use tensor::*;
use ::*;

pub type VarList<T> = Vec<Variable<T>>;

pub enum SavedVarKind {
    FloatVariable(SavedVariable<f32>),
    LongVariable(SavedVariable<i64>),
}
pub enum VarKind {
    FloatVariable(Variable<f32>),
    LongVariable(Variable<i64>),
}

impl Clone for VarKind {
    fn clone(&self) -> Self {
        unimplemented!()
    }
}

pub struct VariableImpl<T> {
    // AKA Creator
    grad_fn: OptRcMut<Function>,
    grad: OptRcMut<Variable<T>>,
    // version_counter etc ...
    dirty: bool,
    volatile: bool,
    requires_grad: bool,
}

impl<T> VariableImpl<T> {
    fn new(args: VariableArgs) -> Self {

        let grad_fn = match args.creator {
            Some(creator) => Some(RcMutNew(creator)),
            _ => None,
        };

        VariableImpl {
            grad_fn: grad_fn,
            grad: None,
            dirty: false,
            volatile: args.volatile,
            requires_grad: args.requires_grad,
        }
    }
}

pub struct Variable<T> {
    pub data: Tensor<T>,
    value: RcMut<VariableImpl<T>>,
}

impl<T> Clone for Variable<T> {
    fn clone(&self) -> Self {
        Variable {
            data: self.data.clone(),
            value: self.value.clone(),
        }
    }
}

pub struct SavedVariable<T> {
    data: Box<Tensor<T>>,
    grad_fn: OptRcMut<Function>,
    grad: OptRcMut<Variable<T>>,
	// version_counter etc ...
}

#[derive(Default, Clone)]
pub struct BackwardArgs {}

pub struct VariableArgs {
    pub creator: Option<Function>,
    pub volatile: bool,
    pub requires_grad: bool,
}

impl Default for VariableArgs {
    fn default() -> Self {
        VariableArgs {
            creator: None,
            volatile: false,
            requires_grad: true,
        }
    }
}

impl<T> Variable<T> {
    pub fn new(data: Tensor<T>) -> Self {
        Variable::new_args(data, VariableArgs::default())
    }
    fn inner(&mut self) -> RefMut<VariableImpl<T>> {
        self.value.borrow_mut()
    }
    pub fn is_volatile(&self) -> bool {
        self.inner().volatile
    }
    pub fn new_args(data: Tensor<T>, args: VariableArgs) -> Self {
        Variable {
            data: data,
            value: RcMutNew(VariableImpl::new(args)),
        }
    }
    pub fn apply(&mut self, callback: fn(&mut Tensor<T>)) {
        callback(&mut self.data);
    }
    pub fn mark_dirty(&mut self) {
        self.value.borrow_mut().dirty = true;
    }
    pub fn view(&self, dims: &[i32]) -> Self {
        unimplemented!()
    }
    // Computes the gradient of current variable w.r.t. graph leaves
    pub fn backward_args(&mut self, gradient_: Option<&mut Tensor<T>>, retain_variables: bool) {
        let mut store;
        if self.inner().volatile {
            panic!("calling backward on a volatile variable")
        }
        if !self.inner().requires_grad {
            panic!("calling backward on a variable that doesn't require a gradient")
        }
        let mut gradient = match gradient_ {
            Some(gradient) => gradient,
            None => {
                store = self.data.new_(1);
                &mut store
            }
        };
        ExecutionEngine::run_backward(self, &mut gradient, retain_variables)
    }
    pub fn backward(&mut self) {
        self.backward_args(None, false)
    }
    // Detach from graph
    pub fn detach_(&mut self) {
        unimplemented!()
    }
    // return a new variable detached from graph
    pub fn detach(&self) -> Variable<T> {
        unimplemented!()
    }
}

impl<T> Default for Variable<T> {
    fn default() -> Self {
        unimplemented!()
    }
}

impl<T: Copy> Index<isize> for Variable<T> {
    type Output = T;

    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}

impl AddAssign<Variable<f32>> for f32 {
    fn add_assign(&mut self, rhs: Variable<f32>) {
        *self = *self + rhs[0]
    }
}
<|endoftext|>


<commit_before>#![cfg(not(tarpaulin))]

#[test]
fn example_tests() {
    let t = trycmd::TestCases::new();
    let features = [
        #[cfg(feature = "std")]
        "std",
        #[cfg(feature = "derive")]
        "derive",
        #[cfg(feature = "cargo")]
        "cargo",
        #[cfg(feature = "color")]
        "color",
        #[cfg(feature = "env")]
        "env",
        #[cfg(feature = "suggestions")]
        "suggestions",
        #[cfg(feature = "unicode")]
        "unicode",
        #[cfg(feature = "wrap_help")]
        "wrap_help",
        #[cfg(feature = "unstable-replace")]
        "unstable-replace",
        #[cfg(feature = "unstable-multicall")]
        "unstable-multicall",
        #[cfg(feature = "unstable-grouped")]
        "unstable-grouped",
    ]
    .join(" ");
    t.register_bins(trycmd::cargo::compile_examples(["--features", &features]).unwrap());
    t.case("examples/**/*.md");
    #[cfg(not(feature = "unstable-multicall"))]
    {
        t.skip("examples/24a_multicall_busybox.md");
        t.skip("examples/24b_multicall_hostname.md");
    }
}
<commit_msg>chore: Remove dead code<commit_after>#![cfg(not(tarpaulin))]

#[test]
fn example_tests() {
    let t = trycmd::TestCases::new();
    let features = [
        #[cfg(feature = "std")]
        "std",
        #[cfg(feature = "derive")]
        "derive",
        #[cfg(feature = "cargo")]
        "cargo",
        #[cfg(feature = "color")]
        "color",
        #[cfg(feature = "env")]
        "env",
        #[cfg(feature = "suggestions")]
        "suggestions",
        #[cfg(feature = "unicode")]
        "unicode",
        #[cfg(feature = "wrap_help")]
        "wrap_help",
        #[cfg(feature = "unstable-replace")]
        "unstable-replace",
        #[cfg(feature = "unstable-multicall")]
        "unstable-multicall",
        #[cfg(feature = "unstable-grouped")]
        "unstable-grouped",
    ]
    .join(" ");
    t.register_bins(trycmd::cargo::compile_examples(["--features", &features]).unwrap());
    t.case("examples/**/*.md");
}
<|endoftext|>


<commit_before>use crate::types::{get_value_from_input_event, Msg};
use web_sys::HtmlInputElement;
use yew::prelude::*;

pub struct CommandLine {
    valid_entries: Vec<Entry>,
    // Among valid (filtered) entries.
    selected_command_index: usize,
    value: String,
}

#[derive(PartialEq, Clone, Properties, Debug)]
pub struct CommandLineProperties {
    pub value: String,
    pub entries: Vec<Entry>,
    pub enabled: bool,
    pub input_node_ref: NodeRef,
    #[prop_or_default]
    pub oninput: Callback<String>,
    #[prop_or_default]
    pub onselect: Callback<Msg>,
    #[prop_or_default]
    pub onenter: Callback<()>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Entry {
    pub label: String,
    pub description: String,
    pub action: Msg,
    pub valid_classes: Vec<String>,
}

#[derive(Debug)]
pub enum CommandLineMsg {
    Click,
    Key(KeyboardEvent),
    Input(String),
}

impl Component for CommandLine {
    type Message = CommandLineMsg;
    type Properties = CommandLineProperties;

    fn create(ctx: &Context<Self>) -> Self {
        Self {
            valid_entries: ctx.props().entries.clone(),
            selected_command_index: 0,
            value: ctx.props().value.clone(),
        }
    }

    fn changed(&mut self, ctx: &Context<Self>) -> bool {
        self.valid_entries = ctx.props().entries.clone();
        self.value = ctx.props().value.clone();
        true
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        let props = ctx.props();
        let value = &self.value;
        let enabled = props.enabled;
        let valid_entries = &self.valid_entries;
        let selected_entry = valid_entries.get(self.selected_command_index);
        let selected_entry_suffix = selected_entry
            .cloned()
            .map(|v| v.label.clone())
            .unwrap_or_default()
            .strip_prefix(value)
            .map(|v| v.to_string())
            .unwrap_or_default();
        let selected = true;
        // TODO: Fuzzy search.
        let entries: Vec<_> = if selected {
            valid_entries
                .iter()
                .enumerate()
                .map(|(i, v)| {
                    let value_string = v.label.clone();
                    let value_suffix = value_string.strip_prefix(value).unwrap_or_default();

                    // let node = v.to_node();
                    let action = v.action.clone();
                    let onselect = props.onselect.clone();
                    let onclick = Callback::from(move |_e: MouseEvent| {
                        onselect.emit(action.clone());
                    });
                    let mut classes_item = vec!["block", "border"];
                    if i == self.selected_command_index {
                        classes_item.push("selected");
                    }
                    // Avoid re-selecting the node, we want to move to next.
                    html! {

                          { value.clone() }
                          { value_suffix }

                    }
                })
                .collect()
        } else {
            vec![]
        };
        let classes_dropdown = vec!["absolute", "z-10", "bg-white"];
        // let id = view::command_input_id(&path);
        let style = if value.len() > 0 {
            format!("width: {}ch;", value.len())
        } else {
            "width: 0.1ch;".to_string()
        };
        let rows = value.split('\n').count();
        // XXX: Chrome inspector CSS color editor.
        let placeholder = "";
        let placeholder = if placeholder.is_empty() {
            None
        } else {
            Some(html! {

{ placeholder }

            })
        };
        let suffix = if selected {
            selected_entry_suffix
        } else {
            "".to_string()
        };
        let mut class = vec![
            "inline-flex",
            "w-full",
            "bg-transparent",
            "resize-none",
            "overflow-hidden",
        ];
        // let errors = vec![];
        // if !errors.is_empty() {
        //     class.push("error");
        // }

        // let editing = if model.mode == crate::types::Mode::Edit {
        let dropdown = if enabled && selected {
            html! {

                    { for entries }

            }
        } else {
            html! {}
        };
        let suffix = if enabled && selected {
            html! {
                { suffix }
            }
        } else {
            html! {}
        };
        let mut classes = if enabled && selected {
            match selected_entry {
                Some(entry) => entry.valid_classes.clone().join(" "),
                None => "".to_string(),
            }
        } else {
            "".to_string()
        };
        classes.push_str(" flex");

        let oninput = props.oninput.clone();
        let oninput = ctx.link().callback(move |e: InputEvent| {
            let v = get_value_from_input_event(e);
            oninput.emit(v.clone());
            CommandLineMsg::Input(v)
        });

        let onclick = ctx.link().callback(|_| CommandLineMsg::Click);
        let onfocus = ctx.link().callback(|_| CommandLineMsg::Click);
        let onkeydown = ctx
            .link()
            .callback(move |e: KeyboardEvent| CommandLineMsg::Key(e));

        html! {

                { for placeholder }

                        <textarea
                        rows={ format!("{}", rows) }
                        ref={ ctx.props().input_node_ref.clone() }
                        //   id={ id }
                        class={ class }
                        type="text"
                        oninput={ oninput }
                        onkeydown={ onkeydown }
                        //   onfocus={ onfocus }
                        value={ value.to_string() }
                        style={ style }
                        //   disabled={ model.mode != crate::types::Mode::Edit }
                        autocomplete="off"
                        >
                        </textarea>
                        { suffix }

                    { dropdown }

        }
    }

    fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
        match msg {
            CommandLineMsg::Click => {
                let input_node = ctx.props().input_node_ref.clone();
                input_node
                    .cast::<HtmlInputElement>()
                    .unwrap()
                    .focus()
                    .unwrap();
                true
            }
            CommandLineMsg::Input(value) => {
                self.value = value.clone();
                self.valid_entries = ctx
                    .props()
                    .entries
                    .clone()
                    .into_iter()
                    .filter(|v| v.label.starts_with(&value))
                    .collect();
                true
            }
            CommandLineMsg::Key(e) => {
                let props = ctx.props();
                let entries = &self.valid_entries;
                let selected_command_index = self.selected_command_index;
                if e.shift_key() {
                    return false;
                }
                match e.key().as_ref() {
                    "ArrowUp" => {
                        if entries.len() > 0 {
                            self.selected_command_index = if selected_command_index > 0 {
                                selected_command_index - 1
                            } else {
                                entries.len() - 1
                            }
                        }
                    }
                    "ArrowDown" => {
                        if entries.len() > 0 {
                            self.selected_command_index =
                                if selected_command_index < entries.len() - 1 {
                                    selected_command_index + 1
                                } else {
                                    0
                                }
                        }
                    }
                    "Enter" => {
                        e.prevent_default();
                        let selected_entry = entries.get(selected_command_index).cloned();
                        if let Some(selected_entry) = selected_entry {
                            let action = selected_entry.action.clone();
                            props.onselect.emit(action);
                        } else {
                            props.onenter.emit(());
                        }
                    }
                    _ => {}
                };
                true
            }
        }
    }
}
<commit_msg>Update valid entries<commit_after>use crate::types::{get_value_from_input_event, Msg};
use web_sys::HtmlInputElement;
use yew::prelude::*;

pub struct CommandLine {
    all_entries: Vec<Entry>,
    valid_entries: Vec<Entry>,
    // Among valid (filtered) entries.
    selected_command_index: usize,
    value: String,
}

#[derive(PartialEq, Clone, Properties, Debug)]
pub struct CommandLineProperties {
    pub value: String,
    pub entries: Vec<Entry>,
    pub enabled: bool,
    pub input_node_ref: NodeRef,
    #[prop_or_default]
    pub oninput: Callback<String>,
    #[prop_or_default]
    pub onselect: Callback<Msg>,
    #[prop_or_default]
    pub onenter: Callback<()>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Entry {
    pub label: String,
    pub description: String,
    pub action: Msg,
    pub valid_classes: Vec<String>,
}

#[derive(Debug)]
pub enum CommandLineMsg {
    Click,
    Key(KeyboardEvent),
    Input(String),
}

impl Component for CommandLine {
    type Message = CommandLineMsg;
    type Properties = CommandLineProperties;

    fn create(ctx: &Context<Self>) -> Self {
        Self {
            all_entries: ctx.props().entries.clone(),
            valid_entries: vec![],
            selected_command_index: 0,
            value: ctx.props().value.clone(),
        }
    }

    fn changed(&mut self, ctx: &Context<Self>) -> bool {
        self.all_entries = ctx.props().entries.clone();
        self.value = ctx.props().value.clone();
        self.update_valid_entries();
        true
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        let props = ctx.props();
        let value = &self.value;
        let enabled = props.enabled;
        let valid_entries = &self.valid_entries;
        let selected_entry = valid_entries.get(self.selected_command_index);
        let selected_entry_suffix = selected_entry
            .cloned()
            .map(|v| v.label.clone())
            .unwrap_or_default()
            .strip_prefix(value)
            .map(|v| v.to_string())
            .unwrap_or_default();
        let selected = true;
        // TODO: Fuzzy search.
        let entries: Vec<_> = if selected {
            valid_entries
                .iter()
                .enumerate()
                .map(|(i, v)| {
                    let value_string = v.label.clone();
                    let value_suffix = value_string.strip_prefix(value).unwrap_or_default();

                    // let node = v.to_node();
                    let action = v.action.clone();
                    let onselect = props.onselect.clone();
                    let onclick = Callback::from(move |_e: MouseEvent| {
                        onselect.emit(action.clone());
                    });
                    let mut classes_item = vec!["block", "border"];
                    if i == self.selected_command_index {
                        classes_item.push("selected");
                    }
                    // Avoid re-selecting the node, we want to move to next.
                    html! {

                          { value.clone() }
                          { value_suffix }

                    }
                })
                .collect()
        } else {
            vec![]
        };
        let classes_dropdown = vec!["absolute", "z-10", "bg-white"];
        // let id = view::command_input_id(&path);
        let style = if value.len() > 0 {
            format!("width: {}ch;", value.len())
        } else {
            "width: 0.1ch;".to_string()
        };
        let rows = value.split('\n').count();
        // XXX: Chrome inspector CSS color editor.
        let placeholder = "";
        let placeholder = if placeholder.is_empty() {
            None
        } else {
            Some(html! {

{ placeholder }

            })
        };
        let suffix = if selected {
            selected_entry_suffix
        } else {
            "".to_string()
        };
        let mut class = vec![
            "inline-flex",
            "w-full",
            "bg-transparent",
            "resize-none",
            "overflow-hidden",
        ];
        // let errors = vec![];
        // if !errors.is_empty() {
        //     class.push("error");
        // }

        // let editing = if model.mode == crate::types::Mode::Edit {
        let dropdown = if enabled && selected {
            html! {

                    { for entries }

            }
        } else {
            html! {}
        };
        let suffix = if enabled && selected {
            html! {
                { suffix }
            }
        } else {
            html! {}
        };
        let mut classes = if enabled && selected {
            match selected_entry {
                Some(entry) => entry.valid_classes.clone().join(" "),
                None => "".to_string(),
            }
        } else {
            "".to_string()
        };
        classes.push_str(" flex");

        let oninput = props.oninput.clone();
        let oninput = ctx.link().callback(move |e: InputEvent| {
            let v = get_value_from_input_event(e);
            oninput.emit(v.clone());
            CommandLineMsg::Input(v)
        });

        let onclick = ctx.link().callback(|_| CommandLineMsg::Click);
        let onfocus = ctx.link().callback(|_| CommandLineMsg::Click);
        let onkeydown = ctx
            .link()
            .callback(move |e: KeyboardEvent| CommandLineMsg::Key(e));

        html! {

                { for placeholder }

                        <textarea
                        rows={ format!("{}", rows) }
                        ref={ ctx.props().input_node_ref.clone() }
                        //   id={ id }
                        class={ class }
                        type="text"
                        oninput={ oninput }
                        onkeydown={ onkeydown }
                        //   onfocus={ onfocus }
                        value={ value.to_string() }
                        style={ style }
                        //   disabled={ model.mode != crate::types::Mode::Edit }
                        autocomplete="off"
                        >
                        </textarea>
                        { suffix }

                    { dropdown }

        }
    }

    fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
        match msg {
            CommandLineMsg::Click => {
                let input_node = ctx.props().input_node_ref.clone();
                input_node
                    .cast::<HtmlInputElement>()
                    .unwrap()
                    .focus()
                    .unwrap();
                true
            }
            CommandLineMsg::Input(value) => {
                self.value = value.clone();
                self.update_valid_entries();
                true
            }
            CommandLineMsg::Key(e) => {
                let props = ctx.props();
                let entries = &self.valid_entries;
                let selected_command_index = self.selected_command_index;
                if e.shift_key() {
                    return false;
                }
                match e.key().as_ref() {
                    "ArrowUp" => {
                        if entries.len() > 0 {
                            self.selected_command_index = if selected_command_index > 0 {
                                selected_command_index - 1
                            } else {
                                entries.len() - 1
                            }
                        }
                    }
                    "ArrowDown" => {
                        if entries.len() > 0 {
                            self.selected_command_index =
                                if selected_command_index < entries.len() - 1 {
                                    selected_command_index + 1
                                } else {
                                    0
                                }
                        }
                    }
                    "Enter" => {
                        e.prevent_default();
                        let selected_entry = entries.get(selected_command_index).cloned();
                        if let Some(selected_entry) = selected_entry {
                            let action = selected_entry.action.clone();
                            props.onselect.emit(action);
                        } else {
                            props.onenter.emit(());
                        }
                    }
                    _ => {}
                };
                true
            }
        }
    }
}

impl CommandLine {
    fn update_valid_entries(&mut self) {
        self.valid_entries = ctx
            .props()
            .entries
            .clone()
            .into_iter()
            .filter(|v| v.label.starts_with(&self.value))
            .collect();
    }
}
<|endoftext|>


<commit_before>fn main() {
    println("Hello, world.");
}
<commit_msg>Update code sample for chapter 3.<commit_after>fn main() {
    println!("Hello, world.");
}
<|endoftext|>


<commit_before>use sdl2::render::{Renderer, BlendMode, Texture};
use sdl2_image::{LoadTexture, INIT_PNG, INIT_JPG, init as image_init};
use sdl2_ttf::{Sdl2TtfContext,init as ttf_init};
use std::path::Path;
use ::display::font::*;

pub struct Displayer<'a> {
    pub fonts: FontList,
    pub renderer: Renderer<'a>,
    #[allow(dead_code)]
    ttf_context: Sdl2TtfContext,
    pub lyrics_logo: Option<Texture>
}

impl<'a> Displayer<'a> {
    pub fn new(mut renderer: Renderer<'a>)
               -> Result<Displayer<'a>, ()> {
        renderer.set_blend_mode(BlendMode::Blend);
        let ttf_context = ttf_init().unwrap();
        let font_list = FontList::new(&ttf_context).unwrap();
        let _image_context = image_init(INIT_PNG | INIT_JPG).unwrap();
        // we dont care if imag econtext dies, we only load images once (for now)
        let lyrics_logo = renderer.load_texture(Path::new("logo_toyunda.png")).ok();
        let displayer = Displayer {
            fonts: font_list,
            ttf_context: ttf_context,
            renderer: renderer,
            lyrics_logo:lyrics_logo
        };
        Ok(displayer)
    }

    pub fn copy_lyrics_logo(&mut self,rect: ::sdl2::rect::Rect) {
        match self.lyrics_logo {
            Some(ref texture) => {
                self.renderer.copy(texture,None,Some(rect));
            },
            None => {}
        };
    }

    // TODO use this somewhere ?
    #[allow(dead_code)]
    pub fn fatal_error_message(&self,title:&str,info:&str) {
        use ::sdl2::messagebox::ShowMessageError ;
        let res = ::sdl2::messagebox::show_simple_message_box(::sdl2::messagebox::MESSAGEBOX_ERROR,
                                                              title,
                                                              info,
                                                              self.sdl_renderer().window());
        match res {
            Ok(_) => {},
            Err(ShowMessageError::SdlError(string)) => {
                error!("Unexpected SDL_ERROR {} when creating MessageBox",string);
            }
            Err(_) => {error!("Unexpected Error when creating MessageBox")}
        }
    }

    // width and height must be between 0 and 1
    pub fn sub_screen_dims(&self,
                           width: Option<f32>,
                           height: Option<f32>)
                           -> (Option<u32>, Option<u32>) {
        let dims: (u32, u32) = self.renderer.window().unwrap().size();
        (width.and_then(|width| Some((width * (dims.0 as f32)) as u32)),
         height.and_then(|height| Some((height * (dims.1 as f32)) as u32)))
    }

    pub fn render(&mut self) {
        self.renderer.window().unwrap().gl_swap_window();
    }

    #[inline]
    pub fn sdl_renderer_mut(&mut self) -> &mut Renderer<'a> {
        &mut self.renderer
    }

    #[inline]
    pub fn sdl_renderer(&self) -> &Renderer<'a> {
        &self.renderer
    }
}
<commit_msg>logo_toyunda.png is taken from current_exe dir<commit_after>use sdl2::render::{Renderer, BlendMode, Texture};
use sdl2_image::{LoadTexture, INIT_PNG, INIT_JPG, init as image_init};
use sdl2_ttf::{Sdl2TtfContext,init as ttf_init};
use std::path::{Path,PathBuf};
use ::display::font::*;

pub struct Displayer<'a> {
    pub fonts: FontList,
    pub renderer: Renderer<'a>,
    #[allow(dead_code)]
    ttf_context: Sdl2TtfContext,
    pub lyrics_logo: Option<Texture>
}

impl<'a> Displayer<'a> {
    pub fn new(mut renderer: Renderer<'a>)
               -> Result<Displayer<'a>, ()> {
        renderer.set_blend_mode(BlendMode::Blend);
        let ttf_context = ttf_init().unwrap();
        let font_list = FontList::new(&ttf_context).unwrap();
        let _image_context = image_init(INIT_PNG | INIT_JPG).unwrap();
        // we dont care if imag econtext dies, we only load images once (for now)
        let lyrics_logo : Option<Texture> = match ::std::env::current_exe() {
            Ok(current_exe_path) => {
                match renderer.load_texture(&*current_exe_path.with_file_name("logo_toyunda.png")) {
                    Ok(texture) => Some(texture),
                    Err(e) => {
                        error!("Failed to load logo_toyunda.png : error '{}' ({:?})",e,e);
                        None
                    }
                }
            },
            _ => {
                error!("Failed to open logo_toyunda.png : failed to find current executable");
                None
            }
        };
        let displayer = Displayer {
            fonts: font_list,
            ttf_context: ttf_context,
            renderer: renderer,
            lyrics_logo:lyrics_logo
        };
        Ok(displayer)
    }

    pub fn copy_lyrics_logo(&mut self,rect: ::sdl2::rect::Rect) {
        match self.lyrics_logo {
            Some(ref texture) => {
                self.renderer.copy(texture,None,Some(rect));
            },
            None => {}
        };
    }

    // TODO use this somewhere ?
    #[allow(dead_code)]
    pub fn fatal_error_message(&self,title:&str,info:&str) {
        use ::sdl2::messagebox::ShowMessageError ;
        let res = ::sdl2::messagebox::show_simple_message_box(::sdl2::messagebox::MESSAGEBOX_ERROR,
                                                              title,
                                                              info,
                                                              self.sdl_renderer().window());
        match res {
            Ok(_) => {},
            Err(ShowMessageError::SdlError(string)) => {
                error!("Unexpected SDL_ERROR {} when creating MessageBox",string);
            }
            Err(_) => {error!("Unexpected Error when creating MessageBox")}
        }
    }

    // width and height must be between 0 and 1
    pub fn sub_screen_dims(&self,
                           width: Option<f32>,
                           height: Option<f32>)
                           -> (Option<u32>, Option<u32>) {
        let dims: (u32, u32) = self.renderer.window().unwrap().size();
        (width.and_then(|width| Some((width * (dims.0 as f32)) as u32)),
         height.and_then(|height| Some((height * (dims.1 as f32)) as u32)))
    }

    pub fn render(&mut self) {
        self.renderer.window().unwrap().gl_swap_window();
    }

    #[inline]
    pub fn sdl_renderer_mut(&mut self) -> &mut Renderer<'a> {
        &mut self.renderer
    }

    #[inline]
    pub fn sdl_renderer(&self) -> &Renderer<'a> {
        &self.renderer
    }
}
<|endoftext|>


<commit_before>use core::hash::{Hash, Hasher};

fn assert_sufficiently_different(a: u64, b: u64, tolerance: i32) {
    let (same_byte_count, same_nibble_count) = count_same_bytes_and_nibbles(a, b);
    assert!(same_byte_count <= tolerance, "{:x} vs {:x}: {:}", a, b, same_byte_count);
    assert!(
        same_nibble_count <= tolerance * 3,
        "{:x} vs {:x}: {:}",
        a,
        b,
        same_nibble_count
    );
    let flipped_bits = (a ^ b).count_ones();
    assert!(
        flipped_bits > 12 && flipped_bits < 52,
        "{:x} and {:x}: {:}",
        a,
        b,
        flipped_bits
    );
    for rotate in 0..64 {
        let flipped_bits2 = (a ^ (b.rotate_left(rotate))).count_ones();
        assert!(
            flipped_bits2 > 10 && flipped_bits2 < 54,
            "{:x} and {:x}: {:}",
            a,
            b.rotate_left(rotate),
            flipped_bits2
        );
    }
}

fn count_same_bytes_and_nibbles(a: u64, b: u64) -> (i32, i32) {
    let mut same_byte_count = 0;
    let mut same_nibble_count = 0;
    for byte in 0..8 {
        let ba = (a >> (8 * byte)) as u8;
        let bb = (b >> (8 * byte)) as u8;
        if ba == bb {
            same_byte_count += 1;
        }
        if ba & 0xF0u8 == bb & 0xF0u8 {
            same_nibble_count += 1;
        }
        if ba & 0x0Fu8 == bb & 0x0Fu8 {
            same_nibble_count += 1;
        }
    }
    (same_byte_count, same_nibble_count)
}

fn test_keys_change_output<T: Hasher>(constructor: impl Fn(u64, u64) -> T) {
    let mut a = constructor(1, 1);
    let mut b = constructor(1, 2);
    let mut c = constructor(2, 1);
    let mut d = constructor(2, 2);
    "test".hash(&mut a);
    "test".hash(&mut b);
    "test".hash(&mut c);
    "test".hash(&mut d);
    assert_sufficiently_different(a.finish(), b.finish(), 1);
    assert_sufficiently_different(a.finish(), c.finish(), 1);
    assert_sufficiently_different(a.finish(), d.finish(), 1);
    assert_sufficiently_different(b.finish(), c.finish(), 1);
    assert_sufficiently_different(b.finish(), d.finish(), 1);
    assert_sufficiently_different(c.finish(), d.finish(), 1);
}

fn test_input_affect_every_byte<T: Hasher>(constructor: impl Fn(u64, u64) -> T) {
    let mut base = constructor(0, 0);
    0.hash(&mut base);
    let base = base.finish();
    for shift in 0..16 {
        let mut alternitives = vec![];
        for v in 0..256 {
            let input = (v as u128) << (shift * 8);
            let mut hasher = constructor(0, 0);
            input.hash(&mut hasher);
            alternitives.push(hasher.finish());
        }
        assert_each_byte_differes(base, alternitives);
    }
}

fn test_keys_affect_every_byte<T: Hasher>(constructor: impl Fn(u64, u64) -> T) {
    let mut base = constructor(0, 0);
    0.hash(&mut base);
    let base = base.finish();
    for shift in 0..8 {
        let mut alternitives1 = vec![];
        let mut alternitives2 = vec![];
        for v in 0..256 {
            let input = (v as u64) << (shift * 8);
            let mut hasher1 = constructor(input, 0);
            let mut hasher2 = constructor(0, input);
            0.hash(&mut hasher1);
            0.hash(&mut hasher2);
            alternitives1.push(hasher1.finish());
            alternitives2.push(hasher2.finish());
        }
        assert_each_byte_differes(base, alternitives1);
        assert_each_byte_differes(base, alternitives2);
    }
}

fn assert_each_byte_differes(base: u64, alternitives: Vec<u64>) {
    let mut changed_bits = 0_u64;
    for alternitive in alternitives {
        changed_bits |= base ^ alternitive
    }
    assert_eq!(core::u64::MAX, changed_bits, "Bits changed: {:x}", changed_bits);
}

fn test_finish_is_consistant<T: Hasher>(constructor: impl Fn(u64, u64) -> T) {
    let mut hasher = constructor(1, 2);
    "Foo".hash(&mut hasher);
    let a = hasher.finish();
    let b = hasher.finish();
    assert_eq!(a, b);
}

fn test_single_key_bit_flip<T: Hasher>(constructor: impl Fn(u64, u64) -> T) {
    for bit in 0..64 {
        let mut a = constructor(0, 0);
        let mut b = constructor(0, 1 << bit);
        let mut c = constructor(1 << bit, 0);
        "1234".hash(&mut a);
        "1234".hash(&mut b);
        "1234".hash(&mut c);
        assert_sufficiently_different(a.finish(), b.finish(), 2);
        assert_sufficiently_different(a.finish(), c.finish(), 2);
        assert_sufficiently_different(b.finish(), c.finish(), 2);
        let mut a = constructor(0, 0);
        let mut b = constructor(0, 1 << bit);
        let mut c = constructor(1 << bit, 0);
        "12345678".hash(&mut a);
        "12345678".hash(&mut b);
        "12345678".hash(&mut c);
        assert_sufficiently_different(a.finish(), b.finish(), 2);
        assert_sufficiently_different(a.finish(), c.finish(), 2);
        assert_sufficiently_different(b.finish(), c.finish(), 2);
        let mut a = constructor(0, 0);
        let mut b = constructor(0, 1 << bit);
        let mut c = constructor(1 << bit, 0);
        "1234567812345678".hash(&mut a);
        "1234567812345678".hash(&mut b);
        "1234567812345678".hash(&mut c);
        assert_sufficiently_different(a.finish(), b.finish(), 2);
        assert_sufficiently_different(a.finish(), c.finish(), 2);
        assert_sufficiently_different(b.finish(), c.finish(), 2);
    }
}

fn test_all_bytes_matter<T: Hasher>(hasher: impl Fn() -> T) {
    let mut item = vec![0; 256];
    let base_hash = hash(&item, &hasher);
    for pos in 0..256 {
        item[pos] = 255;
        let hash = hash(&item, &hasher);
        assert_ne!(base_hash, hash, "Position {} did not affect output", pos);
        item[pos] = 0;
    }
}

fn hash<T: Hasher>(b: &impl Hash, hasher: &dyn Fn() -> T) -> u64 {
    let mut hasher = hasher();
    b.hash(&mut hasher);
    hasher.finish()
}

fn test_single_bit_flip<T: Hasher>(hasher: impl Fn() -> T) {
    let size = 32;
    let compare_value = hash(&0u32, &hasher);
    for pos in 0..size {
        let test_value = hash(&(1u32 << pos), &hasher);
        assert_sufficiently_different(compare_value, test_value, 2);
    }
    let size = 64;
    let compare_value = hash(&0u64, &hasher);
    for pos in 0..size {
        let test_value = hash(&(1u64 << pos), &hasher);
        assert_sufficiently_different(compare_value, test_value, 2);
    }
    let size = 128;
    let compare_value = hash(&0u128, &hasher);
    for pos in 0..size {
        let test_value = hash(&(1u128 << pos), &hasher);
        assert_sufficiently_different(compare_value, test_value, 2);
    }
}

fn test_padding_doesnot_collide<T: Hasher>(hasher: impl Fn() -> T) {
    for c in 0..128u8 {
        for string in ["", "1234", "12345678", "1234567812345678"].iter() {
            let mut short = hasher();
            string.hash(&mut short);
            let value = short.finish();
            let mut string = string.to_string();
            for num in 1..=128 {
                let mut long = hasher();
                string.push(c as char);
                string.hash(&mut long);
                let (same_bytes, same_nibbles) = count_same_bytes_and_nibbles(value, long.finish());
                assert!(
                    same_bytes <= 2,
                    format!("{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish())
                );
                assert!(
                    same_nibbles <= 8,
                    format!("{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish())
                );
                let flipped_bits = (value ^ long.finish()).count_ones();
                assert!(flipped_bits > 10);
            }
        }
    }
}

#[cfg(test)]
mod fallback_tests {
    use crate::fallback_hash::*;
    use crate::hash_quality_test::*;

    #[test]
    fn fallback_single_bit_flip() {
        test_single_bit_flip(|| AHasher::test_with_keys(0, 0))
    }

    #[test]
    fn fallback_single_key_bit_flip() {
        test_single_key_bit_flip(AHasher::test_with_keys)
    }

    #[test]
    fn fallback_all_bytes_matter() {
        test_all_bytes_matter(|| AHasher::test_with_keys(0, 0));
    }

    #[test]
    fn fallback_keys_change_output() {
        test_keys_change_output(AHasher::test_with_keys);
    }

    #[test]
    fn fallback_input_affect_every_byte() {
        test_input_affect_every_byte(AHasher::test_with_keys);
    }

    #[test]
    fn fallback_keys_affect_every_byte() {
        test_keys_affect_every_byte(AHasher::test_with_keys);
    }

    #[test]
    fn fallback_finish_is_consistant() {
        test_finish_is_consistant(AHasher::test_with_keys)
    }

    #[test]
    fn fallback_padding_doesnot_collide() {
        test_padding_doesnot_collide(|| AHasher::test_with_keys(0, 1))
    }
}

///Basic sanity tests of the cypto properties of aHash.
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
#[cfg(test)]
mod aes_tests {
    use crate::aes_hash::*;
    use crate::hash_quality_test::*;
    use std::hash::{Hash, Hasher};

    const BAD_KEY: u64 = 0x5252_5252_5252_5252; //Thi   s encrypts to 0.

    #[test]
    fn test_single_bit_in_byte() {
        let mut hasher1 = AHasher::new_with_keys(64, 64);
        8_u32.hash(&mut hasher1);
        let mut hasher2 = AHasher::new_with_keys(64, 64);
        0_u32.hash(&mut hasher2);
        assert_sufficiently_different(hasher1.finish(), hasher2.finish(), 1);
    }

    #[test]
    fn aes_single_bit_flip() {
        test_single_bit_flip(|| AHasher::test_with_keys(BAD_KEY, BAD_KEY))
    }

    #[test]
    fn aes_single_key_bit_flip() {
        test_single_key_bit_flip(|k1, k2| AHasher::test_with_keys(k1, k2))
    }

    #[test]
    fn aes_all_bytes_matter() {
        test_all_bytes_matter(|| AHasher::test_with_keys(BAD_KEY, BAD_KEY));
    }

    #[test]
    fn aes_keys_change_output() {
        test_keys_change_output(AHasher::test_with_keys);
    }

    #[test]
    fn aes_input_affect_every_byte() {
        test_input_affect_every_byte(AHasher::test_with_keys);
    }

    #[test]
    fn aes_keys_affect_every_byte() {
        test_keys_affect_every_byte(AHasher::test_with_keys);
    }
    #[test]
    fn aes_finish_is_consistant() {
        test_finish_is_consistant(AHasher::test_with_keys)
    }

    #[test]
    fn aes_padding_doesnot_collide() {
        test_padding_doesnot_collide(|| AHasher::test_with_keys(BAD_KEY, BAD_KEY))
    }
}
<commit_msg>Add additional hash quality test<commit_after>use core::hash::{Hash, Hasher};

fn assert_sufficiently_different(a: u64, b: u64, tolerance: i32) {
    let (same_byte_count, same_nibble_count) = count_same_bytes_and_nibbles(a, b);
    assert!(same_byte_count <= tolerance, "{:x} vs {:x}: {:}", a, b, same_byte_count);
    assert!(
        same_nibble_count <= tolerance * 3,
        "{:x} vs {:x}: {:}",
        a,
        b,
        same_nibble_count
    );
    let flipped_bits = (a ^ b).count_ones();
    assert!(
        flipped_bits > 12 && flipped_bits < 52,
        "{:x} and {:x}: {:}",
        a,
        b,
        flipped_bits
    );
    for rotate in 0..64 {
        let flipped_bits2 = (a ^ (b.rotate_left(rotate))).count_ones();
        assert!(
            flipped_bits2 > 10 && flipped_bits2 < 54,
            "{:x} and {:x}: {:}",
            a,
            b.rotate_left(rotate),
            flipped_bits2
        );
    }
}

fn count_same_bytes_and_nibbles(a: u64, b: u64) -> (i32, i32) {
    let mut same_byte_count = 0;
    let mut same_nibble_count = 0;
    for byte in 0..8 {
        let ba = (a >> (8 * byte)) as u8;
        let bb = (b >> (8 * byte)) as u8;
        if ba == bb {
            same_byte_count += 1;
        }
        if ba & 0xF0u8 == bb & 0xF0u8 {
            same_nibble_count += 1;
        }
        if ba & 0x0Fu8 == bb & 0x0Fu8 {
            same_nibble_count += 1;
        }
    }
    (same_byte_count, same_nibble_count)
}

fn test_keys_change_output<T: Hasher>(constructor: impl Fn(u64, u64) -> T) {
    let mut a = constructor(1, 1);
    let mut b = constructor(1, 2);
    let mut c = constructor(2, 1);
    let mut d = constructor(2, 2);
    "test".hash(&mut a);
    "test".hash(&mut b);
    "test".hash(&mut c);
    "test".hash(&mut d);
    assert_sufficiently_different(a.finish(), b.finish(), 1);
    assert_sufficiently_different(a.finish(), c.finish(), 1);
    assert_sufficiently_different(a.finish(), d.finish(), 1);
    assert_sufficiently_different(b.finish(), c.finish(), 1);
    assert_sufficiently_different(b.finish(), d.finish(), 1);
    assert_sufficiently_different(c.finish(), d.finish(), 1);
}

fn test_input_affect_every_byte<T: Hasher>(constructor: impl Fn(u64, u64) -> T) {
    let mut base = constructor(0, 0);
    0.hash(&mut base);
    let base = base.finish();
    for shift in 0..16 {
        let mut alternitives = vec![];
        for v in 0..256 {
            let input = (v as u128) << (shift * 8);
            let mut hasher = constructor(0, 0);
            input.hash(&mut hasher);
            alternitives.push(hasher.finish());
        }
        assert_each_byte_differes(base, alternitives);
    }
}

fn test_keys_affect_every_byte<T: Hasher>(constructor: impl Fn(u64, u64) -> T) {
    let mut base = constructor(0, 0);
    0.hash(&mut base);
    let base = base.finish();
    for shift in 0..8 {
        let mut alternitives1 = vec![];
        let mut alternitives2 = vec![];
        for v in 0..256 {
            let input = (v as u64) << (shift * 8);
            let mut hasher1 = constructor(input, 0);
            let mut hasher2 = constructor(0, input);
            0.hash(&mut hasher1);
            0.hash(&mut hasher2);
            alternitives1.push(hasher1.finish());
            alternitives2.push(hasher2.finish());
        }
        assert_each_byte_differes(base, alternitives1);
        assert_each_byte_differes(base, alternitives2);
    }
}

fn assert_each_byte_differes(base: u64, alternitives: Vec<u64>) {
    let mut changed_bits = 0_u64;
    for alternitive in alternitives {
        changed_bits |= base ^ alternitive
    }
    assert_eq!(core::u64::MAX, changed_bits, "Bits changed: {:x}", changed_bits);
}

fn test_finish_is_consistant<T: Hasher>(constructor: impl Fn(u64, u64) -> T) {
    let mut hasher = constructor(1, 2);
    "Foo".hash(&mut hasher);
    let a = hasher.finish();
    let b = hasher.finish();
    assert_eq!(a, b);
}

fn test_single_key_bit_flip<T: Hasher>(constructor: impl Fn(u64, u64) -> T) {
    for bit in 0..64 {
        let mut a = constructor(0, 0);
        let mut b = constructor(0, 1 << bit);
        let mut c = constructor(1 << bit, 0);
        "1234".hash(&mut a);
        "1234".hash(&mut b);
        "1234".hash(&mut c);
        assert_sufficiently_different(a.finish(), b.finish(), 2);
        assert_sufficiently_different(a.finish(), c.finish(), 2);
        assert_sufficiently_different(b.finish(), c.finish(), 2);
        let mut a = constructor(0, 0);
        let mut b = constructor(0, 1 << bit);
        let mut c = constructor(1 << bit, 0);
        "12345678".hash(&mut a);
        "12345678".hash(&mut b);
        "12345678".hash(&mut c);
        assert_sufficiently_different(a.finish(), b.finish(), 2);
        assert_sufficiently_different(a.finish(), c.finish(), 2);
        assert_sufficiently_different(b.finish(), c.finish(), 2);
        let mut a = constructor(0, 0);
        let mut b = constructor(0, 1 << bit);
        let mut c = constructor(1 << bit, 0);
        "1234567812345678".hash(&mut a);
        "1234567812345678".hash(&mut b);
        "1234567812345678".hash(&mut c);
        assert_sufficiently_different(a.finish(), b.finish(), 2);
        assert_sufficiently_different(a.finish(), c.finish(), 2);
        assert_sufficiently_different(b.finish(), c.finish(), 2);
    }
}

fn test_all_bytes_matter<T: Hasher>(hasher: impl Fn() -> T) {
    let mut item = vec![0; 256];
    let base_hash = hash(&item, &hasher);
    for pos in 0..256 {
        item[pos] = 255;
        let hash = hash(&item, &hasher);
        assert_ne!(base_hash, hash, "Position {} did not affect output", pos);
        item[pos] = 0;
    }
}

fn test_no_pair_collisions<T: Hasher>(hasher: impl Fn() -> T) {
    let base = [0_u64, 0_u64];
    let base_hash = hash(&base, &hasher);
    for bitpos1 in 0..64 {
        let a = 1_u64 << bitpos1;
        for bitpos2 in 0..bitpos1 {
            let b = 1_u64 << bitpos2;
            let aa = hash(&[a, a], &hasher);
            let ab = hash(&[a, b], &hasher);
            let ba = hash(&[b, a], &hasher);
            let bb = hash(&[b, b], &hasher);
            assert_sufficiently_different(base_hash, aa, 3);
            assert_sufficiently_different(base_hash, ab, 3);
            assert_sufficiently_different(base_hash, ba, 3);
            assert_sufficiently_different(base_hash, bb, 3);
            assert_sufficiently_different(aa, ab, 3);
            assert_sufficiently_different(ab, ba, 3);
            assert_sufficiently_different(ba, bb, 3);
            assert_sufficiently_different(aa, ba, 3);
            assert_sufficiently_different(ab, bb, 3);
            assert_sufficiently_different(aa, bb, 3);
        }
    }
}

fn hash<T: Hasher>(b: &impl Hash, hasher: &dyn Fn() -> T) -> u64 {
    let mut hasher = hasher();
    b.hash(&mut hasher);
    hasher.finish()
}

fn test_single_bit_flip<T: Hasher>(hasher: impl Fn() -> T) {
    let size = 32;
    let compare_value = hash(&0u32, &hasher);
    for pos in 0..size {
        let test_value = hash(&(1u32 << pos), &hasher);
        assert_sufficiently_different(compare_value, test_value, 2);
    }
    let size = 64;
    let compare_value = hash(&0u64, &hasher);
    for pos in 0..size {
        let test_value = hash(&(1u64 << pos), &hasher);
        assert_sufficiently_different(compare_value, test_value, 2);
    }
    let size = 128;
    let compare_value = hash(&0u128, &hasher);
    for pos in 0..size {
        let test_value = hash(&(1u128 << pos), &hasher);
        assert_sufficiently_different(compare_value, test_value, 2);
    }
}

fn test_padding_doesnot_collide<T: Hasher>(hasher: impl Fn() -> T) {
    for c in 0..128u8 {
        for string in ["", "1234", "12345678", "1234567812345678"].iter() {
            let mut short = hasher();
            string.hash(&mut short);
            let value = short.finish();
            let mut string = string.to_string();
            for num in 1..=128 {
                let mut long = hasher();
                string.push(c as char);
                string.hash(&mut long);
                let (same_bytes, same_nibbles) = count_same_bytes_and_nibbles(value, long.finish());
                assert!(
                    same_bytes <= 2,
                    format!("{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish())
                );
                assert!(
                    same_nibbles <= 8,
                    format!("{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish())
                );
                let flipped_bits = (value ^ long.finish()).count_ones();
                assert!(flipped_bits > 10);
            }
        }
    }
}

#[cfg(test)]
mod fallback_tests {
    use crate::fallback_hash::*;
    use crate::hash_quality_test::*;

    #[test]
    fn fallback_single_bit_flip() {
        test_single_bit_flip(|| AHasher::test_with_keys(0, 0))
    }

    #[test]
    fn fallback_single_key_bit_flip() {
        test_single_key_bit_flip(AHasher::test_with_keys)
    }

    #[test]
    fn fallback_all_bytes_matter() {
        test_all_bytes_matter(|| AHasher::test_with_keys(0, 0));
    }

    #[test]
    fn fallback_test_no_pair_collisions() {
        test_no_pair_collisions(|| AHasher::test_with_keys(0, 0));
    }

    #[test]
    fn fallback_keys_change_output() {
        test_keys_change_output(AHasher::test_with_keys);
    }

    #[test]
    fn fallback_input_affect_every_byte() {
        test_input_affect_every_byte(AHasher::test_with_keys);
    }

    #[test]
    fn fallback_keys_affect_every_byte() {
        test_keys_affect_every_byte(AHasher::test_with_keys);
    }

    #[test]
    fn fallback_finish_is_consistant() {
        test_finish_is_consistant(AHasher::test_with_keys)
    }

    #[test]
    fn fallback_padding_doesnot_collide() {
        test_padding_doesnot_collide(|| AHasher::test_with_keys(0, 1))
    }
}

///Basic sanity tests of the cypto properties of aHash.
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
#[cfg(test)]
mod aes_tests {
    use crate::aes_hash::*;
    use crate::hash_quality_test::*;
    use std::hash::{Hash, Hasher};

    const BAD_KEY: u64  = 0x5252_5252_5252_5252; //This encrypts to 0.
    const BAD_KEY2: u64 = 0x6363_6363_6363_6363; //This decrypts to 0.

    #[test]
    fn test_single_bit_in_byte() {
        let mut hasher1 = AHasher::new_with_keys(64, 64);
        8_u32.hash(&mut hasher1);
        let mut hasher2 = AHasher::new_with_keys(64, 64);
        0_u32.hash(&mut hasher2);
        assert_sufficiently_different(hasher1.finish(), hasher2.finish(), 1);
    }

    #[test]
    fn aes_single_bit_flip() {
        test_single_bit_flip(|| AHasher::test_with_keys(BAD_KEY, BAD_KEY));
        test_single_bit_flip(|| AHasher::test_with_keys(BAD_KEY2, BAD_KEY2));
    }

    #[test]
    fn aes_single_key_bit_flip() {
        test_single_key_bit_flip(|k1, k2| AHasher::test_with_keys(k1, k2))
    }

    #[test]
    fn aes_all_bytes_matter() {
        test_all_bytes_matter(|| AHasher::test_with_keys(BAD_KEY, BAD_KEY));
        test_all_bytes_matter(|| AHasher::test_with_keys(BAD_KEY2, BAD_KEY2));
    }

    #[test]
    fn aes_test_no_pair_collisions() {
        test_no_pair_collisions(|| AHasher::test_with_keys(BAD_KEY, BAD_KEY));
        test_no_pair_collisions(|| AHasher::test_with_keys(BAD_KEY2, BAD_KEY2));
    }

    #[test]
    fn aes_keys_change_output() {
        test_keys_change_output(AHasher::test_with_keys);
    }

    #[test]
    fn aes_input_affect_every_byte() {
        test_input_affect_every_byte(AHasher::test_with_keys);
    }

    #[test]
    fn aes_keys_affect_every_byte() {
        test_keys_affect_every_byte(AHasher::test_with_keys);
    }
    #[test]
    fn aes_finish_is_consistant() {
        test_finish_is_consistant(AHasher::test_with_keys)
    }

    #[test]
    fn aes_padding_doesnot_collide() {
        test_padding_doesnot_collide(|| AHasher::test_with_keys(BAD_KEY, BAD_KEY));
        test_padding_doesnot_collide(|| AHasher::test_with_keys(BAD_KEY2, BAD_KEY2));
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![feature(iterator_for_each)]
#![plugin(clippy)]
use std::iter::repeat;

fn square_is_lower_64(x: &u32) -> bool { x * x < 64 }

#[allow(maybe_infinite_iter)]
#[deny(infinite_iter)]
fn infinite_iters() {
    repeat(0_u8).collect::<Vec<_>>(); // infinite iter
    (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter
    (0..8_u64).chain(0..).max(); // infinite iter
    (0_usize..).chain([0usize, 1, 2].iter().cloned()).skip_while(|x| *x != 42).min(); // infinite iter
    (0..8_u32).rev().cycle().map(|x| x + 1_u32).for_each(|x| println!("{}", x)); // infinite iter
    (0..3_u32).flat_map(|x| x..).sum::<u32>(); // infinite iter
    (0_usize..).flat_map(|x| 0..x).product::<usize>();  // infinite iter
    (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter
    (0..42_u64).by_ref().last(); // not an infinite, because ranges are double-ended
    (0..).next(); // iterator is not exhausted
}

#[deny(maybe_infinite_iter)]
fn potential_infinite_iters() {
    (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter
    repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter
    (1..).scan(0, |state, x| { *state += x; Some(*state) }).min(); // maybe infinite iter
    (0..).find(|x| *x == 24); // maybe infinite iter
    (0..).position(|x| x == 24); // maybe infinite iter
    (0..).any(|x| x == 24); // maybe infinite iter
    (0..).all(|x| x == 24); // maybe infinite iter

    (0..).zip(0..42).take_while(|&(x, _)| x != 42).count(); // not infinite
    repeat(42).take_while(|x| *x == 42).next(); // iterator is not exhausted
}

fn main() {
    infinite_iters();
    potential_infinite_iters();
}
<commit_msg>stabilizing feature iterator_for_each for rust 1.21.0<commit_after>#![feature(plugin)]
#![plugin(clippy)]
use std::iter::repeat;

fn square_is_lower_64(x: &u32) -> bool { x * x < 64 }

#[allow(maybe_infinite_iter)]
#[deny(infinite_iter)]
fn infinite_iters() {
    repeat(0_u8).collect::<Vec<_>>(); // infinite iter
    (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter
    (0..8_u64).chain(0..).max(); // infinite iter
    (0_usize..).chain([0usize, 1, 2].iter().cloned()).skip_while(|x| *x != 42).min(); // infinite iter
    (0..8_u32).rev().cycle().map(|x| x + 1_u32).for_each(|x| println!("{}", x)); // infinite iter
    (0..3_u32).flat_map(|x| x..).sum::<u32>(); // infinite iter
    (0_usize..).flat_map(|x| 0..x).product::<usize>();  // infinite iter
    (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter
    (0..42_u64).by_ref().last(); // not an infinite, because ranges are double-ended
    (0..).next(); // iterator is not exhausted
}

#[deny(maybe_infinite_iter)]
fn potential_infinite_iters() {
    (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter
    repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter
    (1..).scan(0, |state, x| { *state += x; Some(*state) }).min(); // maybe infinite iter
    (0..).find(|x| *x == 24); // maybe infinite iter
    (0..).position(|x| x == 24); // maybe infinite iter
    (0..).any(|x| x == 24); // maybe infinite iter
    (0..).all(|x| x == 24); // maybe infinite iter

    (0..).zip(0..42).take_while(|&(x, _)| x != 42).count(); // not infinite
    repeat(42).take_while(|x| *x == 42).next(); // iterator is not exhausted
}

fn main() {
    infinite_iters();
    potential_infinite_iters();
}
<|endoftext|>