<commit_before>//! Concurrent maps and sets based on [skip lists].
//!
//! This crate provides the types [`SkipMap`] and [`SkipSet`].
//! These data structures provide an interface similar to [`BTreeMap`] and [`BTreeSet`],
//! respectively, except they support safe concurrent access across
//! multiple threads.
//!
//! # Concurrent access
//! [`SkipMap`] and [`SkipSet`] implement `Send` and `Sync`,
//! so they can be shared across threads with ease.
//!
//! Methods which mutate the map, such as [`insert`],
//! take `&self` rather than `&mut self`. This allows
//! them to be invoked concurrently.
//!
//! ```
//! use crossbeam_skiplist::SkipMap;
//! use crossbeam_utils::thread::scope;
//!
//! let person_ages = SkipMap::new();
//!
//! scope(|s| {
//!     // Insert entries into the map from multiple threads.
//!     s.spawn(|_| {
//!         person_ages.insert("Spike Garrett", 22);
//!         person_ages.insert("Stan Hancock", 47);
//!         person_ages.insert("Rea Bryan", 234);
//!
//!         assert_eq!(person_ages.get("Spike Garrett").unwrap().value(), &22);
//!     });
//!     s.spawn(|_| {
//!         person_ages.insert("Bryon Conroy", 65);
//!         person_ages.insert("Lauren Reilly", 2);
//!     });
//! }).unwrap();
//!
//! assert!(person_ages.contains_key("Spike Garrett"));
//! person_ages.remove("Rea Bryan");
//! assert!(!person_ages.contains_key("Rea Bryan"));
//!
//! ```
//!
//! Concurrent access to skip lists is lock-free and sound.
//! Threads won't get blocked waiting for other threads to finish operating
//! on the map.
//!
//! Be warned that, because of this lock-freedom, it's easy to introduce
//! race conditions into your code. For example:
//! ```no_run
//! use crossbeam_skiplist::SkipSet;
//! use crossbeam_utils::thread::scope;
//!
//! let numbers = SkipSet::new();
//! scope(|s| {
//!     numbers.insert(5);
//!
//!     // Spawn a thread which will remove 5 from the set.
//!     s.spawn(|_| {
//!         numbers.remove(&5);
//!     });
//!
//!     // This check can fail!
//!     // The othe thread may remove the value
//!     // we perform this check.
//!     assert!(numbers.contains(&5));
//! }).unwrap();
//! ```
//!
//! In effect, a _single_ operation on the map, such as [`insert`],
//! operates atomically: race conditions are impossible. However,
//! concurrent calls to functions can become interleaved across
//! threads, introducing non-determinism into your code.
//!
//! To avoid this sort of race condition, never assume that a collection's
//! state will remain the same across multiple lines of code. For instance,
//! in the example above, the problem arises from the assumption that
//! the map won't be mutated between the calls to `insert` and `contains`.
//! In sequential code, this would be correct. But when multiple
//! threads are introduced, more care is needed.
//!
//! Note that race conditions do not violate Rust's memory safety rules.
//! A race between multiple threads can never cause memory errors or
//! segfaults. A race condition is a _logic error_ in its entirety.
//!
//! # Mutable access to elements
//! [`SkipMap`] and [`SkipSet`] provide no way to retrieve a mutable reference
//! to a value. Since access methods can be called concurrently, providing
//! e.g. a `get_mut` function could cause data races.
//!
//! A solution to the above is to have the implementation wrap
//! each value in a lock. However, this has some repercussions:
//! * The map would no longer be lock-free, inhibiting scalability
//! and allowing for deadlocks.
//! * If a user of the map doesn't need mutable access, then they pay
//! the price of locks without actually needing them.
//!
//! Instead, the approach taken by this crate gives more control to the user.
//! If mutable access is needed, then you can use interior mutability,
//! such as [`RwLock`]: `SkipMap<Key, RwLock<Value>>`.
//!
//! # Garbage collection
//! A problem faced by many concurrent data structures
//! is choosing when to free unused memory. Care must be
//! taken to prevent use-after-frees and double-frees, both
//! of which cause undefined behvarior.
//!
//! Consider the following sequence of events operating on a [`SkipMap`]:
//! * Thread A calls [`get`] and holds a reference to a value in the map.
//! * Thread B removes that key from the map.
//! * Thread A now attempts to access the value.
//!
//! What happens here? If the map implementation frees the memory
//! belonging to a value when it is
//! removed, then a user-after-free occurs, resulting in memory corruption.
//!
//! To solve the above, this crate uses the _epoch-based memory reclamation_ mechanism
//! implemented in [`crossbeam-epoch`]. Simplified, a value removed from the map
//! is not freed until after all references to it have been dropped. This mechanism
//! is similar to the garbage collection found in some languages, such as Java, except
//! it operates solely on the values inside the map.
//!
//! This garbage collection scheme operates automatically; users don't have to worry about it.
//! However, keep in mind that holding [`Entry`] handles to entries in the map will prevent
//! that memory from being freed until at least after the handles are dropped.
//!
//! # Performance versus B-trees
//! In general, when you need concurrent writes
//! to an ordered collection, skip lists are a reasonable choice.
//! However, they can be substantially slower than B-trees
//! in some scenarios.
//!
//! The main benefit of a skip list over a `RwLock<BTreeMap>`
//! is that it allows concurrent writes to progress without
//! mutual exclusion. However, when the frequency
//! of writes is low, this benefit isn't as useful.
//! In these cases, a shared [`BTreeMap`] may be a faster option.
//!
//! These guidelines should be taken with a grain of salt—performance
//! in practice varies depending on your use case.
//! In the end, the best way to choose between [`BTreeMap`] and [`SkipMap`]
//! is to benchmark them in your own application.
//!
//! [`SkipMap`]: struct.SkipMap.html
//! [`SkipSet`]: struct.SkipSet.html
//! [`insert`]: struct.SkipMap.html#method.insert
//! [`get`]: struct.SkipMap.html#method.get
//! [`Entry`]: map/struct.Entry.html
//! [skip lists]: https://en.wikipedia.org/wiki/Skip_list
//! [`crossbeam-epoch`]: https://docs.rs/crossbeam-epoch
//! [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html
//! [`BTreeSet`]: https://doc.rust-lang.org/std/collections/struct.BTreeSet.html
//! [`RwLock`]: https://doc.rust-lang.org/std/sync/struct.RwLock.html
//!
//! # Examples
//! [`SkipMap`] basic usage:
//! ```
//! use crossbeam_skiplist::SkipMap;
//!
//! // Note that the variable doesn't have to be mutable:
//! // SkipMap methods take &self to support concurrent access.
//! let movie_reviews = SkipMap::new();
//!
//! // Insert some key-value pairs.
//! movie_reviews.insert("Office Space",       "Deals with real issues in the workplace.");
//! movie_reviews.insert("Pulp Fiction",       "Masterpiece.");
//! movie_reviews.insert("The Godfather",      "Very enjoyable.");
//! movie_reviews.insert("The Blues Brothers", "Eye lyked it a lot.");
//!
//! // Get the value associated with a key.
//! // get() returns an Entry, which gives
//! // references to the key and value.
//! let pulp_fiction = movie_reviews.get("Pulp Fiction").unwrap();
//! assert_eq!(*pulp_fiction.key(), "Pulp Fiction");
//! assert_eq!(*pulp_fiction.value(), "Masterpiece.");
//!
//! // Remove a key-value pair.
//! movie_reviews.remove("The Blues Brothers");
//! assert!(movie_reviews.get("The Blues Brothers").is_none());
//!
//! // Iterate over the reviews. Since SkipMap
//! // is an ordered map, the iterator will yield
//! // keys in lexicographical order.
//! for entry in &movie_reviews {
//!     let movie = entry.key();
//!     let review = entry.value();
//!     println!("{}: \"{}\"", movie, review);
//! }
//! ```
//!
//! [`SkipSet`] basic usage:
//! ```
//! use crossbeam_skiplist::SkipSet;
//!
//! let books = SkipSet::new();
//!
//! // Add some books to the set.
//! books.insert("A Dance With Dragons");
//! books.insert("To Kill a Mockingbird");
//! books.insert("The Odyssey");
//! books.insert("The Great Gatsby");
//!
//! // Check for a specific one.
//! if !books.contains("The Winds of Winter") {
//!    println!("We have {} books, but The Winds of Winter ain't one.",
//!             books.len());
//! }
//!
//! // Remove a book from the set.
//! books.remove("To Kill a Mockingbird");
//! assert!(!books.contains("To Kill a Mockingbird"));
//!
//! // Iterate over the books in the set.
//! // Values are returned in lexicographical order.
//! for entry in &books {
//!     let book = entry.value();
//!     println!("{}", book);
//! }
//! ```

#![doc(test(
    no_crate_inject,
    attr(
        deny(warnings, rust_2018_idioms),
        allow(dead_code, unused_assignments, unused_variables)
    )
))]
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]

use cfg_if::cfg_if;

#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
cfg_if! {
    if #[cfg(feature = "alloc")] {
        extern crate alloc;

        use crossbeam_epoch as epoch;
        use crossbeam_utils as utils;

        pub mod base;
        #[doc(inline)]
        pub use crate::base::SkipList;
    }
}

cfg_if! {
    if #[cfg(feature = "std")] {
        pub mod map;
        #[doc(inline)]
        pub use crate::map::SkipMap;

        pub mod set;
        #[doc(inline)]
        pub use crate::set::SkipSet;
    }
}
<commit_msg>Minor doc adjustments + fix typos<commit_after>//! Concurrent maps and sets based on [skip lists].
//!
//! This crate provides the types [`SkipMap`] and [`SkipSet`].
//! These data structures provide an interface similar to [`BTreeMap`] and [`BTreeSet`],
//! respectively, except they support safe concurrent access across
//! multiple threads.
//!
//! # Concurrent access
//! [`SkipMap`] and [`SkipSet`] implement `Send` and `Sync`,
//! so they can be shared across threads with ease.
//!
//! Methods which mutate the map, such as [`insert`],
//! take `&self` rather than `&mut self`. This allows
//! them to be invoked concurrently.
//!
//! ```
//! use crossbeam_skiplist::SkipMap;
//! use crossbeam_utils::thread::scope;
//!
//! let person_ages = SkipMap::new();
//!
//! scope(|s| {
//!     // Insert entries into the map from multiple threads.
//!     s.spawn(|_| {
//!         person_ages.insert("Spike Garrett", 22);
//!         person_ages.insert("Stan Hancock", 47);
//!         person_ages.insert("Rea Bryan", 234);
//!
//!         assert_eq!(person_ages.get("Spike Garrett").unwrap().value(), &22);
//!     });
//!     s.spawn(|_| {
//!         person_ages.insert("Bryon Conroy", 65);
//!         person_ages.insert("Lauren Reilly", 2);
//!     });
//! }).unwrap();
//!
//! assert!(person_ages.contains_key("Spike Garrett"));
//! person_ages.remove("Rea Bryan");
//! assert!(!person_ages.contains_key("Rea Bryan"));
//!
//! ```
//!
//! Concurrent access to skip lists is lock-free and sound.
//! Threads won't get blocked waiting for other threads to finish operating
//! on the map.
//!
//! Be warned that, because of this lock-freedom, it's easy to introduce
//! race conditions into your code. For example:
//! ```no_run
//! use crossbeam_skiplist::SkipSet;
//! use crossbeam_utils::thread::scope;
//!
//! let numbers = SkipSet::new();
//! scope(|s| {
//!     // Spawn a thread which will remove 5 from the set.
//!     s.spawn(|_| {
//!         numbers.remove(&5);
//!     });
//!
//!     // While the thread above is running, insert a value into the set.
//!     numbers.insert(5);
//!
//!     // This check can fail!
//!     // The other thread may remove the value
//!     // before we perform this check.
//!     assert!(numbers.contains(&5));
//! }).unwrap();
//! ```
//!
//! In effect, a _single_ operation on the map, such as [`insert`],
//! operates atomically: race conditions are impossible. However,
//! concurrent calls to functions can become interleaved across
//! threads, introducing non-determinism.
//!
//! To avoid this sort of race condition, never assume that a collection's
//! state will remain the same across multiple lines of code. For instance,
//! in the example above, the problem arises from the assumption that
//! the map won't be mutated between the calls to `insert` and `contains`.
//! In sequential code, this would be correct. But when multiple
//! threads are introduced, more care is needed.
//!
//! Note that race conditions do not violate Rust's memory safety rules.
//! A race between multiple threads can never cause memory errors or
//! segfaults. A race condition is a _logic error_ in its entirety.
//!
//! # Mutable access to elements
//! [`SkipMap`] and [`SkipSet`] provide no way to retrieve a mutable reference
//! to a value. Since access methods can be called concurrently, providing
//! e.g. a `get_mut` function could cause data races.
//!
//! A solution to the above is to have the implementation wrap
//! each value in a lock. However, this has some repercussions:
//! * The map would no longer be lock-free, inhibiting scalability
//! and allowing for deadlocks.
//! * If a user of the map doesn't need mutable access, then they pay
//! the price of locks without actually needing them.
//!
//! Instead, the approach taken by this crate gives more control to the user.
//! If mutable access is needed, then you can use interior mutability,
//! such as [`RwLock`]: `SkipMap<Key, RwLock<Value>>`.
//!
//! # Garbage collection
//! A problem faced by many concurrent data structures
//! is choosing when to free unused memory. Care must be
//! taken to prevent use-after-frees and double-frees, both
//! of which cause undefined behavior.
//!
//! Consider the following sequence of events operating on a [`SkipMap`]:
//! * Thread A calls [`get`] and holds a reference to a value in the map.
//! * Thread B removes that key from the map.
//! * Thread A now attempts to access the value.
//!
//! What happens here? If the map implementation frees the memory
//! belonging to a value when it is
//! removed, then a user-after-free occurs, resulting in memory corruption.
//!
//! To solve the above, this crate uses the _epoch-based memory reclamation_ mechanism
//! implemented in [`crossbeam-epoch`]. Simplified, a value removed from the map
//! is not freed until after all references to it have been dropped. This mechanism
//! is similar to the garbage collection found in some languages, such as Java, except
//! it operates solely on the values inside the map.
//!
//! This garbage collection scheme functions automatically; users don't have to worry about it.
//! However, keep in mind that holding [`Entry`] handles to entries in the map will prevent
//! that memory from being freed until at least after the handles are dropped.
//!
//! # Performance versus B-trees
//! In general, when you need concurrent writes
//! to an ordered collection, skip lists are a reasonable choice.
//! However, they can be substantially slower than B-trees
//! in some scenarios.
//!
//! The main benefit of a skip list over a `RwLock<BTreeMap>`
//! is that it allows concurrent writes to progress without
//! mutual exclusion. However, when the frequency
//! of writes is low, this benefit isn't as useful.
//! In these cases, a shared [`BTreeMap`] may be a faster option.
//!
//! These guidelines should be taken with a grain of salt—performance
//! in practice varies depending on your use case.
//! In the end, the best way to choose between [`BTreeMap`] and [`SkipMap`]
//! is to benchmark them in your own application.
//!
//! [`SkipMap`]: struct.SkipMap.html
//! [`SkipSet`]: struct.SkipSet.html
//! [`insert`]: struct.SkipMap.html#method.insert
//! [`get`]: struct.SkipMap.html#method.get
//! [`Entry`]: map/struct.Entry.html
//! [skip lists]: https://en.wikipedia.org/wiki/Skip_list
//! [`crossbeam-epoch`]: https://docs.rs/crossbeam-epoch
//! [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html
//! [`BTreeSet`]: https://doc.rust-lang.org/std/collections/struct.BTreeSet.html
//! [`RwLock`]: https://doc.rust-lang.org/std/sync/struct.RwLock.html
//!
//! # Examples
//! [`SkipMap`] basic usage:
//! ```
//! use crossbeam_skiplist::SkipMap;
//!
//! // Note that the variable doesn't have to be mutable:
//! // SkipMap methods take &self to support concurrent access.
//! let movie_reviews = SkipMap::new();
//!
//! // Insert some key-value pairs.
//! movie_reviews.insert("Office Space",       "Deals with real issues in the workplace.");
//! movie_reviews.insert("Pulp Fiction",       "Masterpiece.");
//! movie_reviews.insert("The Godfather",      "Very enjoyable.");
//! movie_reviews.insert("The Blues Brothers", "Eye lyked it a lot.");
//!
//! // Get the value associated with a key.
//! // get() returns an Entry, which gives
//! // references to the key and value.
//! let pulp_fiction = movie_reviews.get("Pulp Fiction").unwrap();
//! assert_eq!(*pulp_fiction.key(), "Pulp Fiction");
//! assert_eq!(*pulp_fiction.value(), "Masterpiece.");
//!
//! // Remove a key-value pair.
//! movie_reviews.remove("The Blues Brothers");
//! assert!(movie_reviews.get("The Blues Brothers").is_none());
//!
//! // Iterate over the reviews. Since SkipMap
//! // is an ordered map, the iterator will yield
//! // keys in lexicographical order.
//! for entry in &movie_reviews {
//!     let movie = entry.key();
//!     let review = entry.value();
//!     println!("{}: \"{}\"", movie, review);
//! }
//! ```
//!
//! [`SkipSet`] basic usage:
//! ```
//! use crossbeam_skiplist::SkipSet;
//!
//! let books = SkipSet::new();
//!
//! // Add some books to the set.
//! books.insert("A Dance With Dragons");
//! books.insert("To Kill a Mockingbird");
//! books.insert("The Odyssey");
//! books.insert("The Great Gatsby");
//!
//! // Check for a specific one.
//! if !books.contains("The Winds of Winter") {
//!    println!("We have {} books, but The Winds of Winter ain't one.",
//!             books.len());
//! }
//!
//! // Remove a book from the set.
//! books.remove("To Kill a Mockingbird");
//! assert!(!books.contains("To Kill a Mockingbird"));
//!
//! // Iterate over the books in the set.
//! // Values are returned in lexicographical order.
//! for entry in &books {
//!     let book = entry.value();
//!     println!("{}", book);
//! }
//! ```

#![doc(test(
    no_crate_inject,
    attr(
        deny(warnings, rust_2018_idioms),
        allow(dead_code, unused_assignments, unused_variables)
    )
))]
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]

use cfg_if::cfg_if;

#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
cfg_if! {
    if #[cfg(feature = "alloc")] {
        extern crate alloc;

        use crossbeam_epoch as epoch;
        use crossbeam_utils as utils;

        pub mod base;
        #[doc(inline)]
        pub use crate::base::SkipList;
    }
}

cfg_if! {
    if #[cfg(feature = "std")] {
        pub mod map;
        #[doc(inline)]
        pub use crate::map::SkipMap;

        pub mod set;
        #[doc(inline)]
        pub use crate::set::SkipSet;
    }
}
<|endoftext|>


<commit_before>

// -*- rust -*-
fn fib(n: int) -> int {

    // Several of the posted 'benchmark' versions of this compute the
    // wrong Fibonacci numbers, of course.
    if n == 0 {
        ret 0;
    } else { if n <= 2 { ret 1; } else { ret fib(n - 1) + fib(n - 2); } }
}

fn main() {
    assert (fib(8) == 21);
    assert (fib(15) == 610);
    log(debug, fib(8));
    log(debug, fib(15));
}
<commit_msg>bench: Update shootout-fibo for performance<commit_after>use std;

fn fib(n: int) -> int {
    if n < 2 {
        ret 1;
    } else {
        ret fib(n - 1) + fib(n - 2);
    }
}

fn main(args: [str]) {
    // FIXME: #1527
    sys::set_min_stack(1000000u);
    let n = if vec::len(args) == 2u {
        int::from_str(args[1])
    } else {
        40
    };
    std::io::println(#fmt("%d\n", fib(n)));
}
<|endoftext|>


<commit_before><commit_msg>Revert "Test forge by messing things up"<commit_after><|endoftext|>


<commit_before>extern crate rand;
extern crate regex;

use super::moves::Technique;
use super::pokemon_token::PokemonToken;
use super::enums;
use self::rand::{Rng, thread_rng};
use self::regex::Regex;
use player::Player;

/// Resolves moves that simply deals damage to the opponent.
pub fn deal_damage(attack: &Technique, user: &mut PokemonToken, target: &mut PokemonToken) -> u16 {
    // TODO: Methode die matcht zwischen Attacken die direkt verrechnet werden können und denen,
    // die variable Power haben. Hier muss eine Möglichkeit gefunden werden die Power möglichst
    // effizient für alle Attacken zu berechnen.
    let mut stab = 1.0;
    let mut rng = thread_rng();
    let random = rng.gen_range(0.85, 1.0);
    if attack.get_type() == user.get_types().0 || attack.get_type() == user.get_types().1 {
        stab = 1.5;
    }
    let mut damage = 0;
    if attack.get_power().is_some() {
        let modifier = stab * attack.get_effectiveness(target.clone()) * random;
        damage = ((((2.0 * user.get_level() as f32 + 10.0) / 250.0) *
                   user.get_current().get_stat(&enums::Stats::Attack) as f32 /
                   target.get_current().get_stat(&enums::Stats::Defense) as f32 *
                   attack.get_power().unwrap() as f32 + 2.0) * modifier) as u16;
    }
    let current = target.get_current().get_stat(&enums::Stats::Hp);
    target.get_current().set_stats(enums::Stats::Hp, current - damage);
    println!("Damage: {}", damage);
    println!("HP in resolve: {}",
             target.get_current().get_stat(&enums::Stats::Hp));
    damage
}

// resolves ailment effects
pub fn ailment(name: String,
               move_type: enums::Types,
               ailment: enums::Ailment,
               effect_chance: u8,
               target: &mut PokemonToken) {
    let mut rng = thread_rng();
    let random = rng.gen_range(0, 101);
    // only works if the effect chance of the move is met.
    let probability = effect_chance;
    if random <= probability {
        let powder = Regex::new(r"powder").unwrap();
        let spore = Regex::new(r"spore").unwrap();
        let tmp: &str = &name;
        // some sort of attacks did not work against grass types.
        if (target.get_types().0 == enums::Types::Grass ||
            target.get_types().1 == enums::Types::Grass) &&
           (powder.is_match(tmp) || spore.is_match(tmp)) {
            println!("{} was not affected by {}", target.get_name(), name);
        } else {
            // categorize the moves by the ailment they cause. Ailments usually automatically fail
            // if the target already was hit by a move that caused the same ailment and still suffer
            // from it's effect. Non volatile Ailments even fail if the target is under the effect
            // of one of these kind.
            match ailment {

                enums::Ailment::Paralysis => {
                    // electric type pokemon are immune to paralysis
                    if target.get_non_volatile().0 == enums::NonVolatile::Undefined {
                        if !(target.get_types().0 == enums::Types::Electric) &&
                           !(target.get_types().1 == enums::Types::Electric) {
                            target.set_non_volatile(enums::NonVolatile::Paralysis);
                            let base = target.get_base().clone();
                            target.get_current().set_stats(enums::Stats::Speed,
                                                           base.get_stat(&enums::Stats::Speed) / 2)
                        } else {
                            println!("{} was not affected by {}", target.get_name(), name);
                        }
                    } else {
                        println!("{} is already {}",
                                 target.get_name(),
                                 enums::print_non_volatile(target.get_non_volatile().0));
                    }
                }

                enums::Ailment::Sleep => {
                    if target.get_non_volatile().0 == enums::NonVolatile::Undefined {
                        target.set_non_volatile(enums::NonVolatile::Sleep)
                    } else {
                        println!("{} is already {}",
                                 target.get_name(),
                                 enums::print_non_volatile(target.get_non_volatile().0));
                    }
                }

                enums::Ailment::Freeze => {
                    // ice type pokemon are immune to freeze, but only if the used move is also
                    // from the type ice.
                    if (target.get_types().0 == enums::Types::Ice ||
                        target.get_types().1 == enums::Types::Ice) &&
                       move_type == enums::Types::Ice {
                        println!("{} could not be freezed", target.get_name());
                    } else {
                        target.set_non_volatile(enums::NonVolatile::Freeze);
                    }
                }

                enums::Ailment::Burn => {
                    // Fire types can not be burned (seems logical).
                    if target.get_types().0 == enums::Types::Fire ||
                       target.get_types().1 == enums::Types::Fire {
                        println!("{} could not be burned", target.get_name());
                    } else {
                        target.set_non_volatile(enums::NonVolatile::Burn);
                    }
                }

                enums::Ailment::Poison => {
                    // Neither Poison nor steel pokemon can be poisoned in normal ways.
                    if target.get_types().0 == enums::Types::Poison ||
                       target.get_types().0 == enums::Types::Steel ||
                       target.get_types().1 == enums::Types::Poison ||
                       target.get_types().1 == enums::Types::Steel {
                        println!("{} could not be poisoned", target.get_name());
                    } else {
                        if name == String::from("toxic") {
                            target.set_non_volatile(enums::NonVolatile::BadPoison);
                        } else {
                            target.set_non_volatile(enums::NonVolatile::Poison);
                        }
                    }
                }

                enums::Ailment::LeechSeed => {
                    // Has no effect on grass type (even though given the flavor text leech seeds
                    // are a plant parasite...)
                    if target.get_types().0 == enums::Types::Grass ||
                       target.get_types().1 == enums::Types::Grass {
                        println!("{} was not affected by Leech Seed", target.get_name());
                    } else {
                        target.add_end_flag(enums::EndOfTurn::LeechSeed);
                    }
                }

                enums::Ailment::PerishSong => {
                    // actually only one Attack, that kills all Pokemon after 4 rounds, including
                    // the user. Does not reset the counter if used again, therefore Pokemon, that
                    // are already under the effect of Perish Song are not influenced
                    if target.get_end_of_turn_flags().contains_key(&enums::EndOfTurn::PerishSong) {
                        println!("{} is already doomed", target.get_name());
                    } else {
                        target.add_end_flag(enums::EndOfTurn::PerishSong);
                    }
                }

                enums::Ailment::Yawn => {
                    if target.get_end_of_turn_flags().contains_key(&enums::EndOfTurn::Yawn) ||
                       target.get_non_volatile().0 == enums::NonVolatile::Sleep {
                        println!("{} was not affected by Yawn", target.get_name());
                    } else {
                        target.add_end_flag(enums::EndOfTurn::Yawn);
                    }
                }

                enums::Ailment::Trap => {
                    if !target.get_end_of_turn_flags().contains_key(&enums::EndOfTurn::Trap) {
                        target.add_end_flag(enums::EndOfTurn::Trap);
                    }
                }

                _ => {}
            }
        }
    }
}

// TODO: Methode implementieren, die errechnet wie viel ein Stage für das entsprechende Pokemon ist
// und den Stat entsprechend verringert/erhöht, wenn Stage 6/-6 noch nicht erreicht ist. Gibt einen
// bool zurück der anzeigt, ob der Stat verändert wurde oder nicht.
pub fn change_stats(stages: i8, stat: enums::Stats, target: &mut PokemonToken) -> bool {
    let mut current = target.get_current().get_stat(&stat);
    if target.get_non_volatile().0 == enums::NonVolatile::Paralysis {
        current = current * 2;
    }
    let stage = match stat {
        enums::Stats::Accuracy => {
            match (current as f32 / target.get_base().get_stat(&stat) as f32) * 100.0 {
                0.0...34.0 => -6,
                34.0...38.0 => -5,
                38.0...43.0 => -4,
                43.0...51.0 => -3,
                51.0...61.0 => -2,
                61.0...76.0 => -1,
                76.0...101.0 => 0,
                101.0...134.0 => 1,
                134.0...166.0 => 2,
                166.0...201.0 => 3,
                201.0...234.0 => 4,
                234.0...267.0 => 5,
                267.0...301.0 => 6,
                _ => 0,
            }
        }
        enums::Stats::Evasion => {
            match (current as f32 / target.get_base().get_stat(&stat) as f32) * 100.0 {
                0.0...34.0 => 6,
                34.0...38.0 => 5,
                38.0...43.0 => 4,
                43.0...51.0 => 3,
                51.0...61.0 => 2,
                61.0...76.0 => 1,
                76.0...101.0 => 0,
                101.0...134.0 => -1,
                134.0...166.0 => -2,
                166.0...201.0 => -3,
                201.0...234.0 => -4,
                234.0...267.0 => -5,
                267.0...301.0 => -6,
                _ => 0,
            }
        }
        _ => {
            match (current as f32 / target.get_base().get_stat(&stat) as f32) * 100.0 {
                0.0...26.0 => -6,
                26.0...29.0 => -5,
                29.0...34.0 => -4,
                34.0...41.0 => -3,
                41.0...50.0 => -2,
                50.0...67.0 => -1,
                67.0...101.0 => 0,
                101.0...151.0 => 1,
                151.0...201.0 => 2,
                201.0...251.0 => 3,
                251.0...301.0 => 4,
                301.0...351.0 => 5,
                351.0...401.0 => 6,
                _ => 0,
            }
        }
    };
    let new_stage = stage + stages;
    let mut modifier = 1;
    if target.get_non_volatile().0 == enums::NonVolatile::Paralysis {
        modifier = 2;
    }

    let new_stat = match stat {
        enums::Stats::Accuracy => {
            match new_stage {
                -6 => {}
                -5 => {}
                -4 => {}
                -3 => {}
                -2 => {}
                -1 => {}
                0 => {}
                1 => {}
                2 => {}
                3 => {}
                4 => {}
                5 => {}
                6 => {}
                _ => {}
            }
        }
        _ => {}
    };
    true
}

// heals the targets HP by the provided value, or, if this would raise the HP above the base stat,
// to their base HP.
pub fn heal(target: &mut PokemonToken, value: u16) {
    if value + target.get_current().get_stat(&enums::Stats::Hp) >=
       target.get_base().get_stat(&enums::Stats::Hp) {
        let base = target.get_base().clone();
        target.get_current().set_stats(enums::Stats::Hp, base.get_stat(&enums::Stats::Hp));
    } else {
        let current = target.get_current().clone();
        target.get_current().set_stats(enums::Stats::Hp,
                                       (current.get_stat(&enums::Stats::Hp) + value));
    }
}

// switches the Pokemon of the target Player
pub fn switch_pokemon(target: &mut Player) {
    let alive = target.get_alive_count();
    if alive > 1 {
        let mut rng = thread_rng();
        let range = rng.gen_range(0, alive - 1);
        let id = target.clone().get_alive_list()[range];
        let mut position = 0;
        for elem in target.clone().get_pokemon_list() {
            if elem.get_id() == id {
                target.set_current(position);
                break;
            }
            position += 1;
        }
    }
}

// simply sets the HP of the target to 0 (Thats what K.O. means I suppose.)
pub fn ko_attack(target: &mut PokemonToken) {
    target.get_current().set_stats(enums::Stats::Hp, 0);
}
<commit_msg>finished change stats method<commit_after>extern crate rand;
extern crate regex;

use super::moves::Technique;
use super::pokemon_token::PokemonToken;
use super::enums;
use self::rand::{Rng, thread_rng};
use self::regex::Regex;
use player::Player;

/// Resolves moves that simply deals damage to the opponent.
pub fn deal_damage(attack: &Technique, user: &mut PokemonToken, target: &mut PokemonToken) -> u16 {
    // TODO: Methode die matcht zwischen Attacken die direkt verrechnet werden können und denen,
    // die variable Power haben. Hier muss eine Möglichkeit gefunden werden die Power möglichst
    // effizient für alle Attacken zu berechnen.
    let mut stab = 1.0;
    let mut rng = thread_rng();
    let random = rng.gen_range(0.85, 1.0);
    if attack.get_type() == user.get_types().0 || attack.get_type() == user.get_types().1 {
        stab = 1.5;
    }
    let mut damage = 0;
    if attack.get_power().is_some() {
        let modifier = stab * attack.get_effectiveness(target.clone()) * random;
        damage = ((((2.0 * user.get_level() as f32 + 10.0) / 250.0) *
                   user.get_current().get_stat(&enums::Stats::Attack) as f32 /
                   target.get_current().get_stat(&enums::Stats::Defense) as f32 *
                   attack.get_power().unwrap() as f32 + 2.0) * modifier) as u16;
    }
    let current = target.get_current().get_stat(&enums::Stats::Hp);
    target.get_current().set_stats(enums::Stats::Hp, current - damage);
    println!("Damage: {}", damage);
    println!("HP in resolve: {}",
             target.get_current().get_stat(&enums::Stats::Hp));
    damage
}

// resolves ailment effects
pub fn ailment(name: String,
               move_type: enums::Types,
               ailment: enums::Ailment,
               effect_chance: u8,
               target: &mut PokemonToken) {
    let mut rng = thread_rng();
    let random = rng.gen_range(0, 101);
    // only works if the effect chance of the move is met.
    let probability = effect_chance;
    if random <= probability {
        let powder = Regex::new(r"powder").unwrap();
        let spore = Regex::new(r"spore").unwrap();
        let tmp: &str = &name;
        // some sort of attacks did not work against grass types.
        if (target.get_types().0 == enums::Types::Grass ||
            target.get_types().1 == enums::Types::Grass) &&
           (powder.is_match(tmp) || spore.is_match(tmp)) {
            println!("{} was not affected by {}", target.get_name(), name);
        } else {
            // categorize the moves by the ailment they cause. Ailments usually automatically fail
            // if the target already was hit by a move that caused the same ailment and still suffer
            // from it's effect. Non volatile Ailments even fail if the target is under the effect
            // of one of these kind.
            match ailment {

                enums::Ailment::Paralysis => {
                    // electric type pokemon are immune to paralysis
                    if target.get_non_volatile().0 == enums::NonVolatile::Undefined {
                        if !(target.get_types().0 == enums::Types::Electric) &&
                           !(target.get_types().1 == enums::Types::Electric) {
                            target.set_non_volatile(enums::NonVolatile::Paralysis);
                            let base = target.get_base().clone();
                            target.get_current().set_stats(enums::Stats::Speed,
                                                           base.get_stat(&enums::Stats::Speed) / 2)
                        } else {
                            println!("{} was not affected by {}", target.get_name(), name);
                        }
                    } else {
                        println!("{} is already {}",
                                 target.get_name(),
                                 enums::print_non_volatile(target.get_non_volatile().0));
                    }
                }

                enums::Ailment::Sleep => {
                    if target.get_non_volatile().0 == enums::NonVolatile::Undefined {
                        target.set_non_volatile(enums::NonVolatile::Sleep)
                    } else {
                        println!("{} is already {}",
                                 target.get_name(),
                                 enums::print_non_volatile(target.get_non_volatile().0));
                    }
                }

                enums::Ailment::Freeze => {
                    // ice type pokemon are immune to freeze, but only if the used move is also
                    // from the type ice.
                    if (target.get_types().0 == enums::Types::Ice ||
                        target.get_types().1 == enums::Types::Ice) &&
                       move_type == enums::Types::Ice {
                        println!("{} could not be freezed", target.get_name());
                    } else {
                        target.set_non_volatile(enums::NonVolatile::Freeze);
                    }
                }

                enums::Ailment::Burn => {
                    // Fire types can not be burned (seems logical).
                    if target.get_types().0 == enums::Types::Fire ||
                       target.get_types().1 == enums::Types::Fire {
                        println!("{} could not be burned", target.get_name());
                    } else {
                        target.set_non_volatile(enums::NonVolatile::Burn);
                    }
                }

                enums::Ailment::Poison => {
                    // Neither Poison nor steel pokemon can be poisoned in normal ways.
                    if target.get_types().0 == enums::Types::Poison ||
                       target.get_types().0 == enums::Types::Steel ||
                       target.get_types().1 == enums::Types::Poison ||
                       target.get_types().1 == enums::Types::Steel {
                        println!("{} could not be poisoned", target.get_name());
                    } else {
                        if name == String::from("toxic") {
                            target.set_non_volatile(enums::NonVolatile::BadPoison);
                        } else {
                            target.set_non_volatile(enums::NonVolatile::Poison);
                        }
                    }
                }

                enums::Ailment::LeechSeed => {
                    // Has no effect on grass type (even though given the flavor text leech seeds
                    // are a plant parasite...)
                    if target.get_types().0 == enums::Types::Grass ||
                       target.get_types().1 == enums::Types::Grass {
                        println!("{} was not affected by Leech Seed", target.get_name());
                    } else {
                        target.add_end_flag(enums::EndOfTurn::LeechSeed);
                    }
                }

                enums::Ailment::PerishSong => {
                    // actually only one Attack, that kills all Pokemon after 4 rounds, including
                    // the user. Does not reset the counter if used again, therefore Pokemon, that
                    // are already under the effect of Perish Song are not influenced
                    if target.get_end_of_turn_flags().contains_key(&enums::EndOfTurn::PerishSong) {
                        println!("{} is already doomed", target.get_name());
                    } else {
                        target.add_end_flag(enums::EndOfTurn::PerishSong);
                    }
                }

                enums::Ailment::Yawn => {
                    if target.get_end_of_turn_flags().contains_key(&enums::EndOfTurn::Yawn) ||
                       target.get_non_volatile().0 == enums::NonVolatile::Sleep {
                        println!("{} was not affected by Yawn", target.get_name());
                    } else {
                        target.add_end_flag(enums::EndOfTurn::Yawn);
                    }
                }

                enums::Ailment::Trap => {
                    if !target.get_end_of_turn_flags().contains_key(&enums::EndOfTurn::Trap) {
                        target.add_end_flag(enums::EndOfTurn::Trap);
                    }
                }

                _ => {}
            }
        }
    }
}

// TODO: Methode implementieren, die errechnet wie viel ein Stage für das entsprechende Pokemon ist
// und den Stat entsprechend verringert/erhöht, wenn Stage 6/-6 noch nicht erreicht ist. Gibt einen
// bool zurück der anzeigt, ob der Stat verändert wurde oder nicht.
pub fn change_stats(stages: i8, stat: enums::Stats, target: &mut PokemonToken) -> bool {
    let mut current = target.get_current().get_stat(&stat);
    if target.get_non_volatile().0 == enums::NonVolatile::Paralysis {
        current = current * 2;
    }
    let stage = match stat {
        enums::Stats::Accuracy => {
            match (current as f32 / target.get_base().get_stat(&stat) as f32) * 100.0 {
                0.0...34.0 => -6,
                34.0...38.0 => -5,
                38.0...43.0 => -4,
                43.0...51.0 => -3,
                51.0...61.0 => -2,
                61.0...76.0 => -1,
                76.0...101.0 => 0,
                101.0...134.0 => 1,
                134.0...166.0 => 2,
                166.0...201.0 => 3,
                201.0...234.0 => 4,
                234.0...267.0 => 5,
                267.0...301.0 => 6,
                _ => 0,
            }
        }
        enums::Stats::Evasion => {
            match (current as f32 / target.get_base().get_stat(&stat) as f32) * 100.0 {
                0.0...34.0 => 6,
                34.0...38.0 => 5,
                38.0...43.0 => 4,
                43.0...51.0 => 3,
                51.0...61.0 => 2,
                61.0...76.0 => 1,
                76.0...101.0 => 0,
                101.0...134.0 => -1,
                134.0...166.0 => -2,
                166.0...201.0 => -3,
                201.0...234.0 => -4,
                234.0...267.0 => -5,
                267.0...301.0 => -6,
                _ => 0,
            }
        }
        _ => {
            match (current as f32 / target.get_base().get_stat(&stat) as f32) * 100.0 {
                0.0...26.0 => -6,
                26.0...29.0 => -5,
                29.0...34.0 => -4,
                34.0...41.0 => -3,
                41.0...50.0 => -2,
                50.0...67.0 => -1,
                67.0...101.0 => 0,
                101.0...151.0 => 1,
                151.0...201.0 => 2,
                201.0...251.0 => 3,
                251.0...301.0 => 4,
                301.0...351.0 => 5,
                351.0...401.0 => 6,
                _ => 0,
            }
        }
    };
    if !stage <= -6 || !stage >= 6 {
        let mut new_stage = stage + stages;
        if new_stage > 6 {
            new_stage = 6;
        } else if new_stage < -6 {
            new_stage = -6
        }
        let mut modifier = 1.0;
        if target.get_non_volatile().0 == enums::NonVolatile::Paralysis {
            modifier = 0.5;
        }
        let base = target.get_base().get_stat(&stat) as f32;

        let new_stat = modifier *
                       match stat {
            enums::Stats::Accuracy => {
                match new_stage {
                    -6 => base / 3.0,
                    -5 => base / 8.0 * 3.0,
                    -4 => base / 7.0 * 3.0,
                    -3 => base / 2.0,
                    -2 => base / 5.0 * 3.0,
                    -1 => base / 4.0 * 3.0,
                    0 => base,
                    1 => base / 3.0 * 4.0,
                    2 => base / 3.0 * 5.0,
                    3 => base * 2.0,
                    4 => base / 3.0 * 7.0,
                    5 => base / 3.0 * 8.0,
                    6 => base * 3.0,
                    _ => base,
                }
            }
            enums::Stats::Evasion => {
                match new_stage {
                    6 => base / 3.0,
                    5 => base / 8.0 * 3.0,
                    4 => base / 7.0 * 3.0,
                    3 => base / 2.0,
                    2 => base / 5.0 * 3.0,
                    1 => base / 4.0 * 3.0,
                    0 => base,
                    -1 => base / 3.0 * 4.0,
                    -2 => base / 3.0 * 5.0,
                    -3 => base * 2.0,
                    -4 => base / 3.0 * 7.0,
                    -5 => base / 3.0 * 8.0,
                    -6 => base * 3.0,
                    _ => base,
                }
            }
            _ => {
                match new_stage {
                    -6 => base / 4.0,
                    -5 => base / 7.0 * 2.0,
                    -4 => base / 3.0,
                    -3 => base / 5.0 * 2.0,
                    -2 => base / 2.0,
                    -1 => base / 3.0 * 2.0,
                    0 => base,
                    1 => base * 1.5,
                    2 => base * 2.0,
                    3 => base * 2.5,
                    4 => base * 3.0,
                    5 => base * 3.5,
                    6 => base * 4.0,
                    _ => base,
                }
            }
        };
        target.get_current().set_stats(stat, new_stat as u16);
        return true;
    }
    return false;
}

// heals the targets HP by the provided value, or, if this would raise the HP above the base stat,
// to their base HP.
pub fn heal(target: &mut PokemonToken, value: u16) {
    if value + target.get_current().get_stat(&enums::Stats::Hp) >=
       target.get_base().get_stat(&enums::Stats::Hp) {
        let base = target.get_base().clone();
        target.get_current().set_stats(enums::Stats::Hp, base.get_stat(&enums::Stats::Hp));
    } else {
        let current = target.get_current().clone();
        target.get_current().set_stats(enums::Stats::Hp,
                                       (current.get_stat(&enums::Stats::Hp) + value));
    }
}

// switches the Pokemon of the target Player
pub fn switch_pokemon(target: &mut Player) {
    let alive = target.get_alive_count();
    if alive > 1 {
        let mut rng = thread_rng();
        let range = rng.gen_range(0, alive - 1);
        let id = target.clone().get_alive_list()[range];
        let mut position = 0;
        for elem in target.clone().get_pokemon_list() {
            if elem.get_id() == id {
                target.set_current(position);
                break;
            }
            position += 1;
        }
    }
}

// simply sets the HP of the target to 0 (Thats what K.O. means I suppose.)
pub fn ko_attack(target: &mut PokemonToken) {
    target.get_current().set_stats(enums::Stats::Hp, 0);
}
<|endoftext|>


<commit_before>//! module for finite automation.

use std::collections::HashSet;
use std::hash::Hash;

/// The rule that moves state from one to another.
///
/// `S` - the type parameter of state.
///
/// `T` - the type parameter of input symbol.
#[deriving(PartialEq, Eq, Hash)]
pub struct Rule<S, T> {
  pub state: S,
  pub symbol: Option<T>,
  pub next_state: S
}

impl<S: PartialEq, T: PartialEq> Rule<S, T> {
  /// determine whether the rule applies to the given state and symbol
  pub fn apply_to(&self, state: &S, symbol: &Option<T>) -> bool {
    self.state == *state && self.symbol == *symbol
  }
}

/// The transition relation in DFA,
/// containing all the rules needed by the DFA.
pub struct DFATransitions<S, T> {
  pub rules: HashSet<Rule<S, T>>
}

impl<S: Eq + Hash, T: Eq + Hash> DFATransitions<S, T> {
  /// get the next state for the given state and symbol
  pub fn next_state(&self, state: &S, symbol: &Option<T>) -> Option<&S> {
    self.rule_for(state, symbol).map(|rule| &rule.next_state)
  }

  fn rule_for(&self, state: &S, symbol: &Option<T>) -> Option<&Rule<S, T>> {
    self.rules.iter().find(|rule| { rule.apply_to(state, symbol) })
  }
}

/// A running dfa instance, constructed from a DFA model
pub struct DFA<'a, S: 'a, T: 'a> {
  state: S, // current state
  accept_states: &'a HashSet<S>, // set of accept states
  transitions: &'a DFATransitions<S, T>
}

impl<'a, S: Eq + Hash + Clone, T: Eq + Hash> DFA<'a, S, T> {
  pub fn accepted(&self) -> bool {
    self.accept_states.contains(&self.state)
  }

  pub fn read_symbol(&mut self, sym: &Option<T>) {
    self.state = self.transitions.next_state(&self.state, sym)
                                 .expect("unknown input symbol")
                                 .clone()
  }
}

/// DFA template that can generates dfa instance
pub struct DFAModel<S, T> {
  pub start_state: S,
  pub accept_states: HashSet<S>,
  pub transitions: DFATransitions<S, T>
}

impl<S: Clone + Eq + Hash, T: Eq + Hash> DFAModel<S, T> {
  /// determine whether the given symbols can be accepted by the model
  pub fn accept<I: Iterator<T>>(&self, mut iter: I) -> bool {
    let mut dfa = self.gen_dfa();
    for sym in iter {
      dfa.read_symbol(&Some(sym));
    }

    dfa.accepted()
  }

  /// generate a dfa instance
  fn gen_dfa(&self) -> DFA<S, T> {
    DFA {
      state: self.start_state.clone(),
      accept_states: &self.accept_states,
      transitions: &self.transitions
    }
  }
}

/// The transition relation in NFA,
/// containing all the rules needed by the NFA.
pub struct NFATransitions<S, T> {
  pub rules: HashSet<Rule<S, T>>
}

impl<S: Eq + Hash + Clone, T: Eq + Hash> NFATransitions<S, T> {
  fn empty_move(&self, states: HashSet<S>) -> HashSet<S> {
    let mut nexts = self.next_states(&states, &None);
    if nexts.is_subset(&states) {
      states
    } else {
      nexts.extend(states.move_iter());
      self.empty_move(nexts)
    }
  }

  pub fn next_states(&self, states: &HashSet<S>, symbol: &Option<T>) -> HashSet<S> {
    states.iter().flat_map(|state| {
      // NOTE: use `move_iter` instead of `iter`
      self.next_states_for(state, symbol).move_iter()
    }).collect()
  }

  /// get the next state for the given state and symbol
  fn next_states_for(&self, state: &S, symbol: &Option<T>) -> HashSet<S> {
    self.rules.iter().filter_map(|rule| {
      if rule.apply_to(state, symbol) { Some(rule.next_state.clone()) } else { None }
    }).collect()
  }

  fn rules_for<'a>(&'a self, state: &S, symbol: &Option<T>) -> HashSet<&'a Rule<S, T>> {
    self.rules.iter()
              .filter(|rule| { rule.apply_to(state, symbol) })
              .collect()
  }
}

struct NFA<'a, S: 'a, T: 'a> {
  states: HashSet<S>,
  accept_states: &'a HashSet<S>,
  transitions: &'a NFATransitions<S, T>
}

impl<'a, S: Eq + Hash + Clone, T: Eq + Hash> NFA<'a, S, T> {
  pub fn read_symbol(&mut self, symbol: &Option<T>) {
    // do empty moves
    self.states = self.transitions.empty_move(self.states.clone());

    self.states = self.transitions.next_states(&self.states, symbol)
                                  .iter()
                                  .map(|state| { state.clone() }).collect();

    self.states = self.transitions.empty_move(self.states.clone());
  }

  pub fn accepted(&self) -> bool {
    !self.states.is_disjoint(self.accept_states)
  }
}

pub struct NFAModel<S, T> {
  pub start_state: S,
  pub accept_states: HashSet<S>,
  pub transitions: NFATransitions<S, T>
}

impl<S: Eq + Hash + Clone, T: Eq + Hash> NFAModel<S, T> {
  /// determine whether the given symbols can be accepted by the model
  pub fn accept<I: Iterator<T>>(&self, mut iter: I) -> bool {
    let mut dfa = self.gen_nfa();
    for sym in iter {
      dfa.read_symbol(&Some(sym));
    }

    dfa.accepted()
  }

  /// generate a nfa instance
  fn gen_nfa(&self) -> NFA<S, T> {
    let mut start_states = HashSet::new();
    start_states.insert(self.start_state.clone());
    NFA {
      states: start_states,
      accept_states: &self.accept_states,
      transitions: &self.transitions
    }
  }
}
<commit_msg>replace move_iter with into_iter<commit_after>//! module for finite automation.

use std::collections::HashSet;
use std::hash::Hash;

/// The rule that moves state from one to another.
///
/// `S` - the type parameter of state.
///
/// `T` - the type parameter of input symbol.
#[deriving(PartialEq, Eq, Hash)]
pub struct Rule<S, T> {
  pub state: S,
  pub symbol: Option<T>,
  pub next_state: S
}

impl<S: PartialEq, T: PartialEq> Rule<S, T> {
  /// determine whether the rule applies to the given state and symbol
  pub fn apply_to(&self, state: &S, symbol: &Option<T>) -> bool {
    self.state == *state && self.symbol == *symbol
  }
}

/// The transition relation in DFA,
/// containing all the rules needed by the DFA.
pub struct DFATransitions<S, T> {
  pub rules: HashSet<Rule<S, T>>
}

impl<S: Eq + Hash, T: Eq + Hash> DFATransitions<S, T> {
  /// get the next state for the given state and symbol
  pub fn next_state(&self, state: &S, symbol: &Option<T>) -> Option<&S> {
    self.rule_for(state, symbol).map(|rule| &rule.next_state)
  }

  fn rule_for(&self, state: &S, symbol: &Option<T>) -> Option<&Rule<S, T>> {
    self.rules.iter().find(|rule| { rule.apply_to(state, symbol) })
  }
}

/// A running dfa instance, constructed from a DFA model
pub struct DFA<'a, S: 'a, T: 'a> {
  state: S, // current state
  accept_states: &'a HashSet<S>, // set of accept states
  transitions: &'a DFATransitions<S, T>
}

impl<'a, S: Eq + Hash + Clone, T: Eq + Hash> DFA<'a, S, T> {
  pub fn accepted(&self) -> bool {
    self.accept_states.contains(&self.state)
  }

  pub fn read_symbol(&mut self, sym: &Option<T>) {
    self.state = self.transitions.next_state(&self.state, sym)
                                 .expect("unknown input symbol")
                                 .clone()
  }
}

/// DFA template that can generates dfa instance
pub struct DFAModel<S, T> {
  pub start_state: S,
  pub accept_states: HashSet<S>,
  pub transitions: DFATransitions<S, T>
}

impl<S: Clone + Eq + Hash, T: Eq + Hash> DFAModel<S, T> {
  /// determine whether the given symbols can be accepted by the model
  pub fn accept<I: Iterator<T>>(&self, mut iter: I) -> bool {
    let mut dfa = self.gen_dfa();
    for sym in iter {
      dfa.read_symbol(&Some(sym));
    }

    dfa.accepted()
  }

  /// generate a dfa instance
  fn gen_dfa(&self) -> DFA<S, T> {
    DFA {
      state: self.start_state.clone(),
      accept_states: &self.accept_states,
      transitions: &self.transitions
    }
  }
}

/// The transition relation in NFA,
/// containing all the rules needed by the NFA.
pub struct NFATransitions<S, T> {
  pub rules: HashSet<Rule<S, T>>
}

impl<S: Eq + Hash + Clone, T: Eq + Hash> NFATransitions<S, T> {
  fn empty_move(&self, states: HashSet<S>) -> HashSet<S> {
    let mut nexts = self.next_states(&states, &None);
    if nexts.is_subset(&states) {
      states
    } else {
      nexts.extend(states.into_iter());
      self.empty_move(nexts)
    }
  }

  pub fn next_states(&self, states: &HashSet<S>, symbol: &Option<T>) -> HashSet<S> {
    states.iter().flat_map(|state| {
      // NOTE: use `move_iter` instead of `iter`
      self.next_states_for(state, symbol).into_iter()
    }).collect()
  }

  /// get the next state for the given state and symbol
  fn next_states_for(&self, state: &S, symbol: &Option<T>) -> HashSet<S> {
    self.rules.iter().filter_map(|rule| {
      if rule.apply_to(state, symbol) { Some(rule.next_state.clone()) } else { None }
    }).collect()
  }

  fn rules_for<'a>(&'a self, state: &S, symbol: &Option<T>) -> HashSet<&'a Rule<S, T>> {
    self.rules.iter()
              .filter(|rule| { rule.apply_to(state, symbol) })
              .collect()
  }
}

struct NFA<'a, S: 'a, T: 'a> {
  states: HashSet<S>,
  accept_states: &'a HashSet<S>,
  transitions: &'a NFATransitions<S, T>
}

impl<'a, S: Eq + Hash + Clone, T: Eq + Hash> NFA<'a, S, T> {
  pub fn read_symbol(&mut self, symbol: &Option<T>) {
    // do empty moves
    self.states = self.transitions.empty_move(self.states.clone());

    self.states = self.transitions.next_states(&self.states, symbol)
                                  .iter()
                                  .map(|state| { state.clone() }).collect();

    self.states = self.transitions.empty_move(self.states.clone());
  }

  pub fn accepted(&self) -> bool {
    !self.states.is_disjoint(self.accept_states)
  }
}

pub struct NFAModel<S, T> {
  pub start_state: S,
  pub accept_states: HashSet<S>,
  pub transitions: NFATransitions<S, T>
}

impl<S: Eq + Hash + Clone, T: Eq + Hash> NFAModel<S, T> {
  /// determine whether the given symbols can be accepted by the model
  pub fn accept<I: Iterator<T>>(&self, mut iter: I) -> bool {
    let mut dfa = self.gen_nfa();
    for sym in iter {
      dfa.read_symbol(&Some(sym));
    }

    dfa.accepted()
  }

  /// generate a nfa instance
  fn gen_nfa(&self) -> NFA<S, T> {
    let mut start_states = HashSet::new();
    start_states.insert(self.start_state.clone());
    NFA {
      states: start_states,
      accept_states: &self.accept_states,
      transitions: &self.transitions
    }
  }
}
<|endoftext|>


<commit_before>use std::net::ToSocketAddrs;
use rustc_serialize::Encodable;
use retry::retry_exponentially;
use record::FluentError;
use forwardable::Forwardable;
use forwardable::Entry;
use fluent::Fluent;

#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct Forward<T: Encodable> {
    tag: String,
    entries: Vec<Entry<T>>,
}

impl<T: Encodable> Forward<T> {
    pub fn new(tag: String, entries: Vec<Entry<T>>) -> Forward<T> {
        Forward {
            tag: tag,
            entries: entries,
        }
    }
}

impl<A: ToSocketAddrs> Forwardable for Fluent<A> {
    /// Post record into Fluentd. With time version.
    fn post<T>(self, entries: Vec<Entry<T>>) -> Result<(), FluentError>
        where T: Encodable
    {
        let forward = Forward::new(self.get_tag(), entries);
        let addr = self.get_addr();
        let (max, multiplier) = self.get_conf().build();
        match retry_exponentially(max,
                                  multiplier,
                                  || Fluent::closure_send_as_forward(addr, &forward),
                                  |response| response.is_ok()) {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }
}

#[cfg(test)]
#[cfg(feature="fluentd")]
mod tests {
    use time;
    use fluent::Fluent;

    #[test]
    fn test_post() {
        use std::collections::HashMap;
        use forwardable::Forwardable;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj1: HashMap<String, String> = HashMap::new();
        obj1.insert("hey".to_string(), "Rust with forward mode!".to_string());
        let mut obj2: HashMap<String, String> = HashMap::new();
        obj2.insert("yeah".to_string(), "Also sent together!".to_string());
        let time = time::now().to_timespec().sec;
        let entry = (time, obj1);
        let entry2 = (time, obj2);
        let result = fruently.post(vec![(entry), (entry2)]).is_ok();
        assert_eq!(true, result);
    }
}
<commit_msg>forward: Add rustdoc<commit_after>//! Send records as forward mode.
//!
//! ## Usage
//!
//! This trait is used as follows:
//!
//! ```no_run
//! extern crate fruently;
//! use fruently::fluent::Fluent;
//! use std::collections::HashMap;
//! use fruently::forwardable::Forwardable;
//!
//! fn main() {
//!     let fruently = Fluent::new("0.0.0.0:24224", "test");
//!     let mut obj1: HashMap<String, String> = HashMap::new();
//!     obj1.insert("hey".to_string(), "Rust with forward mode!".to_string());
//!     let mut obj2: HashMap<String, String> = HashMap::new();
//!     obj2.insert("yeah".to_string(), "Also sent together!".to_string());
//!     // In practice, use time::now() or chrono crate's methods instead.
//!     let time = 1462080486;
//!     let entry = (time, obj1);
//!     let entry2 = (time, obj2);
//!     let _ = fruently.post(vec![(entry), (entry2)]);
//! }
//! ```

use std::net::ToSocketAddrs;
use rustc_serialize::Encodable;
use retry::retry_exponentially;
use record::FluentError;
use forwardable::Forwardable;
use forwardable::Entry;
use fluent::Fluent;

#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct Forward<T: Encodable> {
    tag: String,
    entries: Vec<Entry<T>>,
}

impl<T: Encodable> Forward<T> {
    pub fn new(tag: String, entries: Vec<Entry<T>>) -> Forward<T> {
        Forward {
            tag: tag,
            entries: entries,
        }
    }
}

impl<A: ToSocketAddrs> Forwardable for Fluent<A> {
    /// Post record into Fluentd. With time version.
    fn post<T>(self, entries: Vec<Entry<T>>) -> Result<(), FluentError>
        where T: Encodable
    {
        let forward = Forward::new(self.get_tag(), entries);
        let addr = self.get_addr();
        let (max, multiplier) = self.get_conf().build();
        match retry_exponentially(max,
                                  multiplier,
                                  || Fluent::closure_send_as_forward(addr, &forward),
                                  |response| response.is_ok()) {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }
}

#[cfg(test)]
#[cfg(feature="fluentd")]
mod tests {
    use time;
    use fluent::Fluent;

    #[test]
    fn test_post() {
        use std::collections::HashMap;
        use forwardable::Forwardable;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj1: HashMap<String, String> = HashMap::new();
        obj1.insert("hey".to_string(), "Rust with forward mode!".to_string());
        let mut obj2: HashMap<String, String> = HashMap::new();
        obj2.insert("yeah".to_string(), "Also sent together!".to_string());
        let time = time::now().to_timespec().sec;
        let entry = (time, obj1);
        let entry2 = (time, obj2);
        let result = fruently.post(vec![(entry), (entry2)]).is_ok();
        assert_eq!(true, result);
    }
}
<|endoftext|>


<commit_before>// experimental implementation of an Old generation consisting of pages
// goal is to reduce work for full GCs
struct PagedOldGen {

}<commit_msg>pold: start implementing pages<commit_after>use gc::Region;

// experimental implementation of an Old generation consisting of pages
// goal is to reduce work for full GCs
struct PagedOldGen {
    // total size of old generation
    total: Region,

    live_pages: PageSet,
    free_pages: PageSet,
}

// Choose 512K as page size for now
const PAGE_SIZE_BITS: usize = 19;

struct PageId(usize);

struct Page {
    // end of allocated area in page
    top: usize,

    // live objects in bytes
    live: usize,

    // amount of garbage in bytes
    garbage: usize,
}

// An array of Pages
// TODO: implement this as bitset
struct PageSet {
    pages: Vec<PageId>,
}<|endoftext|>


<commit_before>/*
 * Copyright 2017 Sreejith Krishnan R
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

use std::rc::Rc;

use super::{PresentationLayout};
use super::super::{Layout, ConcreteLayout};
use ::props::{LineBreak};
use ::platform::Context;
use ::draw::{Drawable, Wrapper, Space, MeasureMode};

pub struct MspaceLayout {
    pub(crate) width: f32,
    pub(crate) height: f32,
    pub(crate) depth: f32,
    pub(crate) _linebreak: LineBreak,

    pub(crate) presentation_layout: PresentationLayout
}

impl Layout for MspaceLayout {
    fn layout<'a>(&'a self, context: &Context) -> Box<Drawable + 'a> {
        Box::new(ConcreteLayout::layout(self, context))
    }
}

impl<'a> ConcreteLayout<'a, Wrapper<'a, MspaceLayout, Space>> for MspaceLayout {
    fn layout(&'a self, context: &Context) -> Wrapper<'a, MspaceLayout, Space> {
        let space = Space::new(self.width, self.height, self.depth, self.depth);
        let mut wrapper = Wrapper::new(
            self,
            |mspace| &mspace.presentation_layout.math_background
        );

        wrapper.wrap(space);

        wrapper.calculate(context, &MeasureMode::Wrap, &MeasureMode::Wrap);

        wrapper
    }
}<commit_msg>Fix mspace depth not considered when calculating height of element<commit_after>/*
 * Copyright 2017 Sreejith Krishnan R
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

use std::rc::Rc;

use super::{PresentationLayout};
use super::super::{Layout, ConcreteLayout};
use ::props::{LineBreak};
use ::platform::Context;
use ::draw::{Drawable, Wrapper, Space, MeasureMode};

pub struct MspaceLayout {
    pub(crate) width: f32,
    pub(crate) height: f32,
    pub(crate) depth: f32,
    pub(crate) _linebreak: LineBreak,

    pub(crate) presentation_layout: PresentationLayout
}

impl Layout for MspaceLayout {
    fn layout<'a>(&'a self, context: &Context) -> Box<Drawable + 'a> {
        Box::new(ConcreteLayout::layout(self, context))
    }
}

impl<'a> ConcreteLayout<'a, Wrapper<'a, MspaceLayout, Space>> for MspaceLayout {
    fn layout(&'a self, context: &Context) -> Wrapper<'a, MspaceLayout, Space> {
        let space = Space::new(self.width, self.height+self.depth, self.depth, self.depth);
        let mut wrapper = Wrapper::new(
            self,
            |mspace| &mspace.presentation_layout.math_background
        );

        wrapper.wrap(space);

        wrapper.calculate(context, &MeasureMode::Wrap, &MeasureMode::Wrap);

        wrapper
    }
}<|endoftext|>


<commit_before>//! Rustdoc's JSON backend
//!
//! This module contains the logic for rendering a crate as JSON rather than the normal static HTML
//! output. See [the RFC](https://github.com/rust-lang/rfcs/pull/2963) and the [`types`] module
//! docs for usage and details.

mod conversions;
pub mod types;

use std::cell::RefCell;
use std::fs::File;
use std::path::PathBuf;
use std::rc::Rc;

use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty;
use rustc_session::Session;
use rustc_span::edition::Edition;

use crate::clean;
use crate::config::{RenderInfo, RenderOptions};
use crate::error::Error;
use crate::formats::cache::Cache;
use crate::formats::FormatRenderer;
use crate::html::render::cache::ExternalLocation;

#[derive(Clone)]
crate struct JsonRenderer<'tcx> {
    tcx: ty::TyCtxt<'tcx>,
    /// A mapping of IDs that contains all local items for this crate which gets output as a top
    /// level field of the JSON blob.
    index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>,
    /// The directory where the blob will be written to.
    out_path: PathBuf,
}

impl JsonRenderer<'_> {
    fn sess(&self) -> &Session {
        self.tcx.sess
    }

    fn get_trait_implementors(
        &mut self,
        id: rustc_span::def_id::DefId,
        cache: &Cache,
    ) -> Vec<types::Id> {
        cache
            .implementors
            .get(&id)
            .map(|implementors| {
                implementors
                    .iter()
                    .map(|i| {
                        let item = &i.impl_item;
                        self.item(item.clone(), cache).unwrap();
                        item.def_id.into()
                    })
                    .collect()
            })
            .unwrap_or_default()
    }

    fn get_impls(&mut self, id: rustc_span::def_id::DefId, cache: &Cache) -> Vec<types::Id> {
        cache
            .impls
            .get(&id)
            .map(|impls| {
                impls
                    .iter()
                    .filter_map(|i| {
                        let item = &i.impl_item;
                        if item.def_id.is_local() {
                            self.item(item.clone(), cache).unwrap();
                            Some(item.def_id.into())
                        } else {
                            None
                        }
                    })
                    .collect()
            })
            .unwrap_or_default()
    }

    fn get_trait_items(&mut self, cache: &Cache) -> Vec<(types::Id, types::Item)> {
        cache
            .traits
            .iter()
            .filter_map(|(&id, trait_item)| {
                // only need to synthesize items for external traits
                if !id.is_local() {
                    trait_item.items.clone().into_iter().for_each(|i| self.item(i, cache).unwrap());
                    Some((
                        id.into(),
                        types::Item {
                            id: id.into(),
                            crate_id: id.krate.as_u32(),
                            name: cache
                                .paths
                                .get(&id)
                                .unwrap_or_else(|| {
                                    cache
                                        .external_paths
                                        .get(&id)
                                        .expect("Trait should either be in local or external paths")
                                })
                                .0
                                .last()
                                .map(Clone::clone),
                            visibility: types::Visibility::Public,
                            kind: types::ItemKind::Trait,
                            inner: types::ItemEnum::TraitItem(trait_item.clone().into()),
                            source: None,
                            docs: Default::default(),
                            links: Default::default(),
                            attrs: Default::default(),
                            deprecation: Default::default(),
                        },
                    ))
                } else {
                    None
                }
            })
            .collect()
    }
}

impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
    fn init(
        krate: clean::Crate,
        options: RenderOptions,
        _render_info: RenderInfo,
        _edition: Edition,
        _cache: &mut Cache,
        tcx: ty::TyCtxt<'tcx>,
    ) -> Result<(Self, clean::Crate), Error> {
        debug!("Initializing json renderer");
        Ok((
            JsonRenderer {
                tcx,
                index: Rc::new(RefCell::new(FxHashMap::default())),
                out_path: options.output,
            },
            krate,
        ))
    }

    /// Inserts an item into the index. This should be used rather than directly calling insert on
    /// the hashmap because certain items (traits and types) need to have their mappings for trait
    /// implementations filled out before they're inserted.
    fn item(&mut self, item: clean::Item, cache: &Cache) -> Result<(), Error> {
        // Flatten items that recursively store other items
        item.kind.inner_items().for_each(|i| self.item(i.clone(), cache).unwrap());

        let id = item.def_id;
        if let Some(mut new_item) = self.convert_item(item) {
            if let types::ItemEnum::TraitItem(ref mut t) = new_item.inner {
                t.implementors = self.get_trait_implementors(id, cache)
            } else if let types::ItemEnum::StructItem(ref mut s) = new_item.inner {
                s.impls = self.get_impls(id, cache)
            } else if let types::ItemEnum::EnumItem(ref mut e) = new_item.inner {
                e.impls = self.get_impls(id, cache)
            }
            let removed = self.index.borrow_mut().insert(id.into(), new_item.clone());
            // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
            // to make sure the items are unique.
            if let Some(old_item) = removed {
                assert_eq!(old_item, new_item);
            }
        }

        Ok(())
    }

    fn mod_item_in(
        &mut self,
        item: &clean::Item,
        _module_name: &str,
        cache: &Cache,
    ) -> Result<(), Error> {
        use clean::types::ItemKind::*;
        if let ModuleItem(m) = &*item.kind {
            for item in &m.items {
                match &*item.kind {
                    // These don't have names so they don't get added to the output by default
                    ImportItem(_) => self.item(item.clone(), cache).unwrap(),
                    ExternCrateItem(_, _) => self.item(item.clone(), cache).unwrap(),
                    ImplItem(i) => {
                        i.items.iter().for_each(|i| self.item(i.clone(), cache).unwrap())
                    }
                    _ => {}
                }
            }
        }
        self.item(item.clone(), cache).unwrap();
        Ok(())
    }

    fn mod_item_out(&mut self, _item_name: &str) -> Result<(), Error> {
        Ok(())
    }

    fn after_krate(&mut self, krate: &clean::Crate, cache: &Cache) -> Result<(), Error> {
        debug!("Done with crate");
        let mut index = (*self.index).clone().into_inner();
        index.extend(self.get_trait_items(cache));
        let output = types::Crate {
            root: types::Id(String::from("0:0")),
            crate_version: krate.version.clone(),
            includes_private: cache.document_private,
            index,
            paths: cache
                .paths
                .clone()
                .into_iter()
                .chain(cache.external_paths.clone().into_iter())
                .map(|(k, (path, kind))| {
                    (
                        k.into(),
                        types::ItemSummary { crate_id: k.krate.as_u32(), path, kind: kind.into() },
                    )
                })
                .collect(),
            external_crates: cache
                .extern_locations
                .iter()
                .map(|(k, v)| {
                    (
                        k.as_u32(),
                        types::ExternalCrate {
                            name: v.0.to_string(),
                            html_root_url: match &v.2 {
                                ExternalLocation::Remote(s) => Some(s.clone()),
                                _ => None,
                            },
                        },
                    )
                })
                .collect(),
            format_version: 1,
        };
        let mut p = self.out_path.clone();
        p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
        p.set_extension("json");
        let file = File::create(&p).map_err(|error| Error { error: error.to_string(), file: p })?;
        serde_json::ser::to_writer(&file, &output).unwrap();
        Ok(())
    }

    fn after_run(&mut self, _diag: &rustc_errors::Handler) -> Result<(), Error> {
        Ok(())
    }
}
<commit_msg>Bump format version<commit_after>//! Rustdoc's JSON backend
//!
//! This module contains the logic for rendering a crate as JSON rather than the normal static HTML
//! output. See [the RFC](https://github.com/rust-lang/rfcs/pull/2963) and the [`types`] module
//! docs for usage and details.

mod conversions;
pub mod types;

use std::cell::RefCell;
use std::fs::File;
use std::path::PathBuf;
use std::rc::Rc;

use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty;
use rustc_session::Session;
use rustc_span::edition::Edition;

use crate::clean;
use crate::config::{RenderInfo, RenderOptions};
use crate::error::Error;
use crate::formats::cache::Cache;
use crate::formats::FormatRenderer;
use crate::html::render::cache::ExternalLocation;

#[derive(Clone)]
crate struct JsonRenderer<'tcx> {
    tcx: ty::TyCtxt<'tcx>,
    /// A mapping of IDs that contains all local items for this crate which gets output as a top
    /// level field of the JSON blob.
    index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>,
    /// The directory where the blob will be written to.
    out_path: PathBuf,
}

impl JsonRenderer<'_> {
    fn sess(&self) -> &Session {
        self.tcx.sess
    }

    fn get_trait_implementors(
        &mut self,
        id: rustc_span::def_id::DefId,
        cache: &Cache,
    ) -> Vec<types::Id> {
        cache
            .implementors
            .get(&id)
            .map(|implementors| {
                implementors
                    .iter()
                    .map(|i| {
                        let item = &i.impl_item;
                        self.item(item.clone(), cache).unwrap();
                        item.def_id.into()
                    })
                    .collect()
            })
            .unwrap_or_default()
    }

    fn get_impls(&mut self, id: rustc_span::def_id::DefId, cache: &Cache) -> Vec<types::Id> {
        cache
            .impls
            .get(&id)
            .map(|impls| {
                impls
                    .iter()
                    .filter_map(|i| {
                        let item = &i.impl_item;
                        if item.def_id.is_local() {
                            self.item(item.clone(), cache).unwrap();
                            Some(item.def_id.into())
                        } else {
                            None
                        }
                    })
                    .collect()
            })
            .unwrap_or_default()
    }

    fn get_trait_items(&mut self, cache: &Cache) -> Vec<(types::Id, types::Item)> {
        cache
            .traits
            .iter()
            .filter_map(|(&id, trait_item)| {
                // only need to synthesize items for external traits
                if !id.is_local() {
                    trait_item.items.clone().into_iter().for_each(|i| self.item(i, cache).unwrap());
                    Some((
                        id.into(),
                        types::Item {
                            id: id.into(),
                            crate_id: id.krate.as_u32(),
                            name: cache
                                .paths
                                .get(&id)
                                .unwrap_or_else(|| {
                                    cache
                                        .external_paths
                                        .get(&id)
                                        .expect("Trait should either be in local or external paths")
                                })
                                .0
                                .last()
                                .map(Clone::clone),
                            visibility: types::Visibility::Public,
                            kind: types::ItemKind::Trait,
                            inner: types::ItemEnum::TraitItem(trait_item.clone().into()),
                            source: None,
                            docs: Default::default(),
                            links: Default::default(),
                            attrs: Default::default(),
                            deprecation: Default::default(),
                        },
                    ))
                } else {
                    None
                }
            })
            .collect()
    }
}

impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
    fn init(
        krate: clean::Crate,
        options: RenderOptions,
        _render_info: RenderInfo,
        _edition: Edition,
        _cache: &mut Cache,
        tcx: ty::TyCtxt<'tcx>,
    ) -> Result<(Self, clean::Crate), Error> {
        debug!("Initializing json renderer");
        Ok((
            JsonRenderer {
                tcx,
                index: Rc::new(RefCell::new(FxHashMap::default())),
                out_path: options.output,
            },
            krate,
        ))
    }

    /// Inserts an item into the index. This should be used rather than directly calling insert on
    /// the hashmap because certain items (traits and types) need to have their mappings for trait
    /// implementations filled out before they're inserted.
    fn item(&mut self, item: clean::Item, cache: &Cache) -> Result<(), Error> {
        // Flatten items that recursively store other items
        item.kind.inner_items().for_each(|i| self.item(i.clone(), cache).unwrap());

        let id = item.def_id;
        if let Some(mut new_item) = self.convert_item(item) {
            if let types::ItemEnum::TraitItem(ref mut t) = new_item.inner {
                t.implementors = self.get_trait_implementors(id, cache)
            } else if let types::ItemEnum::StructItem(ref mut s) = new_item.inner {
                s.impls = self.get_impls(id, cache)
            } else if let types::ItemEnum::EnumItem(ref mut e) = new_item.inner {
                e.impls = self.get_impls(id, cache)
            }
            let removed = self.index.borrow_mut().insert(id.into(), new_item.clone());
            // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
            // to make sure the items are unique.
            if let Some(old_item) = removed {
                assert_eq!(old_item, new_item);
            }
        }

        Ok(())
    }

    fn mod_item_in(
        &mut self,
        item: &clean::Item,
        _module_name: &str,
        cache: &Cache,
    ) -> Result<(), Error> {
        use clean::types::ItemKind::*;
        if let ModuleItem(m) = &*item.kind {
            for item in &m.items {
                match &*item.kind {
                    // These don't have names so they don't get added to the output by default
                    ImportItem(_) => self.item(item.clone(), cache).unwrap(),
                    ExternCrateItem(_, _) => self.item(item.clone(), cache).unwrap(),
                    ImplItem(i) => {
                        i.items.iter().for_each(|i| self.item(i.clone(), cache).unwrap())
                    }
                    _ => {}
                }
            }
        }
        self.item(item.clone(), cache).unwrap();
        Ok(())
    }

    fn mod_item_out(&mut self, _item_name: &str) -> Result<(), Error> {
        Ok(())
    }

    fn after_krate(&mut self, krate: &clean::Crate, cache: &Cache) -> Result<(), Error> {
        debug!("Done with crate");
        let mut index = (*self.index).clone().into_inner();
        index.extend(self.get_trait_items(cache));
        let output = types::Crate {
            root: types::Id(String::from("0:0")),
            crate_version: krate.version.clone(),
            includes_private: cache.document_private,
            index,
            paths: cache
                .paths
                .clone()
                .into_iter()
                .chain(cache.external_paths.clone().into_iter())
                .map(|(k, (path, kind))| {
                    (
                        k.into(),
                        types::ItemSummary { crate_id: k.krate.as_u32(), path, kind: kind.into() },
                    )
                })
                .collect(),
            external_crates: cache
                .extern_locations
                .iter()
                .map(|(k, v)| {
                    (
                        k.as_u32(),
                        types::ExternalCrate {
                            name: v.0.to_string(),
                            html_root_url: match &v.2 {
                                ExternalLocation::Remote(s) => Some(s.clone()),
                                _ => None,
                            },
                        },
                    )
                })
                .collect(),
            format_version: 2,
        };
        let mut p = self.out_path.clone();
        p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
        p.set_extension("json");
        let file = File::create(&p).map_err(|error| Error { error: error.to_string(), file: p })?;
        serde_json::ser::to_writer(&file, &output).unwrap();
        Ok(())
    }

    fn after_run(&mut self, _diag: &rustc_errors::Handler) -> Result<(), Error> {
        Ok(())
    }
}
<|endoftext|>


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

//! Linux-specific raw type definitions

pub type dev_t = u64;
pub type mode_t = u32;

#[doc(inline)]
pub use self::arch::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};

#[cfg(any(target_arch = "x86",
          target_arch = "le32",
          target_arch = "powerpc",
          target_arch = "arm"))]
mod arch {
    use super::{dev_t, mode_t};
    use os::raw::{c_long, c_short};
    use os::unix::raw::{gid_t, uid_t};

    pub type blkcnt_t = i32;
    pub type blksize_t = i32;
    pub type ino_t = u32;
    pub type nlink_t = u32;
    pub type off_t = i32;
    pub type time_t = i32;

    #[repr(C)]
    pub struct stat {
        pub st_dev: dev_t,
        pub __pad1: c_short,
        pub st_ino: ino_t,
        pub st_mode: mode_t,
        pub st_nlink: nlink_t,
        pub st_uid: uid_t,
        pub st_gid: gid_t,
        pub st_rdev: dev_t,
        pub __pad2: c_short,
        pub st_size: off_t,
        pub st_blksize: blksize_t,
        pub st_blocks: blkcnt_t,
        pub st_atime: time_t,
        pub st_atime_nsec: c_long,
        pub st_mtime: time_t,
        pub st_mtime_nsec: c_long,
        pub st_ctime: time_t,
        pub st_ctime_nsec: c_long,
        pub __unused4: c_long,
        pub __unused5: c_long,
    }
}

#[cfg(any(target_arch = "mips",
          target_arch = "mipsel"))]
mod arch {
    use super::{dev_t, mode_t};
    use os::raw::c_long;
    use os::unix::raw::{gid_t, uid_t};

    pub type blkcnt_t = i32;
    pub type blksize_t = i32;
    pub type ino_t = u32;
    pub type nlink_t = u32;
    pub type off_t = i32;
    pub type time_t = i32;

    #[repr(C)]
    pub struct stat {
        pub st_dev: c_ulong,
        pub st_pad1: [c_long; 3],
        pub st_ino: ino_t,
        pub st_mode: mode_t,
        pub st_nlink: nlink_t,
        pub st_uid: uid_t,
        pub st_gid: gid_t,
        pub st_rdev: c_ulong,
        pub st_pad2: [c_long; 2],
        pub st_size: off_t,
        pub st_pad3: c_long,
        pub st_atime: time_t,
        pub st_atime_nsec: c_long,
        pub st_mtime: time_t,
        pub st_mtime_nsec: c_long,
        pub st_ctime: time_t,
        pub st_ctime_nsec: c_long,
        pub st_blksize: blksize_t,
        pub st_blocks: blkcnt_t,
        pub st_pad5: [c_long; 14],
    }
}

#[cfg(target_arch = "aarch64")]
mod arch {
    use super::{dev_t, mode_t};
    use os::raw::{c_long, c_int};
    use os::unix::raw::{gid_t, uid_t};

    pub type blkcnt_t = i64;
    pub type blksize_t = i32;
    pub type ino_t = u64;
    pub type nlink_t = u32;
    pub type off_t = i64;
    pub type time_t = i64;

    #[repr(C)]
    pub struct stat {
        pub st_dev: dev_t,
        pub st_ino: ino_t,
        pub st_mode: mode_t,
        pub st_nlink: nlink_t,
        pub st_uid: uid_t,
        pub st_gid: gid_t,
        pub st_rdev: dev_t,
        pub __pad1: dev_t,
        pub st_size: off_t,
        pub st_blksize: blksize_t,
        pub __pad2: c_int,
        pub st_blocks: blkcnt_t,
        pub st_atime: time_t,
        pub st_atime_nsec: c_long,
        pub st_mtime: time_t,
        pub st_mtime_nsec: c_long,
        pub st_ctime: time_t,
        pub st_ctime_nsec: c_long,
        pub __unused: [c_int; 2],
    }
}

#[cfg(target_arch = "x86_64")]
mod arch {
    use super::{dev_t, mode_t};
    use os::raw::{c_long, c_int};
    use os::unix::raw::{gid_t, uid_t};

    pub type blkcnt_t = i64;
    pub type blksize_t = i64;
    pub type ino_t = u64;
    pub type nlink_t = u64;
    pub type off_t = i64;
    pub type time_t = i64;

    #[repr(C)]
    pub struct stat {
        pub st_dev: dev_t,
        pub st_ino: ino_t,
        pub st_nlink: nlink_t,
        pub st_mode: mode_t,
        pub st_uid: uid_t,
        pub st_gid: gid_t,
        pub __pad0: c_int,
        pub st_rdev: dev_t,
        pub st_size: off_t,
        pub st_blksize: blksize_t,
        pub st_blocks: blkcnt_t,
        pub st_atime: time_t,
        pub st_atime_nsec: c_long,
        pub st_mtime: time_t,
        pub st_mtime_nsec: c_long,
        pub st_ctime: time_t,
        pub st_ctime_nsec: c_long,
        pub __unused: [c_long; 3],
    }
}
<commit_msg>Fix MIPS build errors in libstd/os/linux/raw.rs<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Linux-specific raw type definitions

pub type dev_t = u64;
pub type mode_t = u32;

#[doc(inline)]
pub use self::arch::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};

#[cfg(any(target_arch = "x86",
          target_arch = "le32",
          target_arch = "powerpc",
          target_arch = "arm"))]
mod arch {
    use super::{dev_t, mode_t};
    use os::raw::{c_long, c_short};
    use os::unix::raw::{gid_t, uid_t};

    pub type blkcnt_t = i32;
    pub type blksize_t = i32;
    pub type ino_t = u32;
    pub type nlink_t = u32;
    pub type off_t = i32;
    pub type time_t = i32;

    #[repr(C)]
    pub struct stat {
        pub st_dev: dev_t,
        pub __pad1: c_short,
        pub st_ino: ino_t,
        pub st_mode: mode_t,
        pub st_nlink: nlink_t,
        pub st_uid: uid_t,
        pub st_gid: gid_t,
        pub st_rdev: dev_t,
        pub __pad2: c_short,
        pub st_size: off_t,
        pub st_blksize: blksize_t,
        pub st_blocks: blkcnt_t,
        pub st_atime: time_t,
        pub st_atime_nsec: c_long,
        pub st_mtime: time_t,
        pub st_mtime_nsec: c_long,
        pub st_ctime: time_t,
        pub st_ctime_nsec: c_long,
        pub __unused4: c_long,
        pub __unused5: c_long,
    }
}

#[cfg(any(target_arch = "mips",
          target_arch = "mipsel"))]
mod arch {
    use super::mode_t;
    use os::raw::{c_long, c_ulong};
    use os::unix::raw::{gid_t, uid_t};

    pub type blkcnt_t = i32;
    pub type blksize_t = i32;
    pub type ino_t = u32;
    pub type nlink_t = u32;
    pub type off_t = i32;
    pub type time_t = i32;

    #[repr(C)]
    pub struct stat {
        pub st_dev: c_ulong,
        pub st_pad1: [c_long; 3],
        pub st_ino: ino_t,
        pub st_mode: mode_t,
        pub st_nlink: nlink_t,
        pub st_uid: uid_t,
        pub st_gid: gid_t,
        pub st_rdev: c_ulong,
        pub st_pad2: [c_long; 2],
        pub st_size: off_t,
        pub st_pad3: c_long,
        pub st_atime: time_t,
        pub st_atime_nsec: c_long,
        pub st_mtime: time_t,
        pub st_mtime_nsec: c_long,
        pub st_ctime: time_t,
        pub st_ctime_nsec: c_long,
        pub st_blksize: blksize_t,
        pub st_blocks: blkcnt_t,
        pub st_pad5: [c_long; 14],
    }
}

#[cfg(target_arch = "aarch64")]
mod arch {
    use super::{dev_t, mode_t};
    use os::raw::{c_long, c_int};
    use os::unix::raw::{gid_t, uid_t};

    pub type blkcnt_t = i64;
    pub type blksize_t = i32;
    pub type ino_t = u64;
    pub type nlink_t = u32;
    pub type off_t = i64;
    pub type time_t = i64;

    #[repr(C)]
    pub struct stat {
        pub st_dev: dev_t,
        pub st_ino: ino_t,
        pub st_mode: mode_t,
        pub st_nlink: nlink_t,
        pub st_uid: uid_t,
        pub st_gid: gid_t,
        pub st_rdev: dev_t,
        pub __pad1: dev_t,
        pub st_size: off_t,
        pub st_blksize: blksize_t,
        pub __pad2: c_int,
        pub st_blocks: blkcnt_t,
        pub st_atime: time_t,
        pub st_atime_nsec: c_long,
        pub st_mtime: time_t,
        pub st_mtime_nsec: c_long,
        pub st_ctime: time_t,
        pub st_ctime_nsec: c_long,
        pub __unused: [c_int; 2],
    }
}

#[cfg(target_arch = "x86_64")]
mod arch {
    use super::{dev_t, mode_t};
    use os::raw::{c_long, c_int};
    use os::unix::raw::{gid_t, uid_t};

    pub type blkcnt_t = i64;
    pub type blksize_t = i64;
    pub type ino_t = u64;
    pub type nlink_t = u64;
    pub type off_t = i64;
    pub type time_t = i64;

    #[repr(C)]
    pub struct stat {
        pub st_dev: dev_t,
        pub st_ino: ino_t,
        pub st_nlink: nlink_t,
        pub st_mode: mode_t,
        pub st_uid: uid_t,
        pub st_gid: gid_t,
        pub __pad0: c_int,
        pub st_rdev: dev_t,
        pub st_size: off_t,
        pub st_blksize: blksize_t,
        pub st_blocks: blkcnt_t,
        pub st_atime: time_t,
        pub st_atime_nsec: c_long,
        pub st_mtime: time_t,
        pub st_mtime_nsec: c_long,
        pub st_ctime: time_t,
        pub st_ctime_nsec: c_long,
        pub __unused: [c_long; 3],
    }
}
<|endoftext|>