<commit_before>// Needed because of https://github.com/Geal/nom/issues/345

use common::{self, word_match};
use nom::digit;
use num_traits::FromPrimitive;
use std::io;
use std::str::{self, FromStr};

#[derive(Debug)]
pub struct Word {
    pub word: String,
    pub score: u8,
}

impl Word {
    pub fn score(self: &Word) -> u8 {
        self.score
    }
}

#[derive(Debug)]
enum RawWord {
    Junk,
    Word(Word),
}

pub fn score(word: &str) -> u8 {
    let mut result = 0;
    for letter in word.chars() {
        result += match letter {
            // Scrabble scores from https://en.wikipedia.org/wiki/Scrabble_letter_distributions#English
            'a' | 'e' | 'i' | 'o' | 'u' | 'n' | 'r' | 't' | 'l' | 's' => 1,
            'd' | 'g' => 2,
            'b' | 'c' | 'm' | 'p' => 3,
            'f' | 'h' | 'v' | 'w' | 'y' => 4,
            'k' => 5,
            'j' | 'x' => 8,
            'q' | 'z' => 10,
            _ => 0,
        }
    }
    return result;
}

named!(get_word<&str, RawWord>,
    alt!(
        word_match => { |(begin, rest)| {
                let mut word = String::from(begin);
                word += rest;
                let sc = score(&word.to_lowercase());
                RawWord::Word(Word{word:word, score:sc})
            }
        } |
        take_s!( 1 )  => { |_| RawWord::Junk }
    )
);

named!(get_wotta<&str, RawWord>,
    map!(tuple!(
        tag_s!("["),
        digit,
        opt!(
            tuple!(
                tag_s!(":"),
                is_not_s!("]")
            )
        ),
        tag_s!("]"),
        opt!(tag_s!("\n"))
    ), |(_, raw_score, comment_opt, _, _)|{
        let word = String::from((comment_opt as Option<(&str, &str)>).unwrap().1);
        RawWord::Word(Word{word: word, score: u8::from_str(raw_score).unwrap()})
        })
);

fn word_filter(word: RawWord) -> Option<Word> {
    if let RawWord::Word(x) = word {
        Some(x)
    } else {
        None
    }
}

pub fn get_words_fn(filename: &str) -> Result<Vec<Word>, io::Error> {
    return common::get_words_core_fn(filename, get_word, word_filter);
}

#[cfg(test)]
pub fn get_words(buffer: &str) -> Result<Vec<Word>, io::Error> {
    return common::get_words_core(buffer, get_word, word_filter);
}

pub fn get_wottas_fn(filename: &str) -> Result<Vec<Word>, io::Error> {
    return common::get_words_core_fn(filename, get_wotta, word_filter);
}

#[cfg(test)]
pub fn get_wottas(buffer: &str) -> Result<Vec<Word>, io::Error> {
    return common::get_words_core(buffer, get_wotta, word_filter);
}

enum_from_primitive! {
    #[allow(non_camel_case_types)]
    #[derive(Debug, PartialEq)]
    enum Command {
        PUSH = 5,
        DISCARD = 6,
        ADD = 7,
        INPUT = 8,
        OUTPUT = 9,
        SUBTRACT = 10,
        SWAP = 11,
        DUP = 12,
        SKIP_AHEAD_ZERO = 13,
        SKIP_AHEAD_NONZERO = 14,
        SKIP_BACK_ZERO = 15,
        SKIP_BACK_NONZERO = 16,
        STOP = 17,
        NOP,
    }
}

fn action(act: u8) -> Command {
    match Command::from_u8(act) {
        Some(val) => val,
        None => Command::NOP,
    }
}

pub fn run_beatnik(words: &[Word]) {
    let mut stack: Vec<u8> = Vec::new();
    let mut pc: usize = 0;
    loop {
        debug!("'{}' = {} ({:?})",
               words[pc].word,
               words[pc].score,
               action(words[pc].score));
        match action(words[pc].score) {
            Command::PUSH => {
                pc += 1;
                debug!("Pushing {} to stack", words[pc].score);
                stack.push(words[pc].score);
            }
            Command::DISCARD => {
                stack.pop().expect("stack value");
            }
            Command::ADD => {
                let x = stack.pop().expect("first value");
                let y = stack.pop().expect("second value");
                stack.push(x.wrapping_add(y));
            }
            Command::INPUT => {
                // FIXME: read from stdin
                stack.push(b'a');
            }
            Command::OUTPUT => print!("{}", stack.pop().expect("character on stack") as char),
            Command::SUBTRACT => {
                let x = stack.pop().expect("first value");
                let y = stack.pop().expect("second value");
                stack.push(y.wrapping_sub(x));
            }
            Command::SWAP => {
                let x = stack.pop().expect("first value");
                let y = stack.pop().expect("second value");
                stack.push(x);
                stack.push(y);
            }
            Command::DUP => {
                let x = stack.pop().expect("first value");
                stack.push(x);
                stack.push(x);
            }
            Command::SKIP_AHEAD_NONZERO => {
                let check = stack.pop().expect("check value");
                pc += 1;
                if check != 0 {
                    pc += words[pc].score as usize;
                }
            }
            Command::SKIP_AHEAD_ZERO => {
                let check = stack.pop().expect("check value");
                pc += 1;
                if check == 0 {
                    pc += words[pc].score as usize;
                }
            }
            Command::SKIP_BACK_ZERO => {
                let check = stack.pop().expect("check value");
                if check == 0 {
                    pc -= words[pc + 1].score as usize;
                }
            }
            Command::SKIP_BACK_NONZERO => {
                let check = stack.pop().expect("check value");
                if check != 0 {
                    pc -= words[pc + 1].score as usize;
                }
            }
            Command::STOP => break,
            Command::NOP => {}
        }
        pc += 1;
        if pc == words.len() {
            break;
        }
    }
    debug!("Stack: {:?}", stack);
}

pub fn output_wottasquare(words: Vec<Word>) {
    for word in words {
        println!("[{}:{:?}]", word.score, action(word.score));
    }
}

#[cfg(test)]
mod tests {
    use super::{get_words, get_wottas};
    use quickcheck::TestResult;

    #[test]
    fn test_apostrophe() {
        let ref word = get_words("she’s").unwrap()[0];
        assert_eq!(word.score, 7);
    }

    quickcheck! {
      fn word_test(xs: String) -> TestResult {
          return match get_words(&xs) {
              Ok(_) => TestResult::passed(),
              Err(err) => {
                  println!("Error: '{}'", xs);
                  TestResult::error(format!("{:?}", err))
              }
          }
      }

      fn wotta_test(xs: String) -> TestResult {
        if xs.len() == 0 {
            return TestResult::discard();
        }
        if xs.find("]").is_some() {
            return TestResult::discard();
        }

        return match get_wottas(&format!("[1:{}]", xs)) {
            Ok(_) => TestResult::passed(),
            Err(err) => {
                println!("Error: '{}'", xs);
                TestResult::error(format!("{:?}", err))
            }
        }
      }
  }
}
<commit_msg>Support reading characters from stdin<commit_after>// Needed because of https://github.com/Geal/nom/issues/345

use common::{self, word_match};
use nom::digit;
use num_traits::FromPrimitive;
use std::io::{self, Read};
use std::str::{self, FromStr};

#[derive(Debug)]
pub struct Word {
    pub word: String,
    pub score: u8,
}

impl Word {
    pub fn score(self: &Word) -> u8 {
        self.score
    }
}

#[derive(Debug)]
enum RawWord {
    Junk,
    Word(Word),
}

pub fn score(word: &str) -> u8 {
    let mut result = 0;
    for letter in word.chars() {
        result += match letter {
            // Scrabble scores from https://en.wikipedia.org/wiki/Scrabble_letter_distributions#English
            'a' | 'e' | 'i' | 'o' | 'u' | 'n' | 'r' | 't' | 'l' | 's' => 1,
            'd' | 'g' => 2,
            'b' | 'c' | 'm' | 'p' => 3,
            'f' | 'h' | 'v' | 'w' | 'y' => 4,
            'k' => 5,
            'j' | 'x' => 8,
            'q' | 'z' => 10,
            _ => 0,
        }
    }
    return result;
}

named!(get_word<&str, RawWord>,
    alt!(
        word_match => { |(begin, rest)| {
                let mut word = String::from(begin);
                word += rest;
                let sc = score(&word.to_lowercase());
                RawWord::Word(Word{word:word, score:sc})
            }
        } |
        take_s!( 1 )  => { |_| RawWord::Junk }
    )
);

named!(get_wotta<&str, RawWord>,
    map!(tuple!(
        tag_s!("["),
        digit,
        opt!(
            tuple!(
                tag_s!(":"),
                is_not_s!("]")
            )
        ),
        tag_s!("]"),
        opt!(tag_s!("\n"))
    ), |(_, raw_score, comment_opt, _, _)|{
        let word = String::from((comment_opt as Option<(&str, &str)>).unwrap().1);
        RawWord::Word(Word{word: word, score: u8::from_str(raw_score).unwrap()})
        })
);

fn word_filter(word: RawWord) -> Option<Word> {
    if let RawWord::Word(x) = word {
        Some(x)
    } else {
        None
    }
}

pub fn get_words_fn(filename: &str) -> Result<Vec<Word>, io::Error> {
    return common::get_words_core_fn(filename, get_word, word_filter);
}

#[cfg(test)]
pub fn get_words(buffer: &str) -> Result<Vec<Word>, io::Error> {
    return common::get_words_core(buffer, get_word, word_filter);
}

pub fn get_wottas_fn(filename: &str) -> Result<Vec<Word>, io::Error> {
    return common::get_words_core_fn(filename, get_wotta, word_filter);
}

#[cfg(test)]
pub fn get_wottas(buffer: &str) -> Result<Vec<Word>, io::Error> {
    return common::get_words_core(buffer, get_wotta, word_filter);
}

enum_from_primitive! {
    #[allow(non_camel_case_types)]
    #[derive(Debug, PartialEq)]
    enum Command {
        PUSH = 5,
        DISCARD = 6,
        ADD = 7,
        INPUT = 8,
        OUTPUT = 9,
        SUBTRACT = 10,
        SWAP = 11,
        DUP = 12,
        SKIP_AHEAD_ZERO = 13,
        SKIP_AHEAD_NONZERO = 14,
        SKIP_BACK_ZERO = 15,
        SKIP_BACK_NONZERO = 16,
        STOP = 17,
        NOP,
    }
}

fn action(act: u8) -> Command {
    match Command::from_u8(act) {
        Some(val) => val,
        None => Command::NOP,
    }
}

fn get_more_input() -> String {
    let mut buffer = String::new();
    io::stdin().read_to_string(&mut buffer).unwrap();
    buffer
}

pub fn run_beatnik(words: &[Word]) {
    let mut stack: Vec<u8> = Vec::new();
    let mut pc: usize = 0;
    let mut input = String::new();
    loop {
        debug!("'{}' = {} ({:?})",
               words[pc].word,
               words[pc].score,
               action(words[pc].score));
        match action(words[pc].score) {
            Command::PUSH => {
                pc += 1;
                debug!("Pushing {} to stack", words[pc].score);
                stack.push(words[pc].score);
            }
            Command::DISCARD => {
                stack.pop().expect("stack value");
            }
            Command::ADD => {
                let x = stack.pop().expect("first value");
                let y = stack.pop().expect("second value");
                stack.push(x.wrapping_add(y));
            }
            Command::INPUT => {
                if input.len() == 0 {
                    input += &get_more_input();
                }
                let new_input = input.remove(0);
                let mut b = [0; 1];
                new_input.encode_utf8(&mut b);
                stack.push(b[0]);
            }
            Command::OUTPUT => print!("{}", stack.pop().expect("character on stack") as char),
            Command::SUBTRACT => {
                let x = stack.pop().expect("first value");
                let y = stack.pop().expect("second value");
                stack.push(y.wrapping_sub(x));
            }
            Command::SWAP => {
                let x = stack.pop().expect("first value");
                let y = stack.pop().expect("second value");
                stack.push(x);
                stack.push(y);
            }
            Command::DUP => {
                let x = stack.pop().expect("first value");
                stack.push(x);
                stack.push(x);
            }
            Command::SKIP_AHEAD_NONZERO => {
                let check = stack.pop().expect("check value");
                pc += 1;
                if check != 0 {
                    pc += words[pc].score as usize;
                }
            }
            Command::SKIP_AHEAD_ZERO => {
                let check = stack.pop().expect("check value");
                pc += 1;
                if check == 0 {
                    pc += words[pc].score as usize;
                }
            }
            Command::SKIP_BACK_ZERO => {
                let check = stack.pop().expect("check value");
                if check == 0 {
                    pc -= words[pc + 1].score as usize;
                }
            }
            Command::SKIP_BACK_NONZERO => {
                let check = stack.pop().expect("check value");
                if check != 0 {
                    pc -= words[pc + 1].score as usize;
                }
            }
            Command::STOP => break,
            Command::NOP => {}
        }
        pc += 1;
        if pc == words.len() {
            break;
        }
    }
    debug!("Stack: {:?}", stack);
}

pub fn output_wottasquare(words: Vec<Word>) {
    for word in words {
        println!("[{}:{:?}]", word.score, action(word.score));
    }
}

#[cfg(test)]
mod tests {
    use super::{get_words, get_wottas};
    use quickcheck::TestResult;

    #[test]
    fn test_apostrophe() {
        let ref word = get_words("she’s").unwrap()[0];
        assert_eq!(word.score, 7);
    }

    quickcheck! {
      fn word_test(xs: String) -> TestResult {
          return match get_words(&xs) {
              Ok(_) => TestResult::passed(),
              Err(err) => {
                  println!("Error: '{}'", xs);
                  TestResult::error(format!("{:?}", err))
              }
          }
      }

      fn wotta_test(xs: String) -> TestResult {
        if xs.len() == 0 {
            return TestResult::discard();
        }
        if xs.find("]").is_some() {
            return TestResult::discard();
        }

        return match get_wottas(&format!("[1:{}]", xs)) {
            Ok(_) => TestResult::passed(),
            Err(err) => {
                println!("Error: '{}'", xs);
                TestResult::error(format!("{:?}", err))
            }
        }
      }
  }
}
<|endoftext|>


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

//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free[^free] foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! [^free]: Strictly speaking, there are some symbols which are needed but
//!          they aren't always necessary.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! # How to use the core library
//!
//! Please note that all of these details are currently not considered stable.
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [rlibc crate](https://crates.io/crates/rlibc).
//!
//! * `rust_begin_panic` - This function takes four arguments, a
//!   `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments
//!   dictate the panic message, the file at which panic was invoked, and the
//!   line and column inside the file. It is up to consumers of this core
//!   library to define this panic function; it is only required to never
//!   return. This requires a `lang` attribute named `panic_impl`.
//!
//! * `rust_eh_personality` - is used by the failure mechanisms of the
//!    compiler. This is often mapped to GCC's personality function, but crates
//!    which do not trigger a panic can be assured that this function is never
//!    called. The `lang` attribute is called `eh_personality`.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.
//
// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
// this, both the generated test artifact and the linked libtest (which
// transitively includes libcore) will both define the same set of lang items,
// and this will cause the E0152 "duplicate lang item found" error. See
// discussion in #50466 for details.
//
// This cfg won't affect doc tests.
#![cfg(not(test))]

#![stable(feature = "core", since = "1.6.0")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
       test(no_crate_inject, attr(deny(warnings))),
       test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]

#![no_core]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(asm)]
#![feature(associated_type_defaults)]
#![feature(attr_literals)]
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(const_int_ops)]
#![feature(core_float)]
#![feature(custom_attribute)]
#![feature(doc_cfg)]
#![feature(doc_spotlight)]
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
#![feature(macro_at_most_once_rep)]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(prelude_import)]
#![feature(repr_simd, platform_intrinsics)]
#![feature(rustc_attrs)]
#![feature(rustc_const_unstable)]
#![feature(simd_ffi)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
#![feature(unboxed_closures)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(doc_alias)]
#![feature(inclusive_range_methods)]
#![feature(mmx_target_feature)]
#![feature(tbm_target_feature)]
#![feature(sse4a_target_feature)]
#![feature(arm_target_feature)]
#![feature(powerpc_target_feature)]
#![feature(mips_target_feature)]
#![feature(aarch64_target_feature)]
#![feature(const_slice_len)]
#![feature(const_str_as_bytes)]
#![feature(const_str_len)]
#![cfg_attr(stage0, feature(repr_transparent))]

#[prelude_import]
#[allow(unused)]
use prelude::v1::*;

#[macro_use]
mod macros;

#[macro_use]
mod internal_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"] pub mod isize;
#[path = "num/i8.rs"]    pub mod i8;
#[path = "num/i16.rs"]   pub mod i16;
#[path = "num/i32.rs"]   pub mod i32;
#[path = "num/i64.rs"]   pub mod i64;
#[path = "num/i128.rs"]  pub mod i128;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]    pub mod u8;
#[path = "num/u16.rs"]   pub mod u16;
#[path = "num/u32.rs"]   pub mod u32;
#[path = "num/u64.rs"]   pub mod u64;
#[path = "num/u128.rs"]  pub mod u128;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod ptr;
pub mod hint;

/* Core language traits */

pub mod marker;
pub mod ops;
pub mod cmp;
pub mod clone;
pub mod default;
pub mod convert;
pub mod borrow;

/* Core types and methods on primitives */

pub mod any;
pub mod array;
pub mod ascii;
pub mod sync;
pub mod cell;
pub mod char;
pub mod panic;
pub mod panicking;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;

pub mod slice;
pub mod str;
pub mod hash;
pub mod fmt;
pub mod time;

pub mod unicode;

/* Async */
pub mod future;
pub mod task;

/* Heap memory allocator trait */
#[allow(missing_docs)]
pub mod alloc;

// note: does not need to be public
mod iter_private;
mod nonzero;
mod tuple;
mod unit;

// Pull in the the `coresimd` crate directly into libcore. This is where all the
// architecture-specific (and vendor-specific) intrinsics are defined. AKA
// things like SIMD and such. Note that the actual source for all this lies in a
// different repository, rust-lang-nursery/stdsimd. That's why the setup here is
// a bit wonky.
#[allow(unused_macros)]
macro_rules! test_v16 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v32 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v64 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v128 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v256 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v512 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! vector_impl { ($([$f:ident, $($args:tt)*]),*) => { $($f!($($args)*);)* } }
#[path = "../stdsimd/coresimd/mod.rs"]
#[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)]
#[unstable(feature = "stdsimd", issue = "48556")]
#[cfg(not(stage0))] // allow changes to how stdsimd works in stage0
mod coresimd;

#[unstable(feature = "stdsimd", issue = "48556")]
#[cfg(not(stage0))]
pub use coresimd::simd;
#[stable(feature = "simd_arch", since = "1.27.0")]
#[cfg(not(stage0))]
pub use coresimd::arch;
<commit_msg>Remove unnecessary feature gate.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free[^free] foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! [^free]: Strictly speaking, there are some symbols which are needed but
//!          they aren't always necessary.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! # How to use the core library
//!
//! Please note that all of these details are currently not considered stable.
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [rlibc crate](https://crates.io/crates/rlibc).
//!
//! * `rust_begin_panic` - This function takes four arguments, a
//!   `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments
//!   dictate the panic message, the file at which panic was invoked, and the
//!   line and column inside the file. It is up to consumers of this core
//!   library to define this panic function; it is only required to never
//!   return. This requires a `lang` attribute named `panic_impl`.
//!
//! * `rust_eh_personality` - is used by the failure mechanisms of the
//!    compiler. This is often mapped to GCC's personality function, but crates
//!    which do not trigger a panic can be assured that this function is never
//!    called. The `lang` attribute is called `eh_personality`.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.
//
// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
// this, both the generated test artifact and the linked libtest (which
// transitively includes libcore) will both define the same set of lang items,
// and this will cause the E0152 "duplicate lang item found" error. See
// discussion in #50466 for details.
//
// This cfg won't affect doc tests.
#![cfg(not(test))]

#![stable(feature = "core", since = "1.6.0")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
       test(no_crate_inject, attr(deny(warnings))),
       test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]

#![no_core]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(asm)]
#![feature(associated_type_defaults)]
#![feature(attr_literals)]
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(const_int_ops)]
#![feature(core_float)]
#![feature(custom_attribute)]
#![feature(doc_cfg)]
#![feature(doc_spotlight)]
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
#![feature(macro_at_most_once_rep)]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(prelude_import)]
#![feature(repr_simd, platform_intrinsics)]
#![feature(rustc_attrs)]
#![feature(rustc_const_unstable)]
#![feature(simd_ffi)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
#![feature(unboxed_closures)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(doc_alias)]
#![feature(inclusive_range_methods)]
#![feature(mmx_target_feature)]
#![feature(tbm_target_feature)]
#![feature(sse4a_target_feature)]
#![feature(arm_target_feature)]
#![feature(powerpc_target_feature)]
#![feature(mips_target_feature)]
#![feature(aarch64_target_feature)]
#![feature(const_slice_len)]
#![feature(const_str_as_bytes)]
#![feature(const_str_len)]

#[prelude_import]
#[allow(unused)]
use prelude::v1::*;

#[macro_use]
mod macros;

#[macro_use]
mod internal_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"] pub mod isize;
#[path = "num/i8.rs"]    pub mod i8;
#[path = "num/i16.rs"]   pub mod i16;
#[path = "num/i32.rs"]   pub mod i32;
#[path = "num/i64.rs"]   pub mod i64;
#[path = "num/i128.rs"]  pub mod i128;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]    pub mod u8;
#[path = "num/u16.rs"]   pub mod u16;
#[path = "num/u32.rs"]   pub mod u32;
#[path = "num/u64.rs"]   pub mod u64;
#[path = "num/u128.rs"]  pub mod u128;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod ptr;
pub mod hint;

/* Core language traits */

pub mod marker;
pub mod ops;
pub mod cmp;
pub mod clone;
pub mod default;
pub mod convert;
pub mod borrow;

/* Core types and methods on primitives */

pub mod any;
pub mod array;
pub mod ascii;
pub mod sync;
pub mod cell;
pub mod char;
pub mod panic;
pub mod panicking;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;

pub mod slice;
pub mod str;
pub mod hash;
pub mod fmt;
pub mod time;

pub mod unicode;

/* Async */
pub mod future;
pub mod task;

/* Heap memory allocator trait */
#[allow(missing_docs)]
pub mod alloc;

// note: does not need to be public
mod iter_private;
mod nonzero;
mod tuple;
mod unit;

// Pull in the the `coresimd` crate directly into libcore. This is where all the
// architecture-specific (and vendor-specific) intrinsics are defined. AKA
// things like SIMD and such. Note that the actual source for all this lies in a
// different repository, rust-lang-nursery/stdsimd. That's why the setup here is
// a bit wonky.
#[allow(unused_macros)]
macro_rules! test_v16 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v32 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v64 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v128 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v256 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v512 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! vector_impl { ($([$f:ident, $($args:tt)*]),*) => { $($f!($($args)*);)* } }
#[path = "../stdsimd/coresimd/mod.rs"]
#[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)]
#[unstable(feature = "stdsimd", issue = "48556")]
#[cfg(not(stage0))] // allow changes to how stdsimd works in stage0
mod coresimd;

#[unstable(feature = "stdsimd", issue = "48556")]
#[cfg(not(stage0))]
pub use coresimd::simd;
#[stable(feature = "simd_arch", since = "1.27.0")]
#[cfg(not(stage0))]
pub use coresimd::arch;
<|endoftext|>


<commit_before>//! Misc low level stuff

use cmp::{Eq, Ord};
use libc::c_void;

export FreeGlue;
export TypeDesc;
export Closure;
export get_type_desc;
export size_of;
export min_align_of;
export pref_align_of;
export refcount;
export log_str;
export shape_eq, shape_lt, shape_le;

type FreeGlue = fn(*TypeDesc, *c_void);

// Corresponds to runtime type_desc type
enum TypeDesc = {
    size: uint,
    align: uint,
    take_glue: uint,
    drop_glue: uint,
    free_glue: uint
    // Remaining fields not listed
};

/// The representation of a Rust closure
struct Closure {
    code: *(),
    env: *(),
}

#[abi = "cdecl"]
extern mod rustrt {
    pure fn shape_log_str(t: *sys::TypeDesc, data: *()) -> ~str;
}

#[abi = "rust-intrinsic"]
extern mod rusti {
    fn get_tydesc<T>() -> *();
    fn size_of<T>() -> uint;
    fn pref_align_of<T>() -> uint;
    fn min_align_of<T>() -> uint;
}

/// Compares contents of two pointers using the default method.
/// Equivalent to `*x1 == *x2`.  Useful for hashtables.
pure fn shape_eq<T:Eq>(x1: &T, x2: &T) -> bool {
    *x1 == *x2
}

pure fn shape_lt<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 < *x2
}

pure fn shape_le<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 <= *x2
}

/**
 * Returns a pointer to a type descriptor.
 *
 * Useful for calling certain function in the Rust runtime or otherwise
 * performing dark magick.
 */
#[inline(always)]
pure fn get_type_desc<T>() -> *TypeDesc {
    unchecked { rusti::get_tydesc::<T>() as *TypeDesc }
}

/// Returns the size of a type
#[inline(always)]
pure fn size_of<T>() -> uint {
    unchecked { rusti::size_of::<T>() }
}

/**
 * Returns the ABI-required minimum alignment of a type
 *
 * This is the alignment used for struct fields. It may be smaller
 * than the preferred alignment.
 */
#[inline(always)]
pure fn min_align_of<T>() -> uint {
    unchecked { rusti::min_align_of::<T>() }
}

/// Returns the preferred alignment of a type
#[inline(always)]
pure fn pref_align_of<T>() -> uint {
    unchecked { rusti::pref_align_of::<T>() }
}

/// Returns the refcount of a shared box (as just before calling this)
#[inline(always)]
pure fn refcount<T>(+t: @T) -> uint {
    unsafe {
        let ref_ptr: *uint = unsafe::reinterpret_cast(&t);
        *ref_ptr - 1
    }
}

pure fn log_str<T>(t: T) -> ~str {
    unsafe {
        let data_ptr: *() = unsafe::reinterpret_cast(&ptr::addr_of(t));
        rustrt::shape_log_str(get_type_desc::<T>(), data_ptr)
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn size_of_basic() {
        assert size_of::<u8>() == 1u;
        assert size_of::<u16>() == 2u;
        assert size_of::<u32>() == 4u;
        assert size_of::<u64>() == 8u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn size_of_32() {
        assert size_of::<uint>() == 4u;
        assert size_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert size_of::<uint>() == 8u;
        assert size_of::<*uint>() == 8u;
    }

    #[test]
    fn align_of_basic() {
        assert pref_align_of::<u8>() == 1u;
        assert pref_align_of::<u16>() == 2u;
        assert pref_align_of::<u32>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn align_of_32() {
        assert pref_align_of::<uint>() == 4u;
        assert pref_align_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert pref_align_of::<uint>() == 8u;
        assert pref_align_of::<*uint>() == 8u;
    }

    #[test]
    fn synthesize_closure() unsafe {
        let x = 10;
        let f: fn(int) -> int = |y| x + y;

        assert f(20) == 30;

        let original_closure: Closure = unsafe::transmute(f);

        let actual_function_pointer = original_closure.code;
        let environment = original_closure.env;

        let new_closure = Closure {
            code: actual_function_pointer,
            env: environment
        };

        let new_f: fn(int) -> int = unsafe::transmute(new_closure);
        assert new_f(20) == 30;
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>libcore: Make %? use the visitor, not shape glue<commit_after>//! Misc low level stuff

use cmp::{Eq, Ord};
use libc::c_void;

export FreeGlue;
export TypeDesc;
export Closure;
export get_type_desc;
export size_of;
export min_align_of;
export pref_align_of;
export refcount;
export log_str;
export shape_eq, shape_lt, shape_le;

type FreeGlue = fn(*TypeDesc, *c_void);

// Corresponds to runtime type_desc type
enum TypeDesc = {
    size: uint,
    align: uint,
    take_glue: uint,
    drop_glue: uint,
    free_glue: uint
    // Remaining fields not listed
};

/// The representation of a Rust closure
struct Closure {
    code: *(),
    env: *(),
}

#[abi = "rust-intrinsic"]
extern mod rusti {
    fn get_tydesc<T>() -> *();
    fn size_of<T>() -> uint;
    fn pref_align_of<T>() -> uint;
    fn min_align_of<T>() -> uint;
}

/// Compares contents of two pointers using the default method.
/// Equivalent to `*x1 == *x2`.  Useful for hashtables.
pure fn shape_eq<T:Eq>(x1: &T, x2: &T) -> bool {
    *x1 == *x2
}

pure fn shape_lt<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 < *x2
}

pure fn shape_le<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 <= *x2
}

/**
 * Returns a pointer to a type descriptor.
 *
 * Useful for calling certain function in the Rust runtime or otherwise
 * performing dark magick.
 */
#[inline(always)]
pure fn get_type_desc<T>() -> *TypeDesc {
    unchecked { rusti::get_tydesc::<T>() as *TypeDesc }
}

/// Returns the size of a type
#[inline(always)]
pure fn size_of<T>() -> uint {
    unchecked { rusti::size_of::<T>() }
}

/**
 * Returns the ABI-required minimum alignment of a type
 *
 * This is the alignment used for struct fields. It may be smaller
 * than the preferred alignment.
 */
#[inline(always)]
pure fn min_align_of<T>() -> uint {
    unchecked { rusti::min_align_of::<T>() }
}

/// Returns the preferred alignment of a type
#[inline(always)]
pure fn pref_align_of<T>() -> uint {
    unchecked { rusti::pref_align_of::<T>() }
}

/// Returns the refcount of a shared box (as just before calling this)
#[inline(always)]
pure fn refcount<T>(+t: @T) -> uint {
    unsafe {
        let ref_ptr: *uint = unsafe::reinterpret_cast(&t);
        *ref_ptr - 1
    }
}

pure fn log_str<T>(t: T) -> ~str {
    unsafe {
        let buffer = io::mem_buffer();
        let writer = io::mem_buffer_writer(buffer);
        repr::write_repr(writer, &t);
        return io::mem_buffer_str(buffer);  // XXX: Extra malloc and copy.
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn size_of_basic() {
        assert size_of::<u8>() == 1u;
        assert size_of::<u16>() == 2u;
        assert size_of::<u32>() == 4u;
        assert size_of::<u64>() == 8u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn size_of_32() {
        assert size_of::<uint>() == 4u;
        assert size_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert size_of::<uint>() == 8u;
        assert size_of::<*uint>() == 8u;
    }

    #[test]
    fn align_of_basic() {
        assert pref_align_of::<u8>() == 1u;
        assert pref_align_of::<u16>() == 2u;
        assert pref_align_of::<u32>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn align_of_32() {
        assert pref_align_of::<uint>() == 4u;
        assert pref_align_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert pref_align_of::<uint>() == 8u;
        assert pref_align_of::<*uint>() == 8u;
    }

    #[test]
    fn synthesize_closure() unsafe {
        let x = 10;
        let f: fn(int) -> int = |y| x + y;

        assert f(20) == 30;

        let original_closure: Closure = unsafe::transmute(f);

        let actual_function_pointer = original_closure.code;
        let environment = original_closure.env;

        let new_closure = Closure {
            code: actual_function_pointer,
            env: environment
        };

        let new_f: fn(int) -> int = unsafe::transmute(new_closure);
        assert new_f(20) == 30;
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>extern crate collections;

use soundex::Soundex;

mod soundex;

#[test]
fn soundex_encoding_retains_sole_letter_of_one_letter_word() {
    let soundex = Soundex::new();
    let encoded = soundex.encode("A");
    assert_eq!(encoded, ~"A000");
}

#[test]
fn soundex_encoding_pads_with_zeros_to_ensure_three_digits() {
    let soundex = Soundex::new();
    let encoded = soundex.encode("I");
    assert_eq!(encoded, ~"I000");
}

#[test]
fn soundex_encoding_replaces_constants_with_appropriate_digits() {
    let soundex = Soundex::new();
    assert_eq!(soundex.encode("Ax"), ~"A200");
}

#[test]
fn soundex_encoding_ignores_non_alphabetics() {
    let soundex = Soundex::new();
    assert_eq!(soundex.encode("A#"), ~"A000");
}
<commit_msg>Refactor tests.<commit_after>extern crate collections;

use soundex::Soundex;

mod soundex;

fn check_soundex(word: ~str, expected: ~str) {
    let soundex = Soundex::new();
    assert_eq!(soundex.encode(word), expected);
}

#[test]
fn soundex_encoding_retains_sole_letter_of_one_letter_word() {
    check_soundex(~"A", ~"A000");
}

#[test]
fn soundex_encoding_pads_with_zeros_to_ensure_three_digits() {
    check_soundex(~"I", ~"I000");
}

#[test]
fn soundex_encoding_replaces_constants_with_appropriate_digits() {
    check_soundex(~"Ax", ~"A200");
}

#[test]
fn soundex_encoding_ignores_non_alphabetics() {
    check_soundex(~"A#", ~"A000");
}
<|endoftext|>


<commit_before>use std::os::unix::io::{RawFd, AsRawFd};

#[cfg(any(target_os = "linux", target_os = "android"))]
use std::mem;
#[cfg(any(target_os = "linux", target_os = "android"))]
use libc;

/// An opaque handle to a kernel timer instance.
///
/// On Linux this contains a file descriptor created with
/// [timerfd_create()](http://man7.org/linux/man-pages/man2/timerfd_create.2.html)
/// On systems using kqueue, a file descriptor is not needed, so it is set to 0.
#[derive(Debug, Clone)]
pub struct Timer {
    #[doc(hidden)]
    pub id: usize,

    #[doc(hidden)]
    pub fd: RawFd
}

impl Timer {
    pub fn get_id(&self) -> usize {
        self.id
    }

    /// Re-arm a recurring timer.
    ///
    /// This method must be called when an interval timer notification is received. If not called,
    /// the next timer notification will not be received.
    ///
    /// The pattern is to store the timers in a hashmap keyed by their IDs. When a timer id is received,
    /// and the timer looked up the user should call arm().
    ///
    /// This method doesn't actually change the timing of the recurring timer. An interval timer
    /// will fire exactly at the interval specified originally. This just allows the kernel poller
    /// to received the timer event and send a notification. On epoll based systems if a timer has
    /// already fired because the timer period has elapsed, the kernel poller will be woken up
    /// immediately after this call and a notification will be sent. Since this call is a no-op on
    /// kqueue based systems, timer notifications will always be sent on time regardless of calls to
    /// arm. This should not be a problem in practice as timers should be re-armed before the next
    /// timer fires. Otherwise the timer interval is too short to be useful.
    ///
    /// Note that this method isn't strictly necessary for kqueue, but due to the semantics of epoll and
    /// the usage of timerfd, it is required that this method be called. For portability, any users
    /// should always call arm() when an interval timer notification is received.
    ///
    pub fn arm(&self) {
        self._arm();
    }

    // On Linux timers are file descriptors registered with epoll. Since we use edge triggering we
    // need to read the file descriptors to change their state. Note that even if we used level
    // triggering we'd still need to do this, but for a different reason. The timer would fire
    // indefinitely as ready in the level triggered case, rather than never firing again as in the
    // edge triggered case.
    //
    // Note that if epoll_wait on Linux returned the file descriptors that were ready we wouldn't
    // need to push this call to the user. It's a sad state of affairs on Linux I'm afraid.
    #[cfg(any(target_os = "linux", target_os = "android"))]
    fn _arm(&self) {
        let buf: u64 = 0;
        unsafe {
            let ptr: *mut libc::c_void = mem::transmute(&buf);
            libc::read(self.fd, ptr, 8);
        }
    }

    #[cfg(any(target_os = "bitrig", target_os = "dragonfly",
              target_os = "freebsd", target_os = "ios", target_os = "macos",
              target_os = "netbsd", target_os = "openbsd"))]
    fn _arm(&self) {}
}

impl AsRawFd for Timer {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}
<commit_msg>Make Timer uncloneable<commit_after>use std::os::unix::io::{RawFd, AsRawFd};

#[cfg(any(target_os = "linux", target_os = "android"))]
use std::mem;
#[cfg(any(target_os = "linux", target_os = "android"))]
use libc;

/// An opaque handle to a kernel timer instance.
///
/// On Linux this contains a file descriptor created with
/// [timerfd_create()](http://man7.org/linux/man-pages/man2/timerfd_create.2.html)
/// On systems using kqueue, a file descriptor is not needed, so it is set to 0.
#[derive(Debug)]
pub struct Timer {
    #[doc(hidden)]
    pub id: usize,

    #[doc(hidden)]
    pub fd: RawFd
}

impl Timer {
    pub fn get_id(&self) -> usize {
        self.id
    }

    /// Re-arm a recurring timer.
    ///
    /// This method must be called when an interval timer notification is received. If not called,
    /// the next timer notification will not be received.
    ///
    /// The pattern is to store the timers in a hashmap keyed by their IDs. When a timer id is received,
    /// and the timer looked up the user should call arm().
    ///
    /// This method doesn't actually change the timing of the recurring timer. An interval timer
    /// will fire exactly at the interval specified originally. This just allows the kernel poller
    /// to received the timer event and send a notification. On epoll based systems if a timer has
    /// already fired because the timer period has elapsed, the kernel poller will be woken up
    /// immediately after this call and a notification will be sent. Since this call is a no-op on
    /// kqueue based systems, timer notifications will always be sent on time regardless of calls to
    /// arm. This should not be a problem in practice as timers should be re-armed before the next
    /// timer fires. Otherwise the timer interval is too short to be useful.
    ///
    /// Note that this method isn't strictly necessary for kqueue, but due to the semantics of epoll and
    /// the usage of timerfd, it is required that this method be called. For portability, any users
    /// should always call arm() when an interval timer notification is received.
    ///
    pub fn arm(&self) {
        self._arm();
    }

    // On Linux timers are file descriptors registered with epoll. Since we use edge triggering we
    // need to read the file descriptors to change their state. Note that even if we used level
    // triggering we'd still need to do this, but for a different reason. The timer would fire
    // indefinitely as ready in the level triggered case, rather than never firing again as in the
    // edge triggered case.
    //
    // Note that if epoll_wait on Linux returned the file descriptors that were ready we wouldn't
    // need to push this call to the user. It's a sad state of affairs on Linux I'm afraid.
    #[cfg(any(target_os = "linux", target_os = "android"))]
    fn _arm(&self) {
        let buf: u64 = 0;
        unsafe {
            let ptr: *mut libc::c_void = mem::transmute(&buf);
            libc::read(self.fd, ptr, 8);
        }
    }

    #[cfg(any(target_os = "bitrig", target_os = "dragonfly",
              target_os = "freebsd", target_os = "ios", target_os = "macos",
              target_os = "netbsd", target_os = "openbsd"))]
    fn _arm(&self) {}
}

impl AsRawFd for Timer {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}
<|endoftext|>


<commit_before>use std::uint;
use std::cmp::max;
use std::time::duration::Duration;
use std::num::UnsignedInt;
use time::precise_time_ns;
use os::token::Token;
use util::Slab;

use self::TimerErrorKind::TimerOverflow;

const EMPTY: Token = Token(uint::MAX);
const NS_PER_MS: u64 = 1_000_000;

// Implements coarse-grained timeouts using an algorithm based on hashed timing
// wheels by Varghese & Lauck.
//
// TODO:
// * Handle the case when the timer falls more than an entire wheel behind. There
//   is no point to loop multiple times around the wheel in one go.
// * New type for tick, now() -> Tick
pub struct Timer<T> {
    // Size of each tick in milliseconds
    tick_ms: u64,
    // Slab of timeout entries
    entries: Slab<Entry<T>>,
    // Timeout wheel. Each tick, the timer will look at the next slot for
    // timeouts that match the current tick.
    wheel: Vec<Token>,
    // Tick 0's time in milliseconds
    start: u64,
    // The current tick
    tick: u64,
    // The next entry to possibly timeout
    next: Token,
    // Masks the target tick to get the slot
    mask: u64,
}

pub struct Timeout {
    // Reference into the timer entry slab
    token: Token,
    // Tick that it should matchup with
    tick: u64,
}

impl<T> Timer<T> {
    pub fn new(tick_ms: u64, mut slots: uint, mut capacity: uint) -> Timer<T> {
        slots = UnsignedInt::next_power_of_two(slots);
        capacity = UnsignedInt::next_power_of_two(capacity);

        Timer {
            tick_ms: tick_ms,
            entries: Slab::new(capacity),
            wheel: Vec::from_fn(slots, |_| EMPTY),
            start: 0,
            tick: 0,
            next: EMPTY,
            mask: (slots as u64) - 1
        }
    }

    pub fn count(&self) -> uint {
        self.entries.count()
    }

    // Number of ms remaining until the next tick
    pub fn next_tick_in_ms(&self) -> u64 {
        let now = self.now_ms();
        let nxt = self.start + (self.tick + 1) * self.tick_ms;

        if nxt <= now {
            return 0;
        }

        nxt - now
    }

    /*
     *
     * ===== Initialization =====
     *
     */

    // Sets the starting time of the timer using the current system time
    pub fn setup(&mut self) {
        let now = self.now_ms();
        self.set_start_ms(now);
    }

    fn set_start_ms(&mut self, start: u64) {
        assert!(!self.is_initialized(), "the timer has already started");
        self.start = start;
    }

    /*
     *
     * ===== Timeout create / cancel =====
     *
     */

    pub fn timeout(&mut self, token: T, delay: Duration) -> TimerResult<Timeout> {
        let at = self.now_ms() + (max(0, delay.num_milliseconds()) as u64);
        self.timeout_at_ms(token, at)
    }

    pub fn timeout_at_ms(&mut self, token: T, mut at: u64) -> TimerResult<Timeout> {
        // Make relative to start
        at -= self.start;
        // Calculate tick
        let mut tick = (at + self.tick_ms - 1) / self.tick_ms;

        // Always target at least 1 tick in the future
        if tick <= self.tick {
            tick = self.tick + 1;
        }

        self.insert(token, tick)
    }

    pub fn clear(&mut self, timeout: Timeout) -> bool {
        let links = match self.entries.get(timeout.token) {
            Some(e) => e.links,
            None => return false
        };

        // Sanity check
        if links.tick != timeout.tick {
            return false;
        }

        self.unlink(&links, timeout.token);
        self.entries.remove(timeout.token);
        true
    }

    fn insert(&mut self, token: T, tick: u64) -> TimerResult<Timeout> {
        // Get the slot for the requested tick
        let slot = (tick & self.mask) as uint;
        let curr = self.wheel[slot];

        // Insert the new entry
        let token = try!(
            self.entries.insert(Entry::new(token, tick, curr))
            .map_err(|_| TimerError::overflow()));

        if curr != EMPTY {
            // If there was a previous entry, set its prev pointer to the new
            // entry
            self.entries[curr].links.prev = token;
        }

        // Update the head slot
        self.wheel[slot] = token;

        debug!("inserted timout; slot={}; token={}", slot, token);

        // Return the new timeout
        Ok(Timeout {
            token: token,
            tick: tick
        })
    }

    fn unlink(&mut self, links: &EntryLinks, token: Token) {
        debug!("unlinking timeout; slot={}; token={}",
               self.slot_for(links.tick), token);

        if links.prev == EMPTY {
            let slot = self.slot_for(links.tick);
            self.wheel[slot] = links.next;
        } else {
            self.entries[links.prev].links.next = links.next;
        }

        if links.next != EMPTY {
            self.entries[links.next].links.prev = links.prev;

            if token == self.next {
                self.next = links.next;
            }
        } else if token == self.next {
            self.next = EMPTY;
        }
    }

    /*
     *
     * ===== Advance time =====
     *
     */

    pub fn now(&self) -> u64 {
        self.ms_to_tick(self.now_ms())
    }

    pub fn tick_to(&mut self, now: u64) -> Option<T> {
        debug!("tick_to; now={}; tick={}", now, self.tick);

        while self.tick <= now {
            let curr = self.next;

            debug!("ticking; curr={}", curr);

            if curr == EMPTY {
                self.tick += 1;
                self.next = self.wheel[self.slot_for(self.tick)];
            } else {
                let links = self.entries[curr].links;

                if links.tick <= self.tick {
                    debug!("triggering; token={}", curr);

                    // Unlink will also advance self.next
                    self.unlink(&links, curr);

                    // Remove and return the token
                    return self.entries.remove(curr)
                        .map(|e| e.token);
                } else {
                    self.next = links.next;
                }
            }
        }

        None
    }

    /*
     *
     * ===== Misc =====
     *
     */

    // Timers are initialized when either the current time has been advanced or a timeout has been set
    #[inline]
    fn is_initialized(&self) -> bool {
        self.tick > 0 || !self.entries.is_empty()
    }

    #[inline]
    fn slot_for(&self, tick: u64) -> uint {
        (self.mask & tick) as uint
    }

    // Convert a ms duration into a number of ticks, rounds up
    #[inline]
    fn ms_to_tick(&self, ms: u64) -> u64 {
        (ms - self.start) / self.tick_ms
    }

    #[inline]
    fn now_ms(&self) -> u64 {
        precise_time_ns() / NS_PER_MS
    }
}

// Doubly linked list of timer entries. Allows for efficient insertion /
// removal of timeouts.
struct Entry<T> {
    token: T,
    links: EntryLinks,
}

impl<T> Entry<T> {
    fn new(token: T, tick: u64, next: Token) -> Entry<T> {
        Entry {
            token: token,
            links: EntryLinks {
                tick: tick,
                prev: EMPTY,
                next: next,
            },
        }
    }
}

struct EntryLinks {
    tick: u64,
    prev: Token,
    next: Token
}

pub type TimerResult<T> = Result<T, TimerError>;

#[deriving(Show)]
pub struct TimerError {
    kind: TimerErrorKind,
    desc: &'static str,
}

impl TimerError {
    fn overflow() -> TimerError {
        TimerError {
            kind: TimerOverflow,
            desc: "too many timer entries"
        }
    }
}

#[deriving(Show)]
pub enum TimerErrorKind {
    TimerOverflow,
}

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

    #[test]
    pub fn test_timeout_next_tick() {
        let mut t = timer();
        let mut tick;

        t.timeout_at_ms("a", 100).unwrap();

        tick = t.ms_to_tick(50);
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(100);
        assert_eq!(Some("a"), t.tick_to(tick));
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(150);
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(200);
        assert_eq!(None, t.tick_to(tick));

        assert_eq!(t.count(), 0);
    }

    #[test]
    pub fn test_clearing_timeout() {
        let mut t = timer();
        let mut tick;

        let to = t.timeout_at_ms("a", 100).unwrap();
        assert!(t.clear(to));

        tick = t.ms_to_tick(100);
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(200);
        assert_eq!(None, t.tick_to(tick));

        assert_eq!(t.count(), 0);
    }

    #[test]
    pub fn test_multiple_timeouts_same_tick() {
        let mut t = timer();
        let mut tick;

        t.timeout_at_ms("a", 100).unwrap();
        t.timeout_at_ms("b", 100).unwrap();

        let mut rcv = vec![];

        tick = t.ms_to_tick(100);
        rcv.push(t.tick_to(tick).unwrap());
        rcv.push(t.tick_to(tick).unwrap());

        assert_eq!(None, t.tick_to(tick));

        rcv.sort();
        assert!(rcv.as_slice() == &["a", "b"], "actual={}", rcv.as_slice());

        tick = t.ms_to_tick(200);
        assert_eq!(None, t.tick_to(tick));

        assert_eq!(t.count(), 0);
    }

    #[test]
    pub fn test_multiple_timeouts_diff_tick() {
        let mut t = timer();
        let mut tick;

        t.timeout_at_ms("a", 110).unwrap();
        t.timeout_at_ms("b", 220).unwrap();
        t.timeout_at_ms("c", 230).unwrap();
        t.timeout_at_ms("d", 440).unwrap();

        tick = t.ms_to_tick(100);
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(200);
        assert_eq!(Some("a"), t.tick_to(tick));
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(300);
        assert_eq!(Some("c"), t.tick_to(tick));
        assert_eq!(Some("b"), t.tick_to(tick));
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(400);
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(500);
        assert_eq!(Some("d"), t.tick_to(tick));
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(600);
        assert_eq!(None, t.tick_to(tick));
    }

    #[test]
    pub fn test_catching_up() {
        let mut t = timer();
        let mut tick;

        t.timeout_at_ms("a", 110).unwrap();
        t.timeout_at_ms("b", 220).unwrap();
        t.timeout_at_ms("c", 230).unwrap();
        t.timeout_at_ms("d", 440).unwrap();

        tick = t.ms_to_tick(600);
        assert_eq!(Some("a"), t.tick_to(tick));
        assert_eq!(Some("c"), t.tick_to(tick));
        assert_eq!(Some("b"), t.tick_to(tick));
        assert_eq!(Some("d"), t.tick_to(tick));
        assert_eq!(None, t.tick_to(tick));
    }

    #[test]
    pub fn test_timeout_hash_collision() {
        let mut t = timer();
        let mut tick;

        t.timeout_at_ms("a", 100).unwrap();
        t.timeout_at_ms("b", 100 + TICK * SLOTS as u64).unwrap();

        tick = t.ms_to_tick(100);
        assert_eq!(Some("a"), t.tick_to(tick));
        assert_eq!(1, t.count());

        tick = t.ms_to_tick(200);
        assert_eq!(None, t.tick_to(tick));
        assert_eq!(1, t.count());

        tick = t.ms_to_tick(100 + TICK * SLOTS as u64);
        assert_eq!(Some("b"), t.tick_to(tick));
        assert_eq!(0, t.count());
    }

    #[test]
    pub fn test_clearing_timeout_between_triggers() {
        let mut t = timer();
        let mut tick;

        let a = t.timeout_at_ms("a", 100).unwrap();
        let _ = t.timeout_at_ms("b", 100).unwrap();
        let _ = t.timeout_at_ms("c", 200).unwrap();

        tick = t.ms_to_tick(100);
        assert_eq!(Some("b"), t.tick_to(tick));
        assert_eq!(2, t.count());

        t.clear(a);
        assert_eq!(1, t.count());

        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(200);
        assert_eq!(Some("c"), t.tick_to(tick));
        assert_eq!(0, t.count());
    }

    const TICK: u64 = 100;
    const SLOTS: uint = 16;

    fn timer() -> Timer<&'static str> {
        Timer::new(TICK, SLOTS, 32)
    }
}
<commit_msg>Track Rust master<commit_after>use std::uint;
use std::cmp::max;
use std::time::duration::Duration;
use std::num::UnsignedInt;
use time::precise_time_ns;
use os::token::Token;
use util::Slab;

use self::TimerErrorKind::TimerOverflow;

const EMPTY: Token = Token(uint::MAX);
const NS_PER_MS: u64 = 1_000_000;

// Implements coarse-grained timeouts using an algorithm based on hashed timing
// wheels by Varghese & Lauck.
//
// TODO:
// * Handle the case when the timer falls more than an entire wheel behind. There
//   is no point to loop multiple times around the wheel in one go.
// * New type for tick, now() -> Tick
pub struct Timer<T> {
    // Size of each tick in milliseconds
    tick_ms: u64,
    // Slab of timeout entries
    entries: Slab<Entry<T>>,
    // Timeout wheel. Each tick, the timer will look at the next slot for
    // timeouts that match the current tick.
    wheel: Vec<Token>,
    // Tick 0's time in milliseconds
    start: u64,
    // The current tick
    tick: u64,
    // The next entry to possibly timeout
    next: Token,
    // Masks the target tick to get the slot
    mask: u64,
}

pub struct Timeout {
    // Reference into the timer entry slab
    token: Token,
    // Tick that it should matchup with
    tick: u64,
}

impl<T> Timer<T> {
    pub fn new(tick_ms: u64, mut slots: uint, mut capacity: uint) -> Timer<T> {
        slots = UnsignedInt::next_power_of_two(slots);
        capacity = UnsignedInt::next_power_of_two(capacity);

        Timer {
            tick_ms: tick_ms,
            entries: Slab::new(capacity),
            wheel: Vec::from_fn(slots, |_| EMPTY),
            start: 0,
            tick: 0,
            next: EMPTY,
            mask: (slots as u64) - 1
        }
    }

    pub fn count(&self) -> uint {
        self.entries.count()
    }

    // Number of ms remaining until the next tick
    pub fn next_tick_in_ms(&self) -> u64 {
        let now = self.now_ms();
        let nxt = self.start + (self.tick + 1) * self.tick_ms;

        if nxt <= now {
            return 0;
        }

        nxt - now
    }

    /*
     *
     * ===== Initialization =====
     *
     */

    // Sets the starting time of the timer using the current system time
    pub fn setup(&mut self) {
        let now = self.now_ms();
        self.set_start_ms(now);
    }

    fn set_start_ms(&mut self, start: u64) {
        assert!(!self.is_initialized(), "the timer has already started");
        self.start = start;
    }

    /*
     *
     * ===== Timeout create / cancel =====
     *
     */

    pub fn timeout(&mut self, token: T, delay: Duration) -> TimerResult<Timeout> {
        let at = self.now_ms() + (max(0, delay.num_milliseconds()) as u64);
        self.timeout_at_ms(token, at)
    }

    pub fn timeout_at_ms(&mut self, token: T, mut at: u64) -> TimerResult<Timeout> {
        // Make relative to start
        at -= self.start;
        // Calculate tick
        let mut tick = (at + self.tick_ms - 1) / self.tick_ms;

        // Always target at least 1 tick in the future
        if tick <= self.tick {
            tick = self.tick + 1;
        }

        self.insert(token, tick)
    }

    pub fn clear(&mut self, timeout: Timeout) -> bool {
        let links = match self.entries.get(timeout.token) {
            Some(e) => e.links,
            None => return false
        };

        // Sanity check
        if links.tick != timeout.tick {
            return false;
        }

        self.unlink(&links, timeout.token);
        self.entries.remove(timeout.token);
        true
    }

    fn insert(&mut self, token: T, tick: u64) -> TimerResult<Timeout> {
        // Get the slot for the requested tick
        let slot = (tick & self.mask) as uint;
        let curr = self.wheel[slot];

        // Insert the new entry
        let token = try!(
            self.entries.insert(Entry::new(token, tick, curr))
            .map_err(|_| TimerError::overflow()));

        if curr != EMPTY {
            // If there was a previous entry, set its prev pointer to the new
            // entry
            self.entries[curr].links.prev = token;
        }

        // Update the head slot
        self.wheel[slot] = token;

        debug!("inserted timout; slot={}; token={}", slot, token);

        // Return the new timeout
        Ok(Timeout {
            token: token,
            tick: tick
        })
    }

    fn unlink(&mut self, links: &EntryLinks, token: Token) {
        debug!("unlinking timeout; slot={}; token={}",
               self.slot_for(links.tick), token);

        if links.prev == EMPTY {
            let slot = self.slot_for(links.tick);
            self.wheel[slot] = links.next;
        } else {
            self.entries[links.prev].links.next = links.next;
        }

        if links.next != EMPTY {
            self.entries[links.next].links.prev = links.prev;

            if token == self.next {
                self.next = links.next;
            }
        } else if token == self.next {
            self.next = EMPTY;
        }
    }

    /*
     *
     * ===== Advance time =====
     *
     */

    pub fn now(&self) -> u64 {
        self.ms_to_tick(self.now_ms())
    }

    pub fn tick_to(&mut self, now: u64) -> Option<T> {
        debug!("tick_to; now={}; tick={}", now, self.tick);

        while self.tick <= now {
            let curr = self.next;

            debug!("ticking; curr={}", curr);

            if curr == EMPTY {
                self.tick += 1;
                self.next = self.wheel[self.slot_for(self.tick)];
            } else {
                let links = self.entries[curr].links;

                if links.tick <= self.tick {
                    debug!("triggering; token={}", curr);

                    // Unlink will also advance self.next
                    self.unlink(&links, curr);

                    // Remove and return the token
                    return self.entries.remove(curr)
                        .map(|e| e.token);
                } else {
                    self.next = links.next;
                }
            }
        }

        None
    }

    /*
     *
     * ===== Misc =====
     *
     */

    // Timers are initialized when either the current time has been advanced or a timeout has been set
    #[inline]
    fn is_initialized(&self) -> bool {
        self.tick > 0 || !self.entries.is_empty()
    }

    #[inline]
    fn slot_for(&self, tick: u64) -> uint {
        (self.mask & tick) as uint
    }

    // Convert a ms duration into a number of ticks, rounds up
    #[inline]
    fn ms_to_tick(&self, ms: u64) -> u64 {
        (ms - self.start) / self.tick_ms
    }

    #[inline]
    fn now_ms(&self) -> u64 {
        precise_time_ns() / NS_PER_MS
    }
}

// Doubly linked list of timer entries. Allows for efficient insertion /
// removal of timeouts.
struct Entry<T> {
    token: T,
    links: EntryLinks,
}

impl<T> Entry<T> {
    fn new(token: T, tick: u64, next: Token) -> Entry<T> {
        Entry {
            token: token,
            links: EntryLinks {
                tick: tick,
                prev: EMPTY,
                next: next,
            },
        }
    }
}

struct EntryLinks {
    tick: u64,
    prev: Token,
    next: Token
}

pub type TimerResult<T> = Result<T, TimerError>;

#[deriving(Show)]
pub struct TimerError {
    kind: TimerErrorKind,
    desc: &'static str,
}

impl TimerError {
    fn overflow() -> TimerError {
        TimerError {
            kind: TimerOverflow,
            desc: "too many timer entries"
        }
    }
}

#[deriving(Show)]
pub enum TimerErrorKind {
    TimerOverflow,
}

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

    #[test]
    pub fn test_timeout_next_tick() {
        let mut t = timer();
        let mut tick;

        t.timeout_at_ms("a", 100).unwrap();

        tick = t.ms_to_tick(50);
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(100);
        assert_eq!(Some("a"), t.tick_to(tick));
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(150);
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(200);
        assert_eq!(None, t.tick_to(tick));

        assert_eq!(t.count(), 0);
    }

    #[test]
    pub fn test_clearing_timeout() {
        let mut t = timer();
        let mut tick;

        let to = t.timeout_at_ms("a", 100).unwrap();
        assert!(t.clear(to));

        tick = t.ms_to_tick(100);
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(200);
        assert_eq!(None, t.tick_to(tick));

        assert_eq!(t.count(), 0);
    }

    #[test]
    pub fn test_multiple_timeouts_same_tick() {
        let mut t = timer();
        let mut tick;

        t.timeout_at_ms("a", 100).unwrap();
        t.timeout_at_ms("b", 100).unwrap();

        let mut rcv = vec![];

        tick = t.ms_to_tick(100);
        rcv.push(t.tick_to(tick).unwrap());
        rcv.push(t.tick_to(tick).unwrap());

        assert_eq!(None, t.tick_to(tick));

        rcv.sort();
        assert!(rcv.as_slice() == ["a", "b"].as_slice(), "actual={}", rcv.as_slice());

        tick = t.ms_to_tick(200);
        assert_eq!(None, t.tick_to(tick));

        assert_eq!(t.count(), 0);
    }

    #[test]
    pub fn test_multiple_timeouts_diff_tick() {
        let mut t = timer();
        let mut tick;

        t.timeout_at_ms("a", 110).unwrap();
        t.timeout_at_ms("b", 220).unwrap();
        t.timeout_at_ms("c", 230).unwrap();
        t.timeout_at_ms("d", 440).unwrap();

        tick = t.ms_to_tick(100);
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(200);
        assert_eq!(Some("a"), t.tick_to(tick));
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(300);
        assert_eq!(Some("c"), t.tick_to(tick));
        assert_eq!(Some("b"), t.tick_to(tick));
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(400);
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(500);
        assert_eq!(Some("d"), t.tick_to(tick));
        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(600);
        assert_eq!(None, t.tick_to(tick));
    }

    #[test]
    pub fn test_catching_up() {
        let mut t = timer();
        let mut tick;

        t.timeout_at_ms("a", 110).unwrap();
        t.timeout_at_ms("b", 220).unwrap();
        t.timeout_at_ms("c", 230).unwrap();
        t.timeout_at_ms("d", 440).unwrap();

        tick = t.ms_to_tick(600);
        assert_eq!(Some("a"), t.tick_to(tick));
        assert_eq!(Some("c"), t.tick_to(tick));
        assert_eq!(Some("b"), t.tick_to(tick));
        assert_eq!(Some("d"), t.tick_to(tick));
        assert_eq!(None, t.tick_to(tick));
    }

    #[test]
    pub fn test_timeout_hash_collision() {
        let mut t = timer();
        let mut tick;

        t.timeout_at_ms("a", 100).unwrap();
        t.timeout_at_ms("b", 100 + TICK * SLOTS as u64).unwrap();

        tick = t.ms_to_tick(100);
        assert_eq!(Some("a"), t.tick_to(tick));
        assert_eq!(1, t.count());

        tick = t.ms_to_tick(200);
        assert_eq!(None, t.tick_to(tick));
        assert_eq!(1, t.count());

        tick = t.ms_to_tick(100 + TICK * SLOTS as u64);
        assert_eq!(Some("b"), t.tick_to(tick));
        assert_eq!(0, t.count());
    }

    #[test]
    pub fn test_clearing_timeout_between_triggers() {
        let mut t = timer();
        let mut tick;

        let a = t.timeout_at_ms("a", 100).unwrap();
        let _ = t.timeout_at_ms("b", 100).unwrap();
        let _ = t.timeout_at_ms("c", 200).unwrap();

        tick = t.ms_to_tick(100);
        assert_eq!(Some("b"), t.tick_to(tick));
        assert_eq!(2, t.count());

        t.clear(a);
        assert_eq!(1, t.count());

        assert_eq!(None, t.tick_to(tick));

        tick = t.ms_to_tick(200);
        assert_eq!(Some("c"), t.tick_to(tick));
        assert_eq!(0, t.count());
    }

    const TICK: u64 = 100;
    const SLOTS: uint = 16;

    fn timer() -> Timer<&'static str> {
        Timer::new(TICK, SLOTS, 32)
    }
}
<|endoftext|>


<commit_before>use memchr::{memchr, memrchr};
use regex::bytes::Regex;
use syntax;

use literals::LiteralSets;
use nonl;
use Result;

#[derive(Clone, Debug)]
pub struct LineSearcher {
    re: Regex,
    required: Option<Regex>,
    opts: Options,
}

#[derive(Clone, Debug)]
pub struct LineSearcherBuilder {
    pattern: String,
    opts: Options,
}

#[derive(Clone, Debug, Default)]
struct Options {
    case_insensitive: bool,
    lines: bool,
    locations: bool,
}

impl LineSearcherBuilder {
    pub fn new(pattern: &str) -> LineSearcherBuilder {
        LineSearcherBuilder {
            pattern: pattern.to_string(),
            opts: Options::default(),
        }
    }

    pub fn case_insensitive(mut self, yes: bool) -> LineSearcherBuilder {
        self.opts.case_insensitive = yes;
        self
    }

    pub fn line_numbers(mut self, yes: bool) -> LineSearcherBuilder {
        self.opts.lines = yes;
        self
    }

    pub fn locations(mut self, yes: bool) -> LineSearcherBuilder {
        self.opts.locations = yes;
        self
    }

    pub fn create(self) -> Result<LineSearcher> {
        let expr = try!(parse(&self.pattern));
        let literals = LiteralSets::create(&expr);
        let pat =
            if self.opts.case_insensitive {
                format!("(?i){}", expr)
            } else {
                expr.to_string()
            };
        // We've already parsed the pattern, so we know it will compiled.
        let re = Regex::new(&pat).unwrap();
        Ok(LineSearcher {
            re: re,
            required: literals.to_matcher(),
            opts: self.opts,
        })
    }
}

impl LineSearcher {
    pub fn search<'b, 's>(&'s self, buf: &'b [u8]) -> Iter<'b, 's> {
        Iter {
            searcher: self,
            buf: buf,
            start: 0,
            count: 0,
        }
    }
}

pub struct Match {
    pub start: usize,
    pub end: usize,
    pub count: usize,
    pub line: Option<usize>,
    pub locations: Vec<(usize, usize)>,
}

pub struct Iter<'b, 's> {
    searcher: &'s LineSearcher,
    buf: &'b [u8],
    start: usize,
    count: usize,
}

impl<'b, 's> Iter<'b, 's> {
    fn next_line_match(&mut self) -> Option<(usize, usize)> {
        if self.start >= self.buf.len() {
            return None;
        }
        if let Some(ref req) = self.searcher.required {
            while self.start < self.buf.len() {
                let (s, e) = match req.find(&self.buf[self.start..]) {
                    None => return None,
                    Some((s, e)) => (self.start + s, self.start + e),
                };
                let (prevnl, nextnl) = self.find_line(s, e);
                match self.searcher.re.find(&self.buf[prevnl..nextnl]) {
                    None => {
                        self.start = nextnl + 1;
                        continue;
                    }
                    Some(_) => return Some((prevnl, nextnl)),
                }
            }
            None
        } else {
            let (s, e) = match self.searcher.re.find(&self.buf[self.start..]) {
                None => return None,
                Some((s, e)) => (self.start + s, self.start + e),
            };
            Some(self.find_line(s, e))
        }
    }

    fn find_line(&self, s: usize, e: usize) -> (usize, usize) {
        let prevnl =
            memrchr(b'\n', &self.buf[0..s]).map_or(0, |i| i + 1);
        let nextnl =
            memchr(b'\n', &self.buf[e..]).map_or(self.buf.len(), |i| e + i);
        (prevnl, nextnl)
    }
}

impl<'b, 's> Iterator for Iter<'b, 's> {
    type Item = Match;

    fn next(&mut self) -> Option<Match> {
        let (prevnl, nextnl) = match self.next_line_match() {
            None => return None,
            Some((s, e)) => (s, e),
        };
        let count = self.count;
        self.start = nextnl + 1;
        self.count += 1;
        Some(Match {
            start: prevnl,
            end: nextnl,
            count: count,
            line: None,
            locations: vec![],
        })
    }
}

fn parse(re: &str) -> Result<syntax::Expr> {
    let expr =
        try!(syntax::ExprBuilder::new()
             .allow_bytes(true)
             .unicode(false)
             .parse(re));
    Ok(try!(nonl::remove(expr)))
}
<commit_msg>short matches<commit_after>use memchr::{memchr, memrchr};
use regex::bytes::Regex;
use syntax;

use literals::LiteralSets;
use nonl;
use Result;

#[derive(Clone, Debug)]
pub struct LineSearcher {
    re: Regex,
    required: Option<Regex>,
    opts: Options,
}

#[derive(Clone, Debug)]
pub struct LineSearcherBuilder {
    pattern: String,
    opts: Options,
}

#[derive(Clone, Debug, Default)]
struct Options {
    case_insensitive: bool,
    lines: bool,
    locations: bool,
}

impl LineSearcherBuilder {
    pub fn new(pattern: &str) -> LineSearcherBuilder {
        LineSearcherBuilder {
            pattern: pattern.to_string(),
            opts: Options::default(),
        }
    }

    pub fn case_insensitive(mut self, yes: bool) -> LineSearcherBuilder {
        self.opts.case_insensitive = yes;
        self
    }

    pub fn line_numbers(mut self, yes: bool) -> LineSearcherBuilder {
        self.opts.lines = yes;
        self
    }

    pub fn locations(mut self, yes: bool) -> LineSearcherBuilder {
        self.opts.locations = yes;
        self
    }

    pub fn create(self) -> Result<LineSearcher> {
        let expr = try!(parse(&self.pattern));
        let literals = LiteralSets::create(&expr);
        let pat =
            if self.opts.case_insensitive {
                format!("(?i){}", expr)
            } else {
                expr.to_string()
            };
        // We've already parsed the pattern, so we know it will compiled.
        let re = Regex::new(&pat).unwrap();
        Ok(LineSearcher {
            re: re,
            required: literals.to_matcher(),
            opts: self.opts,
        })
    }
}

impl LineSearcher {
    pub fn search<'b, 's>(&'s self, buf: &'b [u8]) -> Iter<'b, 's> {
        Iter {
            searcher: self,
            buf: buf,
            start: 0,
            count: 0,
        }
    }
}

pub struct Match {
    pub start: usize,
    pub end: usize,
    pub count: usize,
    pub line: Option<usize>,
    pub locations: Vec<(usize, usize)>,
}

pub struct Iter<'b, 's> {
    searcher: &'s LineSearcher,
    buf: &'b [u8],
    start: usize,
    count: usize,
}

impl<'b, 's> Iter<'b, 's> {
    fn next_line_match(&mut self) -> Option<(usize, usize)> {
        if self.start >= self.buf.len() {
            return None;
        }
        if let Some(ref req) = self.searcher.required {
            while self.start < self.buf.len() {
                let e = match req.shortest_match(&self.buf[self.start..]) {
                    None => return None,
                    Some(e) => self.start + e,
                };
                let (prevnl, nextnl) = self.find_line(e, e);
                match self.searcher.re.shortest_match(&self.buf[prevnl..nextnl]) {
                    None => {
                        self.start = nextnl + 1;
                        continue;
                    }
                    Some(_) => return Some((prevnl, nextnl)),
                }
            }
            None
        } else {
            let e = match self.searcher.re.shortest_match(&self.buf[self.start..]) {
                None => return None,
                Some(e) => self.start + e,
            };
            Some(self.find_line(e, e))
        }
    }

    fn find_line(&self, s: usize, e: usize) -> (usize, usize) {
        let prevnl =
            memrchr(b'\n', &self.buf[0..s]).map_or(0, |i| i + 1);
        let nextnl =
            memchr(b'\n', &self.buf[e..]).map_or(self.buf.len(), |i| e + i);
        (prevnl, nextnl)
    }
}

impl<'b, 's> Iterator for Iter<'b, 's> {
    type Item = Match;

    fn next(&mut self) -> Option<Match> {
        let (prevnl, nextnl) = match self.next_line_match() {
            None => return None,
            Some((s, e)) => (s, e),
        };
        let count = self.count;
        self.start = nextnl + 1;
        self.count += 1;
        Some(Match {
            start: prevnl,
            end: nextnl,
            count: count,
            line: None,
            locations: vec![],
        })
    }
}

fn parse(re: &str) -> Result<syntax::Expr> {
    let expr =
        try!(syntax::ExprBuilder::new()
             .allow_bytes(true)
             .unicode(false)
             .parse(re));
    Ok(try!(nonl::remove(expr)))
}
<|endoftext|>


<commit_before>pub use core::result;
use core::fmt;

pub use afi::*;
pub use safi::*;

pub const VALID_BGP_MARKER: [u8; 16] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];

#[derive(PartialEq)]
pub struct Ipv4Prefix<'a> {
    pub inner: &'a [u8],
}

impl<'a> fmt::Debug for Ipv4Prefix<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let masklen = self.inner[0];
        if masklen == 0 {
            return fmt.write_str("0/0");
        }

        let mut print_period = false;
        for octet in &self.inner[1..] {
            if print_period {
                try!(fmt.write_str("."));
            }
            print_period = true;
            try!(octet.fmt(fmt));
        }
        try!(fmt.write_str("/"));
        masklen.fmt(fmt)
    }
}

#[derive(PartialEq)]
pub struct Ipv6Prefix<'a> {
    pub inner: &'a [u8],
}

impl<'a> fmt::Debug for Ipv6Prefix<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let masklen = self.inner[0];
        if masklen == 0 {
            return fmt.write_str("0/0");
        }

        let mut print_colon = false;
        for chunk in self.inner[1..].chunks(2) {
            let a = chunk[0] as u16;
            let b: u8 = *chunk.get(1).unwrap_or(&0);
            let segment: u16 = a << 8 | (b as u16);
            if print_colon {
                try!(fmt.write_str(":"));
            }
            print_colon = true;
            try!(fmt.write_fmt(format_args!("{:04x}", segment)));
        }
        try!(fmt.write_str("::/"));
        masklen.fmt(fmt)
    }
}
#[derive(Debug, Clone, Copy)]
pub enum BgpError {
    BadLength,
    Invalid,
}

pub type Result<T> = result::Result<T, BgpError>;

impl fmt::Display for BgpError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

<commit_msg>improve ipv6 formatting, most likely still completely broken<commit_after>pub use core::result;
use core::fmt;

pub use afi::*;
pub use safi::*;

pub const VALID_BGP_MARKER: [u8; 16] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];

#[derive(PartialEq)]
pub struct Ipv4Prefix<'a> {
    pub inner: &'a [u8],
}

impl<'a> fmt::Debug for Ipv4Prefix<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let masklen = self.inner[0];
        if masklen == 0 {
            return fmt.write_str("0/0");
        }

        let mut print_period = false;
        for octet in &self.inner[1..] {
            if print_period {
                try!(fmt.write_str("."));
            }
            print_period = true;
            try!(octet.fmt(fmt));
        }
        try!(fmt.write_str("/"));
        masklen.fmt(fmt)
    }
}

#[derive(PartialEq)]
pub struct Ipv6Prefix<'a> {
    pub inner: &'a [u8],
}

impl<'a> fmt::Debug for Ipv6Prefix<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let masklen = self.inner[0];
        if masklen == 0 {
            return fmt.write_str("::/0");
        }

        let mut print_colon = false;
        for chunk in self.inner[1..].chunks(2) {
            let a = chunk[0] as u16;
            let b: u8 = *chunk.get(1).unwrap_or(&0);
            let segment: u16 = a << 8 | (b as u16);
            if print_colon {
                try!(fmt.write_str(":"));
            }
            print_colon = true;
            try!(fmt.write_fmt(format_args!("{:04x}", segment)));
        }
        if masklen < 112 {
            try!(fmt.write_str("::"));
        }
        try!(fmt.write_str("/"));

        masklen.fmt(fmt)
    }
}
#[derive(Debug, Clone, Copy)]
pub enum BgpError {
    BadLength,
    Invalid,
}

pub type Result<T> = result::Result<T, BgpError>;

impl fmt::Display for BgpError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

<|endoftext|>


<commit_before>//! Miscellaneous types used by the library.

use std::cell::{Cell, RefCell};
use std::fmt;

pub use maybe_owned::MaybeOwned;
#[cfg(feature="either")]
pub use either::Either;

// function that becomes uncallable after it returns false.
// callbacks use a MaybeOwned<T> argument so we can choose at runtime if we will send a ref or an owned value
struct FnCell<T>
{
    f: Box<Fn(MaybeOwned<T>) -> bool>,
    alive: Cell<bool>,
}

impl<T> FnCell<T>
{
    fn new<F>(f: F) -> Self
        where F: Fn(MaybeOwned<T>) -> bool + 'static
    {
        FnCell{ f: Box::new(f), alive: Cell::new(true) }
    }

    fn call(&self, arg: MaybeOwned<T>) -> bool
    {
        let is_alive = self.alive.get() && (self.f)(arg);
        self.alive.set(is_alive);
        is_alive
    }

    fn is_alive(&self) -> bool
    {
        self.alive.get()
    }
}

impl<T> fmt::Debug for FnCell<T>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        write!(f, "FnCell {{ f: Fn@{:p}, alive: {} }}", self.f, self.alive.get())
    }
}

// a collection of callbacks
#[derive(Debug)]
pub(crate) struct Callbacks<T>
{
    fs: RefCell<Vec<FnCell<T>>>,
}

impl<T> Callbacks<T>
{
    pub fn new() -> Self
    {
        Callbacks{ fs: Default::default() }
    }

    pub fn push<F>(&self, cb: F)
        where F: Fn(MaybeOwned<T>) -> bool + 'static
    {
        self.fs.borrow_mut().push(FnCell::new(cb))
    }

    // sends a ref to the first N-1 callbacks, and the owned value to the last
    // this way we prevent tons of cloning
    pub fn call(&self, arg: T)
    {
        let fs = self.fs.borrow();
        let n = fs.len();

        let mut i = 0;
        let mut n_dead = 0;
        for _ in 1..n
        {
            if !fs[i].call(MaybeOwned::Borrowed(&arg)) { n_dead += 1 }
            i += 1;
        }
        if n > 0 && !fs[i].call(MaybeOwned::Owned(arg)) { n_dead += 1 }
        drop(fs);

        if n_dead > 0 { self.cleanup(n_dead); }
    }

    pub fn call_ref(&self, arg: &T)
    {
        let n_dead = self.fs.borrow().iter()
            .map(|f| f.call(MaybeOwned::Borrowed(arg)))
            .fold(0, |a, alive| if alive { a } else { a + 1 });

        if n_dead > 0 { self.cleanup(n_dead); }
    }

    // we use this to passthrough an unprocessed value
    pub fn call_dyn(&self, arg: MaybeOwned<T>)
    {
        match arg
        {
            MaybeOwned::Borrowed(r) => self.call_ref(r),
            MaybeOwned::Owned(v) => self.call(v),
        }
    }

    // removes the dead callbacks
    fn cleanup(&self, n_dead: usize)
    {
        if let Ok(mut fs) = self.fs.try_borrow_mut()
        {
            let mut i = 0;
            let mut removed = 0;
            while removed < n_dead && i < fs.len()
            {
                if fs[i].is_alive()
                {
                    i += 1;
                }
                else
                {
                    fs.swap_remove(i);
                    removed += 1;
                }
            }
        }
    }
}

impl<T> Default for Callbacks<T>
{
    fn default() -> Self
    {
        Callbacks::new()
    }
}

/// Generic sum type of two elements.
///
/// It's used to provide generics over the `Option`/`Result`/`Either` types
pub trait SumType2
{
    /// Type of the first variant.
    type Type1;
    /// Type of the second variant.
    type Type2;

    /// Creates a value using the first variant.
    fn from_type1(val: Self::Type1) -> Self;
    /// Creates a value using the second variant.
    fn from_type2(val: Self::Type2) -> Self;

    /// Checks if the value is of the first variant.
    fn is_type1(&self) -> bool;
    /// Checks if the value is of the second variant.
    fn is_type2(&self) -> bool;

    /// Attempts to extract the value contained on the first variant.
    fn into_type1(self) -> Option<Self::Type1>;
    /// Attempts to extract the value contained on the second variant.
    fn into_type2(self) -> Option<Self::Type2>;
}

impl<T> SumType2 for Option<T>
{
    type Type1 = T;
    type Type2 = ();

    fn from_type1(val: Self::Type1) -> Self { Some(val) }
    fn from_type2(_: Self::Type2) -> Self { None }

    fn is_type1(&self) -> bool { self.is_some() }
    fn is_type2(&self) -> bool { self.is_none() }

    fn into_type1(self) -> Option<Self::Type1> { self }
    fn into_type2(self) -> Option<Self::Type2> { self.ok_or(()).err() }
}

impl<T, E> SumType2 for Result<T, E>
{
    type Type1 = T;
    type Type2 = E;

    fn from_type1(val: Self::Type1) -> Self { Ok(val) }
    fn from_type2(val: Self::Type2) -> Self { Err(val) }

    fn is_type1(&self) -> bool { self.is_ok() }
    fn is_type2(&self) -> bool { self.is_err() }

    fn into_type1(self) -> Option<Self::Type1> { self.ok() }
    fn into_type2(self) -> Option<Self::Type2> { self.err() }
}

#[cfg(feature="either")]
impl<L, R> SumType2 for ::either::Either<L, R>
{
    type Type1 = L;
    type Type2 = R;

    fn from_type1(val: Self::Type1) -> Self { Either::Left(val) }
    fn from_type2(val: Self::Type2) -> Self { Either::Right(val) }

    fn is_type1(&self) -> bool { self.is_left() }
    fn is_type2(&self) -> bool { self.is_right() }

    fn into_type1(self) -> Option<Self::Type1> { self.left() }
    fn into_type2(self) -> Option<Self::Type2> { self.right() }
}

/// Storage cell for shared signal values.
#[derive(Debug)]
pub(crate) struct Storage<T>
{
    val: RefCell<Option<T>>,
    serial: Cell<SerialId>,
}

const ERR_EMPTY: &'static str = "storage empty";

impl<T> Storage<T>
{
    pub fn new(val: T) -> Self
    {
        Storage{
            val: RefCell::new(Some(val)),
            serial: Cell::new(SerialId::once()),
        }
    }

    pub fn empty() -> Self
    {
        Storage{
            val: RefCell::new(None),
            serial: Default::default(),
        }
    }

    /// Gets the value by cloning.
    pub fn get(&self) -> T
        where T: Clone
    {
        self.val.borrow().clone().expect(ERR_EMPTY)
    }

    pub fn set(&self, val: T)
    {
        *self.val.borrow_mut() = Some(val);
        SerialId::inc_cell(&self.serial);
    }

    pub fn set_with_serial(&self, val: T, serial: SerialId)
    {
        *self.val.borrow_mut() = Some(val);
        self.serial.set(serial);
    }

    pub fn take(&self) -> T
    {
        self.val.borrow_mut().take().expect(ERR_EMPTY)
    }

    /// Gets the value by borrowing it to a closure.
    pub fn borrow<R, F>(&self, f: F) -> R
        where F: FnOnce(&T) -> R
    {
        f(self.val.borrow().as_ref().expect(ERR_EMPTY))
    }

    pub fn get_serial(&self) -> SerialId
    {
        self.serial.get()
    }
}

/// A counter on how many times a signal value has been modified.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct SerialId(u64);

impl SerialId
{
    /// The serial id of a constant value.
    pub(crate) fn once() -> Self
    {
        SerialId(1)
    }

    pub(crate) fn inc(self) -> Self
    {
        SerialId(self.0 + 1)
    }

    pub(crate) fn inc_cell(cell: &Cell<Self>) -> SerialId
    {
        let ser = cell.get().inc();
        cell.set(ser);
        ser
    }

    /// Gets the count stored on this object.
    #[inline]
    pub fn get(&self) -> u64
    {
        self.0
    }
}
<commit_msg>make SerialId::once public<commit_after>//! Miscellaneous types used by the library.

use std::cell::{Cell, RefCell};
use std::fmt;

pub use maybe_owned::MaybeOwned;
#[cfg(feature="either")]
pub use either::Either;

// function that becomes uncallable after it returns false.
// callbacks use a MaybeOwned<T> argument so we can choose at runtime if we will send a ref or an owned value
struct FnCell<T>
{
    f: Box<Fn(MaybeOwned<T>) -> bool>,
    alive: Cell<bool>,
}

impl<T> FnCell<T>
{
    fn new<F>(f: F) -> Self
        where F: Fn(MaybeOwned<T>) -> bool + 'static
    {
        FnCell{ f: Box::new(f), alive: Cell::new(true) }
    }

    fn call(&self, arg: MaybeOwned<T>) -> bool
    {
        let is_alive = self.alive.get() && (self.f)(arg);
        self.alive.set(is_alive);
        is_alive
    }

    fn is_alive(&self) -> bool
    {
        self.alive.get()
    }
}

impl<T> fmt::Debug for FnCell<T>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        write!(f, "FnCell {{ f: Fn@{:p}, alive: {} }}", self.f, self.alive.get())
    }
}

// a collection of callbacks
#[derive(Debug)]
pub(crate) struct Callbacks<T>
{
    fs: RefCell<Vec<FnCell<T>>>,
}

impl<T> Callbacks<T>
{
    pub fn new() -> Self
    {
        Callbacks{ fs: Default::default() }
    }

    pub fn push<F>(&self, cb: F)
        where F: Fn(MaybeOwned<T>) -> bool + 'static
    {
        self.fs.borrow_mut().push(FnCell::new(cb))
    }

    // sends a ref to the first N-1 callbacks, and the owned value to the last
    // this way we prevent tons of cloning
    pub fn call(&self, arg: T)
    {
        let fs = self.fs.borrow();
        let n = fs.len();

        let mut i = 0;
        let mut n_dead = 0;
        for _ in 1..n
        {
            if !fs[i].call(MaybeOwned::Borrowed(&arg)) { n_dead += 1 }
            i += 1;
        }
        if n > 0 && !fs[i].call(MaybeOwned::Owned(arg)) { n_dead += 1 }
        drop(fs);

        if n_dead > 0 { self.cleanup(n_dead); }
    }

    pub fn call_ref(&self, arg: &T)
    {
        let n_dead = self.fs.borrow().iter()
            .map(|f| f.call(MaybeOwned::Borrowed(arg)))
            .fold(0, |a, alive| if alive { a } else { a + 1 });

        if n_dead > 0 { self.cleanup(n_dead); }
    }

    // we use this to passthrough an unprocessed value
    pub fn call_dyn(&self, arg: MaybeOwned<T>)
    {
        match arg
        {
            MaybeOwned::Borrowed(r) => self.call_ref(r),
            MaybeOwned::Owned(v) => self.call(v),
        }
    }

    // removes the dead callbacks
    fn cleanup(&self, n_dead: usize)
    {
        if let Ok(mut fs) = self.fs.try_borrow_mut()
        {
            let mut i = 0;
            let mut removed = 0;
            while removed < n_dead && i < fs.len()
            {
                if fs[i].is_alive()
                {
                    i += 1;
                }
                else
                {
                    fs.swap_remove(i);
                    removed += 1;
                }
            }
        }
    }
}

impl<T> Default for Callbacks<T>
{
    fn default() -> Self
    {
        Callbacks::new()
    }
}

/// Generic sum type of two elements.
///
/// It's used to provide generics over the `Option`/`Result`/`Either` types
pub trait SumType2
{
    /// Type of the first variant.
    type Type1;
    /// Type of the second variant.
    type Type2;

    /// Creates a value using the first variant.
    fn from_type1(val: Self::Type1) -> Self;
    /// Creates a value using the second variant.
    fn from_type2(val: Self::Type2) -> Self;

    /// Checks if the value is of the first variant.
    fn is_type1(&self) -> bool;
    /// Checks if the value is of the second variant.
    fn is_type2(&self) -> bool;

    /// Attempts to extract the value contained on the first variant.
    fn into_type1(self) -> Option<Self::Type1>;
    /// Attempts to extract the value contained on the second variant.
    fn into_type2(self) -> Option<Self::Type2>;
}

impl<T> SumType2 for Option<T>
{
    type Type1 = T;
    type Type2 = ();

    fn from_type1(val: Self::Type1) -> Self { Some(val) }
    fn from_type2(_: Self::Type2) -> Self { None }

    fn is_type1(&self) -> bool { self.is_some() }
    fn is_type2(&self) -> bool { self.is_none() }

    fn into_type1(self) -> Option<Self::Type1> { self }
    fn into_type2(self) -> Option<Self::Type2> { self.ok_or(()).err() }
}

impl<T, E> SumType2 for Result<T, E>
{
    type Type1 = T;
    type Type2 = E;

    fn from_type1(val: Self::Type1) -> Self { Ok(val) }
    fn from_type2(val: Self::Type2) -> Self { Err(val) }

    fn is_type1(&self) -> bool { self.is_ok() }
    fn is_type2(&self) -> bool { self.is_err() }

    fn into_type1(self) -> Option<Self::Type1> { self.ok() }
    fn into_type2(self) -> Option<Self::Type2> { self.err() }
}

#[cfg(feature="either")]
impl<L, R> SumType2 for ::either::Either<L, R>
{
    type Type1 = L;
    type Type2 = R;

    fn from_type1(val: Self::Type1) -> Self { Either::Left(val) }
    fn from_type2(val: Self::Type2) -> Self { Either::Right(val) }

    fn is_type1(&self) -> bool { self.is_left() }
    fn is_type2(&self) -> bool { self.is_right() }

    fn into_type1(self) -> Option<Self::Type1> { self.left() }
    fn into_type2(self) -> Option<Self::Type2> { self.right() }
}

/// Storage cell for shared signal values.
#[derive(Debug)]
pub(crate) struct Storage<T>
{
    val: RefCell<Option<T>>,
    serial: Cell<SerialId>,
}

const ERR_EMPTY: &'static str = "storage empty";

impl<T> Storage<T>
{
    pub fn new(val: T) -> Self
    {
        Storage{
            val: RefCell::new(Some(val)),
            serial: Cell::new(SerialId::once()),
        }
    }

    pub fn empty() -> Self
    {
        Storage{
            val: RefCell::new(None),
            serial: Default::default(),
        }
    }

    /// Gets the value by cloning.
    pub fn get(&self) -> T
        where T: Clone
    {
        self.val.borrow().clone().expect(ERR_EMPTY)
    }

    pub fn set(&self, val: T)
    {
        *self.val.borrow_mut() = Some(val);
        SerialId::inc_cell(&self.serial);
    }

    pub fn set_with_serial(&self, val: T, serial: SerialId)
    {
        *self.val.borrow_mut() = Some(val);
        self.serial.set(serial);
    }

    pub fn take(&self) -> T
    {
        self.val.borrow_mut().take().expect(ERR_EMPTY)
    }

    /// Gets the value by borrowing it to a closure.
    pub fn borrow<R, F>(&self, f: F) -> R
        where F: FnOnce(&T) -> R
    {
        f(self.val.borrow().as_ref().expect(ERR_EMPTY))
    }

    pub fn get_serial(&self) -> SerialId
    {
        self.serial.get()
    }
}

/// A counter on how many times a signal value has been modified.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct SerialId(u64);

impl SerialId
{
    /// The serial id of a constant value.
    #[inline]
    pub fn once() -> Self
    {
        SerialId(1)
    }

    pub(crate) fn inc(self) -> Self
    {
        SerialId(self.0 + 1)
    }

    pub(crate) fn inc_cell(cell: &Cell<Self>) -> SerialId
    {
        let ser = cell.get().inc();
        cell.set(ser);
        ser
    }

    /// Gets the count stored on this object.
    #[inline]
    pub fn get(&self) -> u64
    {
        self.0
    }
}
<|endoftext|>