<commit_before>extern crate rand;
extern crate rgen3_save;
extern crate rgen3_string;

use rand::{thread_rng, Rng, ThreadRng};
use rgen3_save::{Pokemon, SaveSections, TrainerInfo};
use std::collections::HashSet;

static PREFIX_NAMES: [&'static str; 52] = [
    "Acid", "Axel", "Baal", "Bike", "Bull", "Bald", "Cave", "Diet", "Dray", "Duke", "Easy", "Fact",
    "Face", "Fowl", "Fuzz", "Goat", "Hair", "Head", "Hiss", "Idea", "Iris", "Iron", "Jack", "John",
    "Kart", "Lady", "Limb", "Lime", "Mace", "Mars", "Naga", "Nuke", "Nude", "Omen", "Orca", "Poke",
    "Pyre", "Quiz", "Risk", "Road", "Sock", "Swag", "Teal", "Tree", "Ugly", "Vamp", "Vibe", "Wolf",
    "Xray", "Yoga", "Zeta", "Zoom",
];

static SUFFIX_NAMES: [&'static str; 23] = [
    "Adder", "Baker", "Biter", "Coder", "Curer", "Diver", "Eater", "Faker", "Flier", "Frier",
    "Gamer", "Gazer", "Giver", "Laser", "Lover", "Maker", "Order", "Racer", "Taker", "Tamer",
    "Voter", "Waker", "Zoner",
];

struct PokeGen<'a> {
    chosen_names: HashSet<String>,
    chosen_species: HashSet<u16>,
    n_unique: u16,
    trainer: &'a TrainerInfo,
    rng: ThreadRng,
}

impl<'a> PokeGen<'a> {
    fn new(trainer: &'a TrainerInfo) -> Self {
        PokeGen {
            chosen_names: HashSet::new(),
            chosen_species: HashSet::new(),
            n_unique: 0,
            trainer: trainer,
            rng: thread_rng(),
        }
    }
    fn gen(&mut self) -> Pokemon {
        let mut pokemon = Pokemon::default();
        let mut name;
        loop {
            let prefix = self.rng.choose(&PREFIX_NAMES).unwrap();
            let suffix = self.rng.choose(&SUFFIX_NAMES).unwrap();
            name = format!("{} {}", prefix, suffix);
            // Make sure we don't use the same name twice in our team
            if !self.chosen_names.contains(&name) {
                break;
            }
        }
        rgen3_string::encode_string(&name, &mut pokemon.nickname.0);
        self.chosen_names.insert(name);
        {
            loop {
                let species = self.rng.gen_range(1, 412);
                let result = pokemon.set_species(species);
                if result.is_ok() {
                    if self.chosen_species.contains(&species) {
                        if self.n_unique >= 386 {
                            break;
                        }
                    } else {
                        assert!(self.chosen_species.insert(species));
                        self.n_unique += 1;
                        break;
                    }
                }
            }
            pokemon.data.growth.experience = 1_640_000;
            pokemon.data.growth.friendship = 0xFF;
            pokemon.data.growth.pp_bonuses = 0xFF;
            pokemon.data.attacks.move1 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move2 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move3 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move4 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.pp1 = 99;
            pokemon.data.attacks.pp2 = 99;
            pokemon.data.attacks.pp3 = 99;
            pokemon.data.attacks.pp4 = 99;
            pokemon.data.evs_and_condition.hp = 0xFF;
            pokemon.data.evs_and_condition.attack = 0xFF;
            pokemon.data.evs_and_condition.defense = 0xFF;
            pokemon.data.evs_and_condition.speed = 0xFF;
            pokemon.data.evs_and_condition.sp_attack = 0xFF;
            pokemon.data.evs_and_condition.sp_defense = 0xFF;
            pokemon.data.evs_and_condition.coolness = 0xFF;
            pokemon.data.evs_and_condition.beauty = 0xFF;
            pokemon.data.evs_and_condition.cuteness = 0xFF;
            pokemon.data.evs_and_condition.smartness = 0xFF;
            pokemon.data.evs_and_condition.toughness = 0xFF;
            pokemon.ot_id = self.trainer.full_id();
            pokemon.ot_name = self.trainer.name;
        }
        pokemon
    }
}

fn main() {
    let mut args = std::env::args().skip(1);
    let path = args.next().expect("Need path to save as first arg");
    let mut save = rgen3_save::Save::load_from_file(&path).unwrap();
    {
        let SaveSections {
            trainer, pc_boxes, ..
        } = save.sections();
        let mut generator = PokeGen::new(trainer);
        for b in pc_boxes.iter_mut() {
            for p in &mut b.pokemon {
                *p = Some(generator.gen());
            }
        }
    }
    save.save_to_file(path).unwrap();
}
<commit_msg>fill-pc example: Add "Hugger" to suffix names<commit_after>extern crate rand;
extern crate rgen3_save;
extern crate rgen3_string;

use rand::{thread_rng, Rng, ThreadRng};
use rgen3_save::{Pokemon, SaveSections, TrainerInfo};
use std::collections::HashSet;

static PREFIX_NAMES: [&'static str; 52] = [
    "Acid", "Axel", "Baal", "Bike", "Bull", "Bald", "Cave", "Diet", "Dray", "Duke", "Easy", "Fact",
    "Face", "Fowl", "Fuzz", "Goat", "Hair", "Head", "Hiss", "Idea", "Iris", "Iron", "Jack", "John",
    "Kart", "Lady", "Limb", "Lime", "Mace", "Mars", "Naga", "Nuke", "Nude", "Omen", "Orca", "Poke",
    "Pyre", "Quiz", "Risk", "Road", "Sock", "Swag", "Teal", "Tree", "Ugly", "Vamp", "Vibe", "Wolf",
    "Xray", "Yoga", "Zeta", "Zoom",
];

static SUFFIX_NAMES: [&'static str; 24] = [
    "Adder", "Baker", "Biter", "Coder", "Curer", "Diver", "Eater", "Faker", "Flier", "Frier",
    "Gamer", "Gazer", "Giver", "Laser", "Lover", "Maker", "Order", "Racer", "Taker", "Tamer",
    "Voter", "Waker", "Zoner", "Hugger",
];

struct PokeGen<'a> {
    chosen_names: HashSet<String>,
    chosen_species: HashSet<u16>,
    n_unique: u16,
    trainer: &'a TrainerInfo,
    rng: ThreadRng,
}

impl<'a> PokeGen<'a> {
    fn new(trainer: &'a TrainerInfo) -> Self {
        PokeGen {
            chosen_names: HashSet::new(),
            chosen_species: HashSet::new(),
            n_unique: 0,
            trainer: trainer,
            rng: thread_rng(),
        }
    }
    fn gen(&mut self) -> Pokemon {
        let mut pokemon = Pokemon::default();
        let mut name;
        loop {
            let prefix = self.rng.choose(&PREFIX_NAMES).unwrap();
            let suffix = self.rng.choose(&SUFFIX_NAMES).unwrap();
            name = format!("{} {}", prefix, suffix);
            // Make sure we don't use the same name twice in our team
            if !self.chosen_names.contains(&name) {
                break;
            }
        }
        rgen3_string::encode_string(&name, &mut pokemon.nickname.0);
        self.chosen_names.insert(name);
        {
            loop {
                let species = self.rng.gen_range(1, 412);
                let result = pokemon.set_species(species);
                if result.is_ok() {
                    if self.chosen_species.contains(&species) {
                        if self.n_unique >= 386 {
                            break;
                        }
                    } else {
                        assert!(self.chosen_species.insert(species));
                        self.n_unique += 1;
                        break;
                    }
                }
            }
            pokemon.data.growth.experience = 1_640_000;
            pokemon.data.growth.friendship = 0xFF;
            pokemon.data.growth.pp_bonuses = 0xFF;
            pokemon.data.attacks.move1 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move2 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move3 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.move4 = self.rng.gen_range(0, 354);
            pokemon.data.attacks.pp1 = 99;
            pokemon.data.attacks.pp2 = 99;
            pokemon.data.attacks.pp3 = 99;
            pokemon.data.attacks.pp4 = 99;
            pokemon.data.evs_and_condition.hp = 0xFF;
            pokemon.data.evs_and_condition.attack = 0xFF;
            pokemon.data.evs_and_condition.defense = 0xFF;
            pokemon.data.evs_and_condition.speed = 0xFF;
            pokemon.data.evs_and_condition.sp_attack = 0xFF;
            pokemon.data.evs_and_condition.sp_defense = 0xFF;
            pokemon.data.evs_and_condition.coolness = 0xFF;
            pokemon.data.evs_and_condition.beauty = 0xFF;
            pokemon.data.evs_and_condition.cuteness = 0xFF;
            pokemon.data.evs_and_condition.smartness = 0xFF;
            pokemon.data.evs_and_condition.toughness = 0xFF;
            pokemon.ot_id = self.trainer.full_id();
            pokemon.ot_name = self.trainer.name;
        }
        pokemon
    }
}

fn main() {
    let mut args = std::env::args().skip(1);
    let path = args.next().expect("Need path to save as first arg");
    let mut save = rgen3_save::Save::load_from_file(&path).unwrap();
    {
        let SaveSections {
            trainer, pc_boxes, ..
        } = save.sections();
        let mut generator = PokeGen::new(trainer);
        for b in pc_boxes.iter_mut() {
            for p in &mut b.pokemon {
                *p = Some(generator.gen());
            }
        }
    }
    save.save_to_file(path).unwrap();
}
<|endoftext|>


<commit_before>//! Module for User-Interactive Authentication API types.

use std::{
    collections::BTreeMap,
    fmt::{self, Display, Formatter},
};

use ruma_api::{error::ResponseDeserializationError, EndpointError};
use ruma_serde::Outgoing;
use serde::{Deserialize, Serialize};
use serde_json::{
    from_slice as from_json_slice, to_vec as to_json_vec, value::RawValue as RawJsonValue,
    Value as JsonValue,
};

use crate::error::{Error as MatrixError, ErrorBody};

/// Additional authentication information for the user-interactive authentication API.
#[derive(Clone, Debug, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(untagged)]
pub enum AuthData<'a> {
    /// Used for sending UIAA authentication requests to the homeserver directly from the client.
    // Could be made non-exhaustive by creating a separate struct and making auth_parameters
    // private, but probably not worth the hassle.
    DirectRequest {
        /// The login type that the client is attempting to complete.
        #[serde(rename = "type")]
        kind: &'a str,

        /// The value of the session key given by the homeserver.
        #[serde(skip_serializing_if = "Option::is_none")]
        session: Option<&'a str>,

        /// Parameters submitted for a particular authentication stage.
        #[serde(flatten)]
        auth_parameters: BTreeMap<String, JsonValue>,
    },

    /// Used by the client to acknowledge that the user has completed a UIAA stage through the
    /// fallback method.
    // Exhaustiveness is correct here since this variant is a fallback that explicitly only has a
    // single field. TODO: #[serde(deny_unknown_fields)] not supported on enum variants
    // https://github.com/serde-rs/serde/issues/1982
    FallbackAcknowledgement {
        /// The value of the session key given by the homeserver.
        session: &'a str,
    },
}

/// Information about available authentication flows and status for User-Interactive Authenticiation
/// API.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct UiaaInfo {
    /// List of authentication flows available for this endpoint.
    pub flows: Vec<AuthFlow>,

    /// List of stages in the current flow completed by the client.
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub completed: Vec<String>,

    /// Authentication parameters required for the client to complete authentication.
    ///
    /// To create a `Box<RawJsonValue>`, use `serde_json::value::to_raw_value`.
    pub params: Box<RawJsonValue>,

    /// Session key for client to use to complete authentication.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub session: Option<String>,

    /// Authentication-related errors for previous request returned by homeserver.
    #[serde(flatten, skip_serializing_if = "Option::is_none")]
    pub auth_error: Option<ErrorBody>,
}

impl UiaaInfo {
    /// Creates a new `UiaaInfo` with the given flows and parameters.
    pub fn new(flows: Vec<AuthFlow>, params: Box<RawJsonValue>) -> Self {
        Self { flows, completed: Vec::new(), params, session: None, auth_error: None }
    }
}

/// Description of steps required to authenticate via the User-Interactive Authentication API.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[cfg_attr(test, derive(PartialEq))]
pub struct AuthFlow {
    /// Ordered list of stages required to complete authentication.
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub stages: Vec<String>,
}

impl AuthFlow {
    /// Creates an empty `AuthFlow`.
    pub fn new() -> Self {
        Self { stages: Vec::new() }
    }
}

/// Contains either a User-Interactive Authentication API response body or a Matrix error.
#[derive(Clone, Debug)]
pub enum UiaaResponse {
    /// User-Interactive Authentication API response
    AuthResponse(UiaaInfo),

    /// Matrix error response
    MatrixError(MatrixError),
}

impl Display for UiaaResponse {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::AuthResponse(_) => write!(f, "User-Interactive Authentication required."),
            Self::MatrixError(err) => write!(f, "{}", err),
        }
    }
}

impl From<MatrixError> for UiaaResponse {
    fn from(error: MatrixError) -> Self {
        Self::MatrixError(error)
    }
}

impl EndpointError for UiaaResponse {
    fn try_from_response(
        response: http::Response<Vec<u8>>,
    ) -> Result<Self, ResponseDeserializationError> {
        if response.status() == http::StatusCode::UNAUTHORIZED {
            if let Ok(authentication_info) = from_json_slice::<UiaaInfo>(response.body()) {
                return Ok(UiaaResponse::AuthResponse(authentication_info));
            }
        }

        MatrixError::try_from_response(response).map(From::from)
    }
}

impl std::error::Error for UiaaResponse {}

impl From<UiaaResponse> for http::Response<Vec<u8>> {
    fn from(uiaa_response: UiaaResponse) -> http::Response<Vec<u8>> {
        match uiaa_response {
            UiaaResponse::AuthResponse(authentication_info) => http::Response::builder()
                .header(http::header::CONTENT_TYPE, "application/json")
                .status(&http::StatusCode::UNAUTHORIZED)
                .body(to_json_vec(&authentication_info).unwrap())
                .unwrap(),
            UiaaResponse::MatrixError(error) => http::Response::from(error),
        }
    }
}

#[cfg(test)]
mod tests {
    use maplit::btreemap;
    use matches::assert_matches;
    use ruma_api::EndpointError;
    use serde_json::{
        from_slice as from_json_slice, from_str as from_json_str, from_value as from_json_value,
        json, to_value as to_json_value, value::to_raw_value as to_raw_json_value,
        Value as JsonValue,
    };

    use super::{AuthData, AuthFlow, IncomingAuthData, UiaaInfo, UiaaResponse};
    use crate::error::{ErrorBody, ErrorKind};

    #[test]
    fn serialize_authentication_data_direct_request() {
        let authentication_data = AuthData::DirectRequest {
            kind: "example.type.foo",
            session: Some("ZXY000"),
            auth_parameters: btreemap! {
                "example_credential".to_owned() => json!("verypoorsharedsecret")
            },
        };

        assert_eq!(
            json!({
                "type": "example.type.foo",
                "session": "ZXY000",
                "example_credential": "verypoorsharedsecret",
            }),
            to_json_value(authentication_data).unwrap()
        );
    }

    #[test]
    fn deserialize_authentication_data_direct_request() {
        let json = json!({
            "type": "example.type.foo",
            "session": "opaque_session_id",
            "example_credential": "verypoorsharedsecret",
        });

        assert_matches!(
            from_json_value(json).unwrap(),
            IncomingAuthData::DirectRequest { kind, session: Some(session), auth_parameters }
            if kind == "example.type.foo"
                && session == "opaque_session_id"
                && auth_parameters == btreemap!{
                    "example_credential".to_owned() => json!("verypoorsharedsecret")
                }
        );
    }

    #[test]
    fn serialize_authentication_data_fallback() {
        let authentication_data = AuthData::FallbackAcknowledgement { session: "ZXY000" };

        assert_eq!(json!({ "session": "ZXY000" }), to_json_value(authentication_data).unwrap());
    }

    #[test]
    fn deserialize_authentication_data_fallback() {
        let json = json!({ "session": "opaque_session_id" });

        assert_matches!(
            from_json_value(json).unwrap(),
            IncomingAuthData::FallbackAcknowledgement { session }
            if session == "opaque_session_id"
        );
    }

    #[test]
    fn serialize_uiaa_info() {
        let uiaa_info = UiaaInfo {
            flows: vec![AuthFlow {
                stages: vec!["m.login.password".into(), "m.login.dummy".into()],
            }],
            completed: vec!["m.login.password".into()],
            params: to_raw_json_value(&json!({
                "example.type.baz": {
                    "example_key": "foobar"
                }
            }))
            .unwrap(),
            session: None,
            auth_error: None,
        };

        let json = json!({
            "flows": [{ "stages": ["m.login.password", "m.login.dummy"] }],
            "completed": ["m.login.password"],
            "params": {
                "example.type.baz": {
                    "example_key": "foobar"
                }
            }
        });
        assert_eq!(to_json_value(uiaa_info).unwrap(), json);
    }

    #[test]
    fn deserialize_uiaa_info() {
        let json = json!({
            "errcode": "M_FORBIDDEN",
            "error": "Invalid password",
            "completed": ["example.type.foo"],
            "flows": [
                {
                    "stages": ["example.type.foo", "example.type.bar"]
                },
                {
                    "stages": ["example.type.foo", "example.type.baz"]
                }
            ],
            "params": {
                "example.type.baz": {
                    "example_key": "foobar"
                }
            },
            "session": "xxxxxx"
        });

        assert_matches!(
            from_json_value::<UiaaInfo>(json).unwrap(),
            UiaaInfo {
                auth_error: Some(ErrorBody {
                    kind: ErrorKind::Forbidden,
                    message: error_message,
                }),
                completed,
                flows,
                params,
                session: Some(session),
            } if error_message == "Invalid password"
                && completed == vec!["example.type.foo".to_owned()]
                && flows == vec![
                    AuthFlow {
                        stages: vec![
                            "example.type.foo".into(),
                            "example.type.bar".into(),
                        ],
                    },
                    AuthFlow {
                        stages: vec![
                            "example.type.foo".into(),
                            "example.type.baz".into(),
                        ],
                    },
                ]
                && from_json_str::<JsonValue>(params.get()).unwrap() == json!({
                    "example.type.baz": {
                        "example_key": "foobar"
                    }
                })
                && session == "xxxxxx"
        );
    }

    #[test]
    fn try_uiaa_response_into_http_response() {
        let uiaa_info = UiaaInfo {
            flows: vec![AuthFlow {
                stages: vec!["m.login.password".into(), "m.login.dummy".into()],
            }],
            completed: vec!["m.login.password".into()],
            params: to_raw_json_value(&json!({
                "example.type.baz": {
                    "example_key": "foobar"
                }
            }))
            .unwrap(),
            session: None,
            auth_error: None,
        };
        let uiaa_response: http::Response<Vec<u8>> = UiaaResponse::AuthResponse(uiaa_info).into();

        assert_matches!(
            from_json_slice::<UiaaInfo>(uiaa_response.body()).unwrap(),
            UiaaInfo {
                flows,
                completed,
                params,
                session: None,
                auth_error: None,
            } if flows == vec![AuthFlow {
                    stages: vec!["m.login.password".into(), "m.login.dummy".into()],
                }]
                && completed == vec!["m.login.password".to_owned()]
                && from_json_str::<JsonValue>(params.get()).unwrap() == json!({
                    "example.type.baz": {
                        "example_key": "foobar"
                    }
                })
        );
        assert_eq!(uiaa_response.status(), http::status::StatusCode::UNAUTHORIZED);
    }

    #[test]
    fn try_uiaa_response_from_http_response() {
        let json = serde_json::to_string(&json!({
            "errcode": "M_FORBIDDEN",
            "error": "Invalid password",
            "completed": [ "example.type.foo" ],
            "flows": [
                {
                    "stages": [ "example.type.foo", "example.type.bar" ]
                },
                {
                    "stages": [ "example.type.foo", "example.type.baz" ]
                }
            ],
            "params": {
                "example.type.baz": {
                    "example_key": "foobar"
                }
            },
            "session": "xxxxxx"
        }))
        .unwrap();

        let http_response = http::Response::builder()
            .status(http::StatusCode::UNAUTHORIZED)
            .body(json.into())
            .unwrap();

        let parsed_uiaa_info = match UiaaResponse::try_from_response(http_response).unwrap() {
            UiaaResponse::AuthResponse(uiaa_info) => uiaa_info,
            _ => panic!("Expected UiaaResponse::AuthResponse"),
        };

        assert_matches!(
            parsed_uiaa_info,
            UiaaInfo {
                auth_error: Some(ErrorBody {
                    kind: ErrorKind::Forbidden,
                    message: error_message,
                }),
                completed,
                flows,
                params,
                session: Some(session),
            } if error_message == "Invalid password"
                && completed == vec!["example.type.foo".to_owned()]
                && flows == vec![
                    AuthFlow {
                        stages: vec![
                            "example.type.foo".into(),
                            "example.type.bar".into(),
                        ],
                    },
                    AuthFlow {
                        stages: vec![
                            "example.type.foo".into(),
                            "example.type.baz".into(),
                        ],
                    },
                ]
                && from_json_str::<JsonValue>(params.get()).unwrap() == json!({
                    "example.type.baz": {
                        "example_key": "foobar"
                    }
                })
                && session == "xxxxxx"
        );
    }
}
<commit_msg>client-api: Add convenience constructors for uiaa::AuthData<commit_after>//! Module for User-Interactive Authentication API types.

use std::{
    collections::BTreeMap,
    fmt::{self, Display, Formatter},
};

use ruma_api::{error::ResponseDeserializationError, EndpointError};
use ruma_serde::Outgoing;
use serde::{Deserialize, Serialize};
use serde_json::{
    from_slice as from_json_slice, to_vec as to_json_vec, value::RawValue as RawJsonValue,
    Value as JsonValue,
};

use crate::error::{Error as MatrixError, ErrorBody};

/// Additional authentication information for the user-interactive authentication API.
#[derive(Clone, Debug, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(untagged)]
pub enum AuthData<'a> {
    /// Used for sending UIAA authentication requests to the homeserver directly from the client.
    // Could be made non-exhaustive by creating a separate struct and making auth_parameters
    // private, but probably not worth the hassle.
    DirectRequest {
        /// The login type that the client is attempting to complete.
        #[serde(rename = "type")]
        kind: &'a str,

        /// The value of the session key given by the homeserver.
        #[serde(skip_serializing_if = "Option::is_none")]
        session: Option<&'a str>,

        /// Parameters submitted for a particular authentication stage.
        #[serde(flatten)]
        auth_parameters: BTreeMap<String, JsonValue>,
    },

    /// Used by the client to acknowledge that the user has completed a UIAA stage through the
    /// fallback method.
    // Exhaustiveness is correct here since this variant is a fallback that explicitly only has a
    // single field. TODO: #[serde(deny_unknown_fields)] not supported on enum variants
    // https://github.com/serde-rs/serde/issues/1982
    FallbackAcknowledgement {
        /// The value of the session key given by the homeserver.
        session: &'a str,
    },
}

impl<'a> AuthData<'a> {
    /// Creates a new `AuthData::DirectRequest` with the given login type.
    pub fn direct_request(kind: &'a str) -> Self {
        Self::DirectRequest { kind, session: None, auth_parameters: BTreeMap::new() }
    }

    /// Creates a new `AuthData::FallbackAcknowledgement` with the given session key.
    pub fn fallback_acknowledgement(session: &'a str) -> Self {
        Self::FallbackAcknowledgement { session }
    }
}

/// Information about available authentication flows and status for User-Interactive Authenticiation
/// API.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct UiaaInfo {
    /// List of authentication flows available for this endpoint.
    pub flows: Vec<AuthFlow>,

    /// List of stages in the current flow completed by the client.
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub completed: Vec<String>,

    /// Authentication parameters required for the client to complete authentication.
    ///
    /// To create a `Box<RawJsonValue>`, use `serde_json::value::to_raw_value`.
    pub params: Box<RawJsonValue>,

    /// Session key for client to use to complete authentication.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub session: Option<String>,

    /// Authentication-related errors for previous request returned by homeserver.
    #[serde(flatten, skip_serializing_if = "Option::is_none")]
    pub auth_error: Option<ErrorBody>,
}

impl UiaaInfo {
    /// Creates a new `UiaaInfo` with the given flows and parameters.
    pub fn new(flows: Vec<AuthFlow>, params: Box<RawJsonValue>) -> Self {
        Self { flows, completed: Vec::new(), params, session: None, auth_error: None }
    }
}

/// Description of steps required to authenticate via the User-Interactive Authentication API.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[cfg_attr(test, derive(PartialEq))]
pub struct AuthFlow {
    /// Ordered list of stages required to complete authentication.
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub stages: Vec<String>,
}

impl AuthFlow {
    /// Creates an empty `AuthFlow`.
    pub fn new() -> Self {
        Self { stages: Vec::new() }
    }
}

/// Contains either a User-Interactive Authentication API response body or a Matrix error.
#[derive(Clone, Debug)]
pub enum UiaaResponse {
    /// User-Interactive Authentication API response
    AuthResponse(UiaaInfo),

    /// Matrix error response
    MatrixError(MatrixError),
}

impl Display for UiaaResponse {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::AuthResponse(_) => write!(f, "User-Interactive Authentication required."),
            Self::MatrixError(err) => write!(f, "{}", err),
        }
    }
}

impl From<MatrixError> for UiaaResponse {
    fn from(error: MatrixError) -> Self {
        Self::MatrixError(error)
    }
}

impl EndpointError for UiaaResponse {
    fn try_from_response(
        response: http::Response<Vec<u8>>,
    ) -> Result<Self, ResponseDeserializationError> {
        if response.status() == http::StatusCode::UNAUTHORIZED {
            if let Ok(authentication_info) = from_json_slice::<UiaaInfo>(response.body()) {
                return Ok(UiaaResponse::AuthResponse(authentication_info));
            }
        }

        MatrixError::try_from_response(response).map(From::from)
    }
}

impl std::error::Error for UiaaResponse {}

impl From<UiaaResponse> for http::Response<Vec<u8>> {
    fn from(uiaa_response: UiaaResponse) -> http::Response<Vec<u8>> {
        match uiaa_response {
            UiaaResponse::AuthResponse(authentication_info) => http::Response::builder()
                .header(http::header::CONTENT_TYPE, "application/json")
                .status(&http::StatusCode::UNAUTHORIZED)
                .body(to_json_vec(&authentication_info).unwrap())
                .unwrap(),
            UiaaResponse::MatrixError(error) => http::Response::from(error),
        }
    }
}

#[cfg(test)]
mod tests {
    use maplit::btreemap;
    use matches::assert_matches;
    use ruma_api::EndpointError;
    use serde_json::{
        from_slice as from_json_slice, from_str as from_json_str, from_value as from_json_value,
        json, to_value as to_json_value, value::to_raw_value as to_raw_json_value,
        Value as JsonValue,
    };

    use super::{AuthData, AuthFlow, IncomingAuthData, UiaaInfo, UiaaResponse};
    use crate::error::{ErrorBody, ErrorKind};

    #[test]
    fn serialize_authentication_data_direct_request() {
        let authentication_data = AuthData::DirectRequest {
            kind: "example.type.foo",
            session: Some("ZXY000"),
            auth_parameters: btreemap! {
                "example_credential".to_owned() => json!("verypoorsharedsecret")
            },
        };

        assert_eq!(
            json!({
                "type": "example.type.foo",
                "session": "ZXY000",
                "example_credential": "verypoorsharedsecret",
            }),
            to_json_value(authentication_data).unwrap()
        );
    }

    #[test]
    fn deserialize_authentication_data_direct_request() {
        let json = json!({
            "type": "example.type.foo",
            "session": "opaque_session_id",
            "example_credential": "verypoorsharedsecret",
        });

        assert_matches!(
            from_json_value(json).unwrap(),
            IncomingAuthData::DirectRequest { kind, session: Some(session), auth_parameters }
            if kind == "example.type.foo"
                && session == "opaque_session_id"
                && auth_parameters == btreemap!{
                    "example_credential".to_owned() => json!("verypoorsharedsecret")
                }
        );
    }

    #[test]
    fn serialize_authentication_data_fallback() {
        let authentication_data = AuthData::FallbackAcknowledgement { session: "ZXY000" };

        assert_eq!(json!({ "session": "ZXY000" }), to_json_value(authentication_data).unwrap());
    }

    #[test]
    fn deserialize_authentication_data_fallback() {
        let json = json!({ "session": "opaque_session_id" });

        assert_matches!(
            from_json_value(json).unwrap(),
            IncomingAuthData::FallbackAcknowledgement { session }
            if session == "opaque_session_id"
        );
    }

    #[test]
    fn serialize_uiaa_info() {
        let uiaa_info = UiaaInfo {
            flows: vec![AuthFlow {
                stages: vec!["m.login.password".into(), "m.login.dummy".into()],
            }],
            completed: vec!["m.login.password".into()],
            params: to_raw_json_value(&json!({
                "example.type.baz": {
                    "example_key": "foobar"
                }
            }))
            .unwrap(),
            session: None,
            auth_error: None,
        };

        let json = json!({
            "flows": [{ "stages": ["m.login.password", "m.login.dummy"] }],
            "completed": ["m.login.password"],
            "params": {
                "example.type.baz": {
                    "example_key": "foobar"
                }
            }
        });
        assert_eq!(to_json_value(uiaa_info).unwrap(), json);
    }

    #[test]
    fn deserialize_uiaa_info() {
        let json = json!({
            "errcode": "M_FORBIDDEN",
            "error": "Invalid password",
            "completed": ["example.type.foo"],
            "flows": [
                {
                    "stages": ["example.type.foo", "example.type.bar"]
                },
                {
                    "stages": ["example.type.foo", "example.type.baz"]
                }
            ],
            "params": {
                "example.type.baz": {
                    "example_key": "foobar"
                }
            },
            "session": "xxxxxx"
        });

        assert_matches!(
            from_json_value::<UiaaInfo>(json).unwrap(),
            UiaaInfo {
                auth_error: Some(ErrorBody {
                    kind: ErrorKind::Forbidden,
                    message: error_message,
                }),
                completed,
                flows,
                params,
                session: Some(session),
            } if error_message == "Invalid password"
                && completed == vec!["example.type.foo".to_owned()]
                && flows == vec![
                    AuthFlow {
                        stages: vec![
                            "example.type.foo".into(),
                            "example.type.bar".into(),
                        ],
                    },
                    AuthFlow {
                        stages: vec![
                            "example.type.foo".into(),
                            "example.type.baz".into(),
                        ],
                    },
                ]
                && from_json_str::<JsonValue>(params.get()).unwrap() == json!({
                    "example.type.baz": {
                        "example_key": "foobar"
                    }
                })
                && session == "xxxxxx"
        );
    }

    #[test]
    fn try_uiaa_response_into_http_response() {
        let uiaa_info = UiaaInfo {
            flows: vec![AuthFlow {
                stages: vec!["m.login.password".into(), "m.login.dummy".into()],
            }],
            completed: vec!["m.login.password".into()],
            params: to_raw_json_value(&json!({
                "example.type.baz": {
                    "example_key": "foobar"
                }
            }))
            .unwrap(),
            session: None,
            auth_error: None,
        };
        let uiaa_response: http::Response<Vec<u8>> = UiaaResponse::AuthResponse(uiaa_info).into();

        assert_matches!(
            from_json_slice::<UiaaInfo>(uiaa_response.body()).unwrap(),
            UiaaInfo {
                flows,
                completed,
                params,
                session: None,
                auth_error: None,
            } if flows == vec![AuthFlow {
                    stages: vec!["m.login.password".into(), "m.login.dummy".into()],
                }]
                && completed == vec!["m.login.password".to_owned()]
                && from_json_str::<JsonValue>(params.get()).unwrap() == json!({
                    "example.type.baz": {
                        "example_key": "foobar"
                    }
                })
        );
        assert_eq!(uiaa_response.status(), http::status::StatusCode::UNAUTHORIZED);
    }

    #[test]
    fn try_uiaa_response_from_http_response() {
        let json = serde_json::to_string(&json!({
            "errcode": "M_FORBIDDEN",
            "error": "Invalid password",
            "completed": [ "example.type.foo" ],
            "flows": [
                {
                    "stages": [ "example.type.foo", "example.type.bar" ]
                },
                {
                    "stages": [ "example.type.foo", "example.type.baz" ]
                }
            ],
            "params": {
                "example.type.baz": {
                    "example_key": "foobar"
                }
            },
            "session": "xxxxxx"
        }))
        .unwrap();

        let http_response = http::Response::builder()
            .status(http::StatusCode::UNAUTHORIZED)
            .body(json.into())
            .unwrap();

        let parsed_uiaa_info = match UiaaResponse::try_from_response(http_response).unwrap() {
            UiaaResponse::AuthResponse(uiaa_info) => uiaa_info,
            _ => panic!("Expected UiaaResponse::AuthResponse"),
        };

        assert_matches!(
            parsed_uiaa_info,
            UiaaInfo {
                auth_error: Some(ErrorBody {
                    kind: ErrorKind::Forbidden,
                    message: error_message,
                }),
                completed,
                flows,
                params,
                session: Some(session),
            } if error_message == "Invalid password"
                && completed == vec!["example.type.foo".to_owned()]
                && flows == vec![
                    AuthFlow {
                        stages: vec![
                            "example.type.foo".into(),
                            "example.type.bar".into(),
                        ],
                    },
                    AuthFlow {
                        stages: vec![
                            "example.type.foo".into(),
                            "example.type.baz".into(),
                        ],
                    },
                ]
                && from_json_str::<JsonValue>(params.get()).unwrap() == json!({
                    "example.type.baz": {
                        "example_key": "foobar"
                    }
                })
                && session == "xxxxxx"
        );
    }
}
<|endoftext|>


<commit_before>#[derive(Debug)]
pub enum CalculatorInput {
    Add,
    Subtract,
    Multiply,
    Divide,
    Value(i32),
}

pub fn evaluate(inputs: &[CalculatorInput]) -> Option<i32> {
    let mut operands: Vec<i32> = Vec::new();

    for input in inputs {
        match input {
            CalculatorInput::Value(x) => operands.push(*x),
            _ => {
                if operands.len() < 2 {
                    return None;
                }
                let operand_b = operands.pop().unwrap();
                let operand_a = operands.pop().unwrap();
                let result: i32 = match input {
                    CalculatorInput::Add => operand_a + operand_b,
                    CalculatorInput::Subtract => operand_a - operand_b,
                    CalculatorInput::Multiply => operand_a * operand_b,
                    CalculatorInput::Divide => operand_a / operand_b,
                    CalculatorInput::Value(_) => panic!("input did not match value"),
                };
                operands.push(result);
            }
        }
    }

    if operands.len() == 1 {
        return Some(operands.pop().unwrap());
    }

    return None;
}
<commit_msg>Remove return to satisfy clippy<commit_after>#[derive(Debug)]
pub enum CalculatorInput {
    Add,
    Subtract,
    Multiply,
    Divide,
    Value(i32),
}

pub fn evaluate(inputs: &[CalculatorInput]) -> Option<i32> {
    let mut operands: Vec<i32> = Vec::new();

    for input in inputs {
        match input {
            CalculatorInput::Value(x) => operands.push(*x),
            _ => {
                if operands.len() < 2 {
                    return None;
                }
                let operand_b = operands.pop().unwrap();
                let operand_a = operands.pop().unwrap();
                let result: i32 = match input {
                    CalculatorInput::Add => operand_a + operand_b,
                    CalculatorInput::Subtract => operand_a - operand_b,
                    CalculatorInput::Multiply => operand_a * operand_b,
                    CalculatorInput::Divide => operand_a / operand_b,
                    CalculatorInput::Value(_) => panic!("input did not match value"),
                };
                operands.push(result);
            }
        }
    }

    if operands.len() == 1 {
        return Some(operands.pop().unwrap());
    }
    None
}
<|endoftext|>


<commit_before>use super::RootMove;
use super::super::MAX_THREADS;
use super::root_moves_list::{RootMoveList,RawRootMoveList};

use std::heap::{Alloc, Layout, Heap};
use std::ptr::Unique;
use std::sync::Arc;
use std::sync::atomic::{Ordering,AtomicUsize,fence,compiler_fence};
use std::mem;

use std::iter::{Iterator,IntoIterator};

use pleco::Board;
use pleco::board::movegen::{MoveGen,Legal};
use pleco::core::mono_traits::AllGenType;

struct RawRmManager {
    pub rms: [RawRootMoveList; MAX_THREADS]
}

impl RawRmManager {
    pub fn new() -> Unique<RawRmManager> {
        unsafe {
            println!("Raw RMManager create: start");
            let ptr = Heap.alloc_zeroed(Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
            println!("Raw RMManager create: created ptr");
            let new_ptr = match ptr {
                Ok(ptr) => ptr,
                Err(err) => Heap.oom(err),
            };
            println!("Raw RMManager create: created new_ptr");
            let raw = Unique::new(new_ptr as *mut RawRmManager).unwrap();
            println!("Raw RMManager create: created raw Unique");
            println!("Creating up to {} RMs...",MAX_THREADS );
            for x in 0..MAX_THREADS {
                print!("Attempt {} :", x);
                let raw_list: &mut RawRootMoveList = (*raw.as_ptr()).rms.get_unchecked_mut(x);
                print!(" raw_list ... ");
                raw_list.init();
                println!("Made raw list");
            }
            println!("Raw RMManager create: Done!");
            raw
        }
    }
}

pub struct RmManager {
    threads: Arc<AtomicUsize>,
    moves: Unique<RawRmManager>,
    ref_count: Arc<AtomicUsize>
}

unsafe impl Send for RmManager {}

impl Clone for RmManager {
    fn clone(&self) -> Self {
        let ref_count: Arc<AtomicUsize> = self.ref_count.clone();
        ref_count.fetch_add(1, Ordering::SeqCst);
        RmManager {
            threads: self.threads.clone(),
            moves: self.moves.clone(),
            ref_count
        }
    }
}

impl RmManager {
    pub fn new() -> Self {
        println!("Creating RmManager");
//        RmManager {
//            threads: Arc::new(AtomicUsize::new(0)),
//            moves: RawRmManager::new(),
//            ref_count: Arc::new(AtomicUsize::new(1))
//        }

        let x = RmManager {
            threads: Arc::new(AtomicUsize::new(0)),
            moves: RawRmManager::new(),
            ref_count: Arc::new(AtomicUsize::new(1))
        };
        println!("Created RmManager Successfully!");
        x
    }

    pub fn threads(&self) -> usize {
        self.threads.load(Ordering::Relaxed)
    }

    pub fn add_thread(&mut self) -> Option<RootMoveList> {
        if self.threads() >= MAX_THREADS {
            None
        } else {
            let thread_idx = self.threads.fetch_add(1, Ordering::SeqCst);
            unsafe {
                Some(self.get_list_unchecked(thread_idx))
            }
        }
    }

    pub fn get_list(&self, num: usize) -> Option<RootMoveList> {
        if num >= self.threads() {
            None
        } else {
            unsafe {
                Some(self.get_list_unchecked(num))
            }
        }
    }

    pub unsafe fn get_list_unchecked(&self, num: usize) -> RootMoveList {
        RootMoveList {
            moves: self.as_raw_ptr().offset(num as isize)
        }
    }

    pub unsafe fn replace_moves(&mut self, board: &Board) {
        let legal_moves = MoveGen::generate::<Legal, AllGenType>(&board);
        let mut first = self.as_ptr();
        first.replace(&legal_moves);
        let num = self.threads();
        for i in 1..num {
            self.get_list_unchecked(i).clone_from_other(&first);
        }
    }

    pub unsafe fn as_ptr(&self) -> RootMoveList {
        RootMoveList {
            moves: mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
        }
    }

    unsafe fn as_raw_ptr(&self) -> *mut RawRootMoveList {
        mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
    }

    pub fn wait_for_finish(&self) {
        unsafe {
            for i in 0..self.threads() {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(true);
            }
        }
    }
    pub fn wait_for_start(&self) {
        unsafe {
            let num_threads = self.threads();
            for i in 0..num_threads {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(false);
            }
        }
    }

    pub fn reset_depths(&self) {
        unsafe {
            for i in 0..self.threads() {
                self.get_list_unchecked(i).set_depth_completed(0);
            }
        }
    }

    pub fn thread_best_move_and_depth(&self, thread_id: usize) -> (RootMove, u16) {
        unsafe {
            let mut thread = self.get_list_unchecked(thread_id);
            (thread.first().clone(), thread.depth_completed())
        }

    }

    pub fn best_rootmove(&self, use_stdout: bool) -> RootMove {
        let (mut best_root_move, mut depth_reached): (RootMove, u16) = self.thread_best_move_and_depth(0);
        if use_stdout {
            println!("id: 0, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}", best_root_move.score, best_root_move.prev_score, best_root_move.depth_reached,depth_reached, best_root_move.bit_move);
        }

        for x in 1..self.threads() {
            let (thread_move, thread_depth): (RootMove, u16)  = self.thread_best_move_and_depth(x);
            let depth_diff = thread_depth as i32 - depth_reached as i32;
            let value_diff = thread_move.score - best_root_move.score;
            if x != 0 {
                // If it has a bigger value and greater or equal depth
                if value_diff > 0 && depth_diff >= 0 {
                    best_root_move = thread_move;
                    depth_reached = thread_depth;
                }
            }

            if use_stdout {
                println!("id: {}, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}",x, thread_move.score, thread_move.prev_score, thread_move.depth_reached,thread_depth, thread_move.bit_move);
            }
        }
        best_root_move
    }
}

pub struct RootMovesIter<'a> {
    root_moves: &'a RmManager,
    threads: usize,
    idx: usize,
}

impl<'a> Iterator for RootMovesIter<'a> {
    type Item = RootMoveList;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.threads {
            None
        } else {
            unsafe {
                Some(self.root_moves.get_list_unchecked(self.idx))
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.threads - self.idx, Some(self.threads - self.idx))
    }
}

impl<'a> IntoIterator for &'a RmManager {
    type Item = RootMoveList;
    type IntoIter = RootMovesIter<'a>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        RootMovesIter {
            root_moves: &self,
            threads: self.threads(),
            idx: 0,
        }
    }
}

impl Drop for RmManager {
    fn drop(&mut self) {
        let num = self.ref_count.fetch_sub(1, Ordering::SeqCst);
        if num == 1 {
            unsafe {
                Heap.dealloc(self.as_raw_ptr() as *mut _,
                             Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn rm_basic() {
        let mut rms = RmManager::new();
        assert_eq!(rms.threads(), 0);
        let moves_1 = rms.add_thread().unwrap();
        assert_eq!(rms.threads(), 1);
        assert_eq!(moves_1.len(), 0);
        let board = Board::default();
        unsafe {
            rms.replace_moves(&board);
            let moves_1_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_1.len(), moves_1_clone.len());
            let moves_2 = rms.add_thread().unwrap();
            assert_eq!(rms.threads(), 2);
            rms.replace_moves(&board);
            let moves_2_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_2.len(), moves_2_clone.len());
            assert_eq!(moves_1.len(), moves_2_clone.len());
        }
    }

    #[test]
    fn rm_cloning() {
        let mut rms = RmManager::new();
        let rmsc = rms.clone();
        rms.add_thread();
        rms.add_thread();
        assert_eq!(rms.threads(), rmsc.threads());
    }
}<commit_msg>More attempss<commit_after>use super::RootMove;
use super::super::MAX_THREADS;
use super::root_moves_list::{RootMoveList,RawRootMoveList};

use std::heap::{Alloc, Layout, Heap};
use std::ptr::Unique;
use std::sync::Arc;
use std::sync::atomic::{Ordering,AtomicUsize,fence,compiler_fence};
use std::mem;

use std::iter::{Iterator,IntoIterator};

use pleco::Board;
use pleco::board::movegen::{MoveGen,Legal};
use pleco::core::mono_traits::AllGenType;

struct RawRmManager {
    pub rms: [RawRootMoveList; MAX_THREADS]
}

impl RawRmManager {
    pub fn new() -> Unique<RawRmManager> {
        unsafe {
            println!("Raw RMManager create: start");
            let ptr = Heap.alloc_zeroed(Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
            println!("Raw RMManager create: created ptr");
            let new_ptr = match ptr {
                Ok(ptr) => ptr,
                Err(err) => Heap.oom(err),
            };
            println!("Raw RMManager create: created new_ptr");
            let raw = Unique::new(new_ptr as *mut RawRmManager).unwrap();
            println!("Raw RMManager create: created raw Unique");
            println!("Creating up to {} RMs...",MAX_THREADS );
            for x in 0..MAX_THREADS {
                print!("Attempt {} :", x);
                let mut list = mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(raw.as_ptr())
                    .offset(x as isize);

//                let raw_list: &mut RawRootMoveList = (*raw.as_ptr()).rms.get_unchecked_mut(x);
                print!(" raw_list ... ");
                (*list).init();
//                raw_list.init();
                println!("Made raw list");
            }
            println!("Raw RMManager create: Done!");
            raw
        }
    }
}

pub struct RmManager {
    threads: Arc<AtomicUsize>,
    moves: Unique<RawRmManager>,
    ref_count: Arc<AtomicUsize>
}

unsafe impl Send for RmManager {}

impl Clone for RmManager {
    fn clone(&self) -> Self {
        let ref_count: Arc<AtomicUsize> = self.ref_count.clone();
        ref_count.fetch_add(1, Ordering::SeqCst);
        RmManager {
            threads: self.threads.clone(),
            moves: self.moves.clone(),
            ref_count
        }
    }
}

impl RmManager {
    pub fn new() -> Self {
        println!("Creating RmManager");
//        RmManager {
//            threads: Arc::new(AtomicUsize::new(0)),
//            moves: RawRmManager::new(),
//            ref_count: Arc::new(AtomicUsize::new(1))
//        }

        let x = RmManager {
            threads: Arc::new(AtomicUsize::new(0)),
            moves: RawRmManager::new(),
            ref_count: Arc::new(AtomicUsize::new(1))
        };
        println!("Created RmManager Successfully!");
        x
    }

    pub fn threads(&self) -> usize {
        self.threads.load(Ordering::Relaxed)
    }

    pub fn add_thread(&mut self) -> Option<RootMoveList> {
        if self.threads() >= MAX_THREADS {
            None
        } else {
            let thread_idx = self.threads.fetch_add(1, Ordering::SeqCst);
            unsafe {
                Some(self.get_list_unchecked(thread_idx))
            }
        }
    }

    pub fn get_list(&self, num: usize) -> Option<RootMoveList> {
        if num >= self.threads() {
            None
        } else {
            unsafe {
                Some(self.get_list_unchecked(num))
            }
        }
    }

    pub unsafe fn get_list_unchecked(&self, num: usize) -> RootMoveList {
        RootMoveList {
            moves: self.as_raw_ptr().offset(num as isize)
        }
    }

    pub unsafe fn replace_moves(&mut self, board: &Board) {
        let legal_moves = MoveGen::generate::<Legal, AllGenType>(&board);
        let mut first = self.as_ptr();
        first.replace(&legal_moves);
        let num = self.threads();
        for i in 1..num {
            self.get_list_unchecked(i).clone_from_other(&first);
        }
    }

    pub unsafe fn as_ptr(&self) -> RootMoveList {
        RootMoveList {
            moves: mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
        }
    }

    unsafe fn as_raw_ptr(&self) -> *mut RawRootMoveList {
        mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
    }

    pub fn wait_for_finish(&self) {
        unsafe {
            for i in 0..self.threads() {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(true);
            }
        }
    }
    pub fn wait_for_start(&self) {
        unsafe {
            let num_threads = self.threads();
            for i in 0..num_threads {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(false);
            }
        }
    }

    pub fn reset_depths(&self) {
        unsafe {
            for i in 0..self.threads() {
                self.get_list_unchecked(i).set_depth_completed(0);
            }
        }
    }

    pub fn thread_best_move_and_depth(&self, thread_id: usize) -> (RootMove, u16) {
        unsafe {
            let mut thread = self.get_list_unchecked(thread_id);
            (thread.first().clone(), thread.depth_completed())
        }

    }

    pub fn best_rootmove(&self, use_stdout: bool) -> RootMove {
        let (mut best_root_move, mut depth_reached): (RootMove, u16) = self.thread_best_move_and_depth(0);
        if use_stdout {
            println!("id: 0, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}", best_root_move.score, best_root_move.prev_score, best_root_move.depth_reached,depth_reached, best_root_move.bit_move);
        }

        for x in 1..self.threads() {
            let (thread_move, thread_depth): (RootMove, u16)  = self.thread_best_move_and_depth(x);
            let depth_diff = thread_depth as i32 - depth_reached as i32;
            let value_diff = thread_move.score - best_root_move.score;
            if x != 0 {
                // If it has a bigger value and greater or equal depth
                if value_diff > 0 && depth_diff >= 0 {
                    best_root_move = thread_move;
                    depth_reached = thread_depth;
                }
            }

            if use_stdout {
                println!("id: {}, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}",x, thread_move.score, thread_move.prev_score, thread_move.depth_reached,thread_depth, thread_move.bit_move);
            }
        }
        best_root_move
    }
}

pub struct RootMovesIter<'a> {
    root_moves: &'a RmManager,
    threads: usize,
    idx: usize,
}

impl<'a> Iterator for RootMovesIter<'a> {
    type Item = RootMoveList;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.threads {
            None
        } else {
            unsafe {
                Some(self.root_moves.get_list_unchecked(self.idx))
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.threads - self.idx, Some(self.threads - self.idx))
    }
}

impl<'a> IntoIterator for &'a RmManager {
    type Item = RootMoveList;
    type IntoIter = RootMovesIter<'a>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        RootMovesIter {
            root_moves: &self,
            threads: self.threads(),
            idx: 0,
        }
    }
}

impl Drop for RmManager {
    fn drop(&mut self) {
        let num = self.ref_count.fetch_sub(1, Ordering::SeqCst);
        if num == 1 {
            unsafe {
                Heap.dealloc(self.as_raw_ptr() as *mut _,
                             Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn rm_basic() {
        let mut rms = RmManager::new();
        assert_eq!(rms.threads(), 0);
        let moves_1 = rms.add_thread().unwrap();
        assert_eq!(rms.threads(), 1);
        assert_eq!(moves_1.len(), 0);
        let board = Board::default();
        unsafe {
            rms.replace_moves(&board);
            let moves_1_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_1.len(), moves_1_clone.len());
            let moves_2 = rms.add_thread().unwrap();
            assert_eq!(rms.threads(), 2);
            rms.replace_moves(&board);
            let moves_2_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_2.len(), moves_2_clone.len());
            assert_eq!(moves_1.len(), moves_2_clone.len());
        }
    }

    #[test]
    fn rm_cloning() {
        let mut rms = RmManager::new();
        let rmsc = rms.clone();
        rms.add_thread();
        rms.add_thread();
        assert_eq!(rms.threads(), rmsc.threads());
    }
}<|endoftext|>


<commit_before>use decimal::Decimal;

/// Create a Decimal from a string literal
///
/// Use only when you _know_ that your value is valid.
fn decimal(input: &str) -> Decimal {
    Decimal::try_from(input).expect("That was supposed to be a valid value")
}

/// Some big and precise values we can use for testing. [0] + [1] == [2]
const BIGS: [&'static str; 3] = [
    "100000000000000000000000000000000000000000000.00000000000000000000000000000000000000001",
    "100000000000000000000000000000000000000000000.00000000000000000000000000000000000000002",
    "200000000000000000000000000000000000000000000.00000000000000000000000000000000000000003",
];

// test simple properties of required operations
#[test]
fn test_eq() {
    assert!(decimal("0.0") == decimal("0.0"));
    assert!(decimal("1.0") == decimal("1.0"));
    for big in BIGS.iter() {
        assert!(decimal(big) == decimal(big));
    }
}

#[test]
#[ignore]
fn test_ne() {
    assert!(decimal("0.0") != decimal("1.0"));
    assert!(decimal(BIGS[0]) != decimal(BIGS[1]));
}

#[test]
#[ignore]
fn test_gt() {
    for slice_2 in BIGS.windows(2) {
        assert!(decimal(slice_2[1]) > decimal(slice_2[0]));
        assert!(!(decimal(slice_2[0]) > decimal(slice_2[1])));
    }
}

#[test]
#[ignore]
fn test_lt() {
    for slice_2 in BIGS.windows(2) {
        assert!(decimal(slice_2[0]) < decimal(slice_2[1]));
        assert!(!(decimal(slice_2[1]) < decimal(slice_2[0])));
    }
}

#[test]
#[ignore]
fn test_add() {
    assert_eq!(decimal("0.1") + decimal("0.2"), decimal("0.3"));
    assert_eq!(decimal(BIGS[0]) + decimal(BIGS[1]), decimal(BIGS[2]));
    assert_eq!(decimal(BIGS[1]) + decimal(BIGS[0]), decimal(BIGS[2]));
}

#[test]
#[ignore]
fn test_sub() {
    assert_eq!(decimal(BIGS[2]) - decimal(BIGS[1]), decimal(BIGS[0]));
    assert_eq!(decimal(BIGS[2]) - decimal(BIGS[0]), decimal(BIGS[1]));
}

#[test]
#[ignore]
fn test_mul() {
    for big in BIGS.iter() {
        assert_eq!(decimal(big) * decimal("2"), decimal(big) + decimal(big));
    }
}

// test identities
#[test]
#[ignore]
fn test_add_id() {
    assert_eq!(decimal("1.0") + decimal("0.0"), decimal("1.0"));
    assert_eq!(decimal("0.1") + decimal("0.0"), decimal("0.1"));
    assert_eq!(decimal("0.0") + decimal("1.0"), decimal("1.0"));
    assert_eq!(decimal("0.0") + decimal("0.1"), decimal("0.1"));
}

#[test]
#[ignore]
fn test_sub_id() {
    assert_eq!(decimal("1.0") - decimal("0.0"), decimal("1.0"));
    assert_eq!(decimal("0.1") - decimal("0.0"), decimal("0.1"));
}

#[test]
#[ignore]
fn test_mul_id() {
    assert_eq!(decimal("2.1") * decimal("1.0"), decimal("2.1"));
    assert_eq!(decimal("1.0") * decimal("2.1"), decimal("2.1"));
}

#[test]
#[ignore]
fn test_gt_positive_and_zero() {
    assert!(decimal("1.0") > decimal("0.0"));
    assert!(decimal("0.1") > decimal("0.0"));
}

#[test]
#[ignore]
fn test_gt_negative_and_zero() {
    assert!(decimal("0.0") > decimal("-0.1"));
    assert!(decimal("0.0") > decimal("-1.0"));
}

// tests of arbitrary precision behavior
#[test]
#[ignore]
fn test_add_uneven_position() {
    assert_eq!(decimal("0.1") + decimal("0.02"), decimal("0.12"));
}

#[test]
#[ignore]
fn test_eq_vary_sig_digits() {
    assert!(decimal("0") == decimal("0000000000000.0000000000000000000000"));
    assert!(decimal("1") == decimal("00000000000000001.000000000000000000"));
}

#[test]
#[ignore]
fn test_add_vary_precision() {
    assert_eq!(
        decimal("100000000000000000000000000000000000000000000")
            + decimal("0.00000000000000000000000000000000000000001"),
        decimal(BIGS[0])
    )
}

#[test]
#[ignore]
fn test_cleanup_precision() {
    assert_eq!(
        decimal("10000000000000000000000000000000000000000000000.999999999999999999999999998",)
            + decimal(
                "10000000000000000000000000000000000000000000000.000000000000000000000000002",
            ),
        decimal("20000000000000000000000000000000000000000000001")
    )
}

#[test]
#[ignore]
fn test_gt_varying_positive_precisions() {
    assert!(decimal("1.1") > decimal("1.01"));
    assert!(decimal("1.01") > decimal("1.0"));
    assert!(decimal("1.0") > decimal("0.1"));
    assert!(decimal("0.1") > decimal("0.01"));
}

#[test]
#[ignore]
fn test_gt_positive_and_negative() {
    assert!(decimal("1.0") > decimal("-1.0"));
    assert!(decimal("1.1") > decimal("-1.1"));
    assert!(decimal("0.1") > decimal("-0.1"));
}

#[test]
#[ignore]
fn test_gt_varying_negative_precisions() {
    assert!(decimal("-0.01") > decimal("-0.1"));
    assert!(decimal("-0.1") > decimal("-1.0"));
    assert!(decimal("-1.0") > decimal("-1.01"));
    assert!(decimal("-1.01") > decimal("-1.1"));
}

// test signed properties
#[test]
#[ignore]
fn test_negatives() {
    assert!(Decimal::try_from("-1").is_some());
    assert_eq!(decimal("0") - decimal("1"), decimal("-1"));
    assert_eq!(decimal("5.5") + decimal("-6.5"), decimal("-1"));
}

#[test]
#[ignore]
fn test_explicit_positive() {
    assert_eq!(decimal("+1"), decimal("1"));
    assert_eq!(decimal("+2.0") - decimal("-0002.0"), decimal("4"));
}

#[test]
#[ignore]
fn test_multiply_by_negative() {
    assert_eq!(decimal("5") * decimal("-0.2"), decimal("-1"));
    assert_eq!(decimal("-20") * decimal("-0.2"), decimal("4"));
}

#[test]
#[ignore]
fn test_simple_partial_cmp() {
    assert!(decimal("1.0") < decimal("1.1"));
    assert!(decimal("0.00000000000000000000001") > decimal("-20000000000000000000000000000"));
}

// test carrying rules
// these tests are designed to ensure correctness of implementations for which the
// integer and fractional parts of the number are stored separately
#[test]
#[ignore]
fn test_carry_into_integer() {
    assert_eq!(decimal("0.901") + decimal("0.1"), decimal("1.001"))
}

#[test]
#[ignore]
fn test_carry_into_fractional_with_digits_to_right() {
    assert_eq!(decimal("0.0901") + decimal("0.01"), decimal("0.1001"))
}

#[test]
#[ignore]
fn test_add_carry_over_negative() {
    assert_eq!(decimal("-1.99") + decimal("-0.01"), decimal("-2.0"))
}

#[test]
#[ignore]
fn test_sub_carry_over_negative() {
    assert_eq!(decimal("-1.99") - decimal("0.01"), decimal("-2.0"))
}

#[test]
#[ignore]
fn test_add_carry_over_negative_with_fractional() {
    assert_eq!(decimal("-1.99") + decimal("-0.02"), decimal("-2.01"))
}

#[test]
#[ignore]
fn test_sub_carry_over_negative_with_fractional() {
    assert_eq!(decimal("-1.99") - decimal("0.02"), decimal("-2.01"))
}

#[test]
#[ignore]
fn test_carry_from_rightmost_one() {
    assert_eq!(decimal("0.09") + decimal("0.01"), decimal("0.1"))
}

#[test]
#[ignore]
fn test_carry_from_rightmost_more() {
    assert_eq!(decimal("0.099") + decimal("0.001"), decimal("0.1"))
}

#[test]
#[ignore]
fn test_carry_from_rightmost_into_integer() {
    assert_eq!(decimal("0.999") + decimal("0.001"), decimal("1.0"))
}

// test arithmetic borrow rules
#[test]
#[ignore]
fn test_add_borrow() {
    assert_eq!(decimal("0.01") + decimal("-0.0001"), decimal("0.0099"))
}

#[test]
#[ignore]
fn test_sub_borrow() {
    assert_eq!(decimal("0.01") - decimal("0.0001"), decimal("0.0099"))
}

#[test]
#[ignore]
fn test_add_borrow_integral() {
    assert_eq!(decimal("1.0") + decimal("-0.01"), decimal("0.99"))
}

#[test]
#[ignore]
fn test_sub_borrow_integral() {
    assert_eq!(decimal("1.0") - decimal("0.01"), decimal("0.99"))
}

#[test]
#[ignore]
fn test_add_borrow_integral_zeroes() {
    assert_eq!(decimal("1.0") + decimal("-0.99"), decimal("0.01"))
}

#[test]
#[ignore]
fn test_sub_borrow_integral_zeroes() {
    assert_eq!(decimal("1.0") - decimal("0.99"), decimal("0.01"))
}

#[test]
#[ignore]
fn test_borrow_from_negative() {
    assert_eq!(decimal("-1.0") + decimal("0.01"), decimal("-0.99"))
}

#[test]
#[ignore]
fn test_add_into_fewer_digits() {
    assert_eq!(decimal("0.011") + decimal("-0.001"), decimal("0.01"))
}

// misc tests of arithmetic properties
#[test]
#[ignore]
fn test_sub_into_fewer_digits() {
    assert_eq!(decimal("0.011") - decimal("0.001"), decimal("0.01"))
}

#[test]
#[ignore]
fn test_add_away_decimal() {
    assert_eq!(decimal("1.1") + decimal("-0.1"), decimal("1.0"))
}

#[test]
#[ignore]
fn test_sub_away_decimal() {
    assert_eq!(decimal("1.1") - decimal("0.1"), decimal("1.0"))
}
<commit_msg>decimal: remove 'static lifetime of const<commit_after>use decimal::Decimal;

/// Create a Decimal from a string literal
///
/// Use only when you _know_ that your value is valid.
fn decimal(input: &str) -> Decimal {
    Decimal::try_from(input).expect("That was supposed to be a valid value")
}

/// Some big and precise values we can use for testing. [0] + [1] == [2]
const BIGS: [&str; 3] = [
    "100000000000000000000000000000000000000000000.00000000000000000000000000000000000000001",
    "100000000000000000000000000000000000000000000.00000000000000000000000000000000000000002",
    "200000000000000000000000000000000000000000000.00000000000000000000000000000000000000003",
];

// test simple properties of required operations
#[test]
fn test_eq() {
    assert!(decimal("0.0") == decimal("0.0"));
    assert!(decimal("1.0") == decimal("1.0"));
    for big in BIGS.iter() {
        assert!(decimal(big) == decimal(big));
    }
}

#[test]
#[ignore]
fn test_ne() {
    assert!(decimal("0.0") != decimal("1.0"));
    assert!(decimal(BIGS[0]) != decimal(BIGS[1]));
}

#[test]
#[ignore]
fn test_gt() {
    for slice_2 in BIGS.windows(2) {
        assert!(decimal(slice_2[1]) > decimal(slice_2[0]));
        assert!(!(decimal(slice_2[0]) > decimal(slice_2[1])));
    }
}

#[test]
#[ignore]
fn test_lt() {
    for slice_2 in BIGS.windows(2) {
        assert!(decimal(slice_2[0]) < decimal(slice_2[1]));
        assert!(!(decimal(slice_2[1]) < decimal(slice_2[0])));
    }
}

#[test]
#[ignore]
fn test_add() {
    assert_eq!(decimal("0.1") + decimal("0.2"), decimal("0.3"));
    assert_eq!(decimal(BIGS[0]) + decimal(BIGS[1]), decimal(BIGS[2]));
    assert_eq!(decimal(BIGS[1]) + decimal(BIGS[0]), decimal(BIGS[2]));
}

#[test]
#[ignore]
fn test_sub() {
    assert_eq!(decimal(BIGS[2]) - decimal(BIGS[1]), decimal(BIGS[0]));
    assert_eq!(decimal(BIGS[2]) - decimal(BIGS[0]), decimal(BIGS[1]));
}

#[test]
#[ignore]
fn test_mul() {
    for big in BIGS.iter() {
        assert_eq!(decimal(big) * decimal("2"), decimal(big) + decimal(big));
    }
}

// test identities
#[test]
#[ignore]
fn test_add_id() {
    assert_eq!(decimal("1.0") + decimal("0.0"), decimal("1.0"));
    assert_eq!(decimal("0.1") + decimal("0.0"), decimal("0.1"));
    assert_eq!(decimal("0.0") + decimal("1.0"), decimal("1.0"));
    assert_eq!(decimal("0.0") + decimal("0.1"), decimal("0.1"));
}

#[test]
#[ignore]
fn test_sub_id() {
    assert_eq!(decimal("1.0") - decimal("0.0"), decimal("1.0"));
    assert_eq!(decimal("0.1") - decimal("0.0"), decimal("0.1"));
}

#[test]
#[ignore]
fn test_mul_id() {
    assert_eq!(decimal("2.1") * decimal("1.0"), decimal("2.1"));
    assert_eq!(decimal("1.0") * decimal("2.1"), decimal("2.1"));
}

#[test]
#[ignore]
fn test_gt_positive_and_zero() {
    assert!(decimal("1.0") > decimal("0.0"));
    assert!(decimal("0.1") > decimal("0.0"));
}

#[test]
#[ignore]
fn test_gt_negative_and_zero() {
    assert!(decimal("0.0") > decimal("-0.1"));
    assert!(decimal("0.0") > decimal("-1.0"));
}

// tests of arbitrary precision behavior
#[test]
#[ignore]
fn test_add_uneven_position() {
    assert_eq!(decimal("0.1") + decimal("0.02"), decimal("0.12"));
}

#[test]
#[ignore]
fn test_eq_vary_sig_digits() {
    assert!(decimal("0") == decimal("0000000000000.0000000000000000000000"));
    assert!(decimal("1") == decimal("00000000000000001.000000000000000000"));
}

#[test]
#[ignore]
fn test_add_vary_precision() {
    assert_eq!(
        decimal("100000000000000000000000000000000000000000000")
            + decimal("0.00000000000000000000000000000000000000001"),
        decimal(BIGS[0])
    )
}

#[test]
#[ignore]
fn test_cleanup_precision() {
    assert_eq!(
        decimal("10000000000000000000000000000000000000000000000.999999999999999999999999998",)
            + decimal(
                "10000000000000000000000000000000000000000000000.000000000000000000000000002",
            ),
        decimal("20000000000000000000000000000000000000000000001")
    )
}

#[test]
#[ignore]
fn test_gt_varying_positive_precisions() {
    assert!(decimal("1.1") > decimal("1.01"));
    assert!(decimal("1.01") > decimal("1.0"));
    assert!(decimal("1.0") > decimal("0.1"));
    assert!(decimal("0.1") > decimal("0.01"));
}

#[test]
#[ignore]
fn test_gt_positive_and_negative() {
    assert!(decimal("1.0") > decimal("-1.0"));
    assert!(decimal("1.1") > decimal("-1.1"));
    assert!(decimal("0.1") > decimal("-0.1"));
}

#[test]
#[ignore]
fn test_gt_varying_negative_precisions() {
    assert!(decimal("-0.01") > decimal("-0.1"));
    assert!(decimal("-0.1") > decimal("-1.0"));
    assert!(decimal("-1.0") > decimal("-1.01"));
    assert!(decimal("-1.01") > decimal("-1.1"));
}

// test signed properties
#[test]
#[ignore]
fn test_negatives() {
    assert!(Decimal::try_from("-1").is_some());
    assert_eq!(decimal("0") - decimal("1"), decimal("-1"));
    assert_eq!(decimal("5.5") + decimal("-6.5"), decimal("-1"));
}

#[test]
#[ignore]
fn test_explicit_positive() {
    assert_eq!(decimal("+1"), decimal("1"));
    assert_eq!(decimal("+2.0") - decimal("-0002.0"), decimal("4"));
}

#[test]
#[ignore]
fn test_multiply_by_negative() {
    assert_eq!(decimal("5") * decimal("-0.2"), decimal("-1"));
    assert_eq!(decimal("-20") * decimal("-0.2"), decimal("4"));
}

#[test]
#[ignore]
fn test_simple_partial_cmp() {
    assert!(decimal("1.0") < decimal("1.1"));
    assert!(decimal("0.00000000000000000000001") > decimal("-20000000000000000000000000000"));
}

// test carrying rules
// these tests are designed to ensure correctness of implementations for which the
// integer and fractional parts of the number are stored separately
#[test]
#[ignore]
fn test_carry_into_integer() {
    assert_eq!(decimal("0.901") + decimal("0.1"), decimal("1.001"))
}

#[test]
#[ignore]
fn test_carry_into_fractional_with_digits_to_right() {
    assert_eq!(decimal("0.0901") + decimal("0.01"), decimal("0.1001"))
}

#[test]
#[ignore]
fn test_add_carry_over_negative() {
    assert_eq!(decimal("-1.99") + decimal("-0.01"), decimal("-2.0"))
}

#[test]
#[ignore]
fn test_sub_carry_over_negative() {
    assert_eq!(decimal("-1.99") - decimal("0.01"), decimal("-2.0"))
}

#[test]
#[ignore]
fn test_add_carry_over_negative_with_fractional() {
    assert_eq!(decimal("-1.99") + decimal("-0.02"), decimal("-2.01"))
}

#[test]
#[ignore]
fn test_sub_carry_over_negative_with_fractional() {
    assert_eq!(decimal("-1.99") - decimal("0.02"), decimal("-2.01"))
}

#[test]
#[ignore]
fn test_carry_from_rightmost_one() {
    assert_eq!(decimal("0.09") + decimal("0.01"), decimal("0.1"))
}

#[test]
#[ignore]
fn test_carry_from_rightmost_more() {
    assert_eq!(decimal("0.099") + decimal("0.001"), decimal("0.1"))
}

#[test]
#[ignore]
fn test_carry_from_rightmost_into_integer() {
    assert_eq!(decimal("0.999") + decimal("0.001"), decimal("1.0"))
}

// test arithmetic borrow rules
#[test]
#[ignore]
fn test_add_borrow() {
    assert_eq!(decimal("0.01") + decimal("-0.0001"), decimal("0.0099"))
}

#[test]
#[ignore]
fn test_sub_borrow() {
    assert_eq!(decimal("0.01") - decimal("0.0001"), decimal("0.0099"))
}

#[test]
#[ignore]
fn test_add_borrow_integral() {
    assert_eq!(decimal("1.0") + decimal("-0.01"), decimal("0.99"))
}

#[test]
#[ignore]
fn test_sub_borrow_integral() {
    assert_eq!(decimal("1.0") - decimal("0.01"), decimal("0.99"))
}

#[test]
#[ignore]
fn test_add_borrow_integral_zeroes() {
    assert_eq!(decimal("1.0") + decimal("-0.99"), decimal("0.01"))
}

#[test]
#[ignore]
fn test_sub_borrow_integral_zeroes() {
    assert_eq!(decimal("1.0") - decimal("0.99"), decimal("0.01"))
}

#[test]
#[ignore]
fn test_borrow_from_negative() {
    assert_eq!(decimal("-1.0") + decimal("0.01"), decimal("-0.99"))
}

#[test]
#[ignore]
fn test_add_into_fewer_digits() {
    assert_eq!(decimal("0.011") + decimal("-0.001"), decimal("0.01"))
}

// misc tests of arithmetic properties
#[test]
#[ignore]
fn test_sub_into_fewer_digits() {
    assert_eq!(decimal("0.011") - decimal("0.001"), decimal("0.01"))
}

#[test]
#[ignore]
fn test_add_away_decimal() {
    assert_eq!(decimal("1.1") + decimal("-0.1"), decimal("1.0"))
}

#[test]
#[ignore]
fn test_sub_away_decimal() {
    assert_eq!(decimal("1.1") - decimal("0.1"), decimal("1.0"))
}
<|endoftext|>


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

//! The context within which style is calculated.

use animation::Animation;
use app_units::Au;
use bloom::StyleBloom;
use dom::{OpaqueNode, TElement};
use error_reporting::ParseErrorReporter;
use euclid::Size2D;
use matching::StyleSharingCandidateCache;
use parking_lot::RwLock;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::Sender;
use stylist::Stylist;
use timer::Timer;

/// This structure is used to create a local style context from a shared one.
pub struct ThreadLocalStyleContextCreationInfo {
    new_animations_sender: Sender<Animation>,
}

impl ThreadLocalStyleContextCreationInfo {
    pub fn new(animations_sender: Sender<Animation>) -> Self {
        ThreadLocalStyleContextCreationInfo {
            new_animations_sender: animations_sender,
        }
    }
}

#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum QuirksMode {
    Quirks,
    LimitedQuirks,
    NoQuirks,
}

pub struct SharedStyleContext {
    /// The current viewport size.
    pub viewport_size: Size2D<Au>,

    /// Screen sized changed?
    pub screen_size_changed: bool,

    /// The CSS selector stylist.
    pub stylist: Arc<Stylist>,

    /// Why is this reflow occurring
    pub goal: ReflowGoal,

    /// The animations that are currently running.
    pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,

    /// The list of animations that have expired since the last style recalculation.
    pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,

    ///The CSS error reporter for all CSS loaded in this layout thread
    pub error_reporter: Box<ParseErrorReporter + Sync>,

    /// Data needed to create the thread-local style context from the shared one.
    pub local_context_creation_data: Mutex<ThreadLocalStyleContextCreationInfo>,

    /// The current timer for transitions and animations. This is needed to test
    /// them.
    pub timer: Timer,

    /// The QuirksMode state which the document needs to be rendered with
    pub quirks_mode: QuirksMode,
}

pub struct ThreadLocalStyleContext<E: TElement> {
    pub style_sharing_candidate_cache: StyleSharingCandidateCache<E>,
    pub bloom_filter: StyleBloom<E>,
    /// A channel on which new animations that have been triggered by style
    /// recalculation can be sent.
    pub new_animations_sender: Sender<Animation>,
}

impl<E: TElement> ThreadLocalStyleContext<E> {
    pub fn new(shared: &SharedStyleContext) -> Self {
        ThreadLocalStyleContext {
            style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
            bloom_filter: StyleBloom::new(),
            new_animations_sender: shared.local_context_creation_data.lock().unwrap().new_animations_sender.clone(),
        }
    }
}

pub struct StyleContext<'a, E: TElement + 'a> {
    pub shared: &'a SharedStyleContext,
    pub thread_local: &'a mut ThreadLocalStyleContext<E>,
}

/// Why we're doing reflow.
#[derive(PartialEq, Copy, Clone, Debug)]
pub enum ReflowGoal {
    /// We're reflowing in order to send a display list to the screen.
    ForDisplay,
    /// We're reflowing in order to satisfy a script query. No display list will be created.
    ForScriptQuery,
}
<commit_msg>style: Document the `StyleContext` module.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The context within which style is calculated.
#![deny(missing_docs)]

use animation::Animation;
use app_units::Au;
use bloom::StyleBloom;
use dom::{OpaqueNode, TElement};
use error_reporting::ParseErrorReporter;
use euclid::Size2D;
use matching::StyleSharingCandidateCache;
use parking_lot::RwLock;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::Sender;
use stylist::Stylist;
use timer::Timer;

/// This structure is used to create a local style context from a shared one.
pub struct ThreadLocalStyleContextCreationInfo {
    new_animations_sender: Sender<Animation>,
}

impl ThreadLocalStyleContextCreationInfo {
    /// Trivially constructs a `ThreadLocalStyleContextCreationInfo`.
    pub fn new(animations_sender: Sender<Animation>) -> Self {
        ThreadLocalStyleContextCreationInfo {
            new_animations_sender: animations_sender,
        }
    }
}

/// Which quirks mode is this document in.
///
/// See: https://quirks.spec.whatwg.org/
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum QuirksMode {
    /// Quirks mode.
    Quirks,
    /// Limited quirks mode.
    LimitedQuirks,
    /// No quirks mode.
    NoQuirks,
}

/// A shared style context.
///
/// There's exactly one of these during a given restyle traversal, and it's
/// shared among the worker threads.
pub struct SharedStyleContext {
    /// The current viewport size.
    pub viewport_size: Size2D<Au>,

    /// Screen sized changed?
    pub screen_size_changed: bool,

    /// The CSS selector stylist.
    pub stylist: Arc<Stylist>,

    /// Why is this reflow occurring
    pub goal: ReflowGoal,

    /// The animations that are currently running.
    pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,

    /// The list of animations that have expired since the last style recalculation.
    pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,

    ///The CSS error reporter for all CSS loaded in this layout thread
    pub error_reporter: Box<ParseErrorReporter + Sync>,

    /// Data needed to create the thread-local style context from the shared one.
    pub local_context_creation_data: Mutex<ThreadLocalStyleContextCreationInfo>,

    /// The current timer for transitions and animations. This is needed to test
    /// them.
    pub timer: Timer,

    /// The QuirksMode state which the document needs to be rendered with
    pub quirks_mode: QuirksMode,
}

/// A thread-local style context.
///
/// This context contains data that needs to be used during restyling, but is
/// not required to be unique among worker threads, so we create one per worker
/// thread in order to be able to mutate it without locking.
pub struct ThreadLocalStyleContext<E: TElement> {
    /// A cache to share style among siblings.
    pub style_sharing_candidate_cache: StyleSharingCandidateCache<E>,
    /// The bloom filter used to fast-reject selector-matching.
    pub bloom_filter: StyleBloom<E>,
    /// A channel on which new animations that have been triggered by style
    /// recalculation can be sent.
    pub new_animations_sender: Sender<Animation>,
}

impl<E: TElement> ThreadLocalStyleContext<E> {
    /// Create a new `ThreadLocalStyleContext` from a shared one.
    pub fn new(shared: &SharedStyleContext) -> Self {
        ThreadLocalStyleContext {
            style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
            bloom_filter: StyleBloom::new(),
            new_animations_sender: shared.local_context_creation_data.lock().unwrap().new_animations_sender.clone(),
        }
    }
}

/// A `StyleContext` is just a simple container for a immutable reference to a
/// shared style context, and a mutable reference to a local one.
pub struct StyleContext<'a, E: TElement + 'a> {
    /// The shared style context reference.
    pub shared: &'a SharedStyleContext,
    /// The thread-local style context (mutable) reference.
    pub thread_local: &'a mut ThreadLocalStyleContext<E>,
}

/// Why we're doing reflow.
#[derive(PartialEq, Copy, Clone, Debug)]
pub enum ReflowGoal {
    /// We're reflowing in order to send a display list to the screen.
    ForDisplay,
    /// We're reflowing in order to satisfy a script query. No display list will be created.
    ForScriptQuery,
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;
extern crate sdl2;

#[macro_use]
extern crate clap;

pub mod gpu;
pub mod controller;
mod sound;

#[allow(dead_code)]
mod debugger;

extern crate gb;

use std::fs::{File, OpenOptions};
use std::io::{Read, Write, Seek, SeekFrom};

use gb::Emulator;

use self::controller::{Event, Controller};
use self::debugger::Debugger;

#[cfg(test)]
mod tests;

fn open_save_file(rom_name: &str) -> Result<File, String> {
    let mut v: Vec<&str> = rom_name.split('.').collect();
    // If the file does not end with .gb we might be reading garbage,
    // let's bail.
    if v.pop() != Some("gb") {
        return Err(format!("Invalid ROM name: '{}' filename must end with '.gb'.", rom_name));
    }

    // Replace extension with "sav"
    v.push("srm");

    let save_name = v.join(".");

    Ok(OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(save_name)
        .unwrap())
}

fn open_rom(rom_name: &str) -> Result<File, String> {
    let f = File::open(rom_name);
    f.map_err(|_| format!("Error: ROM '{}' not found.", rom_name))
}

// Similar to try! but for the main function
macro_rules! bail {
    ($expr : expr) => {
        {
            if $expr.is_err() {
                println!("{}", $expr.unwrap_err());
                return;
            }

            $expr.unwrap()
        }
    }
}

pub fn main() {
    let matches = clap_app!(gbrust =>
        (version: "0.1b")
        (author: "Agi Sferro <agi.novanta@gmail.com>")
        (about: "Yet another DMG emulator written in Rust.")
        (@arg ROM: +required "Selects the ROM to run.")
        (@arg mag: -m --magnification +takes_value "Number of times the screen should be magnified. Default is '3'.")
        (@arg debug: -d --debug "Starts in debug mode.")
    ).get_matches();

    let rom_name = matches.value_of("ROM").unwrap();
    let mut save_file = bail!(open_save_file(&rom_name));

    let mag = value_t!(matches.value_of("mag"), u32).unwrap_or_else(|e| {
        println!("Invalid magnification: {}", e);
        3
    });

    let mut controller = Controller::new(gb::SCREEN_X as u32 * mag,
                                         gb::SCREEN_Y as u32 * mag);

    let mut emulator;
    {
        let mut rom_bytes = vec![];
        let mut rom = bail!(open_rom(&rom_name));
        bail!(rom.read_to_end(&mut rom_bytes));

        emulator = Emulator::from_data(&rom_bytes, 44100.0).unwrap();

        // Load save file in ram
        bail!(save_file.read_exact(emulator.cpu.handler_holder.ram()));
    }

    let mut debugger = Debugger::new();

    if matches.occurrences_of("debug") > 0 {
        debugger.breakpoint(&mut emulator);
    }

    let mut natural_speed = true;

    loop {
        debugger.check_breakpoints(&mut emulator);

        emulator.cpu.next_instruction();

        if emulator.cpu.handler_holder.should_refresh() {
            match controller.check_events(&mut emulator) {
                Event::Quit => break,
                Event::Break => {
                    debugger.breakpoint(&mut emulator);
                },
                Event::ToggleSpeed => { natural_speed = !natural_speed },
                Event::Continue => {},
            }

            controller.refresh(&mut emulator);
        }

        debugger.next_instruction(&mut emulator);
    }

    bail!(save_file.seek(SeekFrom::Start(0)));
    bail!(save_file.write_all(emulator.cpu.handler_holder.ram()));
}
<commit_msg>Don't crash the frontend if there isn't a save file.<commit_after>#[macro_use]
extern crate glium;
extern crate sdl2;

#[macro_use]
extern crate clap;

pub mod gpu;
pub mod controller;
mod sound;

#[allow(dead_code)]
mod debugger;

extern crate gb;

use std::fs::{File, OpenOptions};
use std::io::{Read, Write, Seek, SeekFrom};

use gb::Emulator;

use self::controller::{Event, Controller};
use self::debugger::Debugger;

#[cfg(test)]
mod tests;

fn open_save_file(rom_name: &str) -> Result<File, String> {
    let mut v: Vec<&str> = rom_name.split('.').collect();
    // If the file does not end with .gb we might be reading garbage,
    // let's bail.
    if v.pop() != Some("gb") {
        return Err(format!("Invalid ROM name: '{}' filename must end with '.gb'.", rom_name));
    }

    // Replace extension with "sav"
    v.push("srm");

    let save_name = v.join(".");

    Ok(OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(save_name)
        .unwrap())
}

fn open_rom(rom_name: &str) -> Result<File, String> {
    let f = File::open(rom_name);
    f.map_err(|_| format!("Error: ROM '{}' not found.", rom_name))
}

// Similar to try! but for the main function
macro_rules! bail {
    ($expr : expr) => {
        {
            if $expr.is_err() {
                println!("{}", $expr.unwrap_err());
                return;
            }

            $expr.unwrap()
        }
    }
}

pub fn main() {
    let matches = clap_app!(gbrust =>
        (version: "0.1b")
        (author: "Agi Sferro <agi.novanta@gmail.com>")
        (about: "Yet another DMG emulator written in Rust.")
        (@arg ROM: +required "Selects the ROM to run.")
        (@arg mag: -m --magnification +takes_value "Number of times the screen should be magnified. Default is '3'.")
        (@arg debug: -d --debug "Starts in debug mode.")
    ).get_matches();

    let rom_name = matches.value_of("ROM").unwrap();
    let mut save_file = bail!(open_save_file(&rom_name));

    let mag = value_t!(matches.value_of("mag"), u32).unwrap_or_else(|e| {
        println!("Invalid magnification: {}", e);
        3
    });

    let mut controller = Controller::new(gb::SCREEN_X as u32 * mag,
                                         gb::SCREEN_Y as u32 * mag);

    let mut emulator;
    {
        let mut rom_bytes = vec![];
        let mut rom = bail!(open_rom(&rom_name));
        bail!(rom.read_to_end(&mut rom_bytes));

        emulator = Emulator::from_data(&rom_bytes, 44100.0).unwrap();

        // Load save file in ram
        // we don't care if we can't fill the whole buffer, it just
        // means that we don't have a save file
        let _ = save_file.read_exact(emulator.cpu.handler_holder.ram());
    }

    let mut debugger = Debugger::new();

    if matches.occurrences_of("debug") > 0 {
        debugger.breakpoint(&mut emulator);
    }

    let mut natural_speed = true;

    loop {
        debugger.check_breakpoints(&mut emulator);

        emulator.cpu.next_instruction();

        if emulator.cpu.handler_holder.should_refresh() {
            match controller.check_events(&mut emulator) {
                Event::Quit => break,
                Event::Break => {
                    debugger.breakpoint(&mut emulator);
                },
                Event::ToggleSpeed => { natural_speed = !natural_speed },
                Event::Continue => {},
            }

            controller.refresh(&mut emulator);
        }

        debugger.next_instruction(&mut emulator);
    }

    bail!(save_file.seek(SeekFrom::Start(0)));
    bail!(save_file.write_all(emulator.cpu.handler_holder.ram()));
}
<|endoftext|>


<commit_before>#![feature(rustc_attrs)]
#![deny(const_err)]

fn black_box<T>(_: T) {
    unimplemented!()
}

fn main() {
    let b = 200u8 + 200u8 + 200u8;
    //~^ ERROR const_err
    let c = 200u8 * 4;
    //~^ ERROR const_err
    let d = 42u8 - (42u8 + 1);
    //~^ ERROR const_err
    let _e = [5u8][1];
    //~^ ERROR const_err
    //~| ERROR this expression will panic at runtime
    black_box(b);
    black_box(c);
    black_box(d);
}
<commit_msg>fix compile-fail tests<commit_after>#![feature(rustc_attrs)]
#![deny(const_err)]

fn black_box<T>(_: T) {
    unimplemented!()
}

fn main() {
    let b = 200u8 + 200u8 + 200u8;
    //~^ ERROR const_err
    let c = 200u8 * 4;
    //~^ ERROR const_err
    let d = 42u8 - (42u8 + 1);
    //~^ ERROR const_err
    let _e = [5u8][1];
    //~^ ERROR const_err
    black_box(b);
    black_box(c);
    black_box(d);
}
<|endoftext|>


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

#[allow(unused_unsafe)];
#[deny(unsafe_block)];

unsafe fn allowed() {}

#[allow(unsafe_block)] fn also_allowed() { unsafe {} }

fn main() {
    unsafe {} //~ ERROR: usage of an `unsafe` block
}
<commit_msg>auto merge of #10606 : huonw/rust/lint-unsafe-in-macro, r=thestinger<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[allow(unused_unsafe)];
#[deny(unsafe_block)];
#[feature(macro_rules)];

unsafe fn allowed() {}

#[allow(unsafe_block)] fn also_allowed() { unsafe {} }

macro_rules! unsafe_in_macro {
    () => {
        unsafe {} //~ ERROR: usage of an `unsafe` block
    }
}

fn main() {
    unsafe {} //~ ERROR: usage of an `unsafe` block

    unsafe_in_macro!()
}
<|endoftext|>


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

// Test incremental compilation tracking where we change field names
// in between revisions (hashing should be stable).

// revisions:rpass1 rpass2 rpass3
// compile-flags: -Z query-dep-graph

#![feature(rustc_attrs)]

// Check that reordering otherwise identical items is not considered a
// change at all.
#[rustc_clean(label="Krate", cfg="rpass2")]

// But removing an item, naturally, is.
#[rustc_dirty(label="Krate", cfg="rpass3")]

#[cfg(rpass1)]
pub struct X {
    pub x: u32,
}

pub struct Y {
    pub x: u32,
}

#[cfg(rpass2)]
pub struct X {
    pub x: u32,
}

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

// Test that the crate hash is not affected by reordering items.

// revisions:rpass1 rpass2 rpass3
// compile-flags: -Z query-dep-graph

#![feature(rustc_attrs)]

// Check that reordering otherwise identical items is not considered a
// change at all.
#[rustc_clean(label="Krate", cfg="rpass2")]

// But removing an item, naturally, is.
#[rustc_dirty(label="Krate", cfg="rpass3")]

#[cfg(rpass1)]
pub struct X {
    pub x: u32,
}

pub struct Y {
    pub x: u32,
}

#[cfg(rpass2)]
pub struct X {
    pub x: u32,
}

pub fn main() { }
<|endoftext|>