<commit_before>#![cfg(test)]

// These tests are primarily targeting "abusive" producers that will
// try to drive the "collect consumer" incorrectly. These should
// result in panics.

use iter::internal::*;
use super::Collect;

/// Promises to produce 2 items, but then produces 3.  Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "too many values")]
fn produce_too_many_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 2);
    let consumer = collect.as_consumer();
    let mut folder = consumer.into_folder();
    folder = folder.consume(22);
    folder = folder.consume(23);
    folder.consume(24);
}

/// Produces less items than promised. Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "too few values")]
fn produce_too_few_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 5);
    let consumer =  collect.as_consumer();
    let mut folder = consumer.into_folder();
    folder = folder.consume(22);
    folder = folder.consume(23);
    folder.complete();
}

// Complete is not called by the consumer.Hence,the collection vector is not fully initialized.
#[test]
#[should_panic(expected = "expected 4 total writes, but got 2")]
fn produce_items_with_split_no_complete() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
	{
	    	let consumer =  collect.as_consumer();
	    	let (left_consumer,right_consumer,reducer) = consumer.split_at(2);
	    	let mut left_folder = left_consumer.into_folder();
	    	let mut right_folder = right_consumer.into_folder();
	    	left_folder = left_folder.consume(0).consume(1);
	    	right_folder = right_folder.consume(2).consume(3);
	    	right_folder.complete();
	}
    collect.complete();
}
<commit_msg>indenting code<commit_after>#![cfg(test)]

// These tests are primarily targeting "abusive" producers that will
// try to drive the "collect consumer" incorrectly. These should
// result in panics.

use iter::internal::*;
use super::Collect;

/// Promises to produce 2 items, but then produces 3.  Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "too many values")]
fn produce_too_many_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 2);
    let consumer = collect.as_consumer();
    let mut folder = consumer.into_folder();
    folder = folder.consume(22);
    folder = folder.consume(23);
    folder.consume(24);
}

/// Produces fewer items than promised. Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "too few values")]
fn produce_fewer_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 5);
    let consumer = collect.as_consumer();
    let mut folder = consumer.into_folder();
    folder = folder.consume(22);
    folder = folder.consume(23);
    folder.complete();
}

// Complete is not called by the consumer.Hence,the collection vector is not fully initialized.
#[test]
#[should_panic(expected = "expected 4 total writes, but got 2")]
fn produce_items_with_split_no_complete() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
    {
        let consumer = collect.as_consumer();
        let (left_consumer, right_consumer, reducer) = consumer.split_at(2);
        let mut left_folder = left_consumer.into_folder();
        let mut right_folder = right_consumer.into_folder();
        left_folder = left_folder.consume(0).consume(1);
        right_folder = right_folder.consume(2).consume(3);
        right_folder.complete();
    }
    collect.complete();
}
<|endoftext|>


<commit_before>use std::sync::atomic::Ordering::{Acquire, Release, Relaxed};
use std::ptr;

use mem::epoch::{self, Atomic, Owned};

/// Treiber's lock-free stack.
///
/// Usable with any number of producers and consumers.
pub struct TreiberStack<T> {
    head: Atomic<Node<T>>,
}

struct Node<T> {
    data: T,
    next: Atomic<Node<T>>,
}

impl<T> TreiberStack<T> {
    /// Create a new, empty stack.
    pub fn new() -> TreiberStack<T> {
        TreiberStack {
            head: Atomic::null()
        }
    }

    /// Push `t` on top of the stack.
    pub fn push(&self, t: T) {
        let mut n = Owned::new(Node {
            data: t,
            next: Atomic::null()
        });
        let guard = epoch::pin();
        loop {
            let head = self.head.load(Relaxed, &guard);
            n.next.store_shared(head, Relaxed);
            match self.head.cas_and_ref(head, n, Release, &guard) {
                Ok(_) => break,
                Err(owned) => n = owned,
            }
        }
    }

    /// Attempt to pop the top element of the stack.
    ///
    /// Returns `None` if the stack is observed to be empty.
    pub fn pop(&self) -> Option<T> {
        let guard = epoch::pin();
        loop {
            match self.head.load(Acquire, &guard) {
                Some(head) => {
                    let next = head.next.load(Relaxed, &guard);
                    if self.head.cas_shared(Some(head), next, Release) {
                        unsafe {
                            guard.unlinked(head);
                            return Some(ptr::read(&(*head).data))
                        }
                    }
                }
                None => return None
            }
        }
    }
}
<commit_msg>Add an is_empty() method for TreiberStack<commit_after>use std::sync::atomic::Ordering::{Acquire, Release, Relaxed};
use std::ptr;

use mem::epoch::{self, Atomic, Owned};

/// Treiber's lock-free stack.
///
/// Usable with any number of producers and consumers.
pub struct TreiberStack<T> {
    head: Atomic<Node<T>>,
}

struct Node<T> {
    data: T,
    next: Atomic<Node<T>>,
}

impl<T> TreiberStack<T> {
    /// Create a new, empty stack.
    pub fn new() -> TreiberStack<T> {
        TreiberStack {
            head: Atomic::null()
        }
    }

    /// Push `t` on top of the stack.
    pub fn push(&self, t: T) {
        let mut n = Owned::new(Node {
            data: t,
            next: Atomic::null()
        });
        let guard = epoch::pin();
        loop {
            let head = self.head.load(Relaxed, &guard);
            n.next.store_shared(head, Relaxed);
            match self.head.cas_and_ref(head, n, Release, &guard) {
                Ok(_) => break,
                Err(owned) => n = owned,
            }
        }
    }

    /// Attempt to pop the top element of the stack.
    ///
    /// Returns `None` if the stack is observed to be empty.
    pub fn pop(&self) -> Option<T> {
        let guard = epoch::pin();
        loop {
            match self.head.load(Acquire, &guard) {
                Some(head) => {
                    let next = head.next.load(Relaxed, &guard);
                    if self.head.cas_shared(Some(head), next, Release) {
                        unsafe {
                            guard.unlinked(head);
                            return Some(ptr::read(&(*head).data))
                        }
                    }
                }
                None => return None
            }
        }
    }

    /// Check if this queue is empty.
    pub fn is_empty(&self) -> bool {
        let guard = epoch::pin();
        self.head.load(Acquire, &guard).is_none()
    }
}

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

    #[test]
    fn is_empty() {
        let q: TreiberStack<i64> = TreiberStack::new();
        assert!(q.is_empty());
        q.push(20);
        q.push(20);
        assert!(!q.is_empty());
        assert!(!q.is_empty());
        assert!(q.pop().is_some());
        assert!(q.pop().is_some());
        assert!(q.is_empty());
        q.push(25);
        assert!(!q.is_empty());
    }
}
<|endoftext|>


<commit_before>use tableau::tables::Table;

pub fn get_enter_var_column_index(table: &Table) -> usize {
    let table_rows = table.get_rows();
    let last_row_index = table_rows.len() - 1;
    // Select the most negative cell in the objective function row.
    let mut column_index = 0;
    // Loop until the end of the basic variables (non-basic = number of constraints).
    for i in 1..table_rows[last_row_index].len() - (table_rows.len() - 1) - 1 {
        if table_rows[last_row_index][i] < table_rows[last_row_index][column_index] {
            column_index = i;
        }
    }
    column_index
}
<commit_msg>Remove non-basic variable calculations. Non-basic variables have different meaning.<commit_after>use tableau::tables::Table;

pub fn get_enter_var_column_index(table: &Table) -> usize {
    let table_rows = table.get_rows();
    let last_row_index = table_rows.len() - 1;
    // Select the most negative cell in the objective function row.
    let mut column_index = 0;
    for i in 0..table_rows[last_row_index].len() - 1 {
        if table_rows[last_row_index][i] < table_rows[last_row_index][column_index] {
            column_index = i;
        }
    }
    column_index
}
<|endoftext|>


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

//! A wrapper around another RNG that reseeds it after it
//! generates a certain number of random bytes.

use core::prelude::*;

use {Rng, SeedableRng};
use core::default::Default;

/// How many bytes of entropy the underling RNG is allowed to generate
/// before it is reseeded.
static DEFAULT_GENERATION_THRESHOLD: uint = 32 * 1024;

/// A wrapper around any RNG which reseeds the underlying RNG after it
/// has generated a certain number of random bytes.
pub struct ReseedingRng<R, Rsdr> {
    rng: R,
    generation_threshold: uint,
    bytes_generated: uint,
    /// Controls the behaviour when reseeding the RNG.
    pub reseeder: Rsdr,
}

impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
    /// Create a new `ReseedingRng` with the given parameters.
    ///
    /// # Arguments
    ///
    /// * `rng`: the random number generator to use.
    /// * `generation_threshold`: the number of bytes of entropy at which to reseed the RNG.
    /// * `reseeder`: the reseeding object to use.
    pub fn new(rng: R, generation_threshold: uint, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
        ReseedingRng {
            rng: rng,
            generation_threshold: generation_threshold,
            bytes_generated: 0,
            reseeder: reseeder
        }
    }

    /// Reseed the internal RNG if the number of bytes that have been
    /// generated exceed the threshold.
    pub fn reseed_if_necessary(&mut self) {
        if self.bytes_generated >= self.generation_threshold {
            self.reseeder.reseed(&mut self.rng);
            self.bytes_generated = 0;
        }
    }
}

impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
    fn next_u32(&mut self) -> u32 {
        self.reseed_if_necessary();
        self.bytes_generated += 4;
        self.rng.next_u32()
    }

    fn next_u64(&mut self) -> u64 {
        self.reseed_if_necessary();
        self.bytes_generated += 8;
        self.rng.next_u64()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.reseed_if_necessary();
        self.bytes_generated += dest.len();
        self.rng.fill_bytes(dest)
    }
}

impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R> + Default>
     SeedableRng<(Rsdr, S)> for ReseedingRng<R, Rsdr> {
    fn reseed(&mut self, (rsdr, seed): (Rsdr, S)) {
        self.rng.reseed(seed);
        self.reseeder = rsdr;
        self.bytes_generated = 0;
    }

    /// Create a new `ReseedingRng` from the given reseeder and
    /// seed. This uses a default value for `generation_threshold`.
    fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
        ReseedingRng {
            rng: SeedableRng::from_seed(seed),
            generation_threshold: DEFAULT_GENERATION_THRESHOLD,
            bytes_generated: 0,
            reseeder: rsdr
        }
    }
}

/// Something that can be used to reseed an RNG via `ReseedingRng`.
///
/// # Example
///
/// ```rust
/// use std::rand::{Rng, SeedableRng, StdRng};
/// use std::rand::reseeding::{Reseeder, ReseedingRng};
///
/// struct TickTockReseeder { tick: bool }
/// impl Reseeder<StdRng> for TickTockReseeder {
///     fn reseed(&mut self, rng: &mut StdRng) {
///         let val = if self.tick {0} else {1};
///         rng.reseed(&[val]);
///         self.tick = !self.tick;
///     }
/// }
/// fn main() {
///     let rsdr = TickTockReseeder { tick: true };
///
///     let inner = StdRng::new().unwrap();
///     let mut rng = ReseedingRng::new(inner, 10, rsdr);
///
///     // this will repeat, because it gets reseeded very regularly.
///     let s: String = rng.gen_ascii_chars().take(100).collect();
///     println!("{}", s);
/// }
///
/// ```
pub trait Reseeder<R> {
    /// Reseed the given RNG.
    fn reseed(&mut self, rng: &mut R);
}

/// Reseed an RNG using a `Default` instance. This reseeds by
/// replacing the RNG with the result of a `Default::default` call.
pub struct ReseedWithDefault;

impl Copy for ReseedWithDefault {}

impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
    fn reseed(&mut self, rng: &mut R) {
        *rng = Default::default();
    }
}
impl Default for ReseedWithDefault {
    fn default() -> ReseedWithDefault { ReseedWithDefault }
}

#[cfg(test)]
mod test {
    use std::prelude::*;

    use core::iter::order;
    use super::{ReseedingRng, ReseedWithDefault};
    use std::default::Default;
    use {SeedableRng, Rng};

    struct Counter {
        i: u32
    }

    impl Rng for Counter {
        fn next_u32(&mut self) -> u32 {
            self.i += 1;
            // very random
            self.i - 1
        }
    }
    impl Default for Counter {
        fn default() -> Counter {
            Counter { i: 0 }
        }
    }
    impl SeedableRng<u32> for Counter {
        fn reseed(&mut self, seed: u32) {
            self.i = seed;
        }
        fn from_seed(seed: u32) -> Counter {
            Counter { i: seed }
        }
    }
    type MyRng = ReseedingRng<Counter, ReseedWithDefault>;

    #[test]
    fn test_reseeding() {
        let mut rs = ReseedingRng::new(Counter {i:0}, 400, ReseedWithDefault);

        let mut i = 0;
        for _ in range(0u, 1000) {
            assert_eq!(rs.next_u32(), i % 100);
            i += 1;
        }
    }

    #[test]
    fn test_rng_seeded() {
        let mut ra: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
        let mut rb: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
        assert!(order::equals(ra.gen_ascii_chars().take(100),
                              rb.gen_ascii_chars().take(100)));
    }

    #[test]
    fn test_rng_reseed() {
        let mut r: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3));
        let string1: String = r.gen_ascii_chars().take(100).collect();

        r.reseed((ReseedWithDefault, 3));

        let string2: String = r.gen_ascii_chars().take(100).collect();
        assert_eq!(string1, string2);
    }

    static FILL_BYTES_V_LEN: uint = 13579;
    #[test]
    fn test_rng_fill_bytes() {
        let mut v = Vec::from_elem(FILL_BYTES_V_LEN, 0u8);
        ::test::rng().fill_bytes(v.as_mut_slice());

        // Sanity test: if we've gotten here, `fill_bytes` has not infinitely
        // recursed.
        assert_eq!(v.len(), FILL_BYTES_V_LEN);

        // To test that `fill_bytes` actually did something, check that the
        // average of `v` is not 0.
        let mut sum = 0.0;
        for &x in v.iter() {
            sum += x as f64;
        }
        assert!(sum / v.len() as f64 != 0.0);
    }
}
<commit_msg>std: Second pass stabilization of `default`<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A wrapper around another RNG that reseeds it after it
//! generates a certain number of random bytes.

use core::prelude::*;

use {Rng, SeedableRng};
use core::default::Default;

/// How many bytes of entropy the underling RNG is allowed to generate
/// before it is reseeded.
static DEFAULT_GENERATION_THRESHOLD: uint = 32 * 1024;

/// A wrapper around any RNG which reseeds the underlying RNG after it
/// has generated a certain number of random bytes.
pub struct ReseedingRng<R, Rsdr> {
    rng: R,
    generation_threshold: uint,
    bytes_generated: uint,
    /// Controls the behaviour when reseeding the RNG.
    pub reseeder: Rsdr,
}

impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
    /// Create a new `ReseedingRng` with the given parameters.
    ///
    /// # Arguments
    ///
    /// * `rng`: the random number generator to use.
    /// * `generation_threshold`: the number of bytes of entropy at which to reseed the RNG.
    /// * `reseeder`: the reseeding object to use.
    pub fn new(rng: R, generation_threshold: uint, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
        ReseedingRng {
            rng: rng,
            generation_threshold: generation_threshold,
            bytes_generated: 0,
            reseeder: reseeder
        }
    }

    /// Reseed the internal RNG if the number of bytes that have been
    /// generated exceed the threshold.
    pub fn reseed_if_necessary(&mut self) {
        if self.bytes_generated >= self.generation_threshold {
            self.reseeder.reseed(&mut self.rng);
            self.bytes_generated = 0;
        }
    }
}

impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
    fn next_u32(&mut self) -> u32 {
        self.reseed_if_necessary();
        self.bytes_generated += 4;
        self.rng.next_u32()
    }

    fn next_u64(&mut self) -> u64 {
        self.reseed_if_necessary();
        self.bytes_generated += 8;
        self.rng.next_u64()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.reseed_if_necessary();
        self.bytes_generated += dest.len();
        self.rng.fill_bytes(dest)
    }
}

impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R> + Default>
     SeedableRng<(Rsdr, S)> for ReseedingRng<R, Rsdr> {
    fn reseed(&mut self, (rsdr, seed): (Rsdr, S)) {
        self.rng.reseed(seed);
        self.reseeder = rsdr;
        self.bytes_generated = 0;
    }

    /// Create a new `ReseedingRng` from the given reseeder and
    /// seed. This uses a default value for `generation_threshold`.
    fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
        ReseedingRng {
            rng: SeedableRng::from_seed(seed),
            generation_threshold: DEFAULT_GENERATION_THRESHOLD,
            bytes_generated: 0,
            reseeder: rsdr
        }
    }
}

/// Something that can be used to reseed an RNG via `ReseedingRng`.
///
/// # Example
///
/// ```rust
/// use std::rand::{Rng, SeedableRng, StdRng};
/// use std::rand::reseeding::{Reseeder, ReseedingRng};
///
/// struct TickTockReseeder { tick: bool }
/// impl Reseeder<StdRng> for TickTockReseeder {
///     fn reseed(&mut self, rng: &mut StdRng) {
///         let val = if self.tick {0} else {1};
///         rng.reseed(&[val]);
///         self.tick = !self.tick;
///     }
/// }
/// fn main() {
///     let rsdr = TickTockReseeder { tick: true };
///
///     let inner = StdRng::new().unwrap();
///     let mut rng = ReseedingRng::new(inner, 10, rsdr);
///
///     // this will repeat, because it gets reseeded very regularly.
///     let s: String = rng.gen_ascii_chars().take(100).collect();
///     println!("{}", s);
/// }
///
/// ```
pub trait Reseeder<R> {
    /// Reseed the given RNG.
    fn reseed(&mut self, rng: &mut R);
}

/// Reseed an RNG using a `Default` instance. This reseeds by
/// replacing the RNG with the result of a `Default::default` call.
pub struct ReseedWithDefault;

impl Copy for ReseedWithDefault {}

impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
    fn reseed(&mut self, rng: &mut R) {
        *rng = Default::default();
    }
}
#[stable]
impl Default for ReseedWithDefault {
    #[stable]
    fn default() -> ReseedWithDefault { ReseedWithDefault }
}

#[cfg(test)]
mod test {
    use std::prelude::*;

    use core::iter::order;
    use super::{ReseedingRng, ReseedWithDefault};
    use std::default::Default;
    use {SeedableRng, Rng};

    struct Counter {
        i: u32
    }

    impl Rng for Counter {
        fn next_u32(&mut self) -> u32 {
            self.i += 1;
            // very random
            self.i - 1
        }
    }
    impl Default for Counter {
        fn default() -> Counter {
            Counter { i: 0 }
        }
    }
    impl SeedableRng<u32> for Counter {
        fn reseed(&mut self, seed: u32) {
            self.i = seed;
        }
        fn from_seed(seed: u32) -> Counter {
            Counter { i: seed }
        }
    }
    type MyRng = ReseedingRng<Counter, ReseedWithDefault>;

    #[test]
    fn test_reseeding() {
        let mut rs = ReseedingRng::new(Counter {i:0}, 400, ReseedWithDefault);

        let mut i = 0;
        for _ in range(0u, 1000) {
            assert_eq!(rs.next_u32(), i % 100);
            i += 1;
        }
    }

    #[test]
    fn test_rng_seeded() {
        let mut ra: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
        let mut rb: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
        assert!(order::equals(ra.gen_ascii_chars().take(100),
                              rb.gen_ascii_chars().take(100)));
    }

    #[test]
    fn test_rng_reseed() {
        let mut r: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3));
        let string1: String = r.gen_ascii_chars().take(100).collect();

        r.reseed((ReseedWithDefault, 3));

        let string2: String = r.gen_ascii_chars().take(100).collect();
        assert_eq!(string1, string2);
    }

    static FILL_BYTES_V_LEN: uint = 13579;
    #[test]
    fn test_rng_fill_bytes() {
        let mut v = Vec::from_elem(FILL_BYTES_V_LEN, 0u8);
        ::test::rng().fill_bytes(v.as_mut_slice());

        // Sanity test: if we've gotten here, `fill_bytes` has not infinitely
        // recursed.
        assert_eq!(v.len(), FILL_BYTES_V_LEN);

        // To test that `fill_bytes` actually did something, check that the
        // average of `v` is not 0.
        let mut sum = 0.0;
        for &x in v.iter() {
            sum += x as f64;
        }
        assert!(sum / v.len() as f64 != 0.0);
    }
}
<|endoftext|>


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

extern crate kythe_rust_indexer;
use kythe_rust_indexer::{
    error::KytheError,
    providers::{FileProvider, KzipFileProvider},
};
extern crate runfiles;
use runfiles::Runfiles;
use std::fs::File;
use std::path::PathBuf;

/// Get the path of the provided runfile
fn get_runfile(file: &str) -> PathBuf {
    let r = Runfiles::create().unwrap();
    let location = String::from("io_kythe/kythe/rust/indexer/tests/");
    r.rlocation(location + file)
}

#[test]
fn test_kzip_provider() {
    // Load test kzip from the test files
    let kzip_path = get_runfile("testkzip.kzip");
    let kzip_file = File::open(kzip_path).expect("Test kzip file could not be found");

    // Create a new FileProvider using the test kzip
    let mut kzip_provider = KzipFileProvider::new(kzip_file).unwrap();

    // Check the `exists` function
    let file_hash = "c9d04c9565fc665c80681fb1d829938026871f66e14f501e08531df66938a789";
    assert!(
        kzip_provider.exists("/tmp/main.rs", file_hash).unwrap(),
        "File should exist in kzip but doesn't"
    );
    assert!(!kzip_provider.exists("invalid", "invalid").unwrap(), "File shouldn't exist but does");

    // Check the `contents` function
    let contents_result = kzip_provider.contents("/tmp/main.rs", file_hash);
    assert!(!contents_result.is_err());
    let contents_string =
        String::from_utf8(contents_result.unwrap()).expect("File contents was not valid UTF-8");
    assert_eq!(contents_string, "Test\n", "File contents did not match expected contents");

    let invalid_contents = kzip_provider.contents("invalid", "invalid");
    assert!(invalid_contents.is_err(), "Expected Err while reading contents for non-existent file, but received file contents: {:?}", invalid_contents.unwrap());
    let contents_error = invalid_contents.err().unwrap();
    match contents_error {
        KytheError::FileNotFoundError(_) => {}
        _ => panic!(
            "Unexpected error while getting contents of nonexistent file: {}",
            contents_error
        ),
    }

    // Check `get_compilation_units` function
    let units = kzip_provider.get_compilation_units().unwrap();
    assert_eq!(units.len(), 0, "Expected units vector to be empty");
}
<commit_msg>chore(rust_indexer): change test to make text replacement easier (#5182)<commit_after>// Copyright 2020 The Kythe Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate kythe_rust_indexer;
use kythe_rust_indexer::{
    error::KytheError,
    providers::{FileProvider, KzipFileProvider},
};
extern crate runfiles;
use runfiles::Runfiles;
use std::fs::File;
use std::path::PathBuf;

/// Get the path of the provided runfile
fn get_runfile(file: &str) -> PathBuf {
    let r = Runfiles::create().unwrap();
    r.rlocation("io_kythe/kythe/rust/indexer/tests/".to_owned() + file)
}

#[test]
fn test_kzip_provider() {
    // Load test kzip from the test files
    let kzip_path = get_runfile("testkzip.kzip");
    let kzip_file = File::open(kzip_path).expect("Test kzip file could not be found");

    // Create a new FileProvider using the test kzip
    let mut kzip_provider = KzipFileProvider::new(kzip_file).unwrap();

    // Check the `exists` function
    let file_hash = "c9d04c9565fc665c80681fb1d829938026871f66e14f501e08531df66938a789";
    assert!(
        kzip_provider.exists("/tmp/main.rs", file_hash).unwrap(),
        "File should exist in kzip but doesn't"
    );
    assert!(!kzip_provider.exists("invalid", "invalid").unwrap(), "File shouldn't exist but does");

    // Check the `contents` function
    let contents_result = kzip_provider.contents("/tmp/main.rs", file_hash);
    assert!(!contents_result.is_err());
    let contents_string =
        String::from_utf8(contents_result.unwrap()).expect("File contents was not valid UTF-8");
    assert_eq!(contents_string, "Test\n", "File contents did not match expected contents");

    let invalid_contents = kzip_provider.contents("invalid", "invalid");
    assert!(invalid_contents.is_err(), "Expected Err while reading contents for non-existent file, but received file contents: {:?}", invalid_contents.unwrap());
    let contents_error = invalid_contents.err().unwrap();
    match contents_error {
        KytheError::FileNotFoundError(_) => {}
        _ => panic!(
            "Unexpected error while getting contents of nonexistent file: {}",
            contents_error
        ),
    }

    // Check `get_compilation_units` function
    let units = kzip_provider.get_compilation_units().unwrap();
    assert_eq!(units.len(), 0, "Expected units vector to be empty");
}
<|endoftext|>


<commit_before>#![recursion_limit = "1024"]
#[macro_use]
extern crate quote;
extern crate proc_macro;

use proc_macro::TokenStream;
use std::{env, path::Path};
use syn::{export::TokenStream2, Data, DeriveInput, Fields, Lit, Meta};

#[cfg(all(debug_assertions, not(feature = "debug-embed")))]
fn generate_assets(ident: &syn::Ident, folder_path: String) -> TokenStream2 {
  quote! {
      impl #ident {
          pub fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
              use std::fs::File;
              use std::io::Read;
              use std::path::Path;

              let file_path = Path::new(#folder_path).join(file_path);
              let mut file = match File::open(file_path) {
                  Ok(mut file) => file,
                  Err(_e) => {
                      return None
                  }
              };
              let mut data: Vec<u8> = Vec::new();
              match file.read_to_end(&mut data) {
                  Ok(_) => Some(std::borrow::Cow::from(data)),
                  Err(_e) =>  {
                      return None
                  }
              }
          }

          pub fn iter() -> impl Iterator<Item = std::borrow::Cow<'static, str>> {
              use std::path::Path;
              rust_embed::utils::get_files(String::from(#folder_path)).map(|e| std::borrow::Cow::from(e.rel_path))
          }
      }
      impl rust_embed::RustEmbed for #ident {
        fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
          #ident::get(file_path)
        }
        fn iter() -> rust_embed::Filenames {
          // the return type of iter() is unnamable, so we have to box it
          rust_embed::Filenames::Dynamic(Box::new(#ident::iter()))
        }
      }
  }
}

#[cfg(all(not(feature = "compression"), any(not(debug_assertions), feature = "debug-embed")))]
fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
  quote! {
    #rel_path => {
        let bytes = &include_bytes!(#full_canonical_path)[..];
        Some(std::borrow::Cow::from(bytes))
    },
  }
}

#[cfg(all(feature = "compression", any(not(debug_assertions), feature = "debug-embed")))]
fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
  quote! {
    #rel_path => {
        rust_embed::flate!(static FILE: [u8] from #full_canonical_path);

        let bytes = &FILE[..];
        Some(std::borrow::Cow::from(bytes))
    },
  }
}

#[cfg(any(not(debug_assertions), feature = "debug-embed"))]
fn generate_assets(ident: &syn::Ident, folder_path: String) -> TokenStream2 {
  extern crate rust_embed_utils;

  let mut match_values = Vec::<TokenStream2>::new();
  let mut list_values = Vec::<String>::new();

  for rust_embed_utils::FileEntry { rel_path, full_canonical_path } in rust_embed_utils::get_files(folder_path) {
    match_values.push(embed_file(&rel_path, &full_canonical_path));
    list_values.push(rel_path);
  }

  let array_len = list_values.len();

  quote! {
      impl #ident {
          pub fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
              match file_path {
                  #(#match_values)*
                  _ => None,
              }
          }

          fn names() -> std::slice::Iter<'static, &'static str> {
            const items: [&str; #array_len] = [#(#list_values),*];
            items.iter()
          }
          pub fn iter() -> impl Iterator<Item = std::borrow::Cow<'static, str>> {
              Self::names().map(|x| std::borrow::Cow::from(*x))
          }
      }
      impl rust_embed::RustEmbed for #ident {
        fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
          #ident::get(file_path)
        }
        fn iter() -> rust_embed::Filenames {
          rust_embed::Filenames::Embedded(#ident::names())
        }
      }
  }
}

fn impl_rust_embed(ast: &syn::DeriveInput) -> TokenStream2 {
  match ast.data {
    Data::Struct(ref data) => match data.fields {
      Fields::Unit => {}
      _ => panic!("RustEmbed can only be derived for unit structs"),
    },
    _ => panic!("RustEmbed can only be derived for unit structs"),
  };

  let attribute = ast
    .attrs
    .iter()
    .find(|value| value.path.is_ident("folder"))
    .expect("#[derive(RustEmbed)] should contain one attribute like this #[folder = \"examples/public/\"]");
  let meta = attribute
    .parse_meta()
    .expect("#[derive(RustEmbed)] should contain one attribute like this #[folder = \"examples/public/\"]");
  let literal_value = match meta {
    Meta::NameValue(ref data) => &data.lit,
    _ => panic!("#[derive(RustEmbed)] should contain one attribute like this #[folder = \"examples/public/\"]"),
  };
  let folder_path = match literal_value {
    Lit::Str(ref val) => val.clone().value(),
    _ => {
      panic!("#[derive(RustEmbed)] attribute value must be a string literal");
    }
  };

  #[cfg(feature = "interpolate-folder-path")]
  let folder_path = shellexpand::full(&folder_path).unwrap().to_string();

  // Base relative paths on the Cargo.toml location
  let folder_path = if Path::new(&folder_path).is_relative() {
    Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap())
      .join(folder_path)
      .to_str()
      .unwrap()
      .to_owned()
  } else {
    folder_path
  };

  if !Path::new(&folder_path).exists() {
    let mut message = format!(
      "#[derive(RustEmbed)] folder '{}' does not exist. cwd: '{}'",
      folder_path,
      std::env::current_dir().unwrap().to_str().unwrap()
    );

    // Add a message about the interpolate-folder-path feature if the path may
    // include a variable
    if folder_path.contains('$') && cfg!(not(feature = "interpolate-folder-path")) {
      message += "\nA variable has been detected. RustEmbed can expand variables \
                  when the `interpolate-folder-path` feature is enabled.";
    }

    panic!(message);
  };

  generate_assets(&ast.ident, folder_path)
}

#[proc_macro_derive(RustEmbed, attributes(folder))]
pub fn derive_input_object(input: TokenStream) -> TokenStream {
  let ast: DeriveInput = syn::parse(input).unwrap();
  let gen = impl_rust_embed(&ast);
  gen.into()
}
<commit_msg>Fix clippy::verbose_file_reads warning in nightly<commit_after>#![recursion_limit = "1024"]
#[macro_use]
extern crate quote;
extern crate proc_macro;

use proc_macro::TokenStream;
use std::{env, path::Path};
use syn::{export::TokenStream2, Data, DeriveInput, Fields, Lit, Meta};

#[cfg(all(debug_assertions, not(feature = "debug-embed")))]
fn generate_assets(ident: &syn::Ident, folder_path: String) -> TokenStream2 {
  quote! {
      impl #ident {
          pub fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
              use std::fs;
              use std::path::Path;

              let file_path = Path::new(#folder_path).join(file_path);
              match fs::read(file_path) {
                  Ok(contents) => Some(std::borrow::Cow::from(contents)),
                  Err(_e) =>  {
                      return None
                  }
              }
          }

          pub fn iter() -> impl Iterator<Item = std::borrow::Cow<'static, str>> {
              use std::path::Path;
              rust_embed::utils::get_files(String::from(#folder_path)).map(|e| std::borrow::Cow::from(e.rel_path))
          }
      }
      impl rust_embed::RustEmbed for #ident {
        fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
          #ident::get(file_path)
        }
        fn iter() -> rust_embed::Filenames {
          // the return type of iter() is unnamable, so we have to box it
          rust_embed::Filenames::Dynamic(Box::new(#ident::iter()))
        }
      }
  }
}

#[cfg(all(not(feature = "compression"), any(not(debug_assertions), feature = "debug-embed")))]
fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
  quote! {
    #rel_path => {
        let bytes = &include_bytes!(#full_canonical_path)[..];
        Some(std::borrow::Cow::from(bytes))
    },
  }
}

#[cfg(all(feature = "compression", any(not(debug_assertions), feature = "debug-embed")))]
fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
  quote! {
    #rel_path => {
        rust_embed::flate!(static FILE: [u8] from #full_canonical_path);

        let bytes = &FILE[..];
        Some(std::borrow::Cow::from(bytes))
    },
  }
}

#[cfg(any(not(debug_assertions), feature = "debug-embed"))]
fn generate_assets(ident: &syn::Ident, folder_path: String) -> TokenStream2 {
  extern crate rust_embed_utils;

  let mut match_values = Vec::<TokenStream2>::new();
  let mut list_values = Vec::<String>::new();

  for rust_embed_utils::FileEntry { rel_path, full_canonical_path } in rust_embed_utils::get_files(folder_path) {
    match_values.push(embed_file(&rel_path, &full_canonical_path));
    list_values.push(rel_path);
  }

  let array_len = list_values.len();

  quote! {
      impl #ident {
          pub fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
              match file_path {
                  #(#match_values)*
                  _ => None,
              }
          }

          fn names() -> std::slice::Iter<'static, &'static str> {
            const items: [&str; #array_len] = [#(#list_values),*];
            items.iter()
          }
          pub fn iter() -> impl Iterator<Item = std::borrow::Cow<'static, str>> {
              Self::names().map(|x| std::borrow::Cow::from(*x))
          }
      }
      impl rust_embed::RustEmbed for #ident {
        fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
          #ident::get(file_path)
        }
        fn iter() -> rust_embed::Filenames {
          rust_embed::Filenames::Embedded(#ident::names())
        }
      }
  }
}

fn impl_rust_embed(ast: &syn::DeriveInput) -> TokenStream2 {
  match ast.data {
    Data::Struct(ref data) => match data.fields {
      Fields::Unit => {}
      _ => panic!("RustEmbed can only be derived for unit structs"),
    },
    _ => panic!("RustEmbed can only be derived for unit structs"),
  };

  let attribute = ast
    .attrs
    .iter()
    .find(|value| value.path.is_ident("folder"))
    .expect("#[derive(RustEmbed)] should contain one attribute like this #[folder = \"examples/public/\"]");
  let meta = attribute
    .parse_meta()
    .expect("#[derive(RustEmbed)] should contain one attribute like this #[folder = \"examples/public/\"]");
  let literal_value = match meta {
    Meta::NameValue(ref data) => &data.lit,
    _ => panic!("#[derive(RustEmbed)] should contain one attribute like this #[folder = \"examples/public/\"]"),
  };
  let folder_path = match literal_value {
    Lit::Str(ref val) => val.clone().value(),
    _ => {
      panic!("#[derive(RustEmbed)] attribute value must be a string literal");
    }
  };

  #[cfg(feature = "interpolate-folder-path")]
  let folder_path = shellexpand::full(&folder_path).unwrap().to_string();

  // Base relative paths on the Cargo.toml location
  let folder_path = if Path::new(&folder_path).is_relative() {
    Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap())
      .join(folder_path)
      .to_str()
      .unwrap()
      .to_owned()
  } else {
    folder_path
  };

  if !Path::new(&folder_path).exists() {
    let mut message = format!(
      "#[derive(RustEmbed)] folder '{}' does not exist. cwd: '{}'",
      folder_path,
      std::env::current_dir().unwrap().to_str().unwrap()
    );

    // Add a message about the interpolate-folder-path feature if the path may
    // include a variable
    if folder_path.contains('$') && cfg!(not(feature = "interpolate-folder-path")) {
      message += "\nA variable has been detected. RustEmbed can expand variables \
                  when the `interpolate-folder-path` feature is enabled.";
    }

    panic!(message);
  };

  generate_assets(&ast.ident, folder_path)
}

#[proc_macro_derive(RustEmbed, attributes(folder))]
pub fn derive_input_object(input: TokenStream) -> TokenStream {
  let ast: DeriveInput = syn::parse(input).unwrap();
  let gen = impl_rust_embed(&ast);
  gen.into()
}
<|endoftext|>


<commit_before>extern crate nom;

use std::str;
use nom::{
    is_digit,
    is_hex_digit,
};

fn is_ws(c: char) -> bool {
    let u = c as u32;
    u == 0x20 || u == 0x9 || u == 0xD || u == 0xA
}

fn is_anon(c: char) -> bool {
    c == '[' || c == ']' || is_ws(c)
}

fn is_digit_c(c: char) -> bool {
    is_digit(c as u8)
}

#[derive(PartialEq, Debug)]
pub struct Integer<'a> {
    sign:          Option<&'a str>,
    integer_part:  &'a str,
}
/* [19] INTEGER */
named!(pub integer<&str, Integer>, do_parse!(
    sign:          opt!(alt!(tag!("+") | tag!("-"))) >>
    integer_part:  take_while1_s!(is_digit_c)        >>
    (Integer{
        sign:          sign,
        integer_part:  integer_part,
    })
));

#[derive(PartialEq, Debug)]
pub struct Decimal<'a> {
    sign:          Option<&'a str>,
    integer_part:  &'a str,
    decimal_point: &'a str,
    decimal_part:  &'a str,
}
/* [20] DECIMAL */
named!(pub decimal<&str, Decimal>, do_parse!(
    sign:          opt!(alt!(tag!("+") | tag!("-"))) >>
    integer_part:  take_while_s!(is_digit_c)         >>
    decimal_point: tag!(".")                         >>
    decimal_part:  take_while1_s!(is_digit_c)        >>
    (Decimal{
        sign:          sign,
        integer_part:  integer_part,
        decimal_point: decimal_point,
        decimal_part:  decimal_part,
    })
));

#[derive(PartialEq, Debug)]
pub enum Mantissa<'a> {
    IntegerDecimal {
        integer_part:  &'a str,
        decimal_point: &'a str,
        decimal_part:  &'a str,
    },
    Decimal {
        decimal_point: &'a str,
        decimal_part:  &'a str,
    },
    Integer {
        integer_part: &'a str,
    },
}
#[derive(PartialEq, Debug)]
pub struct Double<'a> {
    sign:     Option<&'a str>,
    mantissa: Mantissa<'a>,
    exponent: Exponent<'a>,
}
/* [21] DOUBLE */
named!(pub double<&str, Double>, do_parse!(
    sign:     opt!(alt!(tag!("+") | tag!("-"))) >>
    mantissa: alt!(
        do_parse!(
            integer_part:  take_while1_s!(is_digit_c) >>
            decimal_point: tag!(".")                  >>
            decimal_part:  take_while_s!(is_digit_c)  >>
            (Mantissa::IntegerDecimal{
                integer_part:  integer_part,
                decimal_point: decimal_point,
                decimal_part:  decimal_part,
            })
        ) |
        do_parse!(
            decimal_point: tag!(".")                  >>
            decimal_part:  take_while1_s!(is_digit_c) >>
            (Mantissa::Decimal{
                decimal_point: decimal_point,
                decimal_part:  decimal_part,
            })
        ) |
        do_parse!(
            integer_part: take_while1_s!(is_digit_c) >>
            (Mantissa::Integer{
                integer_part: integer_part,
            })
        )
    ) >>
    exponent: exponent >>
    (Double{
        sign:     sign,
        mantissa: mantissa,
        exponent: exponent,
    })
));

#[derive(PartialEq, Debug)]
pub struct Exponent<'a> {
    exponent_symbol: &'a str,
    sign:            Option<&'a str>,
    exponent_number: &'a str,
}

/* [154s] EXPONENT */
named!(pub exponent<&str, Exponent>, do_parse!(
    exponent_symbol: alt!(tag!("e") | tag!("E"))       >>
    sign:            opt!(alt!(tag!("+") | tag!("-"))) >>
    exponent_number: take_while1_s!(is_digit_c)        >>
    (Exponent{
        exponent_symbol: exponent_symbol,
        sign:            sign,
        exponent_number: exponent_number,
    })
));

/* [161s] WS */
named!(pub ws<&str, &str>, take_while_s!(is_ws));

/* [162s] ANON */
named!(pub anon<&str, &str>, verify!(
    take_while_s!(is_anon),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                c == '['
            } else if idx == len - 1 {
                c == ']'
            } else {
                is_ws(c)
            }
        })
    }
));

/* [170s] PERCENT */
named!(pub percent<&str, &str>, verify!(
    take_s!(3),
    |val:&str| {
        let bytes = val.as_bytes();
        bytes[0] == 0x25 && is_hex_digit(bytes[1]) && is_hex_digit(bytes[2])
    }
));

#[cfg(test)]
mod test {
    use super::*;
    use nom::IResult;

    #[test]
    fn integer_normal_test() {
        let input    = "-1234rest";
        let expected = IResult::Done("rest", Integer{
            sign:          Some("-"),
            integer_part:  "1234",
        });
        assert_eq!(integer(input), expected);
    }

    #[test]
    fn decimal_normal_test() {
        let input    = "-1234.5678rest";
        let expected = IResult::Done("rest", Decimal{
            sign:          Some("-"),
            integer_part:  "1234",
            decimal_point: ".",
            decimal_part:  "5678",
        });
        assert_eq!(decimal(input), expected);
    }

    #[test]
    fn double_normal_test() {
        let input    = "-1234.5678e-0123456789rest";
        let expected = IResult::Done("rest", Double{
            sign:     Some("-"),
            mantissa: Mantissa::IntegerDecimal {
                integer_part:  "1234",
                decimal_point: ".",
                decimal_part:  "5678",
            },
            exponent: Exponent {
                exponent_symbol: "e",
                sign:            Some("-"),
                exponent_number: "0123456789",
            },
        });
        assert_eq!(double(input), expected);

        let input    = "-.5678e-0123456789rest";
        let expected = IResult::Done("rest", Double{
            sign:     Some("-"),
            mantissa: Mantissa::Decimal {
                decimal_point: ".",
                decimal_part:  "5678",
            },
            exponent: Exponent {
                exponent_symbol: "e",
                sign:            Some("-"),
                exponent_number: "0123456789",
            },
        });
        assert_eq!(double(input), expected);

        let input    = "+5678e-0123456789rest";
        let expected = IResult::Done("rest", Double{
            sign:     Some("+"),
            mantissa: Mantissa::Integer {
                integer_part: "5678",
            },
            exponent: Exponent {
                exponent_symbol: "e",
                sign:            Some("-"),
                exponent_number: "0123456789",
            },
        });
        assert_eq!(double(input), expected);
    }

    #[test]
    fn exponent_normal_test() {
        let input    = "e-0123456789rest";
        let expected = IResult::Done("rest", Exponent{
            exponent_symbol: "e",
            sign:            Some("-"),
            exponent_number: "0123456789",
        });
        assert_eq!(exponent(input), expected);

        let input    = "E+0123456789rest";
        let expected = IResult::Done("rest", Exponent{
            exponent_symbol: "E",
            sign:            Some("+"),
            exponent_number: "0123456789",
        });
        assert_eq!(exponent(input), expected);

        let input    = "e0123456789rest";
        let expected = IResult::Done("rest", Exponent{
            exponent_symbol: "e",
            sign:            None,
            exponent_number: "0123456789",
        });
        assert_eq!(exponent(input), expected);
    }

    #[test]
    fn ws_test() {
        assert_eq!(ws("   a"), IResult::Done("a", "   "));
    }

    #[test]
    fn anon_test() {
        assert_eq!(anon("[ ]a"), IResult::Done("a", "[ ]"));
    }

    #[test]
    fn percent_test() {
        assert_eq!(percent("%2Abc"), IResult::Done("bc", "%2A"));
    }
}
<commit_msg>Implement LANGTAG<commit_after>extern crate nom;

use std::str;
use nom::{
    is_digit,
    is_hex_digit,
};

fn is_ws(c: char) -> bool {
    let u = c as u32;
    u == 0x20 || u == 0x9 || u == 0xD || u == 0xA
}

fn is_anon(c: char) -> bool {
    c == '[' || c == ']' || is_ws(c)
}

fn is_digit_c(c: char) -> bool {
    is_digit(c as u8)
#[derive(PartialEq, Debug)]
pub struct Langtag<'a> {
    language: &'a str,
    subtags:  Vec<&'a str>,
}
/* [144s] LANGTAG */
named!(pub langtag<&str, Langtag>, do_parse!(
    tag!("@") >>
    language: alpha >>
    tag!("-") >>
    subtags:  separated_list_complete!(
        tag!("-"),
        alphanumeric
    ) >>
    (Langtag{
        language: language,
        subtags:  subtags,
    })
));

#[derive(PartialEq, Debug)]
pub struct Integer<'a> {
    sign:          Option<&'a str>,
    integer_part:  &'a str,
}
/* [19] INTEGER */
named!(pub integer<&str, Integer>, do_parse!(
    sign:          opt!(alt!(tag!("+") | tag!("-"))) >>
    integer_part:  take_while1_s!(is_digit_c)        >>
    (Integer{
        sign:          sign,
        integer_part:  integer_part,
    })
));

#[derive(PartialEq, Debug)]
pub struct Decimal<'a> {
    sign:          Option<&'a str>,
    integer_part:  &'a str,
    decimal_point: &'a str,
    decimal_part:  &'a str,
}
/* [20] DECIMAL */
named!(pub decimal<&str, Decimal>, do_parse!(
    sign:          opt!(alt!(tag!("+") | tag!("-"))) >>
    integer_part:  take_while_s!(is_digit_c)         >>
    decimal_point: tag!(".")                         >>
    decimal_part:  take_while1_s!(is_digit_c)        >>
    (Decimal{
        sign:          sign,
        integer_part:  integer_part,
        decimal_point: decimal_point,
        decimal_part:  decimal_part,
    })
));

#[derive(PartialEq, Debug)]
pub enum Mantissa<'a> {
    IntegerDecimal {
        integer_part:  &'a str,
        decimal_point: &'a str,
        decimal_part:  &'a str,
    },
    Decimal {
        decimal_point: &'a str,
        decimal_part:  &'a str,
    },
    Integer {
        integer_part: &'a str,
    },
}
#[derive(PartialEq, Debug)]
pub struct Double<'a> {
    sign:     Option<&'a str>,
    mantissa: Mantissa<'a>,
    exponent: Exponent<'a>,
}
/* [21] DOUBLE */
named!(pub double<&str, Double>, do_parse!(
    sign:     opt!(alt!(tag!("+") | tag!("-"))) >>
    mantissa: alt!(
        do_parse!(
            integer_part:  take_while1_s!(is_digit_c) >>
            decimal_point: tag!(".")                  >>
            decimal_part:  take_while_s!(is_digit_c)  >>
            (Mantissa::IntegerDecimal{
                integer_part:  integer_part,
                decimal_point: decimal_point,
                decimal_part:  decimal_part,
            })
        ) |
        do_parse!(
            decimal_point: tag!(".")                  >>
            decimal_part:  take_while1_s!(is_digit_c) >>
            (Mantissa::Decimal{
                decimal_point: decimal_point,
                decimal_part:  decimal_part,
            })
        ) |
        do_parse!(
            integer_part: take_while1_s!(is_digit_c) >>
            (Mantissa::Integer{
                integer_part: integer_part,
            })
        )
    ) >>
    exponent: exponent >>
    (Double{
        sign:     sign,
        mantissa: mantissa,
        exponent: exponent,
    })
));

#[derive(PartialEq, Debug)]
pub struct Exponent<'a> {
    exponent_symbol: &'a str,
    sign:            Option<&'a str>,
    exponent_number: &'a str,
}

/* [154s] EXPONENT */
named!(pub exponent<&str, Exponent>, do_parse!(
    exponent_symbol: alt!(tag!("e") | tag!("E"))       >>
    sign:            opt!(alt!(tag!("+") | tag!("-"))) >>
    exponent_number: take_while1_s!(is_digit_c)        >>
    (Exponent{
        exponent_symbol: exponent_symbol,
        sign:            sign,
        exponent_number: exponent_number,
    })
));

/* [161s] WS */
named!(pub ws<&str, &str>, take_while_s!(is_ws));

/* [162s] ANON */
named!(pub anon<&str, &str>, verify!(
    take_while_s!(is_anon),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                c == '['
            } else if idx == len - 1 {
                c == ']'
            } else {
                is_ws(c)
            }
        })
    }
));

/* [170s] PERCENT */
named!(pub percent<&str, &str>, verify!(
    take_s!(3),
    |val:&str| {
        let bytes = val.as_bytes();
        bytes[0] == 0x25 && is_hex_digit(bytes[1]) && is_hex_digit(bytes[2])
    }
));

#[cfg(test)]
mod test {
    use super::*;
    use nom::IResult;
    use nom::ErrorKind;

    #[test]
    fn langtag_normal_test() {
        let input    = "@en-a-bbb-a-ccc,rest";
        let expected = IResult::Done(",rest", Langtag{
            language: "en",
            subtags:  vec!["a", "bbb", "a", "ccc"]
        });
        assert_eq!(langtag(input), expected);
    }

    #[test]
    fn langtag_abnormal_test() {
        let input    = "@en01-a-bbb-a-ccc,rest";
        let expected = IResult::Error(ErrorKind::Tag);
        assert_eq!(langtag(input), expected);
    }

    #[test]
    fn integer_normal_test() {
        let input    = "-1234rest";
        let expected = IResult::Done("rest", Integer{
            sign:          Some("-"),
            integer_part:  "1234",
        });
        assert_eq!(integer(input), expected);
    }

    #[test]
    fn decimal_normal_test() {
        let input    = "-1234.5678rest";
        let expected = IResult::Done("rest", Decimal{
            sign:          Some("-"),
            integer_part:  "1234",
            decimal_point: ".",
            decimal_part:  "5678",
        });
        assert_eq!(decimal(input), expected);
    }

    #[test]
    fn double_normal_test() {
        let input    = "-1234.5678e-0123456789rest";
        let expected = IResult::Done("rest", Double{
            sign:     Some("-"),
            mantissa: Mantissa::IntegerDecimal {
                integer_part:  "1234",
                decimal_point: ".",
                decimal_part:  "5678",
            },
            exponent: Exponent {
                exponent_symbol: "e",
                sign:            Some("-"),
                exponent_number: "0123456789",
            },
        });
        assert_eq!(double(input), expected);

        let input    = "-.5678e-0123456789rest";
        let expected = IResult::Done("rest", Double{
            sign:     Some("-"),
            mantissa: Mantissa::Decimal {
                decimal_point: ".",
                decimal_part:  "5678",
            },
            exponent: Exponent {
                exponent_symbol: "e",
                sign:            Some("-"),
                exponent_number: "0123456789",
            },
        });
        assert_eq!(double(input), expected);

        let input    = "+5678e-0123456789rest";
        let expected = IResult::Done("rest", Double{
            sign:     Some("+"),
            mantissa: Mantissa::Integer {
                integer_part: "5678",
            },
            exponent: Exponent {
                exponent_symbol: "e",
                sign:            Some("-"),
                exponent_number: "0123456789",
            },
        });
        assert_eq!(double(input), expected);
    }

    #[test]
    fn exponent_normal_test() {
        let input    = "e-0123456789rest";
        let expected = IResult::Done("rest", Exponent{
            exponent_symbol: "e",
            sign:            Some("-"),
            exponent_number: "0123456789",
        });
        assert_eq!(exponent(input), expected);

        let input    = "E+0123456789rest";
        let expected = IResult::Done("rest", Exponent{
            exponent_symbol: "E",
            sign:            Some("+"),
            exponent_number: "0123456789",
        });
        assert_eq!(exponent(input), expected);

        let input    = "e0123456789rest";
        let expected = IResult::Done("rest", Exponent{
            exponent_symbol: "e",
            sign:            None,
            exponent_number: "0123456789",
        });
        assert_eq!(exponent(input), expected);
    }

    #[test]
    fn ws_test() {
        assert_eq!(ws("   a"), IResult::Done("a", "   "));
    }

    #[test]
    fn anon_test() {
        assert_eq!(anon("[ ]a"), IResult::Done("a", "[ ]"));
    }

    #[test]
    fn percent_test() {
        assert_eq!(percent("%2Abc"), IResult::Done("bc", "%2A"));
    }
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) delim

use clap::{crate_version, App, AppSettings, Arg};
use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Read, stdout, Write};
use std::path::Path;
use uucore::error::{FromIo, UResult};

static ABOUT: &str = "Write lines consisting of the sequentially corresponding lines from each
FILE, separated by TABs, to standard output.";

mod options {
    pub const DELIMITER: &str = "delimiters";
    pub const SERIAL: &str = "serial";
    pub const FILE: &str = "file";
}

// Wraps BufReader and stdin
fn read_line<R: Read>(
    reader: Option<&mut BufReader<R>>,
    buf: &mut String,
) -> std::io::Result<usize> {
    match reader {
        Some(reader) => reader.read_line(buf),
        None => stdin().read_line(buf),
    }
}

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let matches = uu_app().get_matches_from(args);

    let serial = matches.is_present(options::SERIAL);
    let delimiters = matches.value_of(options::DELIMITER).unwrap();
    let files = matches
        .values_of(options::FILE)
        .unwrap()
        .map(|s| s.to_owned())
        .collect();
    paste(files, serial, delimiters)
}

pub fn uu_app<'a>() -> App<'a> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .setting(AppSettings::InferLongArgs)
        .arg(
            Arg::new(options::SERIAL)
                .long(options::SERIAL)
                .short('s')
                .help("paste one file at a time instead of in parallel"),
        )
        .arg(
            Arg::new(options::DELIMITER)
                .long(options::DELIMITER)
                .short('d')
                .help("reuse characters from LIST instead of TABs")
                .value_name("LIST")
                .default_value("\t")
                .hide_default_value(true),
        )
        .arg(
            Arg::new(options::FILE)
                .value_name("FILE")
                .multiple_occurrences(true)
                .default_value("-"),
        )
}

fn paste(filenames: Vec<String>, serial: bool, delimiters: &str) -> UResult<()> {
    let mut files = vec![];
    for name in filenames {
        let file = if name == "-" {
            None
        } else {
            let path = Path::new(&name);
            let r = File::open(path).map_err_context(String::new)?;
            Some(BufReader::new(r))
        };
        files.push(file);
    }

    let delimiters: Vec<char> = unescape(delimiters).chars().collect();
    let mut delim_count = 0;
    let stdout = stdout();
    let mut stdout = stdout.lock();

    let mut line = String::new();
    if serial {
        for file in &mut files {
            let mut output = String::new();
            loop {
                line.clear();
                match read_line(file.as_mut(), &mut line) {
                    Ok(0) => break,
                    Ok(_) => {
                        output.push_str(line.trim_end());
                        output.push(delimiters[delim_count % delimiters.len()]);
                    }
                    Err(e) => return Err(e.map_err_context(String::new)),
                }
                delim_count += 1;
            }
            output.pop();
            writeln!(stdout, "{}", output)?;
        }
    } else {
        let mut eof = vec![false; files.len()];
        loop {
            let mut output = String::new();
            let mut eof_count = 0;
            for (i, file) in files.iter_mut().enumerate() {
                if eof[i] {
                    eof_count += 1;
                } else {
                    line.clear();
                    match read_line(file.as_mut(), &mut line) {
                        Ok(0) => {
                            eof[i] = true;
                            eof_count += 1;
                        }
                        Ok(_) => output.push_str(line.trim_end()),
                        Err(e) => return Err(e.map_err_context(String::new)),
                    }
                }
                output.push(delimiters[delim_count % delimiters.len()]);
                delim_count += 1;
            }
            if files.len() == eof_count {
                break;
            }
            // Remove final delimiter
            output.pop();
            writeln!(stdout, "{}", output)?;
            delim_count = 0;
        }
    }
    Ok(())
}

// Unescape all special characters
// TODO: this will need work to conform to GNU implementation
fn unescape(s: &str) -> String {
    s.replace("\\n", "\n")
        .replace("\\t", "\t")
        .replace("\\\\", "\\")
        .replace('\\', "")
}
<commit_msg>paste: Reuse `output` allocation<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) delim

use clap::{crate_version, App, AppSettings, Arg};
use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Read, stdout, Write};
use std::path::Path;
use uucore::error::{FromIo, UResult};

static ABOUT: &str = "Write lines consisting of the sequentially corresponding lines from each
FILE, separated by TABs, to standard output.";

mod options {
    pub const DELIMITER: &str = "delimiters";
    pub const SERIAL: &str = "serial";
    pub const FILE: &str = "file";
}

// Wraps BufReader and stdin
fn read_line<R: Read>(
    reader: Option<&mut BufReader<R>>,
    buf: &mut String,
) -> std::io::Result<usize> {
    match reader {
        Some(reader) => reader.read_line(buf),
        None => stdin().read_line(buf),
    }
}

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let matches = uu_app().get_matches_from(args);

    let serial = matches.is_present(options::SERIAL);
    let delimiters = matches.value_of(options::DELIMITER).unwrap();
    let files = matches
        .values_of(options::FILE)
        .unwrap()
        .map(|s| s.to_owned())
        .collect();
    paste(files, serial, delimiters)
}

pub fn uu_app<'a>() -> App<'a> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .setting(AppSettings::InferLongArgs)
        .arg(
            Arg::new(options::SERIAL)
                .long(options::SERIAL)
                .short('s')
                .help("paste one file at a time instead of in parallel"),
        )
        .arg(
            Arg::new(options::DELIMITER)
                .long(options::DELIMITER)
                .short('d')
                .help("reuse characters from LIST instead of TABs")
                .value_name("LIST")
                .default_value("\t")
                .hide_default_value(true),
        )
        .arg(
            Arg::new(options::FILE)
                .value_name("FILE")
                .multiple_occurrences(true)
                .default_value("-"),
        )
}

fn paste(filenames: Vec<String>, serial: bool, delimiters: &str) -> UResult<()> {
    let mut files = vec![];
    for name in filenames {
        let file = if name == "-" {
            None
        } else {
            let path = Path::new(&name);
            let r = File::open(path).map_err_context(String::new)?;
            Some(BufReader::new(r))
        };
        files.push(file);
    }

    let delimiters: Vec<char> = unescape(delimiters).chars().collect();
    let mut delim_count = 0;
    let stdout = stdout();
    let mut stdout = stdout.lock();

    let mut line = String::new();
    let mut output = String::new();
    if serial {
        for file in &mut files {
            output.clear();
            loop {
                line.clear();
                match read_line(file.as_mut(), &mut line) {
                    Ok(0) => break,
                    Ok(_) => {
                        output.push_str(line.trim_end());
                        output.push(delimiters[delim_count % delimiters.len()]);
                    }
                    Err(e) => return Err(e.map_err_context(String::new)),
                }
                delim_count += 1;
            }
            output.pop();
            writeln!(stdout, "{}", output)?;
        }
    } else {
        let mut eof = vec![false; files.len()];
        loop {
            output.clear();
            let mut eof_count = 0;
            for (i, file) in files.iter_mut().enumerate() {
                if eof[i] {
                    eof_count += 1;
                } else {
                    line.clear();
                    match read_line(file.as_mut(), &mut line) {
                        Ok(0) => {
                            eof[i] = true;
                            eof_count += 1;
                        }
                        Ok(_) => output.push_str(line.trim_end()),
                        Err(e) => return Err(e.map_err_context(String::new)),
                    }
                }
                output.push(delimiters[delim_count % delimiters.len()]);
                delim_count += 1;
            }
            if files.len() == eof_count {
                break;
            }
            // Remove final delimiter
            output.pop();
            writeln!(stdout, "{}", output)?;
            delim_count = 0;
        }
    }
    Ok(())
}

// Unescape all special characters
// TODO: this will need work to conform to GNU implementation
fn unescape(s: &str) -> String {
    s.replace("\\n", "\n")
        .replace("\\t", "\t")
        .replace("\\\\", "\\")
        .replace('\\', "")
}
<|endoftext|>


<commit_before>//! Fields which are common to all segment-section and gate descriptors

use shared::PrivilegeLevel;
use shared::segmentation;

/// System-Segment and Gate-Descriptor Types for IA32e mode.  When the `S`
/// (descriptor type) flag in a segment descriptor is clear, the descriptor type
/// is a system descriptor.
///
/// See Intel manual 3a, 3.5 "System Descriptor Types", and Table 3-2,
/// System-Segment and Gate-Descriptor Types".
#[repr(u8)]
pub enum SystemType {
    // Reserved = 0
    TssAvailable = 1,
    /// Only for 16-bit
    LocalDescriptorTable = 2,
    TssBusy = 3,
    CallGate = 4,
    /// Only for 16-bit
    TaskGate = 5,
    InterruptGate = 6,
    TrapGate = 7,
}

/// A high-level representation of a descriptor type. One can convert to and
/// from the `Flags` bitfield to encode/decode an actual descriptor.
#[repr(u8)]
pub enum Type {
    SystemDescriptor {
        /// false/0: 16-bit
        /// true/1: native (32- or 64-bit)
        size: bool,
        ty: SystemType
    },
    SegmentDescriptor {
        ty: segmentation::Type,
        accessed: bool
    }
}

impl Type {
    pub fn pack(self) -> u8 {
        match self {
            Type::SystemDescriptor { size, ty } =>
                (size as u8) << 3 | (ty as u8) | FLAGS_TYPE_SYS.bits,
            Type::SegmentDescriptor { ty, accessed } =>
                (accessed as u8)  | ty.pack()  | FLAGS_TYPE_SYS.bits,
        }
    }
}

bitflags!{
    /// Actual encoding of the flags in byte 6 common to all descriptors.
    ///
    /// See Intel manual 3a, figures 3-8, 6-2, and 6-7.
    pub flags Flags: u8 {
        /// Descriptor is Present.
        const FLAGS_PRESENT = 1 << 7,

        // Descriptor privilege level
        const FLAGS_DPL_RING_0 = 0b00 << 5,
        const FLAGS_DPL_RING_1 = 0b01 << 5,
        const FLAGS_DPL_RING_2 = 0b10 << 5,
        const FLAGS_DPL_RING_3 = 0b11 << 5,

        // Is system descriptor
        const FLAGS_TYPE_SYS = 0 << 4,
        const FLAGS_TYPE_SEG = 1 << 4,

        // System-Segment and Gate-Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is clear,
        // the descriptor type is a system descriptor

        // All modes (supporting segments)
        const TYPE_SYS_LDT = 0b0_0010,

        // Protected Mode and older
        const FLAGS_TYPE_SYS_16BIT_TSS_AVAILABLE = 0b0_0001,
        const FLAGS_TYPE_SYS_16BIT_TSS_BUSY = 0b0_0011,
        const FLAGS_TYPE_SYS_16BIT_CALL_GATE = 0b0_0100,
        const FLAGS_TYPE_SYS_16BIT_TASK_GATE = 0b0_0101,
        const FLAGS_TYPE_SYS_16BIT_INTERRUPT_GATE = 0b0_0110,
        const FLAGS_TYPE_SYS_16BIT_TRAP_GATE = 0b0_0111,

        // 64-bit in IA-32e Mode (either submode), 32-bit in Protected Mode
        const FLAGS_TYPE_SYS_NATIVE_TSS_AVAILABLE = 0b0_1001,
        const FLAGS_TYPE_SYS_NATIVE_TSS_BUSY = 0b0_1011,
        const FLAGS_TYPE_SYS_NATIVE_CALL_GATE = 0b0_1100,
        const FLAGS_TYPE_SYS_NATIVE_INTERRUPT_GATE = 0b0_1110,
        const FLAGS_TYPE_SYS_NATIVE_TRAP_GATE = 0b0_1111,

        // Code- and Data-Segment Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is set,
        // the descriptor is for either a code or a data segment.

        /// Data or code, accessed
        const FLAGS_TYPE_SEG_ACCESSED = 0b1_0001,

        const FLAGS_TYPE_DATA = 0b1_0000,
        const FLAGS_TYPE_CODE = 0b1_1000,

        // Data => permissions
        const FLAGS_TYPE_SEG_D_WRITE = 0b1_0010,
        const FLAGS_TYPE_SEG_D_EXPAND_DOWN = 0b1_0100,

        // Code => permissions
        const FLAGS_TYPE_SEG_C_READ = 0b1_0010,
        const FLAGS_TYPE_SEG_D_CONFORMING = 0b1_0100,

        /// Data Read-Only
        const FLAGS_TYPE_SEG_D_RO     = FLAGS_TYPE_DATA.bits,
        /// Data Read-Only, accessed
        const FLAGS_TYPE_SEG_D_ROA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write
        const FLAGS_TYPE_SEG_D_RW     = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits,
        /// Data Read/Write, accessed
        const FLAGS_TYPE_SEG_D_RWA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read-Only, expand-down
        const FLAGS_TYPE_SEG_D_ROEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read-Only, expand-down, accessed
        const FLAGS_TYPE_SEG_D_ROEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write, expand-down
        const FLAGS_TYPE_SEG_D_RWEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read/Write, expand-down, accessed
        const FLAGS_TYPE_SEG_D_RWEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,

        /// Code Execute-Only
        const FLAGS_TYPE_SEG_C_EO     = FLAGS_TYPE_DATA.bits,
        /// Code Execute-Only, accessed
        const FLAGS_TYPE_SEG_C_EOA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read
        const FLAGS_TYPE_SEG_C_ER     = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits,
        /// Code Execute/Read, accessed
        const FLAGS_TYPE_SEG_C_ERA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute-Only, conforming
        const FLAGS_TYPE_SEG_C_EOC    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits,
        /// Code Execute-Only, conforming, accessed
        const FLAGS_TYPE_SEG_C_EOCA   = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read, conforming
        const FLAGS_TYPE_SEG_C_ERC    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits,
        /// Code Execute/Read, conforming, accessed
        const FLAGS_TYPE_SEG_C_ERCA   = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
    }
}

impl Flags {
    pub const BLANK: Flags = Flags { bits: 0 };

    pub const fn from_priv(dpl: PrivilegeLevel) -> Flags {
        Flags { bits: (dpl as u8) << 5 }
    }

    pub fn from_type(ty: Type) -> Flags {
        Flags { bits: ty.pack() }
    }

    pub const fn const_or(self, other: Self) -> Flags {
        Flags { bits: self.bits | other.bits }
    }

    pub const fn cond(self, cond: bool) -> Flags {
        Flags { bits: (-(cond as i8) as u8) & self.bits }
    }

    pub const fn const_mux(self, other: Self, cond: bool) -> Flags {
        self.cond(cond).const_or(other.cond(!cond))
    }
}
<commit_msg>Fix FLAGS_TYPE_SEG_C_* - they should be based on FLAGS_TYPE_CODE, not FLAGS_TYPE_DATA.<commit_after>//! Fields which are common to all segment-section and gate descriptors

use shared::PrivilegeLevel;
use shared::segmentation;

/// System-Segment and Gate-Descriptor Types for IA32e mode.  When the `S`
/// (descriptor type) flag in a segment descriptor is clear, the descriptor type
/// is a system descriptor.
///
/// See Intel manual 3a, 3.5 "System Descriptor Types", and Table 3-2,
/// System-Segment and Gate-Descriptor Types".
#[repr(u8)]
pub enum SystemType {
    // Reserved = 0
    TssAvailable = 1,
    /// Only for 16-bit
    LocalDescriptorTable = 2,
    TssBusy = 3,
    CallGate = 4,
    /// Only for 16-bit
    TaskGate = 5,
    InterruptGate = 6,
    TrapGate = 7,
}

/// A high-level representation of a descriptor type. One can convert to and
/// from the `Flags` bitfield to encode/decode an actual descriptor.
#[repr(u8)]
pub enum Type {
    SystemDescriptor {
        /// false/0: 16-bit
        /// true/1: native (32- or 64-bit)
        size: bool,
        ty: SystemType
    },
    SegmentDescriptor {
        ty: segmentation::Type,
        accessed: bool
    }
}

impl Type {
    pub fn pack(self) -> u8 {
        match self {
            Type::SystemDescriptor { size, ty } =>
                (size as u8) << 3 | (ty as u8) | FLAGS_TYPE_SYS.bits,
            Type::SegmentDescriptor { ty, accessed } =>
                (accessed as u8)  | ty.pack()  | FLAGS_TYPE_SYS.bits,
        }
    }
}

bitflags!{
    /// Actual encoding of the flags in byte 6 common to all descriptors.
    ///
    /// See Intel manual 3a, figures 3-8, 6-2, and 6-7.
    pub flags Flags: u8 {
        /// Descriptor is Present.
        const FLAGS_PRESENT = 1 << 7,

        // Descriptor privilege level
        const FLAGS_DPL_RING_0 = 0b00 << 5,
        const FLAGS_DPL_RING_1 = 0b01 << 5,
        const FLAGS_DPL_RING_2 = 0b10 << 5,
        const FLAGS_DPL_RING_3 = 0b11 << 5,

        // Is system descriptor
        const FLAGS_TYPE_SYS = 0 << 4,
        const FLAGS_TYPE_SEG = 1 << 4,

        // System-Segment and Gate-Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is clear,
        // the descriptor type is a system descriptor

        // All modes (supporting segments)
        const TYPE_SYS_LDT = 0b0_0010,

        // Protected Mode and older
        const FLAGS_TYPE_SYS_16BIT_TSS_AVAILABLE = 0b0_0001,
        const FLAGS_TYPE_SYS_16BIT_TSS_BUSY = 0b0_0011,
        const FLAGS_TYPE_SYS_16BIT_CALL_GATE = 0b0_0100,
        const FLAGS_TYPE_SYS_16BIT_TASK_GATE = 0b0_0101,
        const FLAGS_TYPE_SYS_16BIT_INTERRUPT_GATE = 0b0_0110,
        const FLAGS_TYPE_SYS_16BIT_TRAP_GATE = 0b0_0111,

        // 64-bit in IA-32e Mode (either submode), 32-bit in Protected Mode
        const FLAGS_TYPE_SYS_NATIVE_TSS_AVAILABLE = 0b0_1001,
        const FLAGS_TYPE_SYS_NATIVE_TSS_BUSY = 0b0_1011,
        const FLAGS_TYPE_SYS_NATIVE_CALL_GATE = 0b0_1100,
        const FLAGS_TYPE_SYS_NATIVE_INTERRUPT_GATE = 0b0_1110,
        const FLAGS_TYPE_SYS_NATIVE_TRAP_GATE = 0b0_1111,

        // Code- and Data-Segment Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is set,
        // the descriptor is for either a code or a data segment.

        /// Data or code, accessed
        const FLAGS_TYPE_SEG_ACCESSED = 0b1_0001,

        const FLAGS_TYPE_DATA = 0b1_0000,
        const FLAGS_TYPE_CODE = 0b1_1000,

        // Data => permissions
        const FLAGS_TYPE_SEG_D_WRITE = 0b1_0010,
        const FLAGS_TYPE_SEG_D_EXPAND_DOWN = 0b1_0100,

        // Code => permissions
        const FLAGS_TYPE_SEG_C_READ = 0b1_0010,
        const FLAGS_TYPE_SEG_D_CONFORMING = 0b1_0100,

        /// Data Read-Only
        const FLAGS_TYPE_SEG_D_RO     = FLAGS_TYPE_DATA.bits,
        /// Data Read-Only, accessed
        const FLAGS_TYPE_SEG_D_ROA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write
        const FLAGS_TYPE_SEG_D_RW     = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits,
        /// Data Read/Write, accessed
        const FLAGS_TYPE_SEG_D_RWA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read-Only, expand-down
        const FLAGS_TYPE_SEG_D_ROEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read-Only, expand-down, accessed
        const FLAGS_TYPE_SEG_D_ROEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write, expand-down
        const FLAGS_TYPE_SEG_D_RWEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read/Write, expand-down, accessed
        const FLAGS_TYPE_SEG_D_RWEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,

        /// Code Execute-Only
        const FLAGS_TYPE_SEG_C_EO     = FLAGS_TYPE_CODE.bits,
        /// Code Execute-Only, accessed
        const FLAGS_TYPE_SEG_C_EOA    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read
        const FLAGS_TYPE_SEG_C_ER     = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits,
        /// Code Execute/Read, accessed
        const FLAGS_TYPE_SEG_C_ERA    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute-Only, conforming
        const FLAGS_TYPE_SEG_C_EOC    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits,
        /// Code Execute-Only, conforming, accessed
        const FLAGS_TYPE_SEG_C_EOCA   = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read, conforming
        const FLAGS_TYPE_SEG_C_ERC    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits,
        /// Code Execute/Read, conforming, accessed
        const FLAGS_TYPE_SEG_C_ERCA   = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
    }
}

impl Flags {
    pub const BLANK: Flags = Flags { bits: 0 };

    pub const fn from_priv(dpl: PrivilegeLevel) -> Flags {
        Flags { bits: (dpl as u8) << 5 }
    }

    pub fn from_type(ty: Type) -> Flags {
        Flags { bits: ty.pack() }
    }

    pub const fn const_or(self, other: Self) -> Flags {
        Flags { bits: self.bits | other.bits }
    }

    pub const fn cond(self, cond: bool) -> Flags {
        Flags { bits: (-(cond as i8) as u8) & self.bits }
    }

    pub const fn const_mux(self, other: Self, cond: bool) -> Flags {
        self.cond(cond).const_or(other.cond(!cond))
    }
}
<|endoftext|>


<commit_before>use std::util;

use cow::btree::BTreeMap;
use snowmew::core::{Database, object_key};

use vertex_buffer::VertexBuffer;
use shader::Shader;

use ovr;

static VS_SRC: &'static str =
"#version 400
uniform mat4 mat_model;
uniform mat4 mat_proj_view;

in vec3 position;
in vec2 in_texture;
in vec3 in_normal;

out vec2 fs_texture;
out vec3 fs_normal;

void main() {
    gl_Position = mat_proj_view * mat_model * vec4(position, 1.);
    fs_texture = in_texture;
    fs_normal = in_normal;
}
";

static VS_INSTANCED_SRC: &'static str =
"#version 430
layout(location = 0) uniform mat4 mat_proj_view;
layout(location = 1) uniform int instance_offset;

layout(std430, binding = 3) buffer MyBuffer
{
    mat4 model_matrix[];
};

in vec3 position;
in vec2 in_texture;
in vec3 in_normal;

out vec2 fs_texture;
out vec3 fs_normal;

void main() {
    gl_Position = mat_proj_view * model_matrix[instance_offset+gl_InstanceID] * vec4(position, 1.);
    fs_texture = in_texture;
    fs_normal = in_normal;
}
";

static FS_RAINBOW_NORMAL_SRC: &'static str =
"#version 400

in vec2 fs_texture;
in vec3 fs_normal;

out vec4 color;

void main() {
    color = vec4(fs_normal, 1);
}
";

static FS_RAINBOW_TEXTURE_SRC: &'static str =
"#version 400

in vec2 fs_texture;
in vec3 fs_normal;

out vec4 color;

void main() {
    color = vec4(fs_texture, 0.5, 1);
}
";

static VR_VS_SRC: &'static str =
"#version 400
in vec3 pos;
out vec2 TexPos;

void main() {
    gl_Position = vec4(pos.x, pos.y, 0.5, 1.);
    TexPos = vec2((pos.x+1)/2, (pos.y+1)/2);
}
";

static VR_FS_SRC: &'static str = ovr::SHADER_FRAG_CHROMAB;

static FS_FLAT_SRC: &'static str =
"#version 400
in vec2 fs_texture;
in vec3 fs_normal;

uniform vec3 ambient;

out vec4 color;

void main() {
    color = vec4(ambient, 1);
}
";

#[deriving(Clone)]
pub struct Graphics
{
    last: Database,
    current: Database,
    vertex: BTreeMap<object_key, VertexBuffer>,

    rainbow_normal: Option<Shader>,
    rainbow_texture: Option<Shader>,

    flat_shader: Option<Shader>,
    flat_instanced_shader: Option<Shader>,

    ovr_shader: Option<Shader>,
}

impl Graphics
{
    pub fn new(db: Database) -> Graphics
    {
        Graphics {
            current: db.clone(),
            last: db,
            vertex: BTreeMap::new(),
            rainbow_normal: None,
            rainbow_texture: None,
            flat_shader: None,
            ovr_shader: None,
            flat_instanced_shader: None
        }
    }

    pub fn update(&mut self, db: Database)
    {
        util::swap(&mut self.last, &mut self.current);
        self.current = db;

    }

    fn load_vertex(&mut self)
    {
        for (oid, vbo) in self.current.walk_vertex_buffers()
        {
            match self.vertex.find(oid) {
                Some(_) => (),
                None => {
                    let vb = VertexBuffer::new(&vbo.vertex, vbo.index.as_slice());
                    self.vertex.insert(*oid, vb);
                }
            }
        }
    }

    fn load_shaders(&mut self)
    {
        if self.rainbow_normal.is_none() {
            self.rainbow_normal = Some(Shader::new(VS_SRC, FS_RAINBOW_NORMAL_SRC));
        }
        if self.rainbow_texture.is_none() {
            self.rainbow_texture = Some(Shader::new(VS_SRC, FS_RAINBOW_TEXTURE_SRC));
        }
        if self.ovr_shader.is_none() {
            self.ovr_shader = Some(Shader::new(VR_VS_SRC, VR_FS_SRC));
        }
        if self.flat_shader.is_none() {
            self.flat_shader = Some(Shader::new(VS_SRC, FS_FLAT_SRC));
        }
        if self.flat_instanced_shader.is_none() {
            self.flat_instanced_shader = Some(Shader::new(VS_INSTANCED_SRC, FS_FLAT_SRC));
        }
    }

    pub fn load(&mut self)
    {
        self.load_vertex();
        self.load_shaders();
    }
}<commit_msg>missed std::util<commit_after>use std::mem;

use cow::btree::BTreeMap;
use snowmew::core::{Database, object_key};

use vertex_buffer::VertexBuffer;
use shader::Shader;

use ovr;

static VS_SRC: &'static str =
"#version 400
uniform mat4 mat_model;
uniform mat4 mat_proj_view;

in vec3 position;
in vec2 in_texture;
in vec3 in_normal;

out vec2 fs_texture;
out vec3 fs_normal;

void main() {
    gl_Position = mat_proj_view * mat_model * vec4(position, 1.);
    fs_texture = in_texture;
    fs_normal = in_normal;
}
";

static VS_INSTANCED_SRC: &'static str =
"#version 430
layout(location = 0) uniform mat4 mat_proj_view;
layout(location = 1) uniform int instance_offset;

layout(std430, binding = 3) buffer MyBuffer
{
    mat4 model_matrix[];
};

in vec3 position;
in vec2 in_texture;
in vec3 in_normal;

out vec2 fs_texture;
out vec3 fs_normal;

void main() {
    gl_Position = mat_proj_view * model_matrix[instance_offset+gl_InstanceID] * vec4(position, 1.);
    fs_texture = in_texture;
    fs_normal = in_normal;
}
";

static FS_RAINBOW_NORMAL_SRC: &'static str =
"#version 400

in vec2 fs_texture;
in vec3 fs_normal;

out vec4 color;

void main() {
    color = vec4(fs_normal, 1);
}
";

static FS_RAINBOW_TEXTURE_SRC: &'static str =
"#version 400

in vec2 fs_texture;
in vec3 fs_normal;

out vec4 color;

void main() {
    color = vec4(fs_texture, 0.5, 1);
}
";

static VR_VS_SRC: &'static str =
"#version 400
in vec3 pos;
out vec2 TexPos;

void main() {
    gl_Position = vec4(pos.x, pos.y, 0.5, 1.);
    TexPos = vec2((pos.x+1)/2, (pos.y+1)/2);
}
";

static VR_FS_SRC: &'static str = ovr::SHADER_FRAG_CHROMAB;

static FS_FLAT_SRC: &'static str =
"#version 400
in vec2 fs_texture;
in vec3 fs_normal;

uniform vec3 ambient;

out vec4 color;

void main() {
    color = vec4(ambient, 1);
}
";

#[deriving(Clone)]
pub struct Graphics
{
    last: Database,
    current: Database,
    vertex: BTreeMap<object_key, VertexBuffer>,

    rainbow_normal: Option<Shader>,
    rainbow_texture: Option<Shader>,

    flat_shader: Option<Shader>,
    flat_instanced_shader: Option<Shader>,

    ovr_shader: Option<Shader>,
}

impl Graphics
{
    pub fn new(db: Database) -> Graphics
    {
        Graphics {
            current: db.clone(),
            last: db,
            vertex: BTreeMap::new(),
            rainbow_normal: None,
            rainbow_texture: None,
            flat_shader: None,
            ovr_shader: None,
            flat_instanced_shader: None
        }
    }

    pub fn update(&mut self, db: Database)
    {
        mem::swap(&mut self.last, &mut self.current);
        self.current = db;

    }

    fn load_vertex(&mut self)
    {
        for (oid, vbo) in self.current.walk_vertex_buffers()
        {
            match self.vertex.find(oid) {
                Some(_) => (),
                None => {
                    let vb = VertexBuffer::new(&vbo.vertex, vbo.index.as_slice());
                    self.vertex.insert(*oid, vb);
                }
            }
        }
    }

    fn load_shaders(&mut self)
    {
        if self.rainbow_normal.is_none() {
            self.rainbow_normal = Some(Shader::new(VS_SRC, FS_RAINBOW_NORMAL_SRC));
        }
        if self.rainbow_texture.is_none() {
            self.rainbow_texture = Some(Shader::new(VS_SRC, FS_RAINBOW_TEXTURE_SRC));
        }
        if self.ovr_shader.is_none() {
            self.ovr_shader = Some(Shader::new(VR_VS_SRC, VR_FS_SRC));
        }
        if self.flat_shader.is_none() {
            self.flat_shader = Some(Shader::new(VS_SRC, FS_FLAT_SRC));
        }
        if self.flat_instanced_shader.is_none() {
            self.flat_instanced_shader = Some(Shader::new(VS_INSTANCED_SRC, FS_FLAT_SRC));
        }
    }

    pub fn load(&mut self)
    {
        self.load_vertex();
        self.load_shaders();
    }
}<|endoftext|>


<commit_before>use byteorder::{LittleEndian, ReadBytesExt};
use rustc_serialize::Decodable;
use std::net::{TcpStream, ToSocketAddrs};
use std::io::{Read, Write};
use std;
use super::error::Error;
use super::header::{encode, decode};
use super::message::RosMessage;
use super::decoder::Decoder;

pub trait SubscriberCallback {
    type N: RosMessage + Decodable;

    fn receive(&mut self, message: Self::N);
}

pub struct Subscriber<T: SubscriberCallback> {
    stream: Decoder<std::io::Bytes<TcpStream>>,
    callback: T,
}

impl<T> Subscriber<T>
    where T: SubscriberCallback
{
    pub fn new<U>(address: U,
                  callback: T,
                  caller_id: &str,
                  topic: &str)
                  -> Result<Subscriber<T>, Error>
        where U: ToSocketAddrs
    {
        let mut stream = try!(TcpStream::connect(address));
        {
            let mut fields = std::collections::HashMap::<String, String>::new();
            fields.insert("message_definition".to_owned(), T::N::msg_definition());
            fields.insert("callerid".to_owned(), caller_id.to_owned());
            fields.insert("topic".to_owned(), topic.to_owned());
            fields.insert("md5sum".to_owned(), T::N::md5sum());
            fields.insert("type".to_owned(), T::N::msg_type());

            let fields = try!(encode(fields));

            try!(stream.write_all(&fields));
        }
        {
            let mut bytes = [0u8; 4];
            try!(stream.read_exact(&mut bytes));
            let mut reader = std::io::Cursor::new(bytes);
            let data_length = try!(reader.read_u32::<LittleEndian>());
            let mut payload = vec![0u8; data_length as usize];
            try!(stream.read_exact(&mut payload));
            let data = bytes.iter().chain(payload.iter()).cloned().collect();
            let fields = try!(decode(data));
            if fields.get("md5sum") != Some(&T::N::md5sum()) {
                return Err(Error::Mismatch);
            }
            if fields.get("type") != Some(&T::N::msg_type()) {
                return Err(Error::Mismatch);
            }
        }

        Ok(Subscriber {
            stream: Decoder::new(stream.bytes()),
            callback: callback,
        })
    }

    pub fn spin(&mut self) -> Result<(), Error> {
        loop {
            self.callback.receive(try!(T::N::decode(&mut self.stream)));
        }
    }
}
<commit_msg>Use iterator interface for TCPROS subscriber<commit_after>use byteorder::{LittleEndian, ReadBytesExt};
use rustc_serialize::Decodable;
use std::net::{TcpStream, ToSocketAddrs};
use std::io::{Read, Write};
use std::sync::mpsc;
use std::thread;
use std;
use super::error::Error;
use super::header::{encode, decode};
use super::message::RosMessage;
use super::decoder::Decoder;

pub struct Subscriber<T>
    where T: RosMessage + Decodable + Send + 'static
{
    rx: mpsc::Receiver<T>,
}

impl<T> Subscriber<T>
    where T: RosMessage + Decodable + Send + 'static
{
    pub fn new<U>(address: U, caller_id: &str, topic: &str) -> Result<Subscriber<T>, Error>
        where U: ToSocketAddrs
    {
        let mut stream = try!(TcpStream::connect(address));
        {
            let mut fields = std::collections::HashMap::<String, String>::new();
            fields.insert("message_definition".to_owned(), T::msg_definition());
            fields.insert("callerid".to_owned(), caller_id.to_owned());
            fields.insert("topic".to_owned(), topic.to_owned());
            fields.insert("md5sum".to_owned(), T::md5sum());
            fields.insert("type".to_owned(), T::msg_type());

            let fields = try!(encode(fields));

            try!(stream.write_all(&fields));
        }
        {
            let mut bytes = [0u8; 4];
            try!(stream.read_exact(&mut bytes));
            let mut reader = std::io::Cursor::new(bytes);
            let data_length = try!(reader.read_u32::<LittleEndian>());
            let mut payload = vec![0u8; data_length as usize];
            try!(stream.read_exact(&mut payload));
            let data = bytes.iter().chain(payload.iter()).cloned().collect();
            let fields = try!(decode(data));
            if fields.get("md5sum") != Some(&T::md5sum()) {
                return Err(Error::Mismatch);
            }
            if fields.get("type") != Some(&T::msg_type()) {
                return Err(Error::Mismatch);
            }
        }

        let (tx, rx) = mpsc::channel();

        thread::spawn(move || spin_subscriber(stream, tx));

        Ok(Subscriber { rx: rx })
    }
}

fn spin_subscriber<T>(stream: TcpStream, tx: mpsc::Sender<T>) -> Result<(), Error>
    where T: Decodable
{
    let mut stream = Decoder::new(stream.bytes());
    while let Ok(()) = tx.send(try!(T::decode(&mut stream))) {
    }
    Ok(())
}

impl<T> std::iter::Iterator for Subscriber<T>
    where T: RosMessage + Decodable + Send + 'static
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.rx.recv().ok()
    }
}
<|endoftext|>


<commit_before>// This test uses procinfo, so can only be run on Linux.
extern crate libc;
extern crate ratelimit_meter;

use ratelimit_meter::{Decider, GCRA};
use ratelimit_meter::{LeakyBucket, MultiDecider};
use std::thread;
use std::time::{Duration, Instant};

fn resident_memsize() -> i64 {
    let mut out: libc::rusage = unsafe { std::mem::zeroed() };
    assert!(unsafe { libc::getrusage(libc::RUSAGE_SELF, &mut out) } == 0);
    out.ru_maxrss
}

const LEAK_TOLERANCE: i64 = 1024 * 100;

fn check_for_leaks(n_iter: usize, usage_before: i64) {
    let usage_after = resident_memsize();
    assert!(
        usage_after <= usage_before + LEAK_TOLERANCE,
        "Plausible memory leak!\nAfter {} iterations, usage before: {}, usage after: {}",
        n_iter,
        usage_before,
        usage_after
    );
}

#[test]
fn memleak_gcra() {
    const N_ITER: usize = 500_000;
    let mut bucket = GCRA::for_capacity(1_000_000).unwrap().build();
    let usage_before = resident_memsize();

    for _i in 0..N_ITER {
        drop(bucket.check());
    }
    check_for_leaks(N_ITER, usage_before);
}

#[test]
fn memleak_gcra_multi() {
    const N_ITER: usize = 500_000;
    let mut bucket = GCRA::for_capacity(1_000_000).unwrap().build();
    let usage_before = resident_memsize();

    for _i in 0..N_ITER {
        drop(bucket.check_n(2));
    }
    check_for_leaks(N_ITER, usage_before);
}

#[test]
fn memleak_gcra_threaded() {
    const N_ITER: usize = 5_000;
    let bucket = GCRA::for_capacity(1_000_000).unwrap().build();
    let usage_before = resident_memsize();

    for _i in 0..N_ITER {
        let mut bucket = bucket.clone();
        thread::spawn(move || drop(bucket.check())).join().unwrap();
    }
    check_for_leaks(N_ITER, usage_before);
}

#[test]
fn memleak_leakybucket() {
    const N_ITER: usize = 500_000;
    let mut bucket = LeakyBucket::per_second(1_000_000).unwrap();
    let usage_before = resident_memsize();

    for _i in 0..N_ITER {
        drop(bucket.check());
    }
    check_for_leaks(N_ITER, usage_before);
}

#[test]
fn memleak_leakybucket_threaded() {
    const N_ITER: usize = 5_000;
    let bucket = LeakyBucket::per_second(1_000_000).unwrap();
    let usage_before = resident_memsize();

    for _i in 0..N_ITER {
        let mut bucket = bucket.clone();
        thread::spawn(move || drop(bucket.check())).join().unwrap();
    }
    check_for_leaks(N_ITER, usage_before);
}
<commit_msg>Bump up the tolerance on the memleak test<commit_after>// This test uses procinfo, so can only be run on Linux.
extern crate libc;
extern crate ratelimit_meter;

use ratelimit_meter::{Decider, GCRA};
use ratelimit_meter::{LeakyBucket, MultiDecider};
use std::thread;

fn resident_memsize() -> i64 {
    let mut out: libc::rusage = unsafe { std::mem::zeroed() };
    assert!(unsafe { libc::getrusage(libc::RUSAGE_SELF, &mut out) } == 0);
    out.ru_maxrss
}

const LEAK_TOLERANCE: i64 = 1024 * 1024 * 10;

fn check_for_leaks(n_iter: usize, usage_before: i64) {
    let usage_after = resident_memsize();
    assert!(
        usage_after <= usage_before + LEAK_TOLERANCE,
        "Plausible memory leak!\nAfter {} iterations, usage before: {}, usage after: {}",
        n_iter,
        usage_before,
        usage_after
    );
}

#[test]
fn memleak_gcra() {
    const N_ITER: usize = 500_000;
    let mut bucket = GCRA::for_capacity(1_000_000).unwrap().build();
    let usage_before = resident_memsize();

    for _i in 0..N_ITER {
        drop(bucket.check());
    }
    check_for_leaks(N_ITER, usage_before);
}

#[test]
fn memleak_gcra_multi() {
    const N_ITER: usize = 500_000;
    let mut bucket = GCRA::for_capacity(1_000_000).unwrap().build();
    let usage_before = resident_memsize();

    for _i in 0..N_ITER {
        drop(bucket.check_n(2));
    }
    check_for_leaks(N_ITER, usage_before);
}

#[test]
fn memleak_gcra_threaded() {
    const N_ITER: usize = 5_000;
    let bucket = GCRA::for_capacity(1_000_000).unwrap().build();
    let usage_before = resident_memsize();

    for _i in 0..N_ITER {
        let mut bucket = bucket.clone();
        thread::spawn(move || drop(bucket.check())).join().unwrap();
    }
    check_for_leaks(N_ITER, usage_before);
}

#[test]
fn memleak_leakybucket() {
    const N_ITER: usize = 500_000;
    let mut bucket = LeakyBucket::per_second(1_000_000).unwrap();
    let usage_before = resident_memsize();

    for _i in 0..N_ITER {
        drop(bucket.check());
    }
    check_for_leaks(N_ITER, usage_before);
}

#[test]
fn memleak_leakybucket_threaded() {
    const N_ITER: usize = 5_000;
    let bucket = LeakyBucket::per_second(1_000_000).unwrap();
    let usage_before = resident_memsize();

    for _i in 0..N_ITER {
        let mut bucket = bucket.clone();
        thread::spawn(move || drop(bucket.check())).join().unwrap();
    }
    check_for_leaks(N_ITER, usage_before);
}
<|endoftext|>