<commit_before>use itertools::Itertools;
use rand::seq::SliceRandom;

/// Convenience function to generate a new petname from default word lists.
#[allow(dead_code)]
#[cfg(feature = "std_rng")]
pub fn petname(words: u8, separator: &str) -> String {
    Petnames::default().generate_one(words, separator)
}

/// A word list.
pub type Words<'a> = Vec<&'a str>;

/// Word lists and the logic to combine them into _petnames_.
///
/// A _petname_ with `n` words will contain, in order:
///
///   * `n - 2` adverbs when `n >= 2`, otherwise 0 adverbs.
///   * 1 adjective when `n >= 2`, otherwise 0 adjectives.
///   * 1 name / noun when `n >= 1`, otherwise 0 names.
///
#[derive(Clone, Debug, PartialEq)]
pub struct Petnames<'a> {
    pub adjectives: Words<'a>,
    pub adverbs: Words<'a>,
    pub names: Words<'a>,
}

impl<'a> Petnames<'a> {
    /// Constructs a new `Petnames` from the default (small) word lists.
    pub fn default() -> Self {
        Self::small()
    }

    /// Constructs a new `Petnames` from the small word lists.
    pub fn small() -> Self {
        Self::init(
            include_str!("../words/small/adjectives.txt"),
            include_str!("../words/small/adverbs.txt"),
            include_str!("../words/small/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the medium word lists.
    pub fn medium() -> Self {
        Self::init(
            include_str!("../words/medium/adjectives.txt"),
            include_str!("../words/medium/adverbs.txt"),
            include_str!("../words/medium/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the large word lists.
    pub fn large() -> Self {
        Self::init(
            include_str!("../words/large/adjectives.txt"),
            include_str!("../words/large/adverbs.txt"),
            include_str!("../words/large/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the given word lists.
    ///
    /// The words are extracted from the given strings by splitting on whitespace.
    pub fn init(adjectives: &'a str, adverbs: &'a str, names: &'a str) -> Self {
        Self {
            adjectives: adjectives.split_whitespace().collect(),
            adverbs: adverbs.split_whitespace().collect(),
            names: names.split_whitespace().collect(),
        }
    }

    /// Keep words matching a predicate.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut petnames = petname::Petnames::default();
    /// petnames.retain(|s| s.starts_with("b"));
    /// # #[cfg(feature = "std_rng")]
    /// petnames.generate_one(2, ".");
    /// ```
    ///
    /// This is merely a convenience wrapper that applies the same predicate to
    /// the adjectives, adverbs, and names lists.
    ///
    pub fn retain<F>(&mut self, mut predicate: F)
    where
        F: FnMut(&str) -> bool,
    {
        self.adjectives.retain(|word| predicate(word));
        self.adverbs.retain(|word| predicate(word));
        self.names.retain(|word| predicate(word));
    }

    /// Calculate the cardinality of this `Petnames`.
    ///
    /// If this is low, names may be repeated by the generator with a higher
    /// frequency than your use-case may allow. If it is 0 (zero) the generator
    /// will panic (unless `words` is also zero).
    ///
    /// This can saturate. If the total possible combinations of words exceeds
    /// `u128::MAX` then this will return `u128::MAX`.
    pub fn cardinality(&self, words: u8) -> u128 {
        Lists(self, words)
            .map(|list| list.len() as u128)
            .fold1(u128::saturating_mul)
            .unwrap_or(0u128)
    }

    /// Generate a new petname.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # #[cfg(feature = "std_rng")]
    /// let mut rng = rand::thread_rng();
    /// # #[cfg(feature = "std_rng")]
    /// petname::Petnames::default().generate(&mut rng, 7, ":");
    /// ```
    ///
    /// # Notes
    ///
    /// This may return fewer words than you request if one or more of the word
    /// lists are empty. For example, if there are no adverbs, requesting 3 or
    /// more words may still yield only "doubtful-salmon".
    ///
    pub fn generate<RNG>(&self, rng: &mut RNG, words: u8, separator: &str) -> String
    where
        RNG: rand::Rng,
    {
        Lists(self, words)
            .filter_map(|list| list.choose(rng))
            .cloned()
            .intersperse(separator)
            .collect::<String>()
    }

    /// Generate a single new petname.
    ///
    /// This is like `generate` but uses `rand::thread_rng` as the random
    /// source. For efficiency use `generate` when creating multiple names, or
    /// when you want to use a custom source of randomness.
    #[cfg(feature = "std_rng")]
    pub fn generate_one(&self, words: u8, separator: &str) -> String {
        self.generate(&mut rand::thread_rng(), words, separator)
    }

    /// Iterator yielding petnames.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # #[cfg(feature = "std_rng")]
    /// let mut rng = rand::thread_rng();
    /// # #[cfg(feature = "std_rng")]
    /// let petnames = petname::Petnames::default();
    /// # #[cfg(feature = "std_rng")]
    /// let mut iter = petnames.iter(&mut rng, 4, "_");
    /// # #[cfg(feature = "std_rng")]
    /// println!("name: {}", iter.next().unwrap());
    /// ```
    ///
    pub fn iter<RNG>(&self, rng: &'a mut RNG, words: u8, separator: &str) -> Names<RNG>
    where
        RNG: rand::Rng,
    {
        Names {
            petnames: self,
            rng,
            words,
            separator: separator.to_string(),
        }
    }
}

impl<'a> Default for Petnames<'a> {
    fn default() -> Self {
        Self::default()
    }
}

/// Iterator over a `Petnames`' word lists.
///
/// This yields the appropriate lists from which to select a word when
/// constructing a petname of `n` words. For example, if you want 3 words in
/// your petname, this will first yield the adverbs word list, then adjectives,
/// then names.
struct Lists<'a>(&'a Petnames<'a>, u8);

impl<'a> Iterator for Lists<'a> {
    type Item = &'a Words<'a>;

    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, Some(self.1 as usize))
    }

    fn next(&mut self) -> Option<Self::Item> {
        let Self(petnames, ref mut word) = self;
        match word {
            0 => None,
            1 => {
                *word -= 1;
                Some(&petnames.names)
            }
            2 => {
                *word -= 1;
                Some(&petnames.adjectives)
            }
            _ => {
                *word -= 1;
                Some(&petnames.adverbs)
            }
        }
    }
}

/// Iterator yielding petnames.
pub struct Names<'a, RNG>
where
    RNG: rand::Rng,
{
    petnames: &'a Petnames<'a>,
    rng: &'a mut RNG,
    words: u8,
    separator: String,
}

impl<'a, RNG> Names<'a, RNG>
where
    RNG: rand::Rng,
{
    /// Calculate the cardinality of this iterator; see `Petnames::cardinality`.
    #[allow(dead_code)]
    pub fn cardinality(&self) -> u128 {
        self.petnames.cardinality(self.words)
    }
}

impl<'a, RNG> Iterator for Names<'a, RNG>
where
    RNG: rand::Rng,
{
    type Item = String;

    fn next(&mut self) -> Option<Self::Item> {
        Some(
            self.petnames
                .generate(self.rng, self.words, &self.separator),
        )
    }
}

#[cfg(test)]
mod tests {

    #[cfg(feature = "std_rng")]
    use super::petname;
    use super::Petnames;
    use rand::rngs::mock::StepRng;

    #[test]
    fn default_petnames_has_adjectives() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adjectives.len(), 0);
    }

    #[test]
    fn default_petnames_has_adverbs() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adverbs.len(), 0);
    }

    #[test]
    fn default_petnames_has_names() {
        let petnames = Petnames::default();
        assert_ne!(petnames.names.len(), 0);
    }

    #[test]
    fn retain_applies_given_predicate() {
        let petnames_expected = Petnames::init("bob", "bob", "bob jane");
        let mut petnames = Petnames::init("alice bob carol", "alice bob", "bob carol jane");
        petnames.retain(|word| word.len() < 5);
        assert_eq!(petnames_expected, petnames);
    }

    #[test]
    fn default_petnames_has_non_zero_cardinality() {
        let petnames = Petnames::default();
        // This test will need to be adjusted when word lists change.
        assert_eq!(0, petnames.cardinality(0));
        assert_eq!(456, petnames.cardinality(1));
        assert_eq!(204744, petnames.cardinality(2));
        assert_eq!(53438184, petnames.cardinality(3));
        assert_eq!(13947366024, petnames.cardinality(4));
    }

    #[test]
    fn generate_uses_adverb_adjective_name() {
        let petnames = Petnames {
            adjectives: vec!["adjective"],
            adverbs: vec!["adverb"],
            names: vec!["name"],
        };
        assert_eq!(
            petnames.generate(&mut StepRng::new(0, 1), 3, "-"),
            "adverb-adjective-name"
        );
    }

    #[test]
    #[cfg(feature = "std_rng")]
    fn petname_renders_desired_number_of_words() {
        assert_eq!(petname(7, "-").split("-").count(), 7);
    }

    #[test]
    #[cfg(feature = "std_rng")]
    fn petname_renders_with_desired_separator() {
        assert_eq!(petname(7, "@").split("@").count(), 7);
    }

    #[test]
    fn petnames_iter_has_cardinality() {
        let mut rng = StepRng::new(0, 1);
        let petnames = Petnames::init("a b", "c d e", "f g h i");
        let names = petnames.iter(&mut rng, 3, ".");
        assert_eq!(24u128, names.cardinality());
    }

    #[test]
    fn petnames_iter_yields_names() {
        let mut rng = StepRng::new(0, 1);
        let petnames = Petnames::init("foo", "bar", "baz");
        let names = petnames.iter(&mut rng, 3, ".");
        // Definintely an Iterator...
        let mut iter: Box<dyn Iterator<Item = _>> = Box::new(names);
        assert_eq!(Some("bar.foo.baz".to_string()), iter.next());
    }
}
<commit_msg>fix clippy lint with char pattern<commit_after>use itertools::Itertools;
use rand::seq::SliceRandom;

/// Convenience function to generate a new petname from default word lists.
#[allow(dead_code)]
#[cfg(feature = "std_rng")]
pub fn petname(words: u8, separator: &str) -> String {
    Petnames::default().generate_one(words, separator)
}

/// A word list.
pub type Words<'a> = Vec<&'a str>;

/// Word lists and the logic to combine them into _petnames_.
///
/// A _petname_ with `n` words will contain, in order:
///
///   * `n - 2` adverbs when `n >= 2`, otherwise 0 adverbs.
///   * 1 adjective when `n >= 2`, otherwise 0 adjectives.
///   * 1 name / noun when `n >= 1`, otherwise 0 names.
///
#[derive(Clone, Debug, PartialEq)]
pub struct Petnames<'a> {
    pub adjectives: Words<'a>,
    pub adverbs: Words<'a>,
    pub names: Words<'a>,
}

impl<'a> Petnames<'a> {
    /// Constructs a new `Petnames` from the default (small) word lists.
    pub fn default() -> Self {
        Self::small()
    }

    /// Constructs a new `Petnames` from the small word lists.
    pub fn small() -> Self {
        Self::init(
            include_str!("../words/small/adjectives.txt"),
            include_str!("../words/small/adverbs.txt"),
            include_str!("../words/small/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the medium word lists.
    pub fn medium() -> Self {
        Self::init(
            include_str!("../words/medium/adjectives.txt"),
            include_str!("../words/medium/adverbs.txt"),
            include_str!("../words/medium/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the large word lists.
    pub fn large() -> Self {
        Self::init(
            include_str!("../words/large/adjectives.txt"),
            include_str!("../words/large/adverbs.txt"),
            include_str!("../words/large/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the given word lists.
    ///
    /// The words are extracted from the given strings by splitting on whitespace.
    pub fn init(adjectives: &'a str, adverbs: &'a str, names: &'a str) -> Self {
        Self {
            adjectives: adjectives.split_whitespace().collect(),
            adverbs: adverbs.split_whitespace().collect(),
            names: names.split_whitespace().collect(),
        }
    }

    /// Keep words matching a predicate.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut petnames = petname::Petnames::default();
    /// petnames.retain(|s| s.starts_with("b"));
    /// # #[cfg(feature = "std_rng")]
    /// petnames.generate_one(2, ".");
    /// ```
    ///
    /// This is merely a convenience wrapper that applies the same predicate to
    /// the adjectives, adverbs, and names lists.
    ///
    pub fn retain<F>(&mut self, mut predicate: F)
    where
        F: FnMut(&str) -> bool,
    {
        self.adjectives.retain(|word| predicate(word));
        self.adverbs.retain(|word| predicate(word));
        self.names.retain(|word| predicate(word));
    }

    /// Calculate the cardinality of this `Petnames`.
    ///
    /// If this is low, names may be repeated by the generator with a higher
    /// frequency than your use-case may allow. If it is 0 (zero) the generator
    /// will panic (unless `words` is also zero).
    ///
    /// This can saturate. If the total possible combinations of words exceeds
    /// `u128::MAX` then this will return `u128::MAX`.
    pub fn cardinality(&self, words: u8) -> u128 {
        Lists(self, words)
            .map(|list| list.len() as u128)
            .fold1(u128::saturating_mul)
            .unwrap_or(0u128)
    }

    /// Generate a new petname.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # #[cfg(feature = "std_rng")]
    /// let mut rng = rand::thread_rng();
    /// # #[cfg(feature = "std_rng")]
    /// petname::Petnames::default().generate(&mut rng, 7, ":");
    /// ```
    ///
    /// # Notes
    ///
    /// This may return fewer words than you request if one or more of the word
    /// lists are empty. For example, if there are no adverbs, requesting 3 or
    /// more words may still yield only "doubtful-salmon".
    ///
    pub fn generate<RNG>(&self, rng: &mut RNG, words: u8, separator: &str) -> String
    where
        RNG: rand::Rng,
    {
        Lists(self, words)
            .filter_map(|list| list.choose(rng))
            .cloned()
            .intersperse(separator)
            .collect::<String>()
    }

    /// Generate a single new petname.
    ///
    /// This is like `generate` but uses `rand::thread_rng` as the random
    /// source. For efficiency use `generate` when creating multiple names, or
    /// when you want to use a custom source of randomness.
    #[cfg(feature = "std_rng")]
    pub fn generate_one(&self, words: u8, separator: &str) -> String {
        self.generate(&mut rand::thread_rng(), words, separator)
    }

    /// Iterator yielding petnames.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # #[cfg(feature = "std_rng")]
    /// let mut rng = rand::thread_rng();
    /// # #[cfg(feature = "std_rng")]
    /// let petnames = petname::Petnames::default();
    /// # #[cfg(feature = "std_rng")]
    /// let mut iter = petnames.iter(&mut rng, 4, "_");
    /// # #[cfg(feature = "std_rng")]
    /// println!("name: {}", iter.next().unwrap());
    /// ```
    ///
    pub fn iter<RNG>(&self, rng: &'a mut RNG, words: u8, separator: &str) -> Names<RNG>
    where
        RNG: rand::Rng,
    {
        Names {
            petnames: self,
            rng,
            words,
            separator: separator.to_string(),
        }
    }
}

impl<'a> Default for Petnames<'a> {
    fn default() -> Self {
        Self::default()
    }
}

/// Iterator over a `Petnames`' word lists.
///
/// This yields the appropriate lists from which to select a word when
/// constructing a petname of `n` words. For example, if you want 3 words in
/// your petname, this will first yield the adverbs word list, then adjectives,
/// then names.
struct Lists<'a>(&'a Petnames<'a>, u8);

impl<'a> Iterator for Lists<'a> {
    type Item = &'a Words<'a>;

    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, Some(self.1 as usize))
    }

    fn next(&mut self) -> Option<Self::Item> {
        let Self(petnames, ref mut word) = self;
        match word {
            0 => None,
            1 => {
                *word -= 1;
                Some(&petnames.names)
            }
            2 => {
                *word -= 1;
                Some(&petnames.adjectives)
            }
            _ => {
                *word -= 1;
                Some(&petnames.adverbs)
            }
        }
    }
}

/// Iterator yielding petnames.
pub struct Names<'a, RNG>
where
    RNG: rand::Rng,
{
    petnames: &'a Petnames<'a>,
    rng: &'a mut RNG,
    words: u8,
    separator: String,
}

impl<'a, RNG> Names<'a, RNG>
where
    RNG: rand::Rng,
{
    /// Calculate the cardinality of this iterator; see `Petnames::cardinality`.
    #[allow(dead_code)]
    pub fn cardinality(&self) -> u128 {
        self.petnames.cardinality(self.words)
    }
}

impl<'a, RNG> Iterator for Names<'a, RNG>
where
    RNG: rand::Rng,
{
    type Item = String;

    fn next(&mut self) -> Option<Self::Item> {
        Some(
            self.petnames
                .generate(self.rng, self.words, &self.separator),
        )
    }
}

#[cfg(test)]
mod tests {

    #[cfg(feature = "std_rng")]
    use super::petname;
    use super::Petnames;
    use rand::rngs::mock::StepRng;

    #[test]
    fn default_petnames_has_adjectives() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adjectives.len(), 0);
    }

    #[test]
    fn default_petnames_has_adverbs() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adverbs.len(), 0);
    }

    #[test]
    fn default_petnames_has_names() {
        let petnames = Petnames::default();
        assert_ne!(petnames.names.len(), 0);
    }

    #[test]
    fn retain_applies_given_predicate() {
        let petnames_expected = Petnames::init("bob", "bob", "bob jane");
        let mut petnames = Petnames::init("alice bob carol", "alice bob", "bob carol jane");
        petnames.retain(|word| word.len() < 5);
        assert_eq!(petnames_expected, petnames);
    }

    #[test]
    fn default_petnames_has_non_zero_cardinality() {
        let petnames = Petnames::default();
        // This test will need to be adjusted when word lists change.
        assert_eq!(0, petnames.cardinality(0));
        assert_eq!(456, petnames.cardinality(1));
        assert_eq!(204744, petnames.cardinality(2));
        assert_eq!(53438184, petnames.cardinality(3));
        assert_eq!(13947366024, petnames.cardinality(4));
    }

    #[test]
    fn generate_uses_adverb_adjective_name() {
        let petnames = Petnames {
            adjectives: vec!["adjective"],
            adverbs: vec!["adverb"],
            names: vec!["name"],
        };
        assert_eq!(
            petnames.generate(&mut StepRng::new(0, 1), 3, "-"),
            "adverb-adjective-name"
        );
    }

    #[test]
    #[cfg(feature = "std_rng")]
    fn petname_renders_desired_number_of_words() {
        assert_eq!(petname(7, "-").split('-').count(), 7);
    }

    #[test]
    #[cfg(feature = "std_rng")]
    fn petname_renders_with_desired_separator() {
        assert_eq!(petname(7, "@").split('@').count(), 7);
    }

    #[test]
    fn petnames_iter_has_cardinality() {
        let mut rng = StepRng::new(0, 1);
        let petnames = Petnames::init("a b", "c d e", "f g h i");
        let names = petnames.iter(&mut rng, 3, ".");
        assert_eq!(24u128, names.cardinality());
    }

    #[test]
    fn petnames_iter_yields_names() {
        let mut rng = StepRng::new(0, 1);
        let petnames = Petnames::init("foo", "bar", "baz");
        let names = petnames.iter(&mut rng, 3, ".");
        // Definintely an Iterator...
        let mut iter: Box<dyn Iterator<Item = _>> = Box::new(names);
        assert_eq!(Some("bar.foo.baz".to_string()), iter.next());
    }
}
<|endoftext|>


<commit_before>//! Space API definitions and serialization.
//!
//! This crate contains all data-related definitions that are present in the
//! [Space API](https://spacedirectory.org/). It also handles serializing and
//! deserializing of that data from/to JSON by implementing the Serde
//! [`Serialize`](https://docs.serde.rs/serde/ser/trait.Serialize.html) and
//! [`Deserialize`](https://docs.serde.rs/serde/de/trait.Deserialize.html)
//! traits for all structs.
//!
//! The currently supported Space API version is 0.13. It is not yet fully
//! implemented.
//!
//! If you want to implement a Space API server on top of these types, you
//! might want to take a look at the [`spaceapi_server`
//! crate](https://github.com/spaceapi-community/spaceapi-server-rs).
//!
//! This library requires Rust 1.15 or newer.
//!
//! # Examples
//!
//! ## Serializing
//!
//! You can create a new `Status` instance by using the `StatusBuilder`.
//!
//!     extern crate serde;
//!     extern crate serde_json;
//!     extern crate spaceapi;
//!
//!     use spaceapi::{Status, StatusBuilder, Location, Contact};
//!
//!     # fn main() {
//!     let status = StatusBuilder::new("coredump")
//!         .logo("https://www.coredump.ch/logo.png")
//!         .url("https://www.coredump.ch/")
//!         .location(
//!             Location {
//!                 address: None,
//!                 lat: 47.22936,
//!                 lon: 8.82949,
//!             })
//!         .contact(
//!             Contact {
//!                 irc: Some("irc://freenode.net/#coredump".into()),
//!                 twitter: Some("@coredump_ch".into()),
//!                 foursquare: Some("525c20e5498e875d8231b1e5".into()),
//!                 email: Some("danilo@coredump.ch".into()),
//!                 ..Default::default()
//!             })
//!         .add_issue_report_channel("email")
//!         .add_issue_report_channel("twitter")
//!         .build()
//!         .expect("Creating status failed");
//!     let serialized = serde_json::to_string(&status).unwrap();
//!     let deserialized: Status = serde_json::from_str(&serialized).unwrap();
//!
//!     # assert!(&serialized[0..1] == "{");
//!     # assert_eq!(deserialized, status);
//!     # }
//!
//! ## Deserializing
//!
//! You can deserialize any struct of the Space API through Serde:
//!
//!     extern crate serde;
//!     extern crate serde_json;
//!     extern crate spaceapi;
//!
//!     use spaceapi::Location;
//!
//!     # fn main() {
//!     let location = "{\"lat\": 47.22936, \"lon\": 8.82949}";
//!     let decoded: Location = serde_json::from_str(location).unwrap();
//!     println!("{:?}", decoded);
//!
//!     // Output:
//!     // Location { address: None, lat: 47.22936000000001, lon: 8.829490000000002 }
//!     # }

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

pub mod sensors;
mod status;
pub use status::*;

/// Return own crate version. Used in API responses.
pub fn get_version() -> &'static str {
    env!("CARGO_PKG_VERSION")
}

#[cfg(test)]
mod test {
    use super::get_version;

    #[test]
    fn test_get_version() {
        let version = get_version();
        assert_eq!(3, version.split('.').count());
    }
}
<commit_msg>Fix wrong minimum Rust version in docstring<commit_after>//! Space API definitions and serialization.
//!
//! This crate contains all data-related definitions that are present in the
//! [Space API](https://spacedirectory.org/). It also handles serializing and
//! deserializing of that data from/to JSON by implementing the Serde
//! [`Serialize`](https://docs.serde.rs/serde/ser/trait.Serialize.html) and
//! [`Deserialize`](https://docs.serde.rs/serde/de/trait.Deserialize.html)
//! traits for all structs.
//!
//! The currently supported Space API version is 0.13. It is not yet fully
//! implemented.
//!
//! If you want to implement a Space API server on top of these types, you
//! might want to take a look at the [`spaceapi_server`
//! crate](https://github.com/spaceapi-community/spaceapi-server-rs).
//!
//! This library requires Rust 1.20.0 or newer.
//!
//! # Examples
//!
//! ## Serializing
//!
//! You can create a new `Status` instance by using the `StatusBuilder`.
//!
//!     extern crate serde;
//!     extern crate serde_json;
//!     extern crate spaceapi;
//!
//!     use spaceapi::{Status, StatusBuilder, Location, Contact};
//!
//!     # fn main() {
//!     let status = StatusBuilder::new("coredump")
//!         .logo("https://www.coredump.ch/logo.png")
//!         .url("https://www.coredump.ch/")
//!         .location(
//!             Location {
//!                 address: None,
//!                 lat: 47.22936,
//!                 lon: 8.82949,
//!             })
//!         .contact(
//!             Contact {
//!                 irc: Some("irc://freenode.net/#coredump".into()),
//!                 twitter: Some("@coredump_ch".into()),
//!                 foursquare: Some("525c20e5498e875d8231b1e5".into()),
//!                 email: Some("danilo@coredump.ch".into()),
//!                 ..Default::default()
//!             })
//!         .add_issue_report_channel("email")
//!         .add_issue_report_channel("twitter")
//!         .build()
//!         .expect("Creating status failed");
//!     let serialized = serde_json::to_string(&status).unwrap();
//!     let deserialized: Status = serde_json::from_str(&serialized).unwrap();
//!
//!     # assert!(&serialized[0..1] == "{");
//!     # assert_eq!(deserialized, status);
//!     # }
//!
//! ## Deserializing
//!
//! You can deserialize any struct of the Space API through Serde:
//!
//!     extern crate serde;
//!     extern crate serde_json;
//!     extern crate spaceapi;
//!
//!     use spaceapi::Location;
//!
//!     # fn main() {
//!     let location = "{\"lat\": 47.22936, \"lon\": 8.82949}";
//!     let decoded: Location = serde_json::from_str(location).unwrap();
//!     println!("{:?}", decoded);
//!
//!     // Output:
//!     // Location { address: None, lat: 47.22936000000001, lon: 8.829490000000002 }
//!     # }

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

pub mod sensors;
mod status;
pub use status::*;

/// Return own crate version. Used in API responses.
pub fn get_version() -> &'static str {
    env!("CARGO_PKG_VERSION")
}

#[cfg(test)]
mod test {
    use super::get_version;

    #[test]
    fn test_get_version() {
        let version = get_version();
        assert_eq!(3, version.split('.').count());
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate redis;

use std::str;
use std::cell::Cell;
use std::thread;
use std::ops::{Deref, Drop};
use std::convert::From;
use std::marker::PhantomData;
use rustc_serialize::{json, Decodable};
use redis::{Value, RedisResult, ErrorKind, Commands};

#[derive(RustcDecodable, RustcEncodable)]
struct Job {
    id: u64
}

pub trait TaskDecodable where Self: Sized {
    fn decode_task(value: &Value) -> RedisResult<Self>;
}

impl<T: Decodable> TaskDecodable for T {
    fn decode_task(value: &Value) -> RedisResult<T> {
        match value {
            &Value::Data(ref v) => {
                let s = try!(str::from_utf8(&v));
                Ok(try!(json::decode(&s).map_err(|_| (ErrorKind::TypeError, "JSON decode failed"))))

            },
            v @ _ => {
                println!("what do we have here: {:?}", v);
                try!(Err((ErrorKind::TypeError, "Can only decode from a string")))
            }
        }
    }
}

pub struct TaskGuard<'a, T: 'a> {
    task: T,
    worker: &'a Worker<T>
}

impl<'a, T: TaskDecodable> TaskGuard<'a, T> {
    pub fn stop(&self) {
        self.worker.stop();
    }

    pub fn inner(&self) -> &T {
        &self.task
    }
}

impl<'a, T> Deref for TaskGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.task
    }
}

impl<'a, T> Drop for TaskGuard<'a, T> {
    fn drop(&mut self) {
        // Pop job from backup queue
        let backup = &self.worker.backup_queue[..];
        let _ : () = self.worker.client.lpop(backup).expect("LPOP from backup queue failed");
    }
}

pub struct Worker<T> {
    queue_name: String,
    backup_queue: String,
    stopped: Cell<bool>,
    pub client: redis::Connection,
    _job_type: PhantomData<T>,
}

impl<T: TaskDecodable> Worker<T> {
    pub fn new(name: String, client: redis::Connection) -> Worker<T> {
        let backup_queue = [thread::current().name().unwrap_or("default".into()), "1"].join(":");
        Worker {
            queue_name: name,
            backup_queue: backup_queue,
            client: client,
            stopped: Cell::new(false),
            _job_type: PhantomData,
        }
    }

    pub fn stop(&self) {
        self.stopped.set(true);
    }

    pub fn is_stopped(&self) -> bool {
        self.stopped.get()
    }

    pub fn next(&self) -> Option<RedisResult<TaskGuard<T>>> {
        if self.stopped.get() {
            return None;
        }

        let v;
        {
            let qname = &self.queue_name[..];
            let backup = &self.backup_queue[..];

            v = match self.client.brpoplpush(qname, backup, 0) {
                Ok(v) => v,
                Err(_) => {
                    return Some(Err(From::from((ErrorKind::TypeError, "next failed"))));
                }
            };
        }

        let v = match v {
            v @ Value::Data(_) => v,
            _ => {
                return Some(Err(From::from((ErrorKind::TypeError, "Not a 2-item Bulk reply"))));
            }
        };

        let task = T::decode_task(&v).unwrap();

        Some(Ok(TaskGuard{task: task, worker: self}))
    }
}

#[test]
fn decodes_job() {
    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();

    let _ : () = con.rpush("default", "{\"id\":42}").unwrap();

    let mut worker = Worker::<Job>::new("default".into(), con);
    let j = worker.next().unwrap().unwrap();
    assert_eq!(42, j.id);
}

#[test]
fn releases_job() {
    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();
    let mut worker = Worker::<Job>::new("default".into(), con);

    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();

    let _ : () = con.lpush("default", "{\"id\":42}").unwrap();

    {
        let j = worker.next().unwrap().unwrap();
        assert_eq!(42, j.id);
        let in_backup : Vec<String> = con.lrange("releases_job:1", 0, -1).unwrap();
        assert_eq!(1, in_backup.len());
        assert_eq!("{\"id\":42}", in_backup[0]);
    }

    let in_backup : Vec<String> = con.lrange("releases_job:1", 0, -1).unwrap();
    assert_eq!(0, in_backup.len());
}

#[test]
fn can_be_stopped() {
    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();
    let _ : () = con.del("stopper").unwrap();
    let _ : () = con.lpush("stopper", "{\"id\":1}").unwrap();
    let _ : () = con.lpush("stopper", "{\"id\":2}").unwrap();
    let _ : () = con.lpush("stopper", "{\"id\":3}").unwrap();

    let len : u32 = con.llen("stopper").unwrap();
    assert_eq!(3, len);

    let mut worker = Worker::<Job>::new("stopper".into(), con);
    while let Some(mut task) = worker.next() {
        let task = task.unwrap();
        task.stop();
    }

    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();
    let len : u32 = con.llen("stopper").unwrap();
    assert_eq!(2, len);
}
<commit_msg>refactor: Move job struct to tests<commit_after>extern crate rustc_serialize;
extern crate redis;

use std::str;
use std::cell::Cell;
use std::thread;
use std::ops::{Deref, Drop};
use std::convert::From;
use rustc_serialize::{json, Decodable};
use redis::{Value, RedisResult, ErrorKind, Commands};

pub trait TaskDecodable where Self: Sized {
    fn decode_task(value: &Value) -> RedisResult<Self>;
}

impl<T: Decodable> TaskDecodable for T {
    fn decode_task(value: &Value) -> RedisResult<T> {
        match value {
            &Value::Data(ref v) => {
                let s = try!(str::from_utf8(&v));
                Ok(try!(json::decode(&s).map_err(|_| (ErrorKind::TypeError, "JSON decode failed"))))

            },
            v @ _ => {
                println!("what do we have here: {:?}", v);
                try!(Err((ErrorKind::TypeError, "Can only decode from a string")))
            }
        }
    }
}

pub struct TaskGuard<'a, T: 'a> {
    task: T,
    worker: &'a Worker
}

impl<'a, T> TaskGuard<'a, T> {
    pub fn stop(&self) {
        self.worker.stop();
    }

    pub fn inner(&self) -> &T {
        &self.task
    }
}

impl<'a, T> Deref for TaskGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.task
    }
}

impl<'a, T> Drop for TaskGuard<'a, T> {
    fn drop(&mut self) {
        // Pop job from backup queue
        let backup = &self.worker.backup_queue[..];
        let _ : () = self.worker.client.lpop(backup).expect("LPOP from backup queue failed");
    }
}

pub struct Worker {
    queue_name: String,
    backup_queue: String,
    stopped: Cell<bool>,
    pub client: redis::Connection,
}

impl Worker {
    pub fn new(name: String, client: redis::Connection) -> Worker {
        let backup_queue = [thread::current().name().unwrap_or("default".into()), "1"].join(":");
        Worker {
            queue_name: name,
            backup_queue: backup_queue,
            client: client,
            stopped: Cell::new(false),
        }
    }

    pub fn stop(&self) {
        self.stopped.set(true);
    }

    pub fn is_stopped(&self) -> bool {
        self.stopped.get()
    }

    pub fn queue(&self) -> &str {
        &self.queue_name
    }

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

    pub fn next<T: TaskDecodable>(&self) -> Option<RedisResult<TaskGuard<T>>> {
        if self.stopped.get() {
            return None;
        }

        let v;
        {
            let qname = &self.queue_name[..];
            let backup = &self.backup_queue[..];

            v = match self.client.brpoplpush(qname, backup, 0) {
                Ok(v) => v,
                Err(_) => {
                    return Some(Err(From::from((ErrorKind::TypeError, "next failed"))));
                }
            };
        }

        let v = match v {
            v @ Value::Data(_) => v,
            _ => {
                return Some(Err(From::from((ErrorKind::TypeError, "Not a 2-item Bulk reply"))));
            }
        };

        let task = T::decode_task(&v).unwrap();

        Some(Ok(TaskGuard{task: task, worker: self}))
    }
}

#[cfg(test)]
mod test {
    extern crate redis;

    use redis::Commands;
    use super::*;

    #[derive(RustcDecodable, RustcEncodable)]
    struct Job {
        id: u64
    }

    #[test]
    fn decodes_job() {
        let client = redis::Client::open("redis://127.0.0.1/").unwrap();
        let con = client.get_connection().unwrap();

        let _ : () = con.rpush("default", "{\"id\":42}").unwrap();

        let worker = Worker::new("default".into(), con);
        let j = worker.next::<Job>().unwrap().unwrap();
        assert_eq!(42, j.id);
    }

    #[test]
    fn releases_job() {
        let client = redis::Client::open("redis://127.0.0.1/").unwrap();
        let con = client.get_connection().unwrap();
        let worker = Worker::new("default".into(), con);
        let bqueue = worker.backup_queue();

        let client = redis::Client::open("redis://127.0.0.1/").unwrap();
        let con = client.get_connection().unwrap();

        let _ : () = con.lpush("default", "{\"id\":42}").unwrap();

        {
            let j = worker.next::<Job>().unwrap().unwrap();
            assert_eq!(42, j.id);
            let in_backup : Vec<String> = con.lrange(bqueue, 0, -1).unwrap();
            assert_eq!(1, in_backup.len());
            assert_eq!("{\"id\":42}", in_backup[0]);
        }

        let in_backup : Vec<String> = con.lrange(bqueue, 0, -1).unwrap();
        assert_eq!(0, in_backup.len());
    }

    #[test]
    fn can_be_stopped() {
        let client = redis::Client::open("redis://127.0.0.1/").unwrap();
        let con = client.get_connection().unwrap();
        let _ : () = con.del("stopper").unwrap();
        let _ : () = con.lpush("stopper", "{\"id\":1}").unwrap();
        let _ : () = con.lpush("stopper", "{\"id\":2}").unwrap();
        let _ : () = con.lpush("stopper", "{\"id\":3}").unwrap();

        let len : u32 = con.llen("stopper").unwrap();
        assert_eq!(3, len);

        let worker = Worker::new("stopper".into(), con);
        while let Some(task) = worker.next::<Job>() {
            let task = task.unwrap();
            task.stop();
        }

        let client = redis::Client::open("redis://127.0.0.1/").unwrap();
        let con = client.get_connection().unwrap();
        let len : u32 = con.llen("stopper").unwrap();
        assert_eq!(2, len);
    }
}
<|endoftext|>


<commit_before>//! Manipulations and data types that represent 2d matrix.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

extern crate num;

use std::fmt::{Display, Formatter, Result};
use std::ops::{Add, Index, IndexMut, Mul, Sub};
use num::{One, Zero};

/// 2D matrix.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Matrix<T> {
    row: usize,
    column: usize,
    data: Vec<T>
}

impl<T> Matrix<T> {
    /// Creates a new `Matrix`.
    #[inline]
    pub fn from_fn<F>(row: usize, column: usize, f: F) -> Matrix<T>
        where F:Fn(usize, usize) -> T
    {
        Matrix {
            row: row,
            column: column,
            data: (0 .. row * column).map(|i| f(i / column, i % column)).collect()
        }
    }

    /// Creates a new `Matrix` from vector.
    #[inline]
    pub fn from_vec(row: usize, column: usize, data: Vec<T>) -> Matrix<T> {
        assert_eq!(row * column, data.len());
        Matrix { row: row, column: column, data: data }
    }

    /// Returns the matrix's row and column.
    #[inline]
    pub fn size(&self) -> (usize, usize) { (self.row(), self.column()) }
    /// Returns the matrix's row.
    #[inline]
    pub fn row(&self) -> usize { self.row }
    /// Returns the matrix's column.
    #[inline]
    pub fn column(&self) -> usize { self.column }
}

impl<T: Zero> Matrix<T> {
    /// Creates a matrix whose elements are all zero.
    #[inline]
    pub fn zero(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |_, _| Zero::zero())
    }
}

impl<T: One + Zero> Matrix<T> {
    /// Creates a identity matrix.
    #[inline]
    pub fn one(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |i, j| {
            if i == j {
                One::one()
            } else {
                Zero::zero()
            }
        })
    }
}

impl<T: Clone> Matrix<T> {
    #[inline]
    /// Returns transpose of the matrix.
    pub fn trans(&self) -> Matrix<T> {
        Matrix::from_fn(self.column(), self.row(), |i, j| self[(j, i)].clone())
    }
}

impl<T: Display> Display for Matrix<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut res = write!(f, "");
        let (row, col) = self.size();

        for i in 0..row {
            // write matrix content
            for j in 0..col {
                res = res.and(write!(f, "{} ", self[(i, j)]));
            }
            res = res.and(write!(f, "\n"));
        }

        res
    }
}

impl<T> Index<(usize, usize)> for Matrix<T> {
    type Output = T;

    #[inline]
    fn index(&self, (i, j): (usize, usize)) -> &T {
        assert!(i < self.row() && j < self.column());
        &self.data[i * self.column() + j]
    }
}

impl<T> IndexMut<(usize, usize)> for Matrix<T> {
    #[inline]
    fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut T {
        assert!(i < self.row && j < self.column);
        &mut self.data[i * self.column + j]
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Matrix<Rhs>> for &'a Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Add<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Add<Rhs>>::Output>;

    #[inline]
    fn add(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Add<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() + other[(i, j)].clone())
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Sub<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Sub<Rhs>>::Output>;

    #[inline]
    fn sub(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Sub<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() - other[(i, j)].clone())
    }
}

impl<Lhs, Rhs> Mul<Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        (&self).mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) ->  Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<&'a Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(other)
    }
}

impl<'a, 'b, Lhs, Rhs> Mul<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        assert_eq!(self.column(), other.row());
        Matrix::from_fn(self.row(), other.column(), |i, j| {
            let mut sum = self[(i, 0)].clone() * other[(0, j)].clone();
            for k in 1 .. self.column() {
                sum = sum + self[(i, k)].clone() * other[(k, j)].clone();
            }
            sum
        })
    }
}

#[cfg(test)]
mod tests {
    use super::Matrix;

    #[test]
    fn from_vec() {
        let mat = Matrix::from_vec(2, 3, vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]);
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index() {
        let mat = Matrix::from_fn(3, 5, |i, j| (i, j));
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index_mut() {
        let mut m = Matrix::one(2, 2);
        m[(1,1)] = 0;
        assert_eq!(Matrix::from_vec(2, 2, vec![1, 0, 0, 0]), m);
    }

    #[test]
    fn mul() {
        let m1 = Matrix::from_vec(1, 3, vec![1.0f64, 2.0, 3.0]);
        let m2 = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]);
        assert_eq!(Matrix::from_vec(1, 1, vec![14.0]), m1 * m2);
        assert_eq!(Matrix::from_vec(3, 1, vec![1.0f64, 4.0, 7.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 1, vec![1.0, 0.0, 0.0]));
        assert_eq!(Matrix::from_vec(3, 2, vec![1.0f64, 3.0, 4.0, 6.0, 7.0, 9.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0]));
    }
}

<commit_msg>removed unknown lint for rust-1.2<commit_after>//! Manipulations and data types that represent 2d matrix.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

extern crate num;

use std::fmt::{Display, Formatter, Result};
use std::ops::{Add, Index, IndexMut, Mul, Sub};
use num::{One, Zero};

/// 2D matrix.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Matrix<T> {
    row: usize,
    column: usize,
    data: Vec<T>
}

impl<T> Matrix<T> {
    /// Creates a new `Matrix`.
    #[inline]
    pub fn from_fn<F>(row: usize, column: usize, f: F) -> Matrix<T>
        where F:Fn(usize, usize) -> T
    {
        Matrix {
            row: row,
            column: column,
            data: (0 .. row * column).map(|i| f(i / column, i % column)).collect()
        }
    }

    /// Creates a new `Matrix` from vector.
    #[inline]
    pub fn from_vec(row: usize, column: usize, data: Vec<T>) -> Matrix<T> {
        assert_eq!(row * column, data.len());
        Matrix { row: row, column: column, data: data }
    }

    /// Returns the matrix's row and column.
    #[inline]
    pub fn size(&self) -> (usize, usize) { (self.row(), self.column()) }
    /// Returns the matrix's row.
    #[inline]
    pub fn row(&self) -> usize { self.row }
    /// Returns the matrix's column.
    #[inline]
    pub fn column(&self) -> usize { self.column }
}

impl<T: Zero> Matrix<T> {
    /// Creates a matrix whose elements are all zero.
    #[inline]
    pub fn zero(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |_, _| Zero::zero())
    }
}

impl<T: One + Zero> Matrix<T> {
    /// Creates a identity matrix.
    #[inline]
    pub fn one(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |i, j| {
            if i == j {
                One::one()
            } else {
                Zero::zero()
            }
        })
    }
}

impl<T: Clone> Matrix<T> {
    #[inline]
    /// Returns transpose of the matrix.
    pub fn trans(&self) -> Matrix<T> {
        Matrix::from_fn(self.column(), self.row(), |i, j| self[(j, i)].clone())
    }
}

impl<T: Display> Display for Matrix<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut res = write!(f, "");
        let (row, col) = self.size();

        for i in 0..row {
            // write matrix content
            for j in 0..col {
                res = res.and(write!(f, "{} ", self[(i, j)]));
            }
            res = res.and(write!(f, "\n"));
        }

        res
    }
}

impl<T> Index<(usize, usize)> for Matrix<T> {
    type Output = T;

    #[inline]
    fn index(&self, (i, j): (usize, usize)) -> &T {
        assert!(i < self.row() && j < self.column());
        &self.data[i * self.column() + j]
    }
}

impl<T> IndexMut<(usize, usize)> for Matrix<T> {
    #[inline]
    fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut T {
        assert!(i < self.row && j < self.column);
        &mut self.data[i * self.column + j]
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Matrix<Rhs>> for &'a Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Add<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Add<Rhs>>::Output>;

    #[inline]
    fn add(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Add<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() + other[(i, j)].clone())
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Sub<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Sub<Rhs>>::Output>;

    #[inline]
    fn sub(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Sub<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() - other[(i, j)].clone())
    }
}

impl<Lhs, Rhs> Mul<Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        (&self).mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) ->  Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<&'a Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(other)
    }
}

impl<'a, 'b, Lhs, Rhs> Mul<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        assert_eq!(self.column(), other.row());
        Matrix::from_fn(self.row(), other.column(), |i, j| {
            let mut sum = self[(i, 0)].clone() * other[(0, j)].clone();
            for k in 1 .. self.column() {
                sum = sum + self[(i, k)].clone() * other[(k, j)].clone();
            }
            sum
        })
    }
}

#[cfg(test)]
mod tests {
    use super::Matrix;

    #[test]
    fn from_vec() {
        let mat = Matrix::from_vec(2, 3, vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]);
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index() {
        let mat = Matrix::from_fn(3, 5, |i, j| (i, j));
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index_mut() {
        let mut m = Matrix::one(2, 2);
        m[(1,1)] = 0;
        assert_eq!(Matrix::from_vec(2, 2, vec![1, 0, 0, 0]), m);
    }

    #[test]
    fn mul() {
        let m1 = Matrix::from_vec(1, 3, vec![1.0f64, 2.0, 3.0]);
        let m2 = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]);
        assert_eq!(Matrix::from_vec(1, 1, vec![14.0]), m1 * m2);
        assert_eq!(Matrix::from_vec(3, 1, vec![1.0f64, 4.0, 7.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 1, vec![1.0, 0.0, 0.0]));
        assert_eq!(Matrix::from_vec(3, 2, vec![1.0f64, 3.0, 4.0, 6.0, 7.0, 9.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0]));
    }
}

<|endoftext|>


<commit_before>use std::sync::Arc;
use std::iter::FromIterator;
use calx_grid::{Dir6, HexFov};
use calx_ecs::Entity;
use calx_resource::{Resource, ResourceStore};
use world::World;
use components::{Alignment, BrainState};
use stats::Intrinsic;
use location::Location;
use brush::Brush;
use stats;
use FovStatus;
use fov::SightFov;
use terraform::TerrainQuery;
use world::Ecs;
use terrain;
use form;
use Prefab;

/// Immutable querying of game world state.
pub trait Query: TerrainQuery {
    /// Return the location of an entity.
    ///
    /// Returns the location of the containing entity for entities inside
    /// containers. It is possible for entities to not have a location.
    fn location(&self, e: Entity) -> Option<Location>;

    /// Return the player entity if one exists.
    fn player(&self) -> Option<Entity>;

    /// Return current time of the world logic clock.
    fn tick(&self) -> u64;

    /// Return world RNG seed
    fn rng_seed(&self) -> u32;

    /// Return maximum health of an entity.
    fn max_hp(&self, e: Entity) -> i32 { self.stats(e).power }

    // XXX: Would be nicer if entities_at returned an iterator. Probably want to wait for impl
    // Trait return types before jumping to this.

    /// Return an iterator to entities at the given location.
    fn entities_at(&self, loc: Location) -> Vec<Entity>;

    /// Return reference to the world entity component system.
    fn ecs<'a>(&'a self) -> &'a Ecs;

    /// Return the AI state of an entity.
    fn brain_state(&self, e: Entity) -> Option<BrainState> {
        self.ecs().brain.get(e).map_or(None, |brain| Some(brain.state))
    }

    /// Return whether the entity is a mobile object (eg. active creature).
    fn is_mob(&self, e: Entity) -> bool { self.ecs().brain.contains(e) }

    /// Return the value for how a mob will react to other mobs.
    fn alignment(&self, e: Entity) -> Option<Alignment> {
        self.ecs().brain.get(e).map(|b| b.alignment)
    }

    /// Return current health of an entity.
    fn hp(&self, e: Entity) -> i32 {
        self.max_hp(e) - if self.ecs().health.contains(e) { self.ecs().health[e].wounds } else { 0 }
    }

    /// Return field of view for a location.
    fn fov_status(&self, loc: Location) -> Option<FovStatus> {
        if let Some(p) = self.player() {
            if self.ecs().map_memory.contains(p) {
                if self.ecs().map_memory[p].seen.contains(&loc) {
                    return Some(FovStatus::Seen);
                }
                if self.ecs().map_memory[p].remembered.contains(&loc) {
                    return Some(FovStatus::Remembered);
                }
                return None;
            }
        }
        // Just show everything by default.
        Some(FovStatus::Seen)
    }

    /// Return visual brush for an entity.
    fn entity_brush(&self, e: Entity) -> Option<Resource<Brush>> {
        self.ecs().desc.get(e).map(|x| x.brush.clone())
    }

    /// Return the (composite) stats for an entity.
    ///
    /// Will return the default value for the Stats type (additive identity in the stat algebra)
    /// for entities that have no stats component defined.
    fn stats(&self, e: Entity) -> stats::Stats {
        self.ecs().composite_stats.get(e).map_or_else(|| self.base_stats(e), |x| x.0)
    }

    /// Return the base stats of the entity. Does not include any added effects.
    ///
    /// You usually want to use the `stats` method instead of this one.
    fn base_stats(&self, e: Entity) -> stats::Stats {
        self.ecs().stats.get(e).cloned().unwrap_or_default()
    }

    /// Return whether the entity can move in a direction.
    fn can_step(&self, e: Entity, dir: Dir6) -> bool {
        self.location(e).map_or(false, |loc| self.can_enter(e, loc + dir.to_v2()))
    }

    /// Return whether location blocks line of sight.
    fn blocks_sight(&self, loc: Location) -> bool { self.terrain(loc).blocks_sight() }

    /// Return whether the entity can occupy a location.
    fn can_enter(&self, e: Entity, loc: Location) -> bool {
        if self.terrain(loc).is_door() && !self.has_intrinsic(e, Intrinsic::Hands) {
            // Can't open doors without hands.
            return false;
        }
        if self.blocks_walk(loc) {
            return false;
        }
        true
    }

    /// Return whether the entity blocks movement of other entities.
    fn is_blocking_entity(&self, e: Entity) -> bool { self.is_mob(e) }

    /// Return whether the location obstructs entity movement.
    fn blocks_walk(&self, loc: Location) -> bool {
        if !self.is_valid_location(loc) {
            return true;
        }
        if self.terrain(loc).blocks_walk() {
            return true;
        }
        if self.entities_at(loc)
               .into_iter()
               .any(|e| self.is_blocking_entity(e)) {
            return true;
        }
        false
    }

    /// Return whether a location contains mobs.
    fn has_mobs(&self, loc: Location) -> bool { self.mob_at(loc).is_some() }

    /// Return mob (if any) at given position.
    fn mob_at(&self, loc: Location) -> Option<Entity> {
        self.entities_at(loc).into_iter().find(|&e| self.is_mob(e))
    }

    /// Return whether the entity has a specific intrinsic property (eg. poison resistance).
    fn has_intrinsic(&self, e: Entity, intrinsic: Intrinsic) -> bool {
        self.stats(e).intrinsics & intrinsic as u32 != 0
    }

    /// Return if the entity is a mob that should get an update this frame
    /// based on its speed properties. Does not check for status effects like
    /// sleep that might prevent actual action.
    fn ticks_this_frame(&self, e: Entity) -> bool {
        if !self.is_mob(e) || !self.is_alive(e) {
            return false;
        }

        // Go through a cycle of 5 phases to get 4 possible speeds.
        // System idea from Jeff Lait.
        let phase = self.tick() % 5;
        match phase {
            0 => return true,
            1 => return self.has_intrinsic(e, Intrinsic::Fast),
            2 => return true,
            3 => return self.has_intrinsic(e, Intrinsic::Quick),
            4 => return !self.has_intrinsic(e, Intrinsic::Slow),
            _ => panic!("Invalid action phase"),
        }
    }

    /// Return whether the entity is dead and should be removed from the world.
    fn is_alive(&self, e: Entity) -> bool { self.location(e).is_some() }

    /// Return true if the game has ended and the player can make no further
    /// actions.
    fn game_over(&self) -> bool { self.player().is_none() }

    /// Return whether an entity is the player avatar mob.
    fn is_player(&self, e: Entity) -> bool {
        // TODO: Should this just check self.flags.player?
        self.brain_state(e) == Some(BrainState::PlayerControl) && self.is_alive(e)
    }

    /// Return whether the entity is an awake mob.
    fn is_active(&self, e: Entity) -> bool {
        match self.brain_state(e) {
            Some(BrainState::Asleep) => false,
            Some(_) => true,
            _ => false,
        }
    }

    /// Return whether the entity is a mob that will act this frame.
    fn acts_this_frame(&self, e: Entity) -> bool {
        if !self.is_active(e) {
            return false;
        }
        return self.ticks_this_frame(e);
    }

    /// Look for targets to shoot in a direction.
    fn find_target(&self, shooter: Entity, dir: Dir6, range: usize) -> Option<Entity> {
        let origin = self.location(shooter).unwrap();
        for i in 1..(range + 1) {
            let loc = origin + dir.to_v2() * (i as i32);
            if self.terrain(loc).blocks_shot() {
                break;
            }
            if let Some(e) = self.mob_at(loc) {
                if self.is_hostile_to(shooter, e) {
                    return Some(e);
                }
            }
        }
        None
    }

    /// Return whether the entity wants to fight the other entity.
    fn is_hostile_to(&self, e: Entity, other: Entity) -> bool {
        match (self.alignment(e), self.alignment(other)) {
            (Some(Alignment::Chaotic), Some(_)) => true,
            (Some(_), Some(Alignment::Chaotic)) => true,
            (Some(Alignment::Evil), Some(Alignment::Good)) => true,
            (Some(Alignment::Good), Some(Alignment::Evil)) => true,
            _ => false,
        }
    }

    /// Return whether the entity should have an idle animation.
    fn is_bobbing(&self, e: Entity) -> bool { self.is_active(e) && !self.is_player(e) }

    /// Return Id value of terrain at location for drawing on screen.
    fn visual_terrain_id(&self, loc: Location) -> u8 {
        let mut idx = self.terrain_id(loc);

        if idx == terrain::Id::Door as u8 {
            // Standing in the doorway opens the door.
            if self.has_mobs(loc) {
                idx = terrain::Id::OpenDoor as u8;
            }
        }

        // TODO: Might want a more generic method of specifying cosmetic terrain variants.
        if idx == terrain::Id::Grass as u8 {
            // Grass is occasionally fancy.
            if loc.noise() > 0.85 {
                idx = terrain::Id::Grass2 as u8;
            }
        }

        idx
    }

    /// Return terrain at location for drawing on screen.
    ///
    /// Terrain is sometimes replaced with a variant for visual effect, but
    /// this should not be reflected in the logical terrain.
    fn visual_terrain(&self, loc: Location) -> Arc<terrain::Tile> {
        terrain::Tile::get_resource(&self.visual_terrain_id(loc)).unwrap()
    }

    /// Return the name that can be used to spawn this entity.
    fn spawn_name<'a>(&'a self, e: Entity) -> Option<&'a str> {
        // TODO: Create a special component for this.
        self.ecs().desc.get(e).map_or(None, |ref desc| Some(&desc.name[..]))
    }

    fn is_spawn_name(&self, spawn_name: &str) -> bool {
        form::FORMS.iter().position(|f| f.name() == Some(spawn_name)).is_some()
    }

    fn extract_prefab<I: IntoIterator<Item=Location>>(&self, locs: I) -> Prefab {
        let mut map = Vec::new();
        let mut origin = None;

        for loc in locs {
            // Store first location as an arbitrary origin.
            let origin = match origin {
                None => { origin = Some(loc); loc }
                Some(origin) => origin,
            };

            let pos = origin.v2_at(loc).expect("Trying to build prefab from multiple z-levels");

            let terrain = terrain::Id::from_u8(self.terrain_id(loc)).expect("Corrupt terrain");

            let entities = Vec::from_iter(
                self.entities_at(loc).into_iter().filter_map(|e| self.spawn_name(e).map(|s| s.to_string())));

            map.push((pos, (terrain, entities)));
        }

        Prefab::from_iter(map.into_iter())
    }
}
<commit_msg>Don't draw off-screen floors as walkable terrain<commit_after>use std::sync::Arc;
use std::iter::FromIterator;
use calx_grid::{Dir6, HexFov};
use calx_ecs::Entity;
use calx_resource::{Resource, ResourceStore};
use world::World;
use components::{Alignment, BrainState};
use stats::Intrinsic;
use location::Location;
use brush::Brush;
use stats;
use FovStatus;
use fov::SightFov;
use terraform::TerrainQuery;
use world::Ecs;
use terrain;
use form;
use Prefab;

/// Immutable querying of game world state.
pub trait Query: TerrainQuery {
    /// Return the location of an entity.
    ///
    /// Returns the location of the containing entity for entities inside
    /// containers. It is possible for entities to not have a location.
    fn location(&self, e: Entity) -> Option<Location>;

    /// Return the player entity if one exists.
    fn player(&self) -> Option<Entity>;

    /// Return current time of the world logic clock.
    fn tick(&self) -> u64;

    /// Return world RNG seed
    fn rng_seed(&self) -> u32;

    /// Return maximum health of an entity.
    fn max_hp(&self, e: Entity) -> i32 { self.stats(e).power }

    // XXX: Would be nicer if entities_at returned an iterator. Probably want to wait for impl
    // Trait return types before jumping to this.

    /// Return an iterator to entities at the given location.
    fn entities_at(&self, loc: Location) -> Vec<Entity>;

    /// Return reference to the world entity component system.
    fn ecs<'a>(&'a self) -> &'a Ecs;

    /// Return the AI state of an entity.
    fn brain_state(&self, e: Entity) -> Option<BrainState> {
        self.ecs().brain.get(e).map_or(None, |brain| Some(brain.state))
    }

    /// Return whether the entity is a mobile object (eg. active creature).
    fn is_mob(&self, e: Entity) -> bool { self.ecs().brain.contains(e) }

    /// Return the value for how a mob will react to other mobs.
    fn alignment(&self, e: Entity) -> Option<Alignment> {
        self.ecs().brain.get(e).map(|b| b.alignment)
    }

    /// Return current health of an entity.
    fn hp(&self, e: Entity) -> i32 {
        self.max_hp(e) - if self.ecs().health.contains(e) { self.ecs().health[e].wounds } else { 0 }
    }

    /// Return field of view for a location.
    fn fov_status(&self, loc: Location) -> Option<FovStatus> {
        if let Some(p) = self.player() {
            if self.ecs().map_memory.contains(p) {
                if self.ecs().map_memory[p].seen.contains(&loc) {
                    return Some(FovStatus::Seen);
                }
                if self.ecs().map_memory[p].remembered.contains(&loc) {
                    return Some(FovStatus::Remembered);
                }
                return None;
            }
        }
        // Just show everything by default.
        Some(FovStatus::Seen)
    }

    /// Return visual brush for an entity.
    fn entity_brush(&self, e: Entity) -> Option<Resource<Brush>> {
        self.ecs().desc.get(e).map(|x| x.brush.clone())
    }

    /// Return the (composite) stats for an entity.
    ///
    /// Will return the default value for the Stats type (additive identity in the stat algebra)
    /// for entities that have no stats component defined.
    fn stats(&self, e: Entity) -> stats::Stats {
        self.ecs().composite_stats.get(e).map_or_else(|| self.base_stats(e), |x| x.0)
    }

    /// Return the base stats of the entity. Does not include any added effects.
    ///
    /// You usually want to use the `stats` method instead of this one.
    fn base_stats(&self, e: Entity) -> stats::Stats {
        self.ecs().stats.get(e).cloned().unwrap_or_default()
    }

    /// Return whether the entity can move in a direction.
    fn can_step(&self, e: Entity, dir: Dir6) -> bool {
        self.location(e).map_or(false, |loc| self.can_enter(e, loc + dir.to_v2()))
    }

    /// Return whether location blocks line of sight.
    fn blocks_sight(&self, loc: Location) -> bool { self.terrain(loc).blocks_sight() }

    /// Return whether the entity can occupy a location.
    fn can_enter(&self, e: Entity, loc: Location) -> bool {
        if self.terrain(loc).is_door() && !self.has_intrinsic(e, Intrinsic::Hands) {
            // Can't open doors without hands.
            return false;
        }
        if self.blocks_walk(loc) {
            return false;
        }
        true
    }

    /// Return whether the entity blocks movement of other entities.
    fn is_blocking_entity(&self, e: Entity) -> bool { self.is_mob(e) }

    /// Return whether the location obstructs entity movement.
    fn blocks_walk(&self, loc: Location) -> bool {
        if !self.is_valid_location(loc) {
            return true;
        }
        if self.terrain(loc).blocks_walk() {
            return true;
        }
        if self.entities_at(loc)
               .into_iter()
               .any(|e| self.is_blocking_entity(e)) {
            return true;
        }
        false
    }

    /// Return whether a location contains mobs.
    fn has_mobs(&self, loc: Location) -> bool { self.mob_at(loc).is_some() }

    /// Return mob (if any) at given position.
    fn mob_at(&self, loc: Location) -> Option<Entity> {
        self.entities_at(loc).into_iter().find(|&e| self.is_mob(e))
    }

    /// Return whether the entity has a specific intrinsic property (eg. poison resistance).
    fn has_intrinsic(&self, e: Entity, intrinsic: Intrinsic) -> bool {
        self.stats(e).intrinsics & intrinsic as u32 != 0
    }

    /// Return if the entity is a mob that should get an update this frame
    /// based on its speed properties. Does not check for status effects like
    /// sleep that might prevent actual action.
    fn ticks_this_frame(&self, e: Entity) -> bool {
        if !self.is_mob(e) || !self.is_alive(e) {
            return false;
        }

        // Go through a cycle of 5 phases to get 4 possible speeds.
        // System idea from Jeff Lait.
        let phase = self.tick() % 5;
        match phase {
            0 => return true,
            1 => return self.has_intrinsic(e, Intrinsic::Fast),
            2 => return true,
            3 => return self.has_intrinsic(e, Intrinsic::Quick),
            4 => return !self.has_intrinsic(e, Intrinsic::Slow),
            _ => panic!("Invalid action phase"),
        }
    }

    /// Return whether the entity is dead and should be removed from the world.
    fn is_alive(&self, e: Entity) -> bool { self.location(e).is_some() }

    /// Return true if the game has ended and the player can make no further
    /// actions.
    fn game_over(&self) -> bool { self.player().is_none() }

    /// Return whether an entity is the player avatar mob.
    fn is_player(&self, e: Entity) -> bool {
        // TODO: Should this just check self.flags.player?
        self.brain_state(e) == Some(BrainState::PlayerControl) && self.is_alive(e)
    }

    /// Return whether the entity is an awake mob.
    fn is_active(&self, e: Entity) -> bool {
        match self.brain_state(e) {
            Some(BrainState::Asleep) => false,
            Some(_) => true,
            _ => false,
        }
    }

    /// Return whether the entity is a mob that will act this frame.
    fn acts_this_frame(&self, e: Entity) -> bool {
        if !self.is_active(e) {
            return false;
        }
        return self.ticks_this_frame(e);
    }

    /// Look for targets to shoot in a direction.
    fn find_target(&self, shooter: Entity, dir: Dir6, range: usize) -> Option<Entity> {
        let origin = self.location(shooter).unwrap();
        for i in 1..(range + 1) {
            let loc = origin + dir.to_v2() * (i as i32);
            if self.terrain(loc).blocks_shot() {
                break;
            }
            if let Some(e) = self.mob_at(loc) {
                if self.is_hostile_to(shooter, e) {
                    return Some(e);
                }
            }
        }
        None
    }

    /// Return whether the entity wants to fight the other entity.
    fn is_hostile_to(&self, e: Entity, other: Entity) -> bool {
        match (self.alignment(e), self.alignment(other)) {
            (Some(Alignment::Chaotic), Some(_)) => true,
            (Some(_), Some(Alignment::Chaotic)) => true,
            (Some(Alignment::Evil), Some(Alignment::Good)) => true,
            (Some(Alignment::Good), Some(Alignment::Evil)) => true,
            _ => false,
        }
    }

    /// Return whether the entity should have an idle animation.
    fn is_bobbing(&self, e: Entity) -> bool { self.is_active(e) && !self.is_player(e) }

    /// Return Id value of terrain at location for drawing on screen.
    fn visual_terrain_id(&self, loc: Location) -> u8 {
        use terrain::Id::*;
        let mut idx = self.terrain_id(loc);

        // Floor terrain dot means "you can step here". So if the floor is outside the valid play
        // area, don't show the dot.
        //
        // XXX: Hardcoded set of floors, must be updated whenever a new floor type is added.
        if !self.is_valid_location(loc) {
            if idx == Ground as u8 || idx == Grass as u8 || idx == Gate as u8 {
                idx = Empty as u8;
            }
        }

        // TODO: Might want a more generic method of specifying cosmetic terrain variants.
        if idx == Grass as u8 {
            // Grass is occasionally fancy.
            if loc.noise() > 0.85 {
                idx = terrain::Id::Grass2 as u8;
            }
        }

        idx
    }

    /// Return terrain at location for drawing on screen.
    ///
    /// Terrain is sometimes replaced with a variant for visual effect, but
    /// this should not be reflected in the logical terrain.
    fn visual_terrain(&self, loc: Location) -> Arc<terrain::Tile> {
        terrain::Tile::get_resource(&self.visual_terrain_id(loc)).unwrap()
    }

    /// Return the name that can be used to spawn this entity.
    fn spawn_name<'a>(&'a self, e: Entity) -> Option<&'a str> {
        // TODO: Create a special component for this.
        self.ecs().desc.get(e).map_or(None, |ref desc| Some(&desc.name[..]))
    }

    fn is_spawn_name(&self, spawn_name: &str) -> bool {
        form::FORMS.iter().position(|f| f.name() == Some(spawn_name)).is_some()
    }

    fn extract_prefab<I: IntoIterator<Item=Location>>(&self, locs: I) -> Prefab {
        let mut map = Vec::new();
        let mut origin = None;

        for loc in locs {
            // Store first location as an arbitrary origin.
            let origin = match origin {
                None => { origin = Some(loc); loc }
                Some(origin) => origin,
            };

            let pos = origin.v2_at(loc).expect("Trying to build prefab from multiple z-levels");

            let terrain = terrain::Id::from_u8(self.terrain_id(loc)).expect("Corrupt terrain");

            let entities = Vec::from_iter(
                self.entities_at(loc).into_iter().filter_map(|e| self.spawn_name(e).map(|s| s.to_string())));

            map.push((pos, (terrain, entities)));
        }

        Prefab::from_iter(map.into_iter())
    }
}
<|endoftext|>


<commit_before>//!Readline for Rust
//!
//!This implementation is based on [Antirez's Linenoise](https://github.com/antirez/linenoise)
//!
//!# Example
//!
//!Usage
//!
//!```
//!let readline = rustyline::readline(">> ");
//!match readline {
//!     Ok(line) => println!("Line: {:?}",line),
//!     Err(_)   => println!("No input"),
//! }
//!```
extern crate libc;
extern crate nix;

use std::io;
use std::io::{Write, Read, Error, ErrorKind};
use nix::errno::Errno;
use nix::Error::Sys;
use nix::sys::termios;
use nix::sys::termios::{BRKINT, ICRNL, INPCK, ISTRIP, IXON, OPOST, CS8, ECHO, ICANON, IEXTEN, ISIG, VMIN, VTIME};

pub mod consts;
pub mod error;

/// Maximum buffer size for the line read
static MAX_LINE: usize = 4096;

/// Unsupported Terminals that don't support RAW mode
static UNSUPPORTED_TERM: [&'static str; 3] = ["dumb","cons25","emacs"];

/// Key Strokes that rustyline should capture
const    NULL     : u8   = 0;
const    CTRL_A   : u8   = 1;
const    CTRL_B   : u8   = 2;
const    CTRL_C   : u8   = 3;
const    CTRL_D   : u8   = 4;
const    CTRL_E   : u8   = 5;
const    CTRL_F   : u8   = 6;
const    CTRL_H   : u8   = 8;
const    TAB      : u8   = 9;
const    CTRL_K   : u8   = 11;
const    CTRL_L   : u8   = 12;
const    ENTER    : u8   = 13;
const    CTRL_N   : u8   = 14;
const    CTRL_P   : u8   = 16;
const    CTRL_T   : u8   = 20;
const    CTRL_U   : u8   = 21;
const    CTRL_W   : u8   = 23;
const    ESC      : u8   = 27;
const    BACKSPACE: u8   = 127;

/// Check to see if STDIN is a TTY
fn is_a_tty() -> bool {
    let isatty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
    isatty
}

/// Check to see if the current `TERM` is unsupported
fn is_unsupported_term() -> bool {
    match std::env::var("TERM") {
        Ok(term) => {
            let mut unsupported = false;
            for iter in &UNSUPPORTED_TERM {
                unsupported = term == *iter
            }
            unsupported
        }
        Err(_) => false
    }
}

/// Enable raw mode for the TERM
fn enable_raw_mode() -> Result<termios::Termios, error::ReadlineError> {
    if !is_a_tty() {
        Err(error::ReadlineError
                          ::from(nix::Error
                                    ::from_errno(Errno::ENOTTY)))
    } else {
        let original_term = try!(termios::tcgetattr(libc::STDIN_FILENO));
        let mut raw = original_term;
        raw.c_iflag = raw.c_iflag   & !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        raw.c_oflag = raw.c_oflag   & !(OPOST);
        raw.c_cflag = raw.c_cflag   | (CS8);
        raw.c_lflag = raw.c_lflag   & !(ECHO | ICANON | IEXTEN | ISIG);
        raw.c_cc[VMIN] = 1;
        raw.c_cc[VTIME] = 0;
        try!(termios::tcsetattr(libc::STDIN_FILENO, termios::TCSAFLUSH, &raw));
        Ok(original_term)
    }
}

/// Disable Raw mode for the term
fn disable_raw_mode(original_termios: termios::Termios) -> Result<(), nix::Error> {
    try!(termios::tcsetattr(libc::STDIN_FILENO,
                            termios::TCSAFLUSH,
                            &original_termios));
    Ok(())
}

/// Handles reading and editting the readline buffer.
/// It will also handle special inputs in an appropriate fashion
/// (e.g., C-c will exit readline)
fn readline_edit() -> Result<String, error::ReadlineError> {
    // Preallocate a buffer for the input line
    let mut buffer = String::with_capacity(MAX_LINE);

    // Input buffer for reading a single UTF-8
    let mut input = String::with_capacity(1);
    loop {
        let numread = io::stdin().read_to_string(&mut input).unwrap();
        match input.as_bytes()[0] {
            CTRL_A => print!("Pressed C-a"),
            CTRL_B => print!("Pressed C-b"),
            CTRL_C => print!("Pressed C-c"),
            CTRL_D => print!("Pressed C-d"),
            CTRL_E => print!("Pressed C-e"),
            CTRL_F => print!("Pressed C-f"),
            CTRL_H => print!("Pressed C-h"),
            CTRL_K => print!("Pressed C-k"),
            CTRL_L => print!("Pressed C-l"),
            CTRL_N => print!("Pressed C-n"),
            CTRL_P => print!("Pressed C-p"),
            CTRL_T => print!("Pressed C-t"),
            CTRL_U => print!("Pressed C-u"),
            CTRL_W => print!("Pressed C-w"),
            ESC    => print!("Pressed esc") ,
            ENTER  => break,
            _      => { print!("{}", input); io::stdout().flush(); }
        }
        buffer.push_str(&input);
    }
    Ok(buffer)
}

/// Readline method that will enable RAW mode, call the ```readline_edit()```
/// method and disable raw mode
fn readline_raw() -> Result<String, error::ReadlineError> {
    if is_a_tty() {
        let original_termios = try!(enable_raw_mode());
        let user_input = readline_edit();
        try!(disable_raw_mode(original_termios));
        user_input
    } else {
        let mut line = String::new();
        match io::stdin().read_line(&mut line) {
            Ok(_) => Ok(line),
            Err(err) => Err(error::ReadlineError::from(err))
        }
    }
}

/// This is the only public library method that will be called by the end-user
pub fn readline(prompt: &'static str) -> Result<String, error::ReadlineError> {
    // Write prompt and flush it to stdout
    let mut stdout = io::stdout();
    try!(stdout.write(prompt.as_bytes()));
    try!(stdout.flush());

    if is_unsupported_term() {
        let mut line = String::new();
        match io::stdin().read_line(&mut line) {
            Ok(_) => Ok(line),
            Err(err) => Err(error::ReadlineError::from(err))
        }
    } else {
        readline_raw()
    }
}
<commit_msg>Added a Result Type that is result::Result<T, ReadLineError><commit_after>//!Readline for Rust
//!
//!This implementation is based on [Antirez's Linenoise](https://github.com/antirez/linenoise)
//!
//!# Example
//!
//!Usage
//!
//!```
//!let readline = rustyline::readline(">> ");
//!match readline {
//!     Ok(line) => println!("Line: {:?}",line),
//!     Err(_)   => println!("No input"),
//! }
//!```
extern crate libc;
extern crate nix;

use std::result;
use std::io;
use std::io::{Write, Read};
use nix::errno::Errno;
use nix::Error::Sys;
use nix::sys::termios;
use nix::sys::termios::{BRKINT, ICRNL, INPCK, ISTRIP, IXON, OPOST, CS8, ECHO, ICANON, IEXTEN, ISIG, VMIN, VTIME};

pub mod consts;
pub mod error;

pub type Result<T> = result::Result<T, error::ReadlineError>;

/// Maximum buffer size for the line read
static MAX_LINE: usize = 4096;

/// Unsupported Terminals that don't support RAW mode
static UNSUPPORTED_TERM: [&'static str; 3] = ["dumb","cons25","emacs"];

/// Key Strokes that rustyline should capture
const    NULL     : u8   = 0;
const    CTRL_A   : u8   = 1;
const    CTRL_B   : u8   = 2;
const    CTRL_C   : u8   = 3;
const    CTRL_D   : u8   = 4;
const    CTRL_E   : u8   = 5;
const    CTRL_F   : u8   = 6;
const    CTRL_H   : u8   = 8;
const    TAB      : u8   = 9;
const    CTRL_K   : u8   = 11;
const    CTRL_L   : u8   = 12;
const    ENTER    : u8   = 13;
const    CTRL_N   : u8   = 14;
const    CTRL_P   : u8   = 16;
const    CTRL_T   : u8   = 20;
const    CTRL_U   : u8   = 21;
const    CTRL_W   : u8   = 23;
const    ESC      : u8   = 27;
const    BACKSPACE: u8   = 127;

/// Check to see if STDIN is a TTY
fn is_a_tty() -> bool {
    let isatty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
    isatty
}

/// Check to see if the current `TERM` is unsupported
fn is_unsupported_term() -> bool {
    match std::env::var("TERM") {
        Ok(term) => {
            let mut unsupported = false;
            for iter in &UNSUPPORTED_TERM {
                unsupported = term == *iter
            }
            unsupported
        }
        Err(_) => false
    }
}

/// Enable raw mode for the TERM
fn enable_raw_mode() -> Result<termios::Termios> {
    if !is_a_tty() {
        Err(error::ReadlineError
                          ::from(nix::Error
                                    ::from_errno(Errno::ENOTTY)))
    } else {
        let original_term = try!(termios::tcgetattr(libc::STDIN_FILENO));
        let mut raw = original_term;
        raw.c_iflag = raw.c_iflag   & !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        raw.c_oflag = raw.c_oflag   & !(OPOST);
        raw.c_cflag = raw.c_cflag   | (CS8);
        raw.c_lflag = raw.c_lflag   & !(ECHO | ICANON | IEXTEN | ISIG);
        raw.c_cc[VMIN] = 1;
        raw.c_cc[VTIME] = 0;
        try!(termios::tcsetattr(libc::STDIN_FILENO, termios::TCSAFLUSH, &raw));
        Ok(original_term)
    }
}

/// Disable Raw mode for the term
fn disable_raw_mode(original_termios: termios::Termios) -> Result<()> {
    try!(termios::tcsetattr(libc::STDIN_FILENO,
                             termios::TCSAFLUSH,
                             &original_termios));
    Ok(())
}

/// Handles reading and editting the readline buffer.
/// It will also handle special inputs in an appropriate fashion
/// (e.g., C-c will exit readline)
fn readline_edit() -> Result<String> {
    // Preallocate a buffer for the input line
    let mut buffer = String::with_capacity(MAX_LINE);

    // Input buffer for reading a single UTF-8
    let mut input = String::with_capacity(1);
    loop {
        io::stdin().read_to_string(&mut input).unwrap();
        match input.as_bytes()[0] {
            CTRL_A => print!("Pressed C-a"),
            CTRL_B => print!("Pressed C-b"),
            CTRL_C => print!("Pressed C-c"),
            CTRL_D => print!("Pressed C-d"),
            CTRL_E => print!("Pressed C-e"),
            CTRL_F => print!("Pressed C-f"),
            CTRL_H => print!("Pressed C-h"),
            CTRL_K => print!("Pressed C-k"),
            CTRL_L => print!("Pressed C-l"),
            CTRL_N => print!("Pressed C-n"),
            CTRL_P => print!("Pressed C-p"),
            CTRL_T => print!("Pressed C-t"),
            CTRL_U => print!("Pressed C-u"),
            CTRL_W => print!("Pressed C-w"),
            ESC    => print!("Pressed esc") ,
            ENTER  => break,
            _      => { print!("{}", input); try!(io::stdout().flush()); }
        }
        buffer.push_str(&input);
    }
    Ok(buffer)
}

/// Readline method that will enable RAW mode, call the ```readline_edit()```
/// method and disable raw mode
fn readline_raw() -> Result<String> {
    if is_a_tty() {
        let original_termios = try!(enable_raw_mode());
        let user_input = readline_edit();
        try!(disable_raw_mode(original_termios));
        user_input
    } else {
        let mut line = String::new();
        try!(io::stdin().read_line(&mut line));
        Ok(line)
    }
}

/// This is the only public library method that will be called by the end-user
pub fn readline(prompt: &'static str) -> Result<String> {
    // Write prompt and flush it to stdout
    let mut stdout = io::stdout();
    try!(stdout.write(prompt.as_bytes()));
    try!(stdout.flush());

    if is_unsupported_term() {
        let mut line = String::new();
        try!(io::stdin().read_line(&mut line));
        Ok(line)
    } else {
        readline_raw()
    }
}
<|endoftext|>


<commit_before>extern crate libc;

mod consts;
mod ansi;
mod terminal;

pub mod stdin;
pub mod matcher;
pub mod matrix;
pub mod scorer;

pub type Match<'a> = (&'a str, f64);

pub fn match_and_score<'a>(needle: &str, haystack: &'a str) -> Option<Match<'a>> {
    if matcher::matches(needle, haystack) {
        Some((haystack, scorer::score(needle, haystack)))
    } else {
        None
    }
}
<commit_msg>Add match_and_score_with_positions<commit_after>extern crate libc;

mod consts;
mod ansi;
mod terminal;

pub mod stdin;
pub mod matcher;
pub mod matrix;
pub mod scorer;

pub type Match<'a> = (&'a str, f64);
pub type MatchWithPositions<'a> = (&'a str, f64, Vec<usize>);

pub fn match_and_score<'a>(needle: &str, haystack: &'a str) -> Option<Match<'a>> {
    if matcher::matches(needle, haystack) {
        Some((haystack, scorer::score(needle, haystack)))
    } else {
        None
    }
}

pub fn match_and_score_with_positions<'a>(needle: &str, haystack: &'a str) -> Option<MatchWithPositions<'a>> {
    if matcher::matches(needle, haystack) {
        let (score, positions) = scorer::score_with_positions(needle, haystack);
        Some((haystack, score, positions))
    } else {
        None
    }
}
<|endoftext|>


<commit_before>//! This crate is a Rust library for using the [Serde] serialization framework
//! with data in [YAML] file format.
//!
//! This library does not reimplement a YAML parser; it uses [yaml-rust] which
//! is a pure Rust YAML 1.2 implementation.
//!
//! [Serde]: https://github.com/serde-rs/serde
//! [YAML]: http://yaml.org
//! [yaml-rust]: https://github.com/chyh1990/yaml-rust
//!
//! # Examples
//!
//! ```
//! use std::collections::BTreeMap;
//!
//! fn main() -> Result<(), serde_yaml::Error> {
//!     // You have some type.
//!     let mut map = BTreeMap::new();
//!     map.insert("x".to_string(), 1.0);
//!     map.insert("y".to_string(), 2.0);
//!
//!     // Serialize it to a YAML string.
//!     let s = serde_yaml::to_string(&map)?;
//!     assert_eq!(s, "---\nx: 1.0\ny: 2.0");
//!
//!     // Deserialize it back to a Rust type.
//!     let deserialized_map: BTreeMap<String, f64> = serde_yaml::from_str(&s)?;
//!     assert_eq!(map, deserialized_map);
//!     Ok(())
//! }
//! ```
//!
//! ## Using Serde derive
//!
//! It can also be used with Serde's serialization code generator `serde_derive` to
//! handle structs and enums defined in your own program.
//!
//! ```
//! # use serde_derive::{Serialize, Deserialize};
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Debug, PartialEq, Serialize, Deserialize)]
//! struct Point {
//!     x: f64,
//!     y: f64,
//! }
//!
//! fn main() -> Result<(), serde_yaml::Error> {
//!     let point = Point { x: 1.0, y: 2.0 };
//!
//!     let s = serde_yaml::to_string(&point)?;
//!     assert_eq!(s, "---\nx: 1.0\ny: 2.0");
//!
//!     let deserialized_point: Point = serde_yaml::from_str(&s)?;
//!     assert_eq!(point, deserialized_point);
//!     Ok(())
//! }
//! ```

#![doc(html_root_url = "https://docs.rs/serde_yaml/0.8.11")]
#![deny(missing_docs)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
    // private Deserializer::next
    should_implement_trait,
    // things are often more readable this way
    cast_lossless,
    module_name_repetitions,
    single_match_else,
    use_self,
    // code is acceptable
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
    // not practical
    indexing_slicing,
    missing_docs_in_private_items,
    // not stable
    checked_conversions,
    empty_enum,
    // meh, some things won't fail
    result_unwrap_used,
    // noisy
    missing_errors_doc,
    must_use_candidate,
))]

pub use crate::de::{from_reader, from_slice, from_str};
pub use crate::error::{Error, Location, Result};
pub use crate::mapping::Mapping;
pub use crate::ser::{to_string, to_vec, to_writer};
pub use crate::value::{from_value, to_value, Index, Number, Sequence, Value};

/// Entry points for deserializing with pre-existing state.
///
/// These functions are only exposed this way because we don't yet expose a
/// Deserializer type. Data formats that have a public Deserializer should not
/// copy these signatures.
pub mod seed {
    pub use super::de::{from_reader_seed, from_slice_seed, from_str_seed};
}

mod de;
mod error;
mod mapping;
mod number;
mod path;
mod ser;
mod value;
<commit_msg>Clarify comment about suppressed lints<commit_after>//! This crate is a Rust library for using the [Serde] serialization framework
//! with data in [YAML] file format.
//!
//! This library does not reimplement a YAML parser; it uses [yaml-rust] which
//! is a pure Rust YAML 1.2 implementation.
//!
//! [Serde]: https://github.com/serde-rs/serde
//! [YAML]: http://yaml.org
//! [yaml-rust]: https://github.com/chyh1990/yaml-rust
//!
//! # Examples
//!
//! ```
//! use std::collections::BTreeMap;
//!
//! fn main() -> Result<(), serde_yaml::Error> {
//!     // You have some type.
//!     let mut map = BTreeMap::new();
//!     map.insert("x".to_string(), 1.0);
//!     map.insert("y".to_string(), 2.0);
//!
//!     // Serialize it to a YAML string.
//!     let s = serde_yaml::to_string(&map)?;
//!     assert_eq!(s, "---\nx: 1.0\ny: 2.0");
//!
//!     // Deserialize it back to a Rust type.
//!     let deserialized_map: BTreeMap<String, f64> = serde_yaml::from_str(&s)?;
//!     assert_eq!(map, deserialized_map);
//!     Ok(())
//! }
//! ```
//!
//! ## Using Serde derive
//!
//! It can also be used with Serde's serialization code generator `serde_derive` to
//! handle structs and enums defined in your own program.
//!
//! ```
//! # use serde_derive::{Serialize, Deserialize};
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Debug, PartialEq, Serialize, Deserialize)]
//! struct Point {
//!     x: f64,
//!     y: f64,
//! }
//!
//! fn main() -> Result<(), serde_yaml::Error> {
//!     let point = Point { x: 1.0, y: 2.0 };
//!
//!     let s = serde_yaml::to_string(&point)?;
//!     assert_eq!(s, "---\nx: 1.0\ny: 2.0");
//!
//!     let deserialized_point: Point = serde_yaml::from_str(&s)?;
//!     assert_eq!(point, deserialized_point);
//!     Ok(())
//! }
//! ```

#![doc(html_root_url = "https://docs.rs/serde_yaml/0.8.11")]
#![deny(missing_docs)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Suppressed clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
// Suppressed clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
    // private Deserializer::next
    should_implement_trait,
    // things are often more readable this way
    cast_lossless,
    module_name_repetitions,
    single_match_else,
    use_self,
    // code is acceptable
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
    // not practical
    indexing_slicing,
    missing_docs_in_private_items,
    // not stable
    checked_conversions,
    empty_enum,
    // meh, some things won't fail
    result_unwrap_used,
    // noisy
    missing_errors_doc,
    must_use_candidate,
))]

pub use crate::de::{from_reader, from_slice, from_str};
pub use crate::error::{Error, Location, Result};
pub use crate::mapping::Mapping;
pub use crate::ser::{to_string, to_vec, to_writer};
pub use crate::value::{from_value, to_value, Index, Number, Sequence, Value};

/// Entry points for deserializing with pre-existing state.
///
/// These functions are only exposed this way because we don't yet expose a
/// Deserializer type. Data formats that have a public Deserializer should not
/// copy these signatures.
pub mod seed {
    pub use super::de::{from_reader_seed, from_slice_seed, from_str_seed};
}

mod de;
mod error;
mod mapping;
mod number;
mod path;
mod ser;
mod value;
<|endoftext|>