<commit_before>#![stable(feature = "futures_api", since = "1.36.0")]

//! Asynchronous values.

#[cfg(not(bootstrap))]
use crate::{
    ops::{Generator, GeneratorState},
    pin::Pin,
    ptr::NonNull,
    task::{Context, Poll},
};

mod future;
#[stable(feature = "futures_api", since = "1.36.0")]
pub use self::future::Future;

/// This type is needed because:
///
/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass
///    a raw pointer.
/// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future
///    non-Send/Sync as well, and we don't want that.
///
/// It also simplifies the HIR lowering of `.await`.
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[derive(Debug, Copy, Clone)]
pub struct ResumeTy(NonNull<Context<'static>>);

#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
unsafe impl Send for ResumeTy {}

#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
unsafe impl Sync for ResumeTy {}

/// Wrap a generator in a future.
///
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
// This is `const` to avoid extra errors after we recover from `const async fn`
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[inline]
pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
where
    T: Generator<ResumeTy, Yield = ()>,
{
    struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);

    // We rely on the fact that async/await futures are immovable in order to create
    // self-referential borrows in the underlying generator.
    impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}

    impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
        type Output = T::Return;
        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
            // Safety: Safe because we're !Unpin + !Drop, and this is just a field projection.
            let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };

            // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
            // `.await` lowering will safely cast that back to a `&mut Context`.
            match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
                GeneratorState::Yielded(()) => Poll::Pending,
                GeneratorState::Complete(x) => Poll::Ready(x),
            }
        }
    }

    GenFuture(gen)
}

#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[inline]
pub unsafe fn poll_with_context<F>(f: Pin<&mut F>, mut cx: ResumeTy) -> Poll<F::Output>
where
    F: Future,
{
    F::poll(f, cx.0.as_mut())
}
<commit_msg>Add issue reference<commit_after>#![stable(feature = "futures_api", since = "1.36.0")]

//! Asynchronous values.

#[cfg(not(bootstrap))]
use crate::{
    ops::{Generator, GeneratorState},
    pin::Pin,
    ptr::NonNull,
    task::{Context, Poll},
};

mod future;
#[stable(feature = "futures_api", since = "1.36.0")]
pub use self::future::Future;

/// This type is needed because:
///
/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass
///    a raw pointer (see https://github.com/rust-lang/rust/issues/68923).
/// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future
///    non-Send/Sync as well, and we don't want that.
///
/// It also simplifies the HIR lowering of `.await`.
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[derive(Debug, Copy, Clone)]
pub struct ResumeTy(NonNull<Context<'static>>);

#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
unsafe impl Send for ResumeTy {}

#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
unsafe impl Sync for ResumeTy {}

/// Wrap a generator in a future.
///
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
// This is `const` to avoid extra errors after we recover from `const async fn`
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[inline]
pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
where
    T: Generator<ResumeTy, Yield = ()>,
{
    struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);

    // We rely on the fact that async/await futures are immovable in order to create
    // self-referential borrows in the underlying generator.
    impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}

    impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
        type Output = T::Return;
        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
            // Safety: Safe because we're !Unpin + !Drop, and this is just a field projection.
            let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };

            // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
            // `.await` lowering will safely cast that back to a `&mut Context`.
            match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
                GeneratorState::Yielded(()) => Poll::Pending,
                GeneratorState::Complete(x) => Poll::Ready(x),
            }
        }
    }

    GenFuture(gen)
}

#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[inline]
pub unsafe fn poll_with_context<F>(f: Pin<&mut F>, mut cx: ResumeTy) -> Poll<F::Output>
where
    F: Future,
{
    F::poll(f, cx.0.as_mut())
}
<|endoftext|>


<commit_before>use proc_macro2::{Ident, Span, TokenStream};

use syn;
use try;

pub fn wrap_in_const(
    serde_path: Option<&syn::Path>,
    trait_: &str,
    ty: &Ident,
    code: TokenStream,
) -> TokenStream {
    let try_replacement = try::replacement();

    let dummy_const = Ident::new(
        &format!("_IMPL_{}_FOR_{}", trait_, unraw(ty)),
        Span::call_site(),
    );

    let use_serde = serde_path
        .map(|path| {
            quote! {
                use #path as _serde;
            }
        })
        .unwrap_or_else(|| {
            quote! {
                #[allow(unknown_lints)]
                #[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))]
                #[allow(rust_2018_idioms)]
                extern crate serde as _serde;
            }
        });

    quote! {
        #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
        const #dummy_const: () = {
            #use_serde
            #try_replacement
            #code
        };
    }
}

#[allow(deprecated)]
fn unraw(ident: &Ident) -> String {
    // str::trim_start_matches was added in 1.30, trim_left_matches deprecated
    // in 1.33. We currently support rustc back to 1.15 so we need to continue
    // to use the deprecated one.
    ident.to_string().trim_left_matches("r#").to_owned()
}
<commit_msg>Match on serde_path to handle Some(path) and None<commit_after>use proc_macro2::{Ident, Span, TokenStream};

use syn;
use try;

pub fn wrap_in_const(
    serde_path: Option<&syn::Path>,
    trait_: &str,
    ty: &Ident,
    code: TokenStream,
) -> TokenStream {
    let try_replacement = try::replacement();

    let dummy_const = Ident::new(
        &format!("_IMPL_{}_FOR_{}", trait_, unraw(ty)),
        Span::call_site(),
    );

    let use_serde = match serde_path {
        Some(path) => quote! {
            use #path as _serde;
        },
        None => quote! {
            #[allow(unknown_lints)]
            #[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))]
            #[allow(rust_2018_idioms)]
            extern crate serde as _serde;
        },
    };

    quote! {
        #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
        const #dummy_const: () = {
            #use_serde
            #try_replacement
            #code
        };
    }
}

#[allow(deprecated)]
fn unraw(ident: &Ident) -> String {
    // str::trim_start_matches was added in 1.30, trim_left_matches deprecated
    // in 1.33. We currently support rustc back to 1.15 so we need to continue
    // to use the deprecated one.
    ident.to_string().trim_left_matches("r#").to_owned()
}
<|endoftext|>


<commit_before>#![crate_type = "dylib"]

#[macro_export]
macro_rules! world {
    ($space:ident ($param:ty), $($name:ident : $component:ty,)*) => {
        /// A collection of pointers to components
        #[derive(Clone, Debug, Eq, PartialEq)]
        pub struct Entity {
            $(
            pub $name: Option<$space::Id<$component>>,
            )*
        }

        impl Entity {
            pub fn new() -> Entity {
                Entity {
                    $(
                    $name: None,
                    )*
                }
            }
        }

        /// A collection of component arrays
        pub struct Components {
            $(
            pub $name: $space::Array<$component>,
            )*
        }

        /// Component add_to() wrapper
        pub struct Adder<'d> {
            pub entity: Entity,
            data: &'d mut Components,
        }
        impl<'d> Adder<'d> {
            $(
            pub fn $name(mut self, value: $component) -> Adder<'d> {
                debug_assert!(self.entity.$name.is_none());
                let id = self.data.$name.add(value);
                self.entity.$name = Some(id);
                self
            }
            )*
        }

        impl Components {
            pub fn new() -> Components {
                Components {
                $(
                    $name: $space::Array::new(),
                )*
                }
            }
            pub fn add<'d>(&'d mut self) -> Adder<'d> {
                Adder {entity: Entity::new(), data: self,}
            }
        }

        /// A system responsible for some aspect (physics, rendering, etc)
        pub trait System {
            fn process(&mut self, $param, &mut Components, &mut Vec<Entity>);
        }

        /// A top level union of entities, their data, and systems
        pub struct World {
            pub data: Components,
            pub entities: Vec<Entity>,
            pub systems: Vec<Box<System + Send>>,
        }

        impl World {
            pub fn new() -> World {
                World {
                    data: Components::new(),
                    entities: Vec::new(),
                    systems: Vec::new(),
                }
            }
            pub fn update(&mut self, param: $param) {
                for sys in self.systems.iter_mut() {
                    sys.process(param, &mut self.data, &mut self.entities);
                }
            }
        }
    }
}
<commit_msg>Added World::add_system<commit_after>#![crate_type = "dylib"]

#[macro_export]
macro_rules! world {
    ($space:ident ($param:ty), $($name:ident : $component:ty,)*) => {
        /// A collection of pointers to components
        #[derive(Clone, Debug, Eq, PartialEq)]
        pub struct Entity {
            $(
            pub $name: Option<$space::Id<$component>>,
            )*
        }

        impl Entity {
            pub fn new() -> Entity {
                Entity {
                    $(
                    $name: None,
                    )*
                }
            }
        }

        /// A collection of component arrays
        pub struct Components {
            $(
            pub $name: $space::Array<$component>,
            )*
        }

        /// Component add_to() wrapper
        pub struct Adder<'d> {
            pub entity: Entity,
            data: &'d mut Components,
        }
        impl<'d> Adder<'d> {
            $(
            pub fn $name(mut self, value: $component) -> Adder<'d> {
                debug_assert!(self.entity.$name.is_none());
                let id = self.data.$name.add(value);
                self.entity.$name = Some(id);
                self
            }
            )*
        }

        impl Components {
            pub fn new() -> Components {
                Components {
                $(
                    $name: $space::Array::new(),
                )*
                }
            }
            pub fn add<'d>(&'d mut self) -> Adder<'d> {
                Adder {entity: Entity::new(), data: self,}
            }
        }

        /// A system responsible for some aspect (physics, rendering, etc)
        pub trait System: Send {
            fn process(&mut self, $param, &mut Components, &mut Vec<Entity>);
        }

        /// A top level union of entities, their data, and systems
        pub struct World {
            pub data: Components,
            pub entities: Vec<Entity>,
            pub systems: Vec<Box<System>>,
        }

        impl World {
            pub fn new() -> World {
                World {
                    data: Components::new(),
                    entities: Vec::new(),
                    systems: Vec::new(),
                }
            }

            pub fn add_system<S: System + 'static>(&mut self, system: S) {
                self.systems.push(Box::new(system));
            }

            pub fn update(&mut self, param: $param) {
                for sys in self.systems.iter_mut() {
                    sys.process(param, &mut self.data, &mut self.entities);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

use std::sync::atomic::AtomicUsize;

// Extension trait to add lock elision primitives to atomic types
pub trait AtomicElisionExt {
    type IntType;

    // Perform a compare_exchange and start a transaction
    fn elision_compare_exchange_acquire(
        &self,
        current: Self::IntType,
        new: Self::IntType,
    ) -> Result<Self::IntType, Self::IntType>;

    // Perform a fetch_sub and end a transaction
    fn elision_fetch_sub_release(&self, val: Self::IntType) -> Self::IntType;
}

// Indicates whether the target architecture supports lock elision
#[inline]
pub fn have_elision() -> bool {
    cfg!(all(
        feature = "nightly",
        any(target_arch = "x86", target_arch = "x86_64"),
    ))
}

// This implementation is never actually called because it is guarded by
// have_elision().
#[cfg(not(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64"))))]
impl AtomicElisionExt for AtomicUsize {
    type IntType = usize;

    #[inline]
    fn elision_compare_exchange_acquire(&self, _: usize, _: usize) -> Result<usize, usize> {
        unreachable!();
    }

    #[inline]
    fn elision_fetch_sub_release(&self, _: usize) -> usize {
        unreachable!();
    }
}

#[cfg(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64")))]
impl AtomicElisionExt for AtomicUsize {
    type IntType = usize;

    #[inline]
    fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result<usize, usize> {
        unsafe {
            let prev: usize;
            asm!(
                "xacquire",
                "lock",
                "cmpxchg [{}], {}",
                in(reg) self,
                in(reg) new,
                inout("rax") current => prev,
            );
            if prev == current {
                Ok(prev)
            } else {
                Err(prev)
            }
        }
    }

    #[inline]
    fn elision_fetch_sub_release(&self, val: usize) -> usize {
        unsafe {
            let prev: usize;
            asm!(
                "xrelease",
                "lock",
                "xadd [{}], {}",
                in(reg) self,
                inout(reg) val.wrapping_neg() => prev,
            );
            prev
        }
    }
}
<commit_msg>Use :e registers on x32<commit_after>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

use std::sync::atomic::AtomicUsize;

// Extension trait to add lock elision primitives to atomic types
pub trait AtomicElisionExt {
    type IntType;

    // Perform a compare_exchange and start a transaction
    fn elision_compare_exchange_acquire(
        &self,
        current: Self::IntType,
        new: Self::IntType,
    ) -> Result<Self::IntType, Self::IntType>;

    // Perform a fetch_sub and end a transaction
    fn elision_fetch_sub_release(&self, val: Self::IntType) -> Self::IntType;
}

// Indicates whether the target architecture supports lock elision
#[inline]
pub fn have_elision() -> bool {
    cfg!(all(
        feature = "nightly",
        any(target_arch = "x86", target_arch = "x86_64"),
    ))
}

// This implementation is never actually called because it is guarded by
// have_elision().
#[cfg(not(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64"))))]
impl AtomicElisionExt for AtomicUsize {
    type IntType = usize;

    #[inline]
    fn elision_compare_exchange_acquire(&self, _: usize, _: usize) -> Result<usize, usize> {
        unreachable!();
    }

    #[inline]
    fn elision_fetch_sub_release(&self, _: usize) -> usize {
        unreachable!();
    }
}

#[cfg(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64")))]
impl AtomicElisionExt for AtomicUsize {
    type IntType = usize;

    #[inline]
    fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result<usize, usize> {
        unsafe {
            let prev: usize;
            #[cfg(target_pointer_width = "32")]
            asm!(
                "xacquire",
                "lock",
                "cmpxchg [{:e}], {:e}",
                in(reg) self,
                in(reg) new,
                inout("eax") current => prev,
            );
            #[cfg(target_pointer_width = "64")]
            asm!(
                "xacquire",
                "lock",
                "cmpxchg [{}], {}",
                in(reg) self,
                in(reg) new,
                inout("rax") current => prev,
            );
            if prev == current {
                Ok(prev)
            } else {
                Err(prev)
            }
        }
    }

    #[inline]
    fn elision_fetch_sub_release(&self, val: usize) -> usize {
        unsafe {
            let prev: usize;
            #[cfg(target_pointer_width = "32")]
            asm!(
                "xrelease",
                "lock",
                "xadd [{:e}], {:e}",
                in(reg) self,
                inout(reg) val.wrapping_neg() => prev,
            );
            #[cfg(target_pointer_width = "64")]
            asm!(
                "xrelease",
                "lock",
                "xadd [{}], {}",
                in(reg) self,
                inout(reg) val.wrapping_neg() => prev,
            );
            prev
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;
use std::collections::HashMap;
use std::collections::HashSet;

pub fn main() {
    let mut edges = HashMap::<char, HashSet<char>>::new();
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let numbers = line.chars().collect::<Vec<_>>();
        {
            let set = edges.entry(numbers[0]).or_insert(HashSet::<char>::new());
            set.insert(numbers[1]);
            set.insert(numbers[2]);
        }
        let set = edges.entry(numbers[1]).or_insert(HashSet::<char>::new());
        set.insert(numbers[2]);
    }
    let mut vec: Vec<_> = edges.iter().collect();
    vec.sort_by_key(|&(_, set)| set.len());
    let mut ans = vec.iter().rev().map(|&(&n, _)| n).collect::<String>();
    let (_ ,last) = vec[0];
    for &c in last {
        ans.push(c);
    }
    println!("{}", ans);
}
<commit_msg>fix a syntax typo (caught by rustfmt)<commit_after>use std::io;
use std::io::prelude::*;
use std::collections::HashMap;
use std::collections::HashSet;

pub fn main() {
    let mut edges = HashMap::<char, HashSet<char>>::new();
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let numbers = line.chars().collect::<Vec<_>>();
        {
            let set = edges.entry(numbers[0]).or_insert(HashSet::<char>::new());
            set.insert(numbers[1]);
            set.insert(numbers[2]);
        }
        let set = edges.entry(numbers[1]).or_insert(HashSet::<char>::new());
        set.insert(numbers[2]);
    }
    let mut vec: Vec<_> = edges.iter().collect();
    vec.sort_by_key(|&(_, set)| set.len());
    let mut ans = vec.iter().rev().map(|&(&n, _)| n).collect::<String>();
    let (_, last) = vec[0];
    for &c in last {
        ans.push(c);
    }
    println!("{}", ans);
}
<|endoftext|>


<commit_before>// Frustum extracting and testing algorithm used from
// http://www.racer.nl/reference/vfc_markmorley.htm

#[derive(Debug)]
pub struct Frustum {
    // left right bottom top near and far planes
    planes: [[f32; 4]; 6],
}

impl Frustum {
    pub fn create(&self, modl: &[f32; 16], proj: &[f32; 16]) -> Frustum {
        println!("Extracting frustum");

        // Combine the two matrices (multiply projection by modelview)
        let clip: [f32; 16] =
            [modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] + modl[3] * proj[12],
             modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] + modl[3] * proj[13],
             modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] + modl[3] * proj[14],
             modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] + modl[3] * proj[15],
             modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] + modl[7] * proj[12],
             modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] + modl[7] * proj[13],
             modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] + modl[7] * proj[14],
             modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] + modl[7] * proj[15],
             modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] + modl[11] * proj[12],
             modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] + modl[11] * proj[13],
             modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] + modl[11] * proj[14],
             modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] + modl[11] * proj[15],
             modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] + modl[15] * proj[12],
             modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] + modl[15] * proj[13],
             modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] + modl[15] * proj[14],
             modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] + modl[15] * proj[15]];

        // Extract the numbers for the RIGHT plane

        let rdx: f32 = clip[3] - clip[0];
        let rdy: f32 = clip[7] - clip[4];
        let rdz: f32 = clip[11] - clip[8];
        let rdw: f32 = clip[15] - clip[12];

        // Divisor to normilize right plane
        let rd: f32 = (rdx.powi(2) + rdy.powi(2) + rdz.powi(2)).sqrt();

        // Extract the numbers for the LEFT plane
        let ldx: f32 = clip[3] + clip[0];
        let ldy: f32 = clip[7] + clip[4];
        let ldz: f32 = clip[11] + clip[8];
        let ldw: f32 = clip[15] + clip[12];

        // Divisor to normilize left plane
        let ld: f32 = (ldx.powi(2) + ldy.powi(2) + ldz.powi(2)).sqrt();

        // Extract the BOTTOM plane */
        let bdx: f32 = clip[3] + clip[1];
        let bdy: f32 = clip[7] + clip[5];
        let bdz: f32 = clip[11] + clip[9];
        let bdw: f32 = clip[15] + clip[13];

        // Divisor to normilize bottom plane
        let bd: f32 = (bdx.powi(2) + bdy.powi(2) + bdz.powi(2)).sqrt();

        // Extract the TOP plane */
        let tdx: f32 = clip[3] - clip[1];
        let tdy: f32 = clip[7] - clip[5];
        let tdz: f32 = clip[11] - clip[9];
        let tdw: f32 = clip[15] - clip[13];

        // Divisor to normilize top plane
        let td: f32 = (tdx.powi(2) + tdy.powi(2) + tdz.powi(2)).sqrt();

        // Extract the FAR plane */
        let fdx: f32 = clip[3] - clip[2];
        let fdy: f32 = clip[7] - clip[6];
        let fdz: f32 = clip[11] - clip[10];
        let fdw: f32 = clip[15] - clip[14];

        // Divisor to normilize far plane
        let fd: f32 = (fdx.powi(2) + fdy.powi(2) + fdz.powi(2)).sqrt();

        // Extract the NEAR plane */
        let ndx: f32 = clip[3] + clip[2];
        let ndy: f32 = clip[7] + clip[6];
        let ndz: f32 = clip[11] + clip[10];
        let ndw: f32 = clip[15] + clip[14];

        // Divisor to normilize near plane
        let nd: f32 = (fdx.powi(2) + fdy.powi(2) + fdz.powi(2)).sqrt();

        Frustum {
            planes: [[rdx / rd, rdy / rd, rdz / rd, rdw / rd],
                     [ldx / ld, ldy / ld, ldz / ld, ldw / ld],
                     [bdx / bd, bdy / bd, bdz / bd, bdw / bd],
                     [tdx / td, tdy / td, tdz / td, tdw / td],
                     [fdx / fd, fdy / fd, fdz / fd, fdw / fd],
                     [ndx / nd, ndy / nd, ndz / nd, ndw / nd]],
        }
    }

    pub fn cube_inside(&self, x: f32, y: f32, z: f32, size: f32) -> bool {
        for p in 0..6 {
            if !((self.planes[p][0] * (x - size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32)) {
                return false;
            }
        }
        true
    }

    pub fn point_inside(&self, x: f32, y: f32, z: f32) -> bool {
        for p in 0..6 {
            if self.planes[p][0] * x + self.planes[p][1] * y + self.planes[p][2] * z <= 0.0f32 {
                return false;
            }
        }
        true
    }

    pub fn sphere_inside(&self, x: f32, y: f32, z: f32, r: f32) -> bool {
        for p in 0..6 {
            if (self.planes[p][0] * x + self.planes[p][1] * y + self.planes[p][2] * z) <= -r {
                return false;
            }
        }
        true
    }
}
<commit_msg>Update frustum.rs<commit_after>// Copyright (C) 2016 Chris Liebert

// Frustum extracting and testing algorithm used from
// http://www.racer.nl/reference/vfc_markmorley.htm

#[derive(Debug)]
pub struct Frustum {
    // left right bottom top near and far planes
    planes: [[f32; 4]; 6],
}

impl Frustum {
    pub fn create(&self, modl: &[f32; 16], proj: &[f32; 16]) -> Frustum {
        println!("Extracting frustum");

        // Combine the two matrices (multiply projection by modelview)
        let clip: [f32; 16] =
            [modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] + modl[3] * proj[12],
             modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] + modl[3] * proj[13],
             modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] + modl[3] * proj[14],
             modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] + modl[3] * proj[15],
             modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] + modl[7] * proj[12],
             modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] + modl[7] * proj[13],
             modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] + modl[7] * proj[14],
             modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] + modl[7] * proj[15],
             modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] + modl[11] * proj[12],
             modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] + modl[11] * proj[13],
             modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] + modl[11] * proj[14],
             modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] + modl[11] * proj[15],
             modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] + modl[15] * proj[12],
             modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] + modl[15] * proj[13],
             modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] + modl[15] * proj[14],
             modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] + modl[15] * proj[15]];

        // Extract the numbers for the RIGHT plane

        let rdx: f32 = clip[3] - clip[0];
        let rdy: f32 = clip[7] - clip[4];
        let rdz: f32 = clip[11] - clip[8];
        let rdw: f32 = clip[15] - clip[12];

        // Divisor to normilize right plane
        let rd: f32 = (rdx.powi(2) + rdy.powi(2) + rdz.powi(2)).sqrt();

        // Extract the numbers for the LEFT plane
        let ldx: f32 = clip[3] + clip[0];
        let ldy: f32 = clip[7] + clip[4];
        let ldz: f32 = clip[11] + clip[8];
        let ldw: f32 = clip[15] + clip[12];

        // Divisor to normilize left plane
        let ld: f32 = (ldx.powi(2) + ldy.powi(2) + ldz.powi(2)).sqrt();

        // Extract the BOTTOM plane */
        let bdx: f32 = clip[3] + clip[1];
        let bdy: f32 = clip[7] + clip[5];
        let bdz: f32 = clip[11] + clip[9];
        let bdw: f32 = clip[15] + clip[13];

        // Divisor to normilize bottom plane
        let bd: f32 = (bdx.powi(2) + bdy.powi(2) + bdz.powi(2)).sqrt();

        // Extract the TOP plane */
        let tdx: f32 = clip[3] - clip[1];
        let tdy: f32 = clip[7] - clip[5];
        let tdz: f32 = clip[11] - clip[9];
        let tdw: f32 = clip[15] - clip[13];

        // Divisor to normilize top plane
        let td: f32 = (tdx.powi(2) + tdy.powi(2) + tdz.powi(2)).sqrt();

        // Extract the FAR plane */
        let fdx: f32 = clip[3] - clip[2];
        let fdy: f32 = clip[7] - clip[6];
        let fdz: f32 = clip[11] - clip[10];
        let fdw: f32 = clip[15] - clip[14];

        // Divisor to normilize far plane
        let fd: f32 = (fdx.powi(2) + fdy.powi(2) + fdz.powi(2)).sqrt();

        // Extract the NEAR plane */
        let ndx: f32 = clip[3] + clip[2];
        let ndy: f32 = clip[7] + clip[6];
        let ndz: f32 = clip[11] + clip[10];
        let ndw: f32 = clip[15] + clip[14];

        // Divisor to normilize near plane
        let nd: f32 = (fdx.powi(2) + fdy.powi(2) + fdz.powi(2)).sqrt();

        Frustum {
            planes: [[rdx / rd, rdy / rd, rdz / rd, rdw / rd],
                     [ldx / ld, ldy / ld, ldz / ld, ldw / ld],
                     [bdx / bd, bdy / bd, bdz / bd, bdw / bd],
                     [tdx / td, tdy / td, tdz / td, tdw / td],
                     [fdx / fd, fdy / fd, fdz / fd, fdw / fd],
                     [ndx / nd, ndy / nd, ndz / nd, ndw / nd]],
        }
    }

    pub fn cube_inside(&self, x: f32, y: f32, z: f32, size: f32) -> bool {
        for p in 0..6 {
            if !((self.planes[p][0] * (x - size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z - size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y - size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x - size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32) ||
                 (self.planes[p][0] * (x + size) + self.planes[p][1] * (y + size) + self.planes[p][2] * (z + size) + self.planes[p][3] > 0.0f32)) {
                return false;
            }
        }
        true
    }

    pub fn point_inside(&self, x: f32, y: f32, z: f32) -> bool {
        for p in 0..6 {
            if self.planes[p][0] * x + self.planes[p][1] * y + self.planes[p][2] * z <= 0.0f32 {
                return false;
            }
        }
        true
    }

    pub fn sphere_inside(&self, x: f32, y: f32, z: f32, r: f32) -> bool {
        for p in 0..6 {
            if (self.planes[p][0] * x + self.planes[p][1] * y + self.planes[p][2] * z) <= -r {
                return false;
            }
        }
        true
    }
}
<|endoftext|>


<commit_before>// pest. Smart PEGs in Rust
// Copyright (C) 2016  Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

/// A `macro` that defines each rule as a method on a `Parser`.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate pest;
/// # use pest::Input;
/// # use pest::StringInput;
/// # use pest::Rdp;
///
/// # fn main() {
/// impl_rdp!(MyRdp);
///
/// impl MyRdp {
///     grammar! {
///         exp = { paren ~ exp | [""] }
///         paren = { ["("] ~ exp ~ [")"] }
///     }
/// }
///
/// let mut parser = MyRdp::new(Box::new(StringInput::new("(())((())())()")));
///
/// assert!(parser.exp());
/// assert!(parser.end());
/// # }
/// ```
#[macro_export]
macro_rules! grammar {
    // handle parens
    ( @conv $slf:ident [ ( $( $head:tt )* ) $( $tail:tt )* ] [ $( $optail:tt )* ]
      [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ $( $head )* @rp $( $tail )* ] [ @lp $( $optail )* ]
                 [ $( $output )* ])
    };
    ( @conv $slf:ident [ @rp $( $tail:tt )* ] [ @lp $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ $( $tail )* ] [ $( $optail )* ] [ $( $output )* ])
    };
    ( @conv $slf:ident [ @rp $( $tail:tt )* ] [ $op:tt $( $optail:tt )* ]
      [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ @rp $( $tail )* ] [ $( $optail )* ] [ $( $output )* $op ])
    };

    // handle operands
    ( @conv $slf:ident [ ~ $( $tail:tt )* ] [ ~ $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ ~ $( $tail )* ] [ $( $optail )* ] [ $( $output )* ~ ])
    };
    ( @conv $slf:ident [ ~ $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt) => {
        grammar!(@conv $slf [ $( $tail )* ] [ ~ $( $optail )* ] $output)
    };
    ( @conv $slf:ident [ | $( $tail:tt )* ] [ ~ $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ | $( $tail )* ] [ $( $optail )* ] [ $( $output )* ~ ])
    };
    ( @conv $slf:ident [ | $( $tail:tt )* ] [ | $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ | $( $tail )* ] [ $( $optail )* ] [ $( $output )* | ])
    };
    ( @conv $slf:ident [ | $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt) => {
        grammar!(@conv $slf [ $( $tail )* ] [ | $( $optail )* ] $output)
    };

    // handle everything else
    ( @conv $slf:ident [ $head:tt $( $tail:tt )* ] $ops:tt [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ $( $tail )* ] $ops [ $( $output )* $head ])
    };

    // output remaining operators
    ( @conv $slf:ident [] [] [ $( $output:tt )* ] ) => {
        grammar!(@process $slf [] [ $( $output )* ])
    };
    ( @conv $slf:ident [] [ $op:tt $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [] [ $( $optail )* ] [ $( $output )* $op ])
    };

    // match
    ( @mtc $slf:ident (( $exp:expr )) ) => (($exp));
    ( @mtc $slf:ident [ $str:expr ]) => ($slf.matches($str));
    ( @mtc $slf:ident $rule:ident) => ($slf.$rule());

    // process postfix
    ( @process $_slf:ident [( $result:expr )] [] ) => ($result);
    ( @process $slf:ident [ $b:tt $a:tt $( $tail:tt )* ] [ ~ $( $optail:tt )* ] ) => {
        {
            let result = $slf.try(Box::new(move |parser| {
                grammar!(@mtc parser $a) && grammar!(@mtc parser $b)
            }));

            grammar!(@process $slf [(( result )) $( $tail )* ] [ $( $optail )* ])
        }
    };
    ( @process $slf:ident [ $b:tt $a:tt $( $tail:tt )* ] [ | $( $optail:tt )* ] ) => {
        {
            let result = grammar!(@mtc $slf $a) || grammar!(@mtc $slf $b);

            grammar!(@process $slf [(( result )) $( $tail )* ] [ $( $optail )* ])
        }
    };
    ( @process $slf:ident [ $a:tt $( $tail:tt )* ] [ * $( $optail:tt )* ] ) => {
        {
            let result = {
                loop {
                    if !grammar!(@mtc $slf $a) {
                        break
                    }
                }

                true
            };

            grammar!(@process $slf [(( result )) $( $tail )* ] [ $( $optail )* ])
        }
    };
    ( @process $slf:ident [ $a:tt $( $tail:tt )* ] [ + $( $optail:tt )* ] ) => {
        {
            let result = if grammar!(@mtc $slf $a) {
                loop {
                    if !grammar!(@mtc $slf $a) {
                        break
                    }
                }

                true
            } else {
                false
            };

            grammar!(@process $slf [(( result )) $( $tail )* ] [ $( $optail )* ])
        }
    };
    ( @process $slf:ident [] [ $single:tt ] ) => {
        grammar!(@mtc $slf $single)
    };
    ( @process $slf:ident [ $( $optail:tt )* ] [ $head:tt $( $tail:tt )* ] ) => {
        grammar!(@process $slf [ $head $( $optail )* ] [ $( $tail )* ])
    };

    ( $( $name:ident = { $( $ts:tt )* } )* ) => {
        $(
            #[allow(unused_parens)]
            #[allow(unused_variables)]
            pub fn $name(&mut self) -> bool {
                grammar!(@conv self [ $( $ts )* ] [] [])
            }
        )*
    };
}

#[cfg(test)]
mod tests {
    use super::super::Rdp;
    use super::super::Parser;
    use super::super::Input;
    use super::super::StringInput;

    impl_rdp!(MyRdp);

    impl MyRdp {
        grammar! {
            exp = { paren ~ exp | [""] }
            paren = { ["("] ~ exp ~ [")"] }
            rep_zero = { ["a"]* }
            rep_one = { ["a"]+ }
        }
    }

    #[test]
    fn basic() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("(())((())())()")));

        assert!(parser.exp());
        assert!(parser.end());
    }

    #[test]
    fn fail() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("(())((())())(")));

        assert!(parser.exp());
        assert!(!parser.end());
    }

    #[test]
    fn rep_zero_empty() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("")));

        assert!(parser.rep_zero());
        assert!(parser.end());
    }

    #[test]
    fn rep_zero_long() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("aaaa")));

        assert!(parser.rep_zero());
        assert!(parser.end());
    }

    #[test]
    fn rep_zero_wrong() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("aaaab")));

        assert!(parser.rep_zero());
        assert!(!parser.end());
    }

    #[test]
    fn rep_one_empty() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("")));

        assert!(!parser.rep_one());
    }

    #[test]
    fn rep_one_long() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("aaaa")));

        assert!(parser.rep_one());
        assert!(parser.end());
    }

    #[test]
    fn rep_one_wrong() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("b")));

        assert!(!parser.rep_one());
        assert!(!parser.end());
    }
}
<commit_msg>Added optional rule. Fixes #4.<commit_after>// pest. Smart PEGs in Rust
// Copyright (C) 2016  Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

/// A `macro` that defines each rule as a method on a `Parser`.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate pest;
/// # use pest::Input;
/// # use pest::StringInput;
/// # use pest::Rdp;
///
/// # fn main() {
/// impl_rdp!(MyRdp);
///
/// impl MyRdp {
///     grammar! {
///         exp = { paren ~ exp | [""] }
///         paren = { ["("] ~ exp ~ [")"] }
///     }
/// }
///
/// let mut parser = MyRdp::new(Box::new(StringInput::new("(())((())())()")));
///
/// assert!(parser.exp());
/// assert!(parser.end());
/// # }
/// ```
#[macro_export]
macro_rules! grammar {
    // handle parens
    ( @conv $slf:ident [ ( $( $head:tt )* ) $( $tail:tt )* ] [ $( $optail:tt )* ]
      [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ $( $head )* @rp $( $tail )* ] [ @lp $( $optail )* ]
                 [ $( $output )* ])
    };
    ( @conv $slf:ident [ @rp $( $tail:tt )* ] [ @lp $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ $( $tail )* ] [ $( $optail )* ] [ $( $output )* ])
    };
    ( @conv $slf:ident [ @rp $( $tail:tt )* ] [ $op:tt $( $optail:tt )* ]
      [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ @rp $( $tail )* ] [ $( $optail )* ] [ $( $output )* $op ])
    };

    // handle operands
    ( @conv $slf:ident [ ~ $( $tail:tt )* ] [ ~ $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ ~ $( $tail )* ] [ $( $optail )* ] [ $( $output )* ~ ])
    };
    ( @conv $slf:ident [ ~ $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt) => {
        grammar!(@conv $slf [ $( $tail )* ] [ ~ $( $optail )* ] $output)
    };
    ( @conv $slf:ident [ | $( $tail:tt )* ] [ ~ $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ | $( $tail )* ] [ $( $optail )* ] [ $( $output )* ~ ])
    };
    ( @conv $slf:ident [ | $( $tail:tt )* ] [ | $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ | $( $tail )* ] [ $( $optail )* ] [ $( $output )* | ])
    };
    ( @conv $slf:ident [ | $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt) => {
        grammar!(@conv $slf [ $( $tail )* ] [ | $( $optail )* ] $output)
    };

    // handle everything else
    ( @conv $slf:ident [ $head:tt $( $tail:tt )* ] $ops:tt [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [ $( $tail )* ] $ops [ $( $output )* $head ])
    };

    // output remaining operators
    ( @conv $slf:ident [] [] [ $( $output:tt )* ] ) => {
        grammar!(@process $slf [] [ $( $output )* ])
    };
    ( @conv $slf:ident [] [ $op:tt $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
        grammar!(@conv $slf [] [ $( $optail )* ] [ $( $output )* $op ])
    };

    // match
    ( @mtc $slf:ident (( $exp:expr )) ) => (($exp));
    ( @mtc $slf:ident [ $str:expr ]) => ($slf.matches($str));
    ( @mtc $slf:ident $rule:ident) => ($slf.$rule());

    // process postfix
    ( @process $_slf:ident [( $result:expr )] [] ) => ($result);
    ( @process $slf:ident [ $b:tt $a:tt $( $tail:tt )* ] [ ~ $( $optail:tt )* ] ) => {
        {
            let result = $slf.try(Box::new(move |parser| {
                grammar!(@mtc parser $a) && grammar!(@mtc parser $b)
            }));

            grammar!(@process $slf [(( result )) $( $tail )* ] [ $( $optail )* ])
        }
    };
    ( @process $slf:ident [ $b:tt $a:tt $( $tail:tt )* ] [ | $( $optail:tt )* ] ) => {
        {
            let result = grammar!(@mtc $slf $a) || grammar!(@mtc $slf $b);

            grammar!(@process $slf [(( result )) $( $tail )* ] [ $( $optail )* ])
        }
    };
    ( @process $slf:ident [ $a:tt $( $tail:tt )* ] [ * $( $optail:tt )* ] ) => {
        {
            let result = {
                loop {
                    if !grammar!(@mtc $slf $a) {
                        break
                    }
                }

                true
            };

            grammar!(@process $slf [(( result )) $( $tail )* ] [ $( $optail )* ])
        }
    };
    ( @process $slf:ident [ $a:tt $( $tail:tt )* ] [ + $( $optail:tt )* ] ) => {
        {
            let result = if grammar!(@mtc $slf $a) {
                loop {
                    if !grammar!(@mtc $slf $a) {
                        break
                    }
                }

                true
            } else {
                false
            };

            grammar!(@process $slf [(( result )) $( $tail )* ] [ $( $optail )* ])
        }
    };
    ( @process $slf:ident [ $a:tt $( $tail:tt )* ] [ ? $( $optail:tt )* ] ) => {
        {
            let result = {
                grammar!(@mtc $slf $a);

                true
            };

            grammar!(@process $slf [(( result )) $( $tail )* ] [ $( $optail )* ])
        }
    };
    ( @process $slf:ident [] [ $single:tt ] ) => {
        grammar!(@mtc $slf $single)
    };
    ( @process $slf:ident [ $( $optail:tt )* ] [ $head:tt $( $tail:tt )* ] ) => {
        grammar!(@process $slf [ $head $( $optail )* ] [ $( $tail )* ])
    };

    ( $( $name:ident = { $( $ts:tt )* } )* ) => {
        $(
            #[allow(unused_parens)]
            #[allow(unused_variables)]
            pub fn $name(&mut self) -> bool {
                grammar!(@conv self [ $( $ts )* ] [] [])
            }
        )*
    };
}

#[cfg(test)]
mod tests {
    use super::super::Rdp;
    use super::super::Parser;
    use super::super::Input;
    use super::super::StringInput;

    impl_rdp!(MyRdp);

    impl MyRdp {
        grammar! {
            exp = { paren ~ exp | [""] }
            paren = { ["("] ~ exp ~ [")"] }
            rep_zero = { ["a"]* }
            rep_one = { ["a"]+ }
            opt = { ["a"]? }
        }
    }

    #[test]
    fn basic() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("(())((())())()")));

        assert!(parser.exp());
        assert!(parser.end());
    }

    #[test]
    fn fail() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("(())((())())(")));

        assert!(parser.exp());
        assert!(!parser.end());
    }

    #[test]
    fn rep_zero_empty() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("")));

        assert!(parser.rep_zero());
        assert!(parser.end());
    }

    #[test]
    fn rep_zero_long() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("aaaa")));

        assert!(parser.rep_zero());
        assert!(parser.end());
    }

    #[test]
    fn rep_zero_wrong() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("aaaab")));

        assert!(parser.rep_zero());
        assert!(!parser.end());
    }

    #[test]
    fn rep_one_empty() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("")));

        assert!(!parser.rep_one());
    }

    #[test]
    fn rep_one_long() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("aaaa")));

        assert!(parser.rep_one());
        assert!(parser.end());
    }

    #[test]
    fn rep_one_wrong() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("b")));

        assert!(!parser.rep_one());
        assert!(!parser.end());
    }

    #[test]
    fn opt_empty() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("")));

        assert!(parser.opt());
        assert!(parser.end());
    }

    #[test]
    fn opt_right() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("a")));

        assert!(parser.opt());
        assert!(parser.end());
    }

    #[test]
    fn opt_wrong() {
        let mut parser = MyRdp::new(Box::new(StringInput::new("b")));

        assert!(parser.opt());
        assert!(!parser.end());
    }
}
<|endoftext|>


<commit_before>use super::RawLink;

use core::mem;

const MIN_ALIGN: usize = 4096;

pub struct Free { next: RawLink<Free> }

pub struct FreeList<'a> {
    /// A pointer to the head of the free list
    head: Option<&'a mut Free>
  , /// Number of blocks in the free list
    pub length: usize
}

impl<'a> FreeList<'a> {

    /// Create a new empty `FreeList`
    const fn new() -> FreeList<'a> {
        FreeList { head: None, length: 0 }
    }

    /// Push a new block onto the free list
    ///
    /// # Unsafe due to
    ///   - `mem::transmute()`
    ///   - Dereferencing a raw pointer
    unsafe fn push(&mut self, block: *mut u8) {
        let block_ptr = block as *mut Free;
        // be nice if rawlink was kinder to pattern-matching but whatever
        *block_ptr = if let Some(head) = self.head.take() {
            Free { next: RawLink::some(head) }
        } else {
            Free { next: RawLink::none() }
        };
        self.head = Some(mem::transmute(block_ptr));
        self.length += 1;
    }
    /// Pop the head block off of the free list.
    ///
    /// # Returns
    ///   - `Some(*mut u8)` if the free list has blocks left
    ///   - `None` if the free list is empty
    ///
    /// # Unsafe due to
    ///   - `mem::transmute()`
    ///   - Dereferencing a raw pointer
    unsafe fn pop(&mut self) -> Option<*mut u8> {
        self.head.take()
            .map(|head| {
                let popped_block
                    = mem::replace(&mut self.head, head.next.resolve_mut());
                let block_ptr: *mut u8
                    = mem::transmute(popped_block);
                block_ptr
            })
    }

    fn iter<'b>(&'b self) -> FreeListIter<'b> {
        // FreeListIter { current: self.head.map(|c| c.borrow())
        //                             .as_ref()
        //              }
        match self.head {
            Some(ref head) => FreeListIter { current: Some(head) }
          , None           => FreeListIter { current: None }
        }
        // unimplemented!()
    }

    fn iter_mut<'b>(&'b mut self) -> FreeListIterMut<'b> {
        // FreeListIterMut { current: self.head.map(|c| *c ).as_mut() }
        match self.head {
            Some(ref mut head) => FreeListIterMut { current: Some(head) }
          , None               => FreeListIterMut { current: None }
        }
    }
}

struct FreeListIter<'a> {
    current: Option<&'a Free>
}

impl<'a> Iterator for FreeListIter<'a> {
    type Item = &'a Free;

    fn next(&mut self) -> Option<&'a Free> {
        self.current
            .map(|c| {
                self.current = unsafe { c.next.resolve() };
                c
            })
    }
}

struct FreeListIterMut<'a> {
    current: Option<&'a mut Free>
}

impl<'a> Iterator for FreeListIterMut<'a> {
    type Item = &'a mut Free;

    fn next(&mut self) -> Option<&'a mut Free> {
        self.current.take()
            .map(|c| {
                self.current = unsafe { c.next.resolve_mut() };
                c
            })
    }
}

pub struct BuddyHeapAllocator<'a> {
    /// Address of the base of the heap. This must be aligned
    /// on a `MIN_ALIGN` boundary.
    start_addr: *mut u8
  , /// The allocator's free list
    free_lists: &'a mut [FreeList<'a>]
  , /// Number of blocks in the heap (must be a power of 2)
    heap_size: usize
  , /// Minimum block size
    min_block_size: usize
}

impl<'a> BuddyHeapAllocator<'a> {
    pub unsafe fn new( start_addr: *mut u8
                     , free_lists: &'a mut [FreeList<'a>]
                     , heap_size: usize)
                     -> BuddyHeapAllocator<'a>
    {
        let n_free_lists = free_lists.len();

        assert!( !start_addr.is_null()
                , "Heap start address cannot be null." );
        assert!( n_free_lists > 0
               , "Allocator must have at least one free list.");
        assert!( start_addr as usize & (MIN_ALIGN-1) == 0
               , "Heap start address must be aligned on a 4k boundary.");

        let min_block_size = heap_size >> (n_free_lists - 1);

        assert!( heap_size >= min_block_size
               , "Heap must be large enough to contain at least one block.");
        assert!( min_block_size >= mem::size_of::<Free>()
               , "Minimum block size must be large enough to contain \
                  the free block header.");

        let mut heap
            = BuddyHeapAllocator { start_addr: start_addr
                                 , free_lists: free_lists
                                 , heap_size: heap_size
                                 , min_block_size: min_block_size
                                 };
        // TODO: put first head block on appropriately-sized freelist
        heap
    }
}
<commit_msg>Free list iterators actually work now?<commit_after>use super::RawLink;

use core::mem;

const MIN_ALIGN: usize = 4096;

pub struct Free { next: RawLink<Free> }

pub struct FreeList<'a> {
    /// A pointer to the head of the free list
    head: Option<&'a mut Free>
  , /// Number of blocks in the free list
    pub length: usize
}

impl<'a> FreeList<'a> {

    /// Create a new empty `FreeList`
    const fn new() -> FreeList<'a> {
        FreeList { head: None, length: 0 }
    }

    /// Push a new block onto the free list
    ///
    /// # Unsafe due to
    ///   - `mem::transmute()`
    ///   - Dereferencing a raw pointer
    unsafe fn push(&mut self, block: *mut u8) {
        let block_ptr = block as *mut Free;
        // be nice if rawlink was kinder to pattern-matching but whatever
        *block_ptr = if let Some(head) = self.head.take() {
            Free { next: RawLink::some(head) }
        } else {
            Free { next: RawLink::none() }
        };
        self.head = Some(mem::transmute(block_ptr));
        self.length += 1;
    }
    /// Pop the head block off of the free list.
    ///
    /// # Returns
    ///   - `Some(*mut u8)` if the free list has blocks left
    ///   - `None` if the free list is empty
    ///
    /// # Unsafe due to
    ///   - `mem::transmute()`
    ///   - Dereferencing a raw pointer
    unsafe fn pop(&mut self) -> Option<*mut u8> {
        self.head.take()
            .map(|head| {
                let popped_block
                    = mem::replace(&mut self.head, head.next.resolve_mut());
                let block_ptr: *mut u8
                    = mem::transmute(popped_block);
                block_ptr
            })
    }

    /// Attempt to remove a block from the free list.
    ///
    /// This function searches the free list for the specified block, and
    /// removes it if it is found, returning whether or not the block was
    /// removed.
    ///
    /// This is quite slow; with a worst-case time complexity of O(log n),
    /// this function is a major bottleneck in our allocator implementation.
    /// By maintaining sorted free lists, we could perhaps improve performance
    /// somewhat.
    ///
    /// # Returns
    ///   - `true` if the block was removed from the free list
    ///   - `false` if the block was not present in the free list
    unsafe fn remove(&mut self, target_block: *mut u8) -> bool {
        let target_ptr = target_block as *mut Free;
        for block in self.iter_mut() {
            let block_ptr: *mut Free = block;
            if block_ptr == target_ptr {
                *block_ptr = Free { next: block.next.take() };
                return true;
            }
        }
        false
    }

    /// Returns an iterator over the blocks in this free list
    fn iter<'b>(&'b self) -> FreeListIter<'b> {
        // FreeListIter { current: self.head.map(|c| c.borrow())
        //                             .as_ref()
        //              }
        match self.head {
            Some(ref head) => FreeListIter { current: Some(head) }
          , None           => FreeListIter { current: None }
        }
        // unimplemented!()
    }

    /// Returns a mutable iterator over the blocks in this free list.
    fn iter_mut<'b>(&'b mut self) -> FreeListIterMut<'b> {
        // FreeListIterMut { current: self.head.map(|c| *c ).as_mut() }
        match self.head {
            Some(ref mut head) => FreeListIterMut { current: Some(head) }
          , None               => FreeListIterMut { current: None }
        }
    }
}

struct FreeListIter<'a> {
    current: Option<&'a Free>
}

impl<'a> Iterator for FreeListIter<'a> {
    type Item = &'a Free;

    fn next(&mut self) -> Option<&'a Free> {
        self.current
            .map(|c| {
                self.current = unsafe { c.next.resolve() };
                c
            })
    }
}

struct FreeListIterMut<'a> {
    current: Option<&'a mut Free>
}

impl<'a> Iterator for FreeListIterMut<'a> {
    type Item = &'a mut Free;

    fn next(&mut self) -> Option<&'a mut Free> {
        self.current.take()
            .map(|c| {
                self.current = unsafe { c.next.resolve_mut() };
                c
            })
    }
}

pub struct BuddyHeapAllocator<'a> {
    /// Address of the base of the heap. This must be aligned
    /// on a `MIN_ALIGN` boundary.
    start_addr: *mut u8
  , /// The allocator's free list
    free_lists: &'a mut [FreeList<'a>]
  , /// Number of blocks in the heap (must be a power of 2)
    heap_size: usize
  , /// Minimum block size
    min_block_size: usize
}

impl<'a> BuddyHeapAllocator<'a> {
    pub unsafe fn new( start_addr: *mut u8
                     , free_lists: &'a mut [FreeList<'a>]
                     , heap_size: usize)
                     -> BuddyHeapAllocator<'a>
    {
        let n_free_lists = free_lists.len();

        assert!( !start_addr.is_null()
                , "Heap start address cannot be null." );
        assert!( n_free_lists > 0
               , "Allocator must have at least one free list.");
        assert!( start_addr as usize & (MIN_ALIGN-1) == 0
               , "Heap start address must be aligned on a 4k boundary.");

        let min_block_size = heap_size >> (n_free_lists - 1);

        assert!( heap_size >= min_block_size
               , "Heap must be large enough to contain at least one block.");
        assert!( min_block_size >= mem::size_of::<Free>()
               , "Minimum block size must be large enough to contain \
                  the free block header.");

        let mut heap
            = BuddyHeapAllocator { start_addr: start_addr
                                 , free_lists: free_lists
                                 , heap_size: heap_size
                                 , min_block_size: min_block_size
                                 };
        // TODO: put first head block on appropriately-sized freelist
        heap
    }
}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

pub use self::rt::{
	init,
	main,
	main_quit,
	main_level,
	main_iteration,
	main_iteration_do
};

pub use self::widgets::{
	Window,
	Label,
	Button,
	_Box,
	ButtonBox,
	Frame,
	AspectFrame,
	Fixed,
	Separator,
	FontButton,
	ToggleButton,
	CheckButton,
	MenuButton,
	ColorButton,
	LinkButton,
	Adjustment,
	ScaleButton,
	VolumeButton,
	Grid,
	EntryBuffer,
	Entry,
	SearchEntry,
	Switch,
	Scale,
	LevelBar,
	SearchBar,
	SpinButton,
	Spinner,
	Image,
	ProgressBar,
	Arrow,
	Calendar,
	Alignment,
	Expander,
	Paned,
	InfoBar,
	Toolbar,
	ToolItem,
	SeparatorToolItem,
	ToolButton,
	ToggleToolButton,
	MenuToolButton
};

pub use self::enums::{
	WindowType,
	TextDirection,
	WindowPosition,
	ButtonBoxStyle,
	Orientation,
	DirectionType,
	CornerType,
	ResizeMode,
	BorderStyle,
	SortType,
	StateFlags,
	DragResult,
	AccelFlags,
	ArrowPlacement,
	ArrowType,
	AttachOptions,
	DeleteType,
	ExpanderStyle,
	IMPreeditStyle,
	IMStatusStyle,
	Justification,
	MovementStep,
	PackType,
	PathPriorityType,
	PathType,
	PolicyType,
	PositionType,
	ReliefStyle,
	ScrollStep,
	ScrollType,
	SelectionMode,
	ShadowType,
	StateType,
	ToolbarStyle,
	JunctionSides,
	RegionFlags,
	IconSize,
	EntryIconPosition,
	InputHints,
	InputPurpose,
	ImageType,
	SpinType,
	SpinButtonUpdatePolicy,
	LevelBarMode,
	CalendarDisplayOptions,
	MessageType
};

pub use self::types::{
	Tooltip,
	WidgetHelpType
};

pub mod cast;
pub mod version;
pub mod traits;
pub mod signals;

mod rt;
mod widgets;
mod enums;
mod types;<commit_msg>Temporary enum reexport fix<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

pub use self::rt::{
	init,
	main,
	main_quit,
	main_level,
	main_iteration,
	main_iteration_do
};

pub use self::widgets::{
	Window,
	Label,
	Button,
	_Box,
	ButtonBox,
	Frame,
	AspectFrame,
	Fixed,
	Separator,
	FontButton,
	ToggleButton,
	CheckButton,
	MenuButton,
	ColorButton,
	LinkButton,
	Adjustment,
	ScaleButton,
	VolumeButton,
	Grid,
	EntryBuffer,
	Entry,
	SearchEntry,
	Switch,
	Scale,
	LevelBar,
	SearchBar,
	SpinButton,
	Spinner,
	Image,
	ProgressBar,
	Arrow,
	Calendar,
	Alignment,
	Expander,
	Paned,
	InfoBar,
	Toolbar,
	ToolItem,
	SeparatorToolItem,
	ToolButton,
	ToggleToolButton,
	MenuToolButton
};

pub use self::enums::{
	WindowType,
	WindowTopLevel,
	WindowPopUp,
	TextDirection,
	TextDirNone,
	TextDirLtr,
	TextDirRtl,
	WindowPosition,
	WinPosNone,
	WinPosCenter,
	WinPosMouse,
	WinPosCenterAlways,
	WinPosCenterOnParent,
	ButtonBoxStyle,
	ButtonBoxSpread,
	ButtonBoxEdge,
	ButtonBoxStart,
	ButtonBoxEnd,
	ButtonBoxCenter,
	Orientation,
	OrientationHorizontal,
	OrientationVertical,
	DirectionType,
	DirTabForward,
	DirTabBackward,
	DirUp,
	DirDown,
	DirLeft,
	DirRight,
	CornerType,
	CornerTopLeft,
	CornerBottomLeft,
	CornerTopRight,
	CornerBottomRight,
	ResizeMode,
	ResizeParent,
	ResizeQueue,
	OrientationtkResizeImmediate,
	BorderStyle,
	BorderStyleNone,
	BorderStyleSolid,
	BorderStyleInset,
	BorderStyleOutset,
	BorderStyleHidden,
	BorderStyleDotted,
	BorderStyleDashed,
	BorderStyleDouble,
	BorderStyleGroove,
	BorderStyleRidge,
	SortType,
	SortAscending,
	SortDescending,
	StateFlags,
	StateFlagNormal,
	StateFlagActive,
	StateFlagPrelight,
	StateFlagSelected,
	StateFlagInsensitive,
	StateFlagInconsistent,
	StateFlagFocused,
	StateFlagBackDrop,
	StateFlagDirLTR,
	StateFlagDirRTL,
	DragResult,
	DragResultSuccess,
	DragResultNoTarget,
	DragResultUserCanceled,
	DragResultTimeoutExpired,
	DragResultGrabBroken,
	DragResultError,
	AccelFlags,
	AccelVisible,
	AccelLocked,
	AccelMask,
	ArrowPlacement,
	ArrowsBoth,
	ArrowsStart,
	ArrowsEnd,
	ArrowType,
	ArrowUp,
	ArrowDown,
	ArrowLeft,
	ArrowRight,
	ArrowNone,
	AttachOptions,
	Expand,
	Shrink,
	Fill,
	DeleteType,
	DeleteChars,
	DeleteWordsEnd,
	DeleteWords,
	DeleteDisplayLines,
	DeleteDisplayLineEnd,
	DeleteParagraphEnds,
	DeleteParagraphs,
	DeleteWhitespac,
	ExpanderStyle,
	ExpanderCollapsed,
	ExpanderSemiCollapsed,
	ExpanderSemiExpanded,
	GGtkExpanderExpanded,
	IMPreeditStyle,
	ImPreeditNothing,
	ImPreeditCallback,
	ImPreeditNone,
	IMStatusStyle,
	ImStatusNothing,
	ImStatusCallback,
	ImStatusNone,
	Justification,
	JustifyLeft,
	JustifyRight,
	JustifyCenter,
	JustifyFill,
	MovementStep,
	MovementLogicalPosition,
	MovementVisualPositions,
	MovementWords,
	MovementDisplayLines,
	MovementDisplayLineEnds,
	MovementParagraphs,
	MovementParagraphEnds,
	MovementPages,
	MovementBufferEnds,
	MovementHorizontalPages,
	PackType,
	PackStart,
	PackEnd,
	PathPriorityType,
	PathPrioLowest,
	PathPrioGtk,
	PathPrioApplication,
	PathPrioTheme,
	PathPrioRc,
	PathPrioHighest,
	PathType,
	PathWidget,
	PathWidgetClass,
	PathClass,
	PolicyType,
	PolicyAlways,
	PolicyAutomatic,
	PolicyNever,
	PositionType,
	PosLeft,
	PosRight,
	PosTop,
	PosBottom,
	ReliefStyle,
	GTkReliefNormal,
	GTkReliefHalf,
	GTkReliefNone,
	ScrollStep,
	ScrollSteps,
	ScrollPages,
	ScrollEnds,
	ScrollHorizontalSteps,
	ScrollHorizontalPages,
	ScrollHorizontalEnds,
	ScrollType,
	ScrollNone,
	ScrollJump,
	ScrollStepBackward,
	ScrollStepForward,
	ScrollPageBackward,
	ScrollPageForward,
	ScrollStepUp,
	ScrollStepDown,
	ScrollPageUp,
	ScrollPageDown,
	ScrollStepLeft,
	ScrollStepRight,
	ScrollPageLeft,
	ScrollPageRight,
	ScrollStart,
	ScrollEnd,
	SelectionMode,
	SelectionNone,
	SelectionSingle,
	SelectionBrowse,
	SelectionMultiple,
	ShadowType,
	ShadowNone,
	ShadowIm,
	ShadowOut,
	ShadowEtchedIn,
	ShadowEtchedOut,
	StateType,
	StateNormal,
	StateActive,
	StatePrelight,
	StateSelected,
	StateInsensitive,
	StateInconsistent,
	StateFocused,
	ToolbarStyle,
	ToolbarIcons,
	ToolbarText,
	ToolbarBoth,
	ToolbarBothHoriz,
	JunctionSides,
	JunctionNone,
	JunctionCornerTopleft,
	JunctionCornerTopRight,
	JunctionCornerBottomLeft,
	JunctionCornerBottomRight,
	JunctionTop,
	JunctionBottom,
	JunctionLeft,
	JunctionRight,
	RegionFlags,
	RegionEven,
	RegionOdd,
	RegionFirst,
	RegionLast,
	RegionOnly,
	RegionSorted,
	IconSize,
	IconSizeInvalid,
	IconSizeMemu,
	IconSizeSmallToolbar,
	IconSizeLargeToolbar,
	IconSizeButton,
	IconSizeDnd,
	IconSizeDisalog,
	EntryIconPosition,
	EntryIconPrimary,
	EntryIconSecondary,
	InputHints,
	InputHintNone,
	InputHintSpellcheck,
	InputHintNoSpellcheck,
	InputHintWordCompletion,
	InputHintLowercase,
	InputHintUppercaseChars,
	InputHintUppercaseWords,
	InputHintUppercaseSentences,
	InputHintInhibitOsk,
	InputPurpose,
	InputPurposeFreeForm,
	InputPurposeAlpha,
	InputPurposeDigits,
	InputPurposeNumber,
	InputPurposePhone,
	InputPurposeUrl,
	InputPurposeEmail,
	InputPurposeName,
	InputPurposePassword,
	InputPurposePin,
	ImageType,
	ImageEmpty,
	ImagePixbuf,
	ImageStock,
	ImageIconSet,
	ImageAnimation,
	ImageIconName,
	ImageGIcon,
	ImageSurface,
	SpinType,
	SpinStepForward,
	SpinStepBackward,
	SpinPageForward,
	SpinPageBackward,
	SpinHome,
	SpinEnd,
	SpinUserDefined,
	SpinButtonUpdatePolicy,
	UpdateAlways,
	UpdateIfValid,
	LevelBarMode,
	LevelBarModeContinuous,
	LevelBarModeDiscrete,
	CalendarDisplayOptions,
	CalendarShowHeading,
	CalendarShowDayNames,
	CalendarNoMonthChange,
	CalendarShowWeekNumbers,
	CalendarShowDetails,
	MessageType,
	MessageInfo,
	MessageWarning,
	MessageQuestion,
	MessageError,
	MessageOther
};

pub use self::types::{
	Tooltip,
	WidgetHelpType
};

pub mod cast;
pub mod version;
pub mod traits;
pub mod signals;

mod rt;
mod widgets;
mod enums;
mod types;<|endoftext|>


<commit_before>use std::cmp::max;

use time::SteadyTime;

use mio::{self, EventLoop, Token, EventSet, Evented, PollOpt};
use mio::util::Slab;

use {Async};

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Abort {
    NoSlabSpace,
    RegisterFailed,
    MachineAddError,
}

pub enum Timeo {
    Fsm(Token),
}

pub enum Notify {
    Fsm(Token),
}

pub struct Cell<M:Sized>(M, Option<(SteadyTime, mio::Timeout)>);

pub struct Handler<Ctx, M> {
    slab: Slab<Cell<M>>,
    context: Ctx,
}

pub trait Registrator {
    fn register(&mut self, io: &Evented, interest: EventSet, opt: PollOpt);
}

struct Reg<'a, H>
    where H: mio::Handler + 'a, H::Timeout: 'a, H::Message: 'a
{
    eloop: &'a mut EventLoop<H>,
    token: Token,
}

impl<'a, H> Registrator for Reg<'a, H>
    where H: mio::Handler + 'a, H::Timeout: 'a, H::Message: 'a
{
    fn register(&mut self, io: &Evented, interest: EventSet, opt: PollOpt)
    {
        self.eloop.register_opt(io, self.token, interest, opt).unwrap();
    }
}

pub trait EventMachine<C>: Sized {
    /// Socket readiness notification
    fn ready(self, events: EventSet, context: &mut C)
        -> Async<Self, Option<Self>>;

    /// Gives socket a chance to register in event loop
    fn register(self, reg: &mut Registrator) -> Async<Self, ()>;

    /// Timeout happened
    fn timeout(self, context: &mut C) -> Async<Self, Option<Self>>;

    /// Message received
    fn wakeup(self, context: &mut C) -> Async<Self, Option<Self>>;
}

impl<C, M> Handler<C, M>
    where M: EventMachine<C>,
{
    pub fn new(context: C, _eloop: &mut EventLoop<Handler<C, M>>)
        -> Handler<C, M>
    {
        // TODO(tailhook) create default config from the ulimit data instead
        // of using real defaults
        Handler {
            slab: Slab::new(4096),
            context: context,
        }
    }
}

fn replacement<M, C, R>(ares: Async<M, R>, eloop: &mut EventLoop<Handler<C, M>>,
    token: Token, old_timer: Option<(SteadyTime, mio::Timeout)>)
    -> (Option<Cell<M>>, Option<R>)
    where M:Sized, M:EventMachine<C>, R:Sized
{
    use async::Async::*;
    match ares {
        Continue(m, result) => {
            if let Some((_, ticket)) = old_timer {
                eloop.clear_timeout(ticket);
            }
            (Some(Cell(m, None)), Some(result))
        }
        Stop => (None, None),
        Timeout(m, deadline) => {
            let ticket = match old_timer {
                Some((dl, t)) if dl == deadline => Some(t),
                Some((_, ticket)) => {
                    eloop.clear_timeout(ticket);
                    None
                }
                None => None,
            };
            let ticket = ticket.unwrap_or_else(|| {
                let left = deadline - SteadyTime::now();
                eloop.timeout_ms(
                        Timeo::Fsm(token),
                        max(left.num_milliseconds(), 0) as u64,
                    ).ok().expect("No more timer slots?")
            });
            (Some(Cell(m, Some((deadline, ticket)))), None)
        }
    }
}

impl<'a, Ctx, M> Handler<Ctx, M>
    where M: EventMachine<Ctx>
{
    pub fn add_root(&mut self, eloop: &mut EventLoop<Self>, m: M) {
        match self.slab.insert(Cell(m, None)) {
            Ok(tok) => {
                self.slab.replace_with(tok, |Cell(m, timer)| {
                    let mach = m.register(&mut Reg {
                        eloop: eloop,
                        token: tok
                        });
                    replacement(mach, eloop, tok, timer).0
                }).unwrap(); // just inserted so must work
            }
            Err(_) => {
                unimplemented!();
            }
        }
    }

    fn action_loop<'x, F>(&mut self, token: Token,
        eloop: &'x mut EventLoop<Self>, fun: F)
        where F: Fn(M, &mut Ctx) -> Async<M, Option<M>>,
    {
        let ref mut ctx = self.context;
        loop {
            let mut new_machine = None;
            self.slab.replace_with(token, |Cell(m, timer)| {
                let mach = fun(m, ctx);
                let (cell, res) = replacement(mach, eloop, token, timer);
                new_machine = res.and_then(|r| r);
                cell
            }).ok();  // Spurious events are ok in mio
            if let Some(new) = new_machine {
                match self.slab.insert(Cell(new, None)) {
                    Ok(tok) => {
                        self.slab.replace_with(tok, |Cell(m, timer)| {
                            let mach = m.register(&mut Reg {
                                eloop: eloop,
                                token: tok
                                });
                            replacement(mach, eloop, tok, timer).0
                        }).unwrap(); // just inserted so must work
                    }
                    Err(_) => {
                        unimplemented!();
                    }
                }
            } else {
                break;
            }
        }
    }
}

impl<Ctx, M> mio::Handler for Handler<Ctx, M>
    where M: EventMachine<Ctx>
{
    type Message = Notify;
    type Timeout = Timeo;
    fn ready<'x>(&mut self, eloop: &'x mut EventLoop<Self>,
        token: Token, events: EventSet)
    {
        self.action_loop(token, eloop, |m, ctx| m.ready(events, ctx));
    }

    fn notify(&mut self, eloop: &mut EventLoop<Self>, msg: Notify) {
        match msg {
            Notify::Fsm(token) => {
                self.action_loop(token, eloop, |m, ctx| m.wakeup(ctx));
            }
        }
    }

    fn timeout(&mut self, eloop: &mut EventLoop<Self>, timeo: Timeo) {
        match timeo {
            Timeo::Fsm(token) => {
                self.action_loop(token, eloop, |m, ctx| m.wakeup(ctx));
            }
        }

    }
}

<commit_msg>More strict handler struct, to have easier to understand errors<commit_after>use std::cmp::max;

use time::SteadyTime;

use mio::{self, EventLoop, Token, EventSet, Evented, PollOpt};
use mio::util::Slab;

use {Async};

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Abort {
    NoSlabSpace,
    RegisterFailed,
    MachineAddError,
}

pub enum Timeo {
    Fsm(Token),
}

pub enum Notify {
    Fsm(Token),
}

pub struct Cell<M:Sized>(M, Option<(SteadyTime, mio::Timeout)>);

pub struct Handler<Ctx, M>
    where M: EventMachine<Ctx>
{
    slab: Slab<Cell<M>>,
    context: Ctx,
}

pub trait Registrator {
    fn register(&mut self, io: &Evented, interest: EventSet, opt: PollOpt);
}

struct Reg<'a, H>
    where H: mio::Handler + 'a, H::Timeout: 'a, H::Message: 'a
{
    eloop: &'a mut EventLoop<H>,
    token: Token,
}

impl<'a, H> Registrator for Reg<'a, H>
    where H: mio::Handler + 'a, H::Timeout: 'a, H::Message: 'a
{
    fn register(&mut self, io: &Evented, interest: EventSet, opt: PollOpt)
    {
        self.eloop.register_opt(io, self.token, interest, opt).unwrap();
    }
}

pub trait EventMachine<C>: Sized {
    /// Socket readiness notification
    fn ready(self, events: EventSet, context: &mut C)
        -> Async<Self, Option<Self>>;

    /// Gives socket a chance to register in event loop
    fn register(self, reg: &mut Registrator) -> Async<Self, ()>;

    /// Timeout happened
    fn timeout(self, context: &mut C) -> Async<Self, Option<Self>>;

    /// Message received
    fn wakeup(self, context: &mut C) -> Async<Self, Option<Self>>;
}

impl<C, M> Handler<C, M>
    where M: EventMachine<C>,
{
    pub fn new(context: C, _eloop: &mut EventLoop<Handler<C, M>>)
        -> Handler<C, M>
    {
        // TODO(tailhook) create default config from the ulimit data instead
        // of using real defaults
        Handler {
            slab: Slab::new(4096),
            context: context,
        }
    }
}

fn replacement<M, C, R>(ares: Async<M, R>, eloop: &mut EventLoop<Handler<C, M>>,
    token: Token, old_timer: Option<(SteadyTime, mio::Timeout)>)
    -> (Option<Cell<M>>, Option<R>)
    where M:Sized, M:EventMachine<C>, R:Sized
{
    use async::Async::*;
    match ares {
        Continue(m, result) => {
            if let Some((_, ticket)) = old_timer {
                eloop.clear_timeout(ticket);
            }
            (Some(Cell(m, None)), Some(result))
        }
        Stop => (None, None),
        Timeout(m, deadline) => {
            let ticket = match old_timer {
                Some((dl, t)) if dl == deadline => Some(t),
                Some((_, ticket)) => {
                    eloop.clear_timeout(ticket);
                    None
                }
                None => None,
            };
            let ticket = ticket.unwrap_or_else(|| {
                let left = deadline - SteadyTime::now();
                eloop.timeout_ms(
                        Timeo::Fsm(token),
                        max(left.num_milliseconds(), 0) as u64,
                    ).ok().expect("No more timer slots?")
            });
            (Some(Cell(m, Some((deadline, ticket)))), None)
        }
    }
}

impl<'a, Ctx, M> Handler<Ctx, M>
    where M: EventMachine<Ctx>
{
    pub fn add_root(&mut self, eloop: &mut EventLoop<Self>, m: M) {
        match self.slab.insert(Cell(m, None)) {
            Ok(tok) => {
                self.slab.replace_with(tok, |Cell(m, timer)| {
                    let mach = m.register(&mut Reg {
                        eloop: eloop,
                        token: tok
                        });
                    replacement(mach, eloop, tok, timer).0
                }).unwrap(); // just inserted so must work
            }
            Err(_) => {
                unimplemented!();
            }
        }
    }

    fn action_loop<'x, F>(&mut self, token: Token,
        eloop: &'x mut EventLoop<Self>, fun: F)
        where F: Fn(M, &mut Ctx) -> Async<M, Option<M>>,
    {
        let ref mut ctx = self.context;
        loop {
            let mut new_machine = None;
            self.slab.replace_with(token, |Cell(m, timer)| {
                let mach = fun(m, ctx);
                let (cell, res) = replacement(mach, eloop, token, timer);
                new_machine = res.and_then(|r| r);
                cell
            }).ok();  // Spurious events are ok in mio
            if let Some(new) = new_machine {
                match self.slab.insert(Cell(new, None)) {
                    Ok(tok) => {
                        self.slab.replace_with(tok, |Cell(m, timer)| {
                            let mach = m.register(&mut Reg {
                                eloop: eloop,
                                token: tok
                                });
                            replacement(mach, eloop, tok, timer).0
                        }).unwrap(); // just inserted so must work
                    }
                    Err(_) => {
                        unimplemented!();
                    }
                }
            } else {
                break;
            }
        }
    }
}

impl<Ctx, M> mio::Handler for Handler<Ctx, M>
    where M: EventMachine<Ctx>
{
    type Message = Notify;
    type Timeout = Timeo;
    fn ready<'x>(&mut self, eloop: &'x mut EventLoop<Self>,
        token: Token, events: EventSet)
    {
        self.action_loop(token, eloop, |m, ctx| m.ready(events, ctx));
    }

    fn notify(&mut self, eloop: &mut EventLoop<Self>, msg: Notify) {
        match msg {
            Notify::Fsm(token) => {
                self.action_loop(token, eloop, |m, ctx| m.wakeup(ctx));
            }
        }
    }

    fn timeout(&mut self, eloop: &mut EventLoop<Self>, timeo: Timeo) {
        match timeo {
            Timeo::Fsm(token) => {
                self.action_loop(token, eloop, |m, ctx| m.wakeup(ctx));
            }
        }

    }
}

<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use executable_helpers::helpers::{
    setup_executable, ARG_CONFIG_PATH, ARG_DISABLE_LOGGING, ARG_PEER_ID,
};
use signal_hook;
use std::sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
};

fn register_signals(term: Arc<AtomicBool>) {
    for signal in &[
        signal_hook::SIGTERM,
        signal_hook::SIGINT,
        signal_hook::SIGHUP,
    ] {
        let term_clone = Arc::clone(&term);
        let thread = std::thread::current();
        unsafe {
            signal_hook::register(*signal, move || {
                term_clone.store(true, Ordering::Relaxed);
                thread.unpark();
            })
            .expect("failed to register signal handler");
        }
    }
}

fn main() {
    let (config, _logger, _args) = setup_executable(
        "Libra single node".to_string(),
        vec![ARG_PEER_ID, ARG_CONFIG_PATH, ARG_DISABLE_LOGGING],
    );
    let (_ac_handle, _node_handle) = libra_node::main_node::setup_environment(&config);

    let term = Arc::new(AtomicBool::new(false));
    register_signals(Arc::clone(&term));

    while !term.load(Ordering::Relaxed) {
        std::thread::park();
    }
}
<commit_msg>[LibraNode] Fix ordering argument for term<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use executable_helpers::helpers::{
    setup_executable, ARG_CONFIG_PATH, ARG_DISABLE_LOGGING, ARG_PEER_ID,
};
use signal_hook;
use std::sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
};

fn register_signals(term: Arc<AtomicBool>) {
    for signal in &[
        signal_hook::SIGTERM,
        signal_hook::SIGINT,
        signal_hook::SIGHUP,
    ] {
        let term_clone = Arc::clone(&term);
        let thread = std::thread::current();
        unsafe {
            signal_hook::register(*signal, move || {
                term_clone.store(true, Ordering::Release);
                thread.unpark();
            })
            .expect("failed to register signal handler");
        }
    }
}

fn main() {
    let (config, _logger, _args) = setup_executable(
        "Libra single node".to_string(),
        vec![ARG_PEER_ID, ARG_CONFIG_PATH, ARG_DISABLE_LOGGING],
    );
    let (_ac_handle, _node_handle) = libra_node::main_node::setup_environment(&config);

    let term = Arc::new(AtomicBool::new(false));
    register_signals(Arc::clone(&term));

    while !term.load(Ordering::Acquire) {
        std::thread::park();
    }
}
<|endoftext|>