<commit_before>//! Types which pin data to its location in memory
//!
//! It is sometimes useful to have objects that are guaranteed to not move,
//! in the sense that their placement in memory does not change, and can thus be relied upon.
//!
//! A prime example of such a scenario would be building self-referencial structs,
//! since moving an object with pointers to itself will invalidate them,
//! which could cause undefined behavior.
//!
//! In order to prevent objects from moving, they must be pinned
//! by wrapping a pointer to the data in the [`Pin`] type. A pointer wrapped
//! in a `Pin` is otherwise equivalent to its normal version, e.g. `Pin<Box<T>>`
//! and `Box<T>` work the same way except that the first is pinning the value
//! of `T` in place.
//!
//! First of all, these are pointer types because pinned data mustn't be passed around by value
//! (that would change its location in memory).
//! Secondly, since data can be moved out of `&mut` and `Box` with functions such as [`swap`],
//! which causes their contents to swap places in memory,
//! we need dedicated types that prohibit such operations.
//!
//! However, these restrictions are usually not necessary,
//! so most types implement the [`Unpin`] auto-trait,
//! which indicates that the type can be moved out safely.
//! Doing so removes the limitations of pinning types,
//! making them the same as their non-pinning counterparts.
//!
//! [`Pin`]: struct.Pin.html
//! [`Unpin`]: trait.Unpin.html
//! [`swap`]: ../../std/mem/fn.swap.html
//! [`Box`]: ../../std/boxed/struct.Box.html
//!
//! # Examples
//!
//! ```rust
//! #![feature(pin)]
//!
//! use std::pin::Pin;
//! use std::marker::Pinned;
//! use std::ptr::NonNull;
//!
//! // This is a self referencial struct since the slice field points to the data field.
//! // We cannot inform the compiler about that with a normal reference,
//! // since this pattern cannot be described with the usual borrowing rules.
//! // Instead we use a raw pointer, though one which is known to not be null,
//! // since we know it's pointing at the string.
//! struct Unmovable {
//!     data: String,
//!     slice: NonNull<String>,
//!     _pin: Pinned,
//! }
//!
//! impl Unmovable {
//!     // To ensure the data doesn't move when the function returns,
//!     // we place it in the heap where it will stay for the lifetime of the object,
//!     // and the only way to access it would be through a pointer to it.
//!     fn new(data: String) -> Pin<Box<Self>> {
//!         let res = Unmovable {
//!             data,
//!             // we only create the pointer once the data is in place
//!             // otherwise it will have already moved before we even started
//!             slice: NonNull::dangling(),
//!             _pin: Pinned,
//!         };
//!         let mut boxed = Box::pinned(res);
//!
//!         let slice = NonNull::from(&boxed.data);
//!         // we know this is safe because modifying a field doesn't move the whole struct
//!         unsafe {
//!             let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut boxed);
//!             Pin::get_mut_unchecked(mut_ref).slice = slice;
//!         }
//!         boxed
//!     }
//! }
//!
//! let unmoved = Unmovable::new("hello".to_string());
//! // The pointer should point to the correct location,
//! // so long as the struct hasn't moved.
//! // Meanwhile, we are free to move the pointer around.
//! # #[allow(unused_mut)]
//! let mut still_unmoved = unmoved;
//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
//!
//! // Since our type doesn't implement Unpin, this will fail to compile:
//! // let new_unmoved = Unmovable::new("world".to_string());
//! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved);
//! ```

#![unstable(feature = "pin", issue = "49150")]

use fmt;
use marker::Sized;
use ops::{Deref, DerefMut, CoerceUnsized};

#[doc(inline)]
pub use marker::Unpin;

/// A pinned pointer.
///
/// This is a wrapper around a kind of pointer which makes that pointer "pin" its
/// value in place, preventing the value referenced by that pointer from being moved
/// unless it implements [`Unpin`].
///
/// See the [`pin` module] documentation for furthur explanation on pinning.
///
/// [`Unpin`]: ../../std/marker/trait.Unpin.html
/// [`pin` module]: ../../std/pin/index.html
//
// Note: the derives below are allowed because they all only use `&P`, so they
// cannot move the value behind `pointer`.
#[unstable(feature = "pin", issue = "49150")]
#[fundamental]
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct Pin
 {
    pointer: P,
}

impl
 Pin

where
    P::Target: Unpin,
{
    /// Construct a new `Pin` around a pointer to some data of a type that
    /// implements `Unpin`.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn new(pointer: P) -> Pin
 {
        // Safety: the value pointed to is `Unpin`, and so has no requirements
        // around pinning.
        unsafe { Pin::new_unchecked(pointer) }
    }
}

impl
 Pin
 {
    /// Construct a new `Pin` around a reference to some data of a type that
    /// may or may not implement `Unpin`.
    ///
    /// # Safety
    ///
    /// This constructor is unsafe because we cannot guarantee that the data
    /// pointed to by `pointer` is pinned. If the constructed `Pin<P>` does
    /// not guarantee that the data `P` points to is pinned, constructing a
    /// `Pin<P>` is undefined behavior.
    ///
    /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used
    /// instead.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub unsafe fn new_unchecked(pointer: P) -> Pin
 {
        Pin { pointer }
    }

    /// Get a pinned shared reference from this pinned pointer.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn as_ref(self: &Pin
) -> Pin<&P::Target> {
        unsafe { Pin::new_unchecked(&*self.pointer) }
    }
}

impl
 Pin
 {
    /// Get a pinned mutable reference from this pinned pointer.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn as_mut(self: &mut Pin
) -> Pin<&mut P::Target> {
        unsafe { Pin::new_unchecked(&mut *self.pointer) }
    }

    /// Assign a new value to the memory behind the pinned reference.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn set(mut self: Pin
, value: P::Target)
    where
        P::Target: Sized,
    {
        *self.pointer = value;
    }
}

impl<'a, T: ?Sized> Pin<&'a T> {
    /// Construct a new pin by mapping the interior value.
    ///
    /// For example, if you  wanted to get a `Pin` of a field of something,
    /// you could use this to get access to that field in one line of code.
    ///
    /// # Safety
    ///
    /// This function is unsafe. You must guarantee that the data you return
    /// will not move so long as the argument value does not move (for example,
    /// because it is one of the fields of that value), and also that you do
    /// not move out of the argument you receive to the interior function.
    #[unstable(feature = "pin", issue = "49150")]
    pub unsafe fn map_unchecked(this: Pin<&'a T>, func: F) -> Pin<&'a U> where
        F: FnOnce(&T) -> &U,
    {
        let pointer = &*this.pointer;
        let new_pointer = func(pointer);
        Pin::new_unchecked(new_pointer)
    }

    /// Get a shared reference out of a pin.
    ///
    /// Note: `Pin` also implements `Deref` to the target, which can be used
    /// to access the inner value. However, `Deref` only provides a reference
    /// that lives for as long as the borrow of the `Pin`, not the lifetime of
    /// the `Pin` itself. This method allows turning the `Pin` into a reference
    /// with the same lifetime as the original `Pin`.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn get_ref(this: Pin<&'a T>) -> &'a T {
        this.pointer
    }
}

impl<'a, T: ?Sized> Pin<&'a mut T> {
    /// Convert this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn into_ref(this: Pin<&'a mut T>) -> Pin<&'a T> {
        Pin { pointer: this.pointer }
    }

    /// Get a mutable reference to the data inside of this `Pin`.
    ///
    /// This requires that the data inside this `Pin` is `Unpin`.
    ///
    /// Note: `Pin` also implements `DerefMut` to the data, which can be used
    /// to access the inner value. However, `DerefMut` only provides a reference
    /// that lives for as long as the borrow of the `Pin`, not the lifetime of
    /// the `Pin` itself. This method allows turning the `Pin` into a reference
    /// with the same lifetime as the original `Pin`.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn get_mut(this: Pin<&'a mut T>) -> &'a mut T
        where T: Unpin,
    {
        this.pointer
    }

    /// Get a mutable reference to the data inside of this `Pin`.
    ///
    /// # Safety
    ///
    /// This function is unsafe. You must guarantee that you will never move
    /// the data out of the mutable reference you receive when you call this
    /// function, so that the invariants on the `Pin` type can be upheld.
    ///
    /// If the underlying data is `Unpin`, `Pin::get_mut` should be used
    /// instead.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub unsafe fn get_mut_unchecked(this: Pin<&'a mut T>) -> &'a mut T {
        this.pointer
    }

    /// Construct a new pin by mapping the interior value.
    ///
    /// For example, if you  wanted to get a `Pin` of a field of something,
    /// you could use this to get access to that field in one line of code.
    ///
    /// # Safety
    ///
    /// This function is unsafe. You must guarantee that the data you return
    /// will not move so long as the argument value does not move (for example,
    /// because it is one of the fields of that value), and also that you do
    /// not move out of the argument you receive to the interior function.
    #[unstable(feature = "pin", issue = "49150")]
    pub unsafe fn map_unchecked_mut(this: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where
        F: FnOnce(&mut T) -> &mut U,
    {
        let pointer = Pin::get_mut_unchecked(this);
        let new_pointer = func(pointer);
        Pin::new_unchecked(new_pointer)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl
 Deref for Pin
 {
    type Target = P::Target;
    fn deref(&self) -> &P::Target {
        Pin::get_ref(Pin::as_ref(self))
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl
 DerefMut for Pin

where
    P::Target: Unpin
{
    fn deref_mut(&mut self) -> &mut P::Target {
        Pin::get_mut(Pin::as_mut(self))
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<'a, P: fmt::Debug> fmt::Debug for Pin
 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.pointer, f)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<'a, P: fmt::Display> fmt::Display for Pin
 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.pointer, f)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<'a, P: fmt::Pointer> fmt::Pointer for Pin
 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Pointer::fmt(&self.pointer, f)
    }
}

// Note: this means that any impl of `CoerceUnsized` that allows coercing from
// a type that impls `Deref<Target=impl !Unpin>` to a type that impls
// `Deref<Target=Unpin>` is unsound. Any such impl would probably be unsound
// for other reasons, though, so we just need to take care not to allow such
// impls to land in std.
#[unstable(feature = "pin", issue = "49150")]
impl<'a, P, U> CoerceUnsized<Pin> for Pin

where
    P: CoerceUnsized,
{}

#[unstable(feature = "pin", issue = "49150")]
impl<'a, P> Unpin for Pin
 {}
<commit_msg>Rollup merge of #54598 - pthariensflame:patch-1, r=sfackler<commit_after>//! Types which pin data to its location in memory
//!
//! It is sometimes useful to have objects that are guaranteed to not move,
//! in the sense that their placement in memory does not change, and can thus be relied upon.
//!
//! A prime example of such a scenario would be building self-referencial structs,
//! since moving an object with pointers to itself will invalidate them,
//! which could cause undefined behavior.
//!
//! In order to prevent objects from moving, they must be pinned
//! by wrapping a pointer to the data in the [`Pin`] type. A pointer wrapped
//! in a `Pin` is otherwise equivalent to its normal version, e.g. `Pin<Box<T>>`
//! and `Box<T>` work the same way except that the first is pinning the value
//! of `T` in place.
//!
//! First of all, these are pointer types because pinned data mustn't be passed around by value
//! (that would change its location in memory).
//! Secondly, since data can be moved out of `&mut` and `Box` with functions such as [`swap`],
//! which causes their contents to swap places in memory,
//! we need dedicated types that prohibit such operations.
//!
//! However, these restrictions are usually not necessary,
//! so most types implement the [`Unpin`] auto-trait,
//! which indicates that the type can be moved out safely.
//! Doing so removes the limitations of pinning types,
//! making them the same as their non-pinning counterparts.
//!
//! [`Pin`]: struct.Pin.html
//! [`Unpin`]: trait.Unpin.html
//! [`swap`]: ../../std/mem/fn.swap.html
//! [`Box`]: ../../std/boxed/struct.Box.html
//!
//! # Examples
//!
//! ```rust
//! #![feature(pin)]
//!
//! use std::pin::Pin;
//! use std::marker::Pinned;
//! use std::ptr::NonNull;
//!
//! // This is a self referencial struct since the slice field points to the data field.
//! // We cannot inform the compiler about that with a normal reference,
//! // since this pattern cannot be described with the usual borrowing rules.
//! // Instead we use a raw pointer, though one which is known to not be null,
//! // since we know it's pointing at the string.
//! struct Unmovable {
//!     data: String,
//!     slice: NonNull<String>,
//!     _pin: Pinned,
//! }
//!
//! impl Unmovable {
//!     // To ensure the data doesn't move when the function returns,
//!     // we place it in the heap where it will stay for the lifetime of the object,
//!     // and the only way to access it would be through a pointer to it.
//!     fn new(data: String) -> Pin<Box<Self>> {
//!         let res = Unmovable {
//!             data,
//!             // we only create the pointer once the data is in place
//!             // otherwise it will have already moved before we even started
//!             slice: NonNull::dangling(),
//!             _pin: Pinned,
//!         };
//!         let mut boxed = Box::pinned(res);
//!
//!         let slice = NonNull::from(&boxed.data);
//!         // we know this is safe because modifying a field doesn't move the whole struct
//!         unsafe {
//!             let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut boxed);
//!             Pin::get_mut_unchecked(mut_ref).slice = slice;
//!         }
//!         boxed
//!     }
//! }
//!
//! let unmoved = Unmovable::new("hello".to_string());
//! // The pointer should point to the correct location,
//! // so long as the struct hasn't moved.
//! // Meanwhile, we are free to move the pointer around.
//! # #[allow(unused_mut)]
//! let mut still_unmoved = unmoved;
//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
//!
//! // Since our type doesn't implement Unpin, this will fail to compile:
//! // let new_unmoved = Unmovable::new("world".to_string());
//! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved);
//! ```

#![unstable(feature = "pin", issue = "49150")]

use fmt;
use marker::Sized;
use ops::{Deref, DerefMut, CoerceUnsized};

#[doc(inline)]
pub use marker::Unpin;

/// A pinned pointer.
///
/// This is a wrapper around a kind of pointer which makes that pointer "pin" its
/// value in place, preventing the value referenced by that pointer from being moved
/// unless it implements [`Unpin`].
///
/// See the [`pin` module] documentation for furthur explanation on pinning.
///
/// [`Unpin`]: ../../std/marker/trait.Unpin.html
/// [`pin` module]: ../../std/pin/index.html
//
// Note: the derives below are allowed because they all only use `&P`, so they
// cannot move the value behind `pointer`.
#[unstable(feature = "pin", issue = "49150")]
#[fundamental]
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct Pin
 {
    pointer: P,
}

impl
 Pin

where
    P::Target: Unpin,
{
    /// Construct a new `Pin` around a pointer to some data of a type that
    /// implements `Unpin`.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn new(pointer: P) -> Pin
 {
        // Safety: the value pointed to is `Unpin`, and so has no requirements
        // around pinning.
        unsafe { Pin::new_unchecked(pointer) }
    }
}

impl
 Pin
 {
    /// Construct a new `Pin` around a reference to some data of a type that
    /// may or may not implement `Unpin`.
    ///
    /// # Safety
    ///
    /// This constructor is unsafe because we cannot guarantee that the data
    /// pointed to by `pointer` is pinned. If the constructed `Pin<P>` does
    /// not guarantee that the data `P` points to is pinned, constructing a
    /// `Pin<P>` is undefined behavior.
    ///
    /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used
    /// instead.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub unsafe fn new_unchecked(pointer: P) -> Pin
 {
        Pin { pointer }
    }

    /// Get a pinned shared reference from this pinned pointer.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn as_ref(self: &Pin
) -> Pin<&P::Target> {
        unsafe { Pin::new_unchecked(&*self.pointer) }
    }
}

impl
 Pin
 {
    /// Get a pinned mutable reference from this pinned pointer.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn as_mut(self: &mut Pin
) -> Pin<&mut P::Target> {
        unsafe { Pin::new_unchecked(&mut *self.pointer) }
    }

    /// Assign a new value to the memory behind the pinned reference.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn set(mut self: Pin
, value: P::Target)
    where
        P::Target: Sized,
    {
        *self.pointer = value;
    }
}

impl<'a, T: ?Sized> Pin<&'a T> {
    /// Construct a new pin by mapping the interior value.
    ///
    /// For example, if you  wanted to get a `Pin` of a field of something,
    /// you could use this to get access to that field in one line of code.
    ///
    /// # Safety
    ///
    /// This function is unsafe. You must guarantee that the data you return
    /// will not move so long as the argument value does not move (for example,
    /// because it is one of the fields of that value), and also that you do
    /// not move out of the argument you receive to the interior function.
    #[unstable(feature = "pin", issue = "49150")]
    pub unsafe fn map_unchecked(this: Pin<&'a T>, func: F) -> Pin<&'a U> where
        F: FnOnce(&T) -> &U,
    {
        let pointer = &*this.pointer;
        let new_pointer = func(pointer);
        Pin::new_unchecked(new_pointer)
    }

    /// Get a shared reference out of a pin.
    ///
    /// Note: `Pin` also implements `Deref` to the target, which can be used
    /// to access the inner value. However, `Deref` only provides a reference
    /// that lives for as long as the borrow of the `Pin`, not the lifetime of
    /// the `Pin` itself. This method allows turning the `Pin` into a reference
    /// with the same lifetime as the original `Pin`.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn get_ref(this: Pin<&'a T>) -> &'a T {
        this.pointer
    }
}

impl<'a, T: ?Sized> Pin<&'a mut T> {
    /// Convert this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn into_ref(this: Pin<&'a mut T>) -> Pin<&'a T> {
        Pin { pointer: this.pointer }
    }

    /// Get a mutable reference to the data inside of this `Pin`.
    ///
    /// This requires that the data inside this `Pin` is `Unpin`.
    ///
    /// Note: `Pin` also implements `DerefMut` to the data, which can be used
    /// to access the inner value. However, `DerefMut` only provides a reference
    /// that lives for as long as the borrow of the `Pin`, not the lifetime of
    /// the `Pin` itself. This method allows turning the `Pin` into a reference
    /// with the same lifetime as the original `Pin`.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub fn get_mut(this: Pin<&'a mut T>) -> &'a mut T
        where T: Unpin,
    {
        this.pointer
    }

    /// Get a mutable reference to the data inside of this `Pin`.
    ///
    /// # Safety
    ///
    /// This function is unsafe. You must guarantee that you will never move
    /// the data out of the mutable reference you receive when you call this
    /// function, so that the invariants on the `Pin` type can be upheld.
    ///
    /// If the underlying data is `Unpin`, `Pin::get_mut` should be used
    /// instead.
    #[unstable(feature = "pin", issue = "49150")]
    #[inline(always)]
    pub unsafe fn get_mut_unchecked(this: Pin<&'a mut T>) -> &'a mut T {
        this.pointer
    }

    /// Construct a new pin by mapping the interior value.
    ///
    /// For example, if you  wanted to get a `Pin` of a field of something,
    /// you could use this to get access to that field in one line of code.
    ///
    /// # Safety
    ///
    /// This function is unsafe. You must guarantee that the data you return
    /// will not move so long as the argument value does not move (for example,
    /// because it is one of the fields of that value), and also that you do
    /// not move out of the argument you receive to the interior function.
    #[unstable(feature = "pin", issue = "49150")]
    pub unsafe fn map_unchecked_mut(this: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where
        F: FnOnce(&mut T) -> &mut U,
    {
        let pointer = Pin::get_mut_unchecked(this);
        let new_pointer = func(pointer);
        Pin::new_unchecked(new_pointer)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl
 Deref for Pin
 {
    type Target = P::Target;
    fn deref(&self) -> &P::Target {
        Pin::get_ref(Pin::as_ref(self))
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl
 DerefMut for Pin

where
    P::Target: Unpin
{
    fn deref_mut(&mut self) -> &mut P::Target {
        Pin::get_mut(Pin::as_mut(self))
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl
 fmt::Debug for Pin
 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.pointer, f)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl
 fmt::Display for Pin
 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.pointer, f)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl
 fmt::Pointer for Pin
 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Pointer::fmt(&self.pointer, f)
    }
}

// Note: this means that any impl of `CoerceUnsized` that allows coercing from
// a type that impls `Deref<Target=impl !Unpin>` to a type that impls
// `Deref<Target=Unpin>` is unsound. Any such impl would probably be unsound
// for other reasons, though, so we just need to take care not to allow such
// impls to land in std.
#[unstable(feature = "pin", issue = "49150")]
impl
 CoerceUnsized<Pin> for Pin

where
    P: CoerceUnsized,
{}

#[unstable(feature = "pin", issue = "49150")]
impl
 Unpin for Pin
 {}
<|endoftext|>


<commit_before>use num::{Signed, CheckedAdd, CheckedMul, Saturating, One, FromPrimitive};
use array_ext::{Array as ArrayExtArray, *};
use std::cmp::{min, max};
use array::{Array, ReplaceItemType};
use arrayvec::{self, ArrayVec};

use super::*;

pub trait PolynomialBase1 {
  type Coefficient: DoubleSizedInteger + Signed;
}
pub trait PolynomialBase2: PolynomialBase1 + Array + arrayvec::Array<Item = <Self as PolynomialBase1>::Coefficient> + ReplaceItemType<[<Self as PolynomialBase1>::Coefficient; 2]> {}

/// Evaluate all Taylor coefficients of a polynomial.
///
/// Returns None if any of the coefficients do not fit in the type.
pub trait AllTaylorCoefficients<Input>: Sized {
  fn all_taylor_coefficients(&self, input: impl Into<Input>)->Option<Self>;
}

macro_rules! impl_polynomials {
  ($($coefficients: expr),*) => {
$(

impl <Coefficient: DoubleSizedInteger + Signed> PolynomialBase1 for [Coefficient; $coefficients] {type Coefficient = Coefficient; }
impl <Coefficient: DoubleSizedInteger + Signed> PolynomialBase2 for [Coefficient; $coefficients] {}

impl <Coefficient: DoubleSizedInteger> AllTaylorCoefficients<<Coefficient as DoubleSizedInteger>::Type> for [Coefficient; $coefficients] {
  fn all_taylor_coefficients(&self, input: impl Into<<Coefficient as DoubleSizedInteger>::Type>)->Option <Self> {
    let input = input.into();
    let mut intermediates: [<Coefficient as DoubleSizedInteger>::Type; $coefficients] = self.map (| coefficient | coefficient.into());
    for first_source in (1..intermediates.len()).rev() {
      for source in first_source..intermediates.len() {
        intermediates[source - 1] = intermediates [source - 1].checked_add (&intermediates[source].checked_mul (&input)?)?;
      }
    }
    let mut output = [Coefficient::zero(); $coefficients];
    for (index, value) in intermediates.iter().enumerate() {
      output [index] = (*value).try_into().ok()?;
    }
    Some (output)
  }

}

)*

  }
}

impl_polynomials!(1,2,3,4,5);

pub trait Polynomial: PolynomialBase1 + PolynomialBase2 + AllTaylorCoefficients<<<Self as PolynomialBase1>::Coefficient as DoubleSizedInteger>::Type> {}
impl<P: PolynomialBase1 + PolynomialBase2 + AllTaylorCoefficients<<<Self as PolynomialBase1>::Coefficient as DoubleSizedInteger>::Type>> Polynomial for P {}

pub struct RangeSearchEndpoint<P: PolynomialBase2> {
  time: P::Coefficient,
  coefficients: P,
}

pub fn coefficient_ranges<P: PolynomialBase2> (endpoints: [& RangeSearchEndpoint<P>; 2])-><P as ReplaceItemType<[P::Coefficient; 2]>>::Type {
  let mut result: <P as ReplaceItemType<[P::Coefficient; 2]>>::Type = array_ext::Array::from_fn(|_| [P::Coefficient::zero(), P::Coefficient::zero()]);
  // TODO what if overflow
  let duration = endpoints [1].time - endpoints [0].time;
  let mut previous = [P::Coefficient::zero(), P::Coefficient::zero()];
  for exponent in (0..result.len()).rev() {
    let left_max = endpoints [0].coefficients.as_slice() [exponent].saturating_add(max(P::Coefficient::zero(), previous[1]).saturating_mul(duration));
    let left_min = endpoints [0].coefficients.as_slice() [exponent].saturating_add(min(P::Coefficient::zero(), previous[0]).saturating_mul(duration));
    let right_max = endpoints [1].coefficients.as_slice() [exponent].saturating_add(max(P::Coefficient::zero(), -previous[0]).saturating_mul(duration));
    let right_min = endpoints [1].coefficients.as_slice() [exponent].saturating_add(min(P::Coefficient::zero(), -previous[1]).saturating_mul(duration));
    let bounds = [max(left_min, right_min), min(left_max, right_max)];
    previous = bounds.map(|a|a.saturating_mul(P::Coefficient::from_usize(exponent).unwrap()));
    result.as_mut_slice() [exponent] = bounds;
  }
  result
}

pub struct RangeSearch<P: PolynomialBase2> {
  polynomial: P,
  stack: ArrayVec<[RangeSearchEndpoint<P>; 64]>,
  next_jump: P::Coefficient,
}

impl<P: Polynomial> RangeSearch<P> {
  pub fn new(polynomial: P, start_time: P::Coefficient)->Option<Self> {
    let mut result = RangeSearch {polynomial, stack: ArrayVec::new(), next_jump: P::Coefficient::one()};
    if let Some(coefficients) = result.polynomial.all_taylor_coefficients (start_time) {
      result.stack.push(RangeSearchEndpoint {time: start_time, coefficients});
      result.add_next_endpoint();
      Some(result)
    }
    else {
      None
    }
  }
  pub fn latest_interval(&self)->[&RangeSearchEndpoint<P>; 2] {
    [
      &self.stack[self.stack.len() - 1],
      &self.stack[self.stack.len() - 2],
    ]
  }
  pub fn split_latest(&mut self) {
    let split_time = mean_floor(self.latest_interval()[0].time, self.latest_interval()[1].time);
    if !self.add_endpoint (split_time) {
      let earliest = self.stack.pop().unwrap();
      self.stack.clear();
      self.stack.push(earliest);
      self.add_next_endpoint();
    }
  }
  pub fn skip_latest(&mut self) {
    self.stack.pop() ;
    if self.stack.len() < 2 {
      self.add_next_endpoint();
    }
  }
  pub fn reached_overflow(&self)->bool {
    self.stack.len() == 2 && self.stack [0].time == self.stack [1].time
  }
  fn add_next_endpoint(&mut self) {
    let last_endpoint_time = self.stack.last().unwrap().time;
    loop {
      let endpoint_time = last_endpoint_time.saturating_add (self.next_jump);
      if self.add_endpoint(endpoint_time) { break; }
      self.next_jump = self.next_jump >> 1;
    }
    self.next_jump = self.next_jump << 1;
  }
  fn add_endpoint(&mut self, time: P::Coefficient)->bool {
    if let Some(coefficients) = self.polynomial.all_taylor_coefficients (time) {
      self.stack.insert (self.stack.len() - 1, RangeSearchEndpoint {time, coefficients});
      true
    }
    else {
      false
    }
  }
}

pub fn next_time_lt <P: Polynomial> (polynomial: P, start_time: P::Coefficient, threshold: P::Coefficient)->Option <P::Coefficient> {
  let mut search = RangeSearch::new(polynomial, start_time)?;

  loop {
    if coefficient_ranges(search.latest_interval()).as_slice()[0][0] < threshold {
      if search.latest_interval()[0].time + P::Coefficient::one() == search.latest_interval()[1].time {
        if search.latest_interval()[0].coefficients.as_slice()[0] < threshold {
          return Some(search.latest_interval()[0].time);
        }
        search.skip_latest();
      }
      else {
        search.split_latest();
      }
    }
    else {
      search.skip_latest();
    }
    if search.reached_overflow() { return None; }
  }
}

/*
fn next_time_in_bounds_2d <T: Polynomial, Input> (polynomials: [T;2], start_time: Input, min: [Coefficient;2], max: Coefficient)->Option <Time> {
  let search: ThresholdSearch = ([min, max+1]);
  while a time when the answer is not yet computed comes before the first time when the answer is known to be within bounds {
    (search with the earliest time not yet computed when the answer is also not yet computed).refine_first_bracketed_root(range of times where it matters);
  }
  search.
}*/

#[cfg(test)]
mod tests {

use super::*;
//use proptest::prelude::*;
use num::{BigInt, One};

fn naive_perfect_evaluate <Coefficient: Integer> (coefficients: & [Coefficient], input: Coefficient)->BigInt where BigInt: From<Coefficient> {
  let input = BigInt::from (input) ;
  let mut result = BigInt::zero();
  for (exponent, coefficient) in coefficients.iter().enumerate() {
    let mut term = BigInt::from(*coefficient);
    for _ in 0..exponent { term = term * &input; }
    result = result + term;
  }
  result
}

fn naive_factorial (value: usize)->BigInt {
  let mut result = BigInt::one();
  for factor in 2..=value {
    result = result * BigInt::from(factor);
  }
  result
}

fn naive_binomial_coefficient(n:usize,k:usize)->BigInt {
  naive_factorial (n)/(naive_factorial (k)*naive_factorial (n-k))
}

fn naive_perfect_nth_taylor_coefficient <Coefficient: Integer> (coefficients: & [Coefficient], input: Coefficient, n: usize)->BigInt where BigInt: From<Coefficient> {
  let input = BigInt::from (input) ;
  let mut result = BigInt::zero();
  for (exponent, coefficient) in coefficients.iter().enumerate().skip(n) {
    let mut term = BigInt::from(*coefficient);
    for _ in n..exponent { term = term * &input; }
    result = result + term * naive_binomial_coefficient (exponent, n);
  }
  result
}

macro_rules! test_polynomials {
  ($($coefficients: expr, $integer: ident, $double: ident, $uniform: ident, $name: ident,)*) => {
$(
  mod $name {
    use super::*;
    //use super::super::*;
    use proptest::prelude::*;
    proptest! {
      #[test]
      fn randomly_test_polynomial_translation_inverts (coefficients in prop::array::$uniform(-16 as $integer..16), input in -16 as $integer..16) {
        let translated = coefficients.all_taylor_coefficients (input);
        prop_assume! (translated.is_some());
        let translated = translated.unwrap();
        let translated_back = translated.all_taylor_coefficients (-input);
        prop_assert! (translated_back.is_some(), "we know that the original value was in bounds, so translating back should return some");
        prop_assert_eq! (coefficients, translated_back.unwrap());

      }

      #[test]
      fn randomly_test_taylor_coefficients_evaluates (coefficients in prop::array::$uniform(-16 as $integer..16), input in -16 as $integer..16) {
        let translated = coefficients.all_taylor_coefficients (input);
        prop_assume! (translated.is_some());
        let translated = translated.unwrap();
        let evaluated = naive_perfect_evaluate (&coefficients, input);
        prop_assert_eq! (BigInt::from(translated[0]), evaluated);
        for which in 0..$coefficients {
          prop_assert_eq! (BigInt::from(translated[which]), naive_perfect_nth_taylor_coefficient(&coefficients, input, which), "Incorrect {}th taylor coefficient ", which);
        }
      }

      #[test]
      fn randomly_test_next_time_lt_is_lt (coefficients in prop::array::$uniform(-16 as $integer..16), input in -16 as $integer..16, threshold in -16 as $integer..16) {
        let time = next_time_lt (coefficients, input, threshold);
        prop_assume! (time .is_some());
        let time = time.unwrap();
        if let Some(coefficients) = coefficients.all_taylor_coefficients (time) { prop_assert!(coefficients[0] < threshold); }
      }

      #[test]
      fn randomly_test_next_time_lt_is_next (coefficients in prop::array::$uniform(-16 as $integer..16), input in -16 as $integer..16, threshold in -16 as $integer..16, test_frac in 0f64..1f64) {
        let time = next_time_lt (coefficients, input, threshold);
        let last_not_lt = match time {
          None => $integer::max_value(),
          Some(k) => {
            prop_assert!(k >= input);
            k-1
          },
        };
        prop_assume!(last_not_lt >= input);
        if let Some(first_coefficients) = coefficients.all_taylor_coefficients (input) { prop_assert!(first_coefficients[0] >= threshold); }
        if let Some(last_coefficients) = coefficients.all_taylor_coefficients (last_not_lt) {prop_assert!(last_coefficients[0] >= threshold); }
        let test_time = input + ((last_not_lt.saturating_sub(input)) as f64 * test_frac).floor() as $integer;
        if let Some(test_coefficients) = coefficients.all_taylor_coefficients (test_time) {prop_assert!(test_coefficients[0] >= threshold); }
      }
    }
  }
)*

  }
}

test_polynomials!(
  1, i32, i64, uniform1, polynomial_tests_1,
  2, i32, i64, uniform2, polynomial_tests_2,
  3, i32, i64, uniform3, polynomial_tests_3,
  4, i32, i64, uniform4, polynomial_tests_4,
  5, i32, i64, uniform5, polynomial_tests_5,
);

}
<commit_msg>Polished some code a bit<commit_after>use num::{Signed, CheckedAdd, CheckedMul, Saturating, One, FromPrimitive};
use array_ext::{Array as ArrayExtArray, *};
use std::cmp::{min, max};
use array::{Array, ReplaceItemType};
use arrayvec::{self, ArrayVec};

use super::*;

pub trait PolynomialBase1 {
  type Coefficient: DoubleSizedInteger + Signed;
}
pub trait PolynomialBase2: PolynomialBase1 + Array + arrayvec::Array<Item = <Self as PolynomialBase1>::Coefficient> + ReplaceItemType<[<Self as PolynomialBase1>::Coefficient; 2]> {}

/// Evaluate all Taylor coefficients of a polynomial.
///
/// Returns None if any of the coefficients do not fit in the type.
pub trait AllTaylorCoefficients<Input>: Sized {
  fn all_taylor_coefficients(&self, input: impl Into<Input>)->Option<Self>;
}

macro_rules! impl_polynomials {
  ($($coefficients: expr),*) => {
$(

impl <Coefficient: DoubleSizedInteger + Signed> PolynomialBase1 for [Coefficient; $coefficients] {type Coefficient = Coefficient; }
impl <Coefficient: DoubleSizedInteger + Signed> PolynomialBase2 for [Coefficient; $coefficients] {}

impl <Coefficient: DoubleSizedInteger> AllTaylorCoefficients<<Coefficient as DoubleSizedInteger>::Type> for [Coefficient; $coefficients] {
  fn all_taylor_coefficients(&self, input: impl Into<<Coefficient as DoubleSizedInteger>::Type>)->Option <Self> {
    let input = input.into();
    let mut intermediates: [<Coefficient as DoubleSizedInteger>::Type; $coefficients] = self.map (| coefficient | coefficient.into());
    for first_source in (1..intermediates.len()).rev() {
      for source in first_source..intermediates.len() {
        intermediates[source - 1] = intermediates [source - 1].checked_add (&intermediates[source].checked_mul (&input)?)?;
      }
    }
    let mut output = [Coefficient::zero(); $coefficients];
    for (index, value) in intermediates.iter().enumerate() {
      output [index] = (*value).try_into().ok()?;
    }
    Some (output)
  }

}

)*

  }
}

impl_polynomials!(1,2,3,4,5);

pub trait Polynomial: PolynomialBase1 + PolynomialBase2 + AllTaylorCoefficients<<<Self as PolynomialBase1>::Coefficient as DoubleSizedInteger>::Type> {}
impl<P: PolynomialBase1 + PolynomialBase2 + AllTaylorCoefficients<<<Self as PolynomialBase1>::Coefficient as DoubleSizedInteger>::Type>> Polynomial for P {}

pub struct RangeSearchEndpoint<P: PolynomialBase2> {
  time: P::Coefficient,
  coefficients: P,
}

pub fn coefficient_ranges<P: PolynomialBase2> (endpoints: [& RangeSearchEndpoint<P>; 2])-><P as ReplaceItemType<[P::Coefficient; 2]>>::Type {
  let mut result: <P as ReplaceItemType<[P::Coefficient; 2]>>::Type = array_ext::Array::from_fn(|_| [P::Coefficient::zero(), P::Coefficient::zero()]);
  // TODO what if overflow
  let duration = endpoints [1].time - endpoints [0].time;
  let mut previous_derivative_range = [P::Coefficient::zero(), P::Coefficient::zero()];
  for exponent in (0..result.len()).rev() {
    let endpoint_0 = endpoints [0].coefficients.as_slice() [exponent];
    let endpoint_1 = endpoints [1].coefficients.as_slice() [exponent];
    let bounds = if previous_derivative_range[0] >= P::Coefficient::zero() {
      [endpoint_0, endpoint_1]
    } else if previous_derivative_range[1] <= P::Coefficient::zero() {
      [endpoint_1, endpoint_0]
    } else {

      // TODO: these bounds can be tightened by analyzing the parallelogram
      // but it might overflow
      // did the algebra as (v1*s1 + v0*-s0 + (t1-t0)*s1*-s0)/(s1+ -s0) = max_value
      // let slope_product = previous_derivative_range[0]*previous_derivative_range[1];

      let previous_max_movement = previous_derivative_range.map(|a|a.saturating_mul(duration));

      let left_max = endpoint_0 + previous_max_movement[1];
      let left_min = endpoint_0 + previous_max_movement[0];

      let right_max = endpoint_1 - previous_max_movement[0];
      let right_min = endpoint_1 - previous_max_movement[1];

      [
        max(left_min, right_min),
        min(left_max, right_max)
      ]
    };

    result.as_mut_slice() [exponent] = bounds;
    previous_derivative_range = bounds.map(|a|a.saturating_mul(P::Coefficient::from_usize(exponent).unwrap()));
  }
  result
}

pub struct RangeSearch<P: PolynomialBase2> {
  polynomial: P,
  stack: ArrayVec<[RangeSearchEndpoint<P>; 64]>,
  next_jump: P::Coefficient,
}

impl<P: Polynomial> RangeSearch<P> {
  pub fn new(polynomial: P, start_time: P::Coefficient)->Option<Self> {
    let mut result = RangeSearch {polynomial, stack: ArrayVec::new(), next_jump: P::Coefficient::one()};
    if let Some(coefficients) = result.polynomial.all_taylor_coefficients (start_time) {
      result.stack.push(RangeSearchEndpoint {time: start_time, coefficients});
      result.add_next_endpoint();
      Some(result)
    }
    else {
      None
    }
  }
  pub fn latest_interval(&self)->[&RangeSearchEndpoint<P>; 2] {
    [
      &self.stack[self.stack.len() - 1],
      &self.stack[self.stack.len() - 2],
    ]
  }
  pub fn split_latest(&mut self) {
    let split_time = mean_floor(self.latest_interval()[0].time, self.latest_interval()[1].time);
    if !self.add_endpoint (split_time) {
      let earliest = self.stack.pop().unwrap();
      self.stack.clear();
      self.stack.push(earliest);
      self.add_next_endpoint();
    }
  }
  pub fn skip_latest(&mut self) {
    self.stack.pop() ;
    if self.stack.len() < 2 {
      self.add_next_endpoint();
    }
  }
  pub fn reached_overflow(&self)->bool {
    self.stack.len() == 2 && self.stack [0].time == self.stack [1].time
  }
  fn add_next_endpoint(&mut self) {
    let last_endpoint_time = self.stack.last().unwrap().time;
    loop {
      let endpoint_time = last_endpoint_time.saturating_add (self.next_jump);
      if self.add_endpoint(endpoint_time) { break; }
      self.next_jump = self.next_jump >> 1;
    }
    self.next_jump = self.next_jump << 1;
  }
  fn add_endpoint(&mut self, time: P::Coefficient)->bool {
    if let Some(coefficients) = self.polynomial.all_taylor_coefficients (time) {
      self.stack.insert (self.stack.len() - 1, RangeSearchEndpoint {time, coefficients});
      true
    }
    else {
      false
    }
  }
}

pub fn next_time_lt <P: Polynomial> (polynomial: P, start_time: P::Coefficient, threshold: P::Coefficient)->Option <P::Coefficient> {
  let mut search = RangeSearch::new(polynomial, start_time)?;

  loop {
    if coefficient_ranges(search.latest_interval()).as_slice()[0][0] < threshold {
      if search.latest_interval()[0].time + P::Coefficient::one() == search.latest_interval()[1].time {
        if search.latest_interval()[0].coefficients.as_slice()[0] < threshold {
          return Some(search.latest_interval()[0].time);
        }
        search.skip_latest();
      }
      else {
        search.split_latest();
      }
    }
    else {
      search.skip_latest();
    }
    if search.reached_overflow() { return None; }
  }
}

/*
fn next_time_in_bounds_2d <T: Polynomial, Input> (polynomials: [T;2], start_time: Input, min: [Coefficient;2], max: Coefficient)->Option <Time> {
  let search: ThresholdSearch = ([min, max+1]);
  while a time when the answer is not yet computed comes before the first time when the answer is known to be within bounds {
    (search with the earliest time not yet computed when the answer is also not yet computed).refine_first_bracketed_root(range of times where it matters);
  }
  search.
}*/

#[cfg(test)]
mod tests {

use super::*;
//use proptest::prelude::*;
use num::{BigInt, One};

fn naive_perfect_evaluate <Coefficient: Integer> (coefficients: & [Coefficient], input: Coefficient)->BigInt where BigInt: From<Coefficient> {
  let input = BigInt::from (input) ;
  let mut result = BigInt::zero();
  for (exponent, coefficient) in coefficients.iter().enumerate() {
    let mut term = BigInt::from(*coefficient);
    for _ in 0..exponent { term = term * &input; }
    result = result + term;
  }
  result
}

fn naive_factorial (value: usize)->BigInt {
  let mut result = BigInt::one();
  for factor in 2..=value {
    result = result * BigInt::from(factor);
  }
  result
}

fn naive_binomial_coefficient(n:usize,k:usize)->BigInt {
  naive_factorial (n)/(naive_factorial (k)*naive_factorial (n-k))
}

fn naive_perfect_nth_taylor_coefficient <Coefficient: Integer> (coefficients: & [Coefficient], input: Coefficient, n: usize)->BigInt where BigInt: From<Coefficient> {
  let input = BigInt::from (input) ;
  let mut result = BigInt::zero();
  for (exponent, coefficient) in coefficients.iter().enumerate().skip(n) {
    let mut term = BigInt::from(*coefficient);
    for _ in n..exponent { term = term * &input; }
    result = result + term * naive_binomial_coefficient (exponent, n);
  }
  result
}

macro_rules! test_polynomials {
  ($($coefficients: expr, $integer: ident, $double: ident, $uniform: ident, $name: ident,)*) => {
$(
  mod $name {
    use super::*;
    //use super::super::*;
    use proptest::prelude::*;
    proptest! {
      #[test]
      fn randomly_test_polynomial_translation_inverts (coefficients in prop::array::$uniform(-16 as $integer..16), input in -16 as $integer..16) {
        let translated = coefficients.all_taylor_coefficients (input);
        prop_assume! (translated.is_some());
        let translated = translated.unwrap();
        let translated_back = translated.all_taylor_coefficients (-input);
        prop_assert! (translated_back.is_some(), "we know that the original value was in bounds, so translating back should return some");
        prop_assert_eq! (coefficients, translated_back.unwrap());

      }

      #[test]
      fn randomly_test_taylor_coefficients_evaluates (coefficients in prop::array::$uniform(-16 as $integer..16), input in -16 as $integer..16) {
        let translated = coefficients.all_taylor_coefficients (input);
        prop_assume! (translated.is_some());
        let translated = translated.unwrap();
        let evaluated = naive_perfect_evaluate (&coefficients, input);
        prop_assert_eq! (BigInt::from(translated[0]), evaluated);
        for which in 0..$coefficients {
          prop_assert_eq! (BigInt::from(translated[which]), naive_perfect_nth_taylor_coefficient(&coefficients, input, which), "Incorrect {}th taylor coefficient ", which);
        }
      }

      #[test]
      fn randomly_test_next_time_lt_is_lt (coefficients in prop::array::$uniform(-16 as $integer..16), input in -16 as $integer..16, threshold in -16 as $integer..16) {
        let time = next_time_lt (coefficients, input, threshold);
        prop_assume! (time .is_some());
        let time = time.unwrap();
        if let Some(coefficients) = coefficients.all_taylor_coefficients (time) { prop_assert!(coefficients[0] < threshold); }
      }

      #[test]
      fn randomly_test_next_time_lt_is_next (coefficients in prop::array::$uniform(-16 as $integer..16), input in -16 as $integer..16, threshold in -16 as $integer..16, test_frac in 0f64..1f64) {
        let time = next_time_lt (coefficients, input, threshold);
        let last_not_lt = match time {
          None => $integer::max_value(),
          Some(k) => {
            prop_assert!(k >= input);
            k-1
          },
        };
        prop_assume!(last_not_lt >= input);
        if let Some(first_coefficients) = coefficients.all_taylor_coefficients (input) { prop_assert!(first_coefficients[0] >= threshold); }
        if let Some(last_coefficients) = coefficients.all_taylor_coefficients (last_not_lt) {prop_assert!(last_coefficients[0] >= threshold); }
        let test_time = input + ((last_not_lt.saturating_sub(input)) as f64 * test_frac).floor() as $integer;
        if let Some(test_coefficients) = coefficients.all_taylor_coefficients (test_time) {prop_assert!(test_coefficients[0] >= threshold); }
      }
    }
  }
)*

  }
}

test_polynomials!(
  1, i32, i64, uniform1, polynomial_tests_1,
  2, i32, i64, uniform2, polynomial_tests_2,
  3, i32, i64, uniform3, polynomial_tests_3,
  4, i32, i64, uniform4, polynomial_tests_4,
  5, i32, i64, uniform5, polynomial_tests_5,
);

}
<|endoftext|>


<commit_before>use std::sync::{
    mpsc::{Receiver, Sender, TryRecvError},
    Arc,
};

use cgmath::prelude::*;
use cgmath::{Point3, Vector4};

use glium::Rect;

use crate::bvh::BVHNode;
use crate::camera::Camera;
use crate::color::Color;
use crate::config::{ColorMode, LightMode, RenderConfig};
use crate::intersect::{Interaction, Ray};
use crate::light::Light;
use crate::pt_renderer::RenderCoordinator;
use crate::scene::Scene;
use crate::Float;

pub struct RenderWorker {
    scene: Arc<Scene>,
    camera: Camera,
    config: RenderConfig,
    coordinator: Arc<RenderCoordinator>,
    message_rx: Receiver<()>,
    result_tx: Sender<(Rect, Vec<f32>)>,
}

impl RenderWorker {
    pub fn new(
        scene: Arc<Scene>,
        camera: Camera,
        config: RenderConfig,
        coordinator: Arc<RenderCoordinator>,
        message_rx: Receiver<()>,
        result_tx: Sender<(Rect, Vec<f32>)>,
    ) -> RenderWorker {
        RenderWorker {
            scene,
            camera,
            config,
            coordinator,
            message_rx,
            result_tx,
        }
    }

    #[allow(clippy::cast_lossless)]
    pub fn run(&self) {
        let (width, height) = (self.coordinator.width, self.coordinator.height);
        let clip_to_world = self.camera.world_to_clip().invert().unwrap();
        let mut node_stack: Vec<(&BVHNode, Float)> = Vec::new();
        loop {
            match self.message_rx.try_recv() {
                Err(TryRecvError::Empty) => (),
                Ok(_) => return,
                Err(TryRecvError::Disconnected) => {
                    println!("Threads were not properly stopped before disconnecting channel!");
                    return;
                }
            }
            if let Some(rect) = self.coordinator.next_block() {
                let mut block = vec![0.0f32; (3 * rect.width * rect.height) as usize];
                for h in 0..rect.height {
                    for w in 0..rect.width {
                        let mut c = Color::black();
                        for j in 0..self.config.samples_per_dir {
                            for i in 0..self.config.samples_per_dir {
                                let dx = (i as Float + rand::random::<Float>())
                                    / self.config.samples_per_dir as Float;
                                let dy = (j as Float + rand::random::<Float>())
                                    / self.config.samples_per_dir as Float;
                                let clip_x =
                                    2.0 * ((rect.left + w) as Float + dx) / width as Float - 1.0;
                                let clip_y =
                                    2.0 * ((rect.bottom + h) as Float + dy) / height as Float - 1.0;
                                let clip_p = Vector4::new(clip_x, clip_y, 1.0, 1.0);
                                let world_p = Point3::from_homogeneous(clip_to_world * clip_p);
                                let ray = Ray::from_point(self.camera.pos, world_p);
                                c += self.trace_ray(ray, &mut node_stack, 0);
                            }
                        }
                        c /= self.config.samples_per_dir.pow(2) as Float;
                        let pixel_i = 3 * (h * rect.width + w) as usize;
                        block[pixel_i] = c.r() as f32;
                        block[pixel_i + 1] = c.g() as f32;
                        block[pixel_i + 2] = c.b() as f32;
                    }
                }
                self.result_tx
                    .send((rect, block))
                    .expect("Receiver closed!");
            } else {
                return;
            }
        }
    }

    fn trace_ray<'a>(
        &'a self,
        mut ray: Ray,
        node_stack: &mut Vec<(&'a BVHNode, Float)>,
        bounce: usize,
    ) -> Color {
        let mut c = Color::black();
        if let Some(hit) = self.scene.intersect(&mut ray, node_stack) {
            let mut isect = hit.interaction(&self.config);
            match self.config.color_mode {
                ColorMode::DebugNormals => return Color::from_normal(isect.n),
                ColorMode::ForwardNormals => {
                    return if isect.n.dot(ray.dir) > 0.0 {
                        Color::from_normal(isect.n)
                    } else {
                        Color::black()
                    }
                }
                ColorMode::Radiance => {
                    // Flip the normal if its pointing to the opposite side from the hit
                    if isect.n.dot(ray.dir) > 0.0 {
                        isect.n *= -1.0;
                    }
                    if bounce == 0 {
                        c += isect.le(-ray.dir);
                    }
                    let (le, mut shadow_ray, light_pdf) = self.sample_light(&isect);
                    if self.scene.intersect(&mut shadow_ray, node_stack).is_none() {
                        let cos_t = isect.n.dot(shadow_ray.dir).max(0.0);
                        c += le * isect.brdf() * cos_t / light_pdf;
                    }
                    let mut pdf = 1.0;
                    let terminate = if bounce < self.config.bounces {
                        false
                    } else if let Some(rr_prob) = self.config.russian_roulette {
                        let rr = rand::random::<Float>();
                        pdf *= 1.0 - rr_prob;
                        rr < rr_prob
                    } else {
                        true
                    };
                    if !terminate {
                        let (brdf, new_ray, brdf_pdf) = isect.sample_brdf();
                        pdf *= brdf_pdf;
                        c += isect.n.dot(new_ray.dir).abs()
                            * brdf
                            * self.trace_ray(new_ray, node_stack, bounce + 1)
                            / pdf;
                    }
                }
            }
        }
        c
    }

    pub fn sample_light(&self, isect: &Interaction) -> (Color, Ray, Float) {
        let (light, pdf) = match self.config.light_mode {
            LightMode::Scene => self.scene.sample_light().unwrap_or((&self.camera, 1.0)),
            LightMode::Camera => (&self.camera as &dyn Light, 1.0),
            LightMode::All => unimplemented!(),
        };
        let (li, ray, lpdf) = light.sample_li(isect);
        (li, ray, pdf * lpdf)
    }
}
<commit_msg>Refactor color modes<commit_after>use std::sync::{
    mpsc::{Receiver, Sender, TryRecvError},
    Arc,
};

use cgmath::prelude::*;
use cgmath::{Point3, Vector4};

use glium::Rect;

use crate::bvh::BVHNode;
use crate::camera::Camera;
use crate::color::Color;
use crate::config::{ColorMode, LightMode, RenderConfig};
use crate::intersect::{Interaction, Ray};
use crate::light::Light;
use crate::pt_renderer::RenderCoordinator;
use crate::scene::Scene;
use crate::Float;

pub struct RenderWorker {
    scene: Arc<Scene>,
    camera: Camera,
    config: RenderConfig,
    coordinator: Arc<RenderCoordinator>,
    message_rx: Receiver<()>,
    result_tx: Sender<(Rect, Vec<f32>)>,
}

impl RenderWorker {
    pub fn new(
        scene: Arc<Scene>,
        camera: Camera,
        config: RenderConfig,
        coordinator: Arc<RenderCoordinator>,
        message_rx: Receiver<()>,
        result_tx: Sender<(Rect, Vec<f32>)>,
    ) -> RenderWorker {
        RenderWorker {
            scene,
            camera,
            config,
            coordinator,
            message_rx,
            result_tx,
        }
    }

    #[allow(clippy::cast_lossless)]
    pub fn run(&self) {
        let (width, height) = (self.coordinator.width, self.coordinator.height);
        let clip_to_world = self.camera.world_to_clip().invert().unwrap();
        let mut node_stack: Vec<(&BVHNode, Float)> = Vec::new();
        loop {
            match self.message_rx.try_recv() {
                Err(TryRecvError::Empty) => (),
                Ok(_) => return,
                Err(TryRecvError::Disconnected) => {
                    println!("Threads were not properly stopped before disconnecting channel!");
                    return;
                }
            }
            if let Some(rect) = self.coordinator.next_block() {
                let mut block = vec![0.0f32; (3 * rect.width * rect.height) as usize];
                for h in 0..rect.height {
                    for w in 0..rect.width {
                        let mut c = Color::black();
                        for j in 0..self.config.samples_per_dir {
                            for i in 0..self.config.samples_per_dir {
                                let dx = (i as Float + rand::random::<Float>())
                                    / self.config.samples_per_dir as Float;
                                let dy = (j as Float + rand::random::<Float>())
                                    / self.config.samples_per_dir as Float;
                                let clip_x =
                                    2.0 * ((rect.left + w) as Float + dx) / width as Float - 1.0;
                                let clip_y =
                                    2.0 * ((rect.bottom + h) as Float + dy) / height as Float - 1.0;
                                let clip_p = Vector4::new(clip_x, clip_y, 1.0, 1.0);
                                let world_p = Point3::from_homogeneous(clip_to_world * clip_p);
                                let ray = Ray::from_point(self.camera.pos, world_p);
                                c += match self.config.color_mode {
                                    ColorMode::DebugNormals => {
                                        self.trace_normals(ray, &mut node_stack, false)
                                    }
                                    ColorMode::ForwardNormals => {
                                        self.trace_normals(ray, &mut node_stack, true)
                                    }
                                    ColorMode::Radiance => {
                                        self.trace_radiance(ray, &mut node_stack, 0)
                                    }
                                }
                            }
                        }
                        c /= self.config.samples_per_dir.pow(2) as Float;
                        let pixel_i = 3 * (h * rect.width + w) as usize;
                        block[pixel_i] = c.r() as f32;
                        block[pixel_i + 1] = c.g() as f32;
                        block[pixel_i + 2] = c.b() as f32;
                    }
                }
                self.result_tx
                    .send((rect, block))
                    .expect("Receiver closed!");
            } else {
                return;
            }
        }
    }

    fn trace_normals<'a>(
        &'a self,
        mut ray: Ray,
        node_stack: &mut Vec<(&'a BVHNode, Float)>,
        forward_only: bool,
    ) -> Color {
        let mut c = Color::black();
        if let Some(hit) = self.scene.intersect(&mut ray, node_stack) {
            let isect = hit.interaction(&self.config);
            if !forward_only || isect.n.dot(ray.dir) > 0.0 {
                c = Color::from_normal(isect.n);
            }
        }
        c
    }

    fn trace_radiance<'a>(
        &'a self,
        mut ray: Ray,
        node_stack: &mut Vec<(&'a BVHNode, Float)>,
        bounce: usize,
    ) -> Color {
        let mut c = Color::black();
        if let Some(hit) = self.scene.intersect(&mut ray, node_stack) {
            let mut isect = hit.interaction(&self.config);
            // Flip the normal if its pointing to the opposite side from the hit
            if isect.n.dot(ray.dir) > 0.0 {
                isect.n *= -1.0;
            }
            if bounce == 0 {
                c += isect.le(-ray.dir);
            }
            let (le, mut shadow_ray, light_pdf) = self.sample_light(&isect);
            if self.scene.intersect(&mut shadow_ray, node_stack).is_none() {
                let cos_t = isect.n.dot(shadow_ray.dir).max(0.0);
                c += le * isect.brdf() * cos_t / light_pdf;
            }
            let mut pdf = 1.0;
            let terminate = if bounce < self.config.bounces {
                false
            } else if let Some(rr_prob) = self.config.russian_roulette {
                let rr = rand::random::<Float>();
                pdf *= 1.0 - rr_prob;
                rr < rr_prob
            } else {
                true
            };
            if !terminate {
                let (brdf, new_ray, brdf_pdf) = isect.sample_brdf();
                pdf *= brdf_pdf;
                c += isect.n.dot(new_ray.dir).abs()
                    * brdf
                    * self.trace_radiance(new_ray, node_stack, bounce + 1)
                    / pdf;
            }
        }
        c
    }

    pub fn sample_light(&self, isect: &Interaction) -> (Color, Ray, Float) {
        let (light, pdf) = match self.config.light_mode {
            LightMode::Scene => self.scene.sample_light().unwrap_or((&self.camera, 1.0)),
            LightMode::Camera => (&self.camera as &dyn Light, 1.0),
            LightMode::All => unimplemented!(),
        };
        let (li, ray, lpdf) = light.sample_li(isect);
        (li, ray, pdf * lpdf)
    }
}
<|endoftext|>


<commit_before><commit_msg>Revert "Bind to localhost"<commit_after><|endoftext|>


<commit_before>use chrono::offset::Local;
use chrono::DateTime;

use ::bot::{Bot, Node, RoomEvent};
use super::backend::Backend;

pub struct ReadQuote {
    quote_db: Backend,
}

impl ReadQuote {
    pub fn new() -> Self {
        Self {
            quote_db: Backend::new()
        }
    }
}

impl<'a> Node<'a> for ReadQuote {
    fn handle(&mut self, bot: &Bot, event: RoomEvent) {
        let revent = &event.raw_event;
        let body = revent.content["body"].as_str().unwrap();

        let mut resp: Option<String> = None;

        if body.starts_with("addquote ") {
            if let Ok(qid) = self.quote_db.add_quote(&revent.sender, &body[9..]) {
                resp = Some(format!("Successfully added quote #{}!", qid));
            } else {
                resp = Some("Failed to add quote.".to_string());
            }
        }

        else if body.starts_with("getquote ") {
            resp = Some(match body[9..].parse() {
                Ok(qid) => {
                    if let Ok((quoter, quote)) = self.quote_db.get_quote(qid) {
                        let datetime: DateTime<Local> = quote.time.into();
                        format!("\"{}\" set by {} {}",
                                quote.value, quoter.user_id,
                                datetime.format("on %Y-%m-%d at %T"))
                    } else {
                        "No quote by that id was found".to_string()
                    }
                },
                Err(_) => "Invalid quote id".to_string(),
            });
        }

        else if body.starts_with("randquote") {
            resp = Some(match self.quote_db.random_quote() {
                Ok((quoter, quote)) => {
                    let datetime: DateTime<Local> = quote.time.into();
                    format!("\"{}\" set by {} {}",
                            quote.value, quoter.user_id,
                            datetime.format("on %Y-%m-%d at %T"))
                },
                Err(_) => "No quote found.".to_string(),
            });
        }

        resp.map(|s| bot.reply(&event, &s));
    }
}
<commit_msg>Output the quote id when getting a random quote<commit_after>use chrono::offset::Local;
use chrono::DateTime;

use ::bot::{Bot, Node, RoomEvent};
use super::backend::Backend;

pub struct ReadQuote {
    quote_db: Backend,
}

impl ReadQuote {
    pub fn new() -> Self {
        Self {
            quote_db: Backend::new()
        }
    }
}

impl<'a> Node<'a> for ReadQuote {
    fn handle(&mut self, bot: &Bot, event: RoomEvent) {
        let revent = &event.raw_event;
        let body = revent.content["body"].as_str().unwrap();

        let mut resp: Option<String> = None;

        if body.starts_with("addquote ") {
            if let Ok(qid) = self.quote_db.add_quote(&revent.sender, &body[9..]) {
                resp = Some(format!("Successfully added quote #{}!", qid));
            } else {
                resp = Some("Failed to add quote.".to_string());
            }
        }

        else if body.starts_with("getquote ") {
            resp = Some(match body[9..].parse() {
                Ok(qid) => {
                    if let Ok((quoter, quote)) = self.quote_db.get_quote(qid) {
                        let datetime: DateTime<Local> = quote.time.into();
                        format!("\"{}\" set by {} {}",
                                quote.value, quoter.user_id,
                                datetime.format("on %Y-%m-%d at %T"))
                    } else {
                        "No quote by that id was found".to_string()
                    }
                },
                Err(_) => "Invalid quote id".to_string(),
            });
        }

        else if body.starts_with("randquote") {
            resp = Some(match self.quote_db.random_quote() {
                Ok((quoter, quote)) => {
                    let datetime: DateTime<Local> = quote.time.into();
                    format!("\"{}\" set by {} {} ~ {}",
                            quote.value, quoter.user_id,
                            datetime.format("on %Y-%m-%d at %T"), quote.id)
                },
                Err(_) => "No quote found.".to_string(),
            });
        }

        resp.map(|s| bot.reply(&event, &s));
    }
}
<|endoftext|>


<commit_before>use bot::LalafellBot;
use tasks::{RunsTask, FromConfig};
use config::Task;
use discord::GetMessages;
use discord::model::ChannelId;
use chrono::prelude::*;
use chrono::Duration;

use error::*;
use serde_json;

use std::sync::Arc;
use std::thread;

#[derive(Debug)]
pub struct DeleteAllMessagesTask {
  config: DeleteAllMessagesTaskConfig,
  next_sleep: i64
}

impl RunsTask for DeleteAllMessagesTask {
  fn start(mut self, s: Arc<LalafellBot>) {
    loop {
      thread::sleep(Duration::seconds(self.next_sleep).to_std().unwrap());
      info!("Delete messages task running");
      let channel = ChannelId(self.config.channel);
      let messages = match s.discord.get_messages(channel, GetMessages::MostRecent, None) {
        Ok(m) => m,
        Err(e) => {
          warn!("Could not get messages for channel {}: {}", channel, e);
          self.next_sleep = 30;
          continue;
        }
      };
      let mut to_delete = Vec::new();
      for message in messages {
        if self.config.except.contains(&message.id.0) {
          continue;
        }
        let timestamp: DateTime<UTC> = match message.timestamp.parse() {
          Ok(t) => t,
          Err(e) => {
            warn!("Could not parse message timestamp: {}", e);
            continue;
          }
        };
        if timestamp + Duration::seconds(self.config.after) > UTC::now() {
          continue;
        }
        to_delete.push(message);
      }
      for chunk in to_delete.chunks(100) {
        let result = if chunk.len() == 1 {
          s.discord.delete_message(channel, chunk[0].id)
        } else {
          let ids: Vec<_> = chunk.iter().map(|m| m.id).collect();
          s.discord.delete_messages(channel, &ids)
        };
        if let Err(e) = result {
          warn!("Could not delete messages: {}", e);
        }
      }
      self.next_sleep = 60;
      info!("Delete messages task done");
    }
  }
}

impl FromConfig for DeleteAllMessagesTask {
  fn from_config(task: &Task) -> Result<Self> {
    let val = match task.config {
      None => bail!("delete_all_messages task is missing configuration"),
      Some(ref val) => val
    };
    let config: DeleteAllMessagesTaskConfig = serde_json::from_value(val.clone()).chain_err(|| "could not parse delete_all_messages configuration")?;
    Ok(DeleteAllMessagesTask {
      config: config,
      next_sleep: Default::default()
    })
  }
}

#[derive(Debug, Deserialize)]
pub struct DeleteAllMessagesTaskConfig {
  pub channel: u64,
  pub after: i64,
  #[serde(default)]
  pub except: Vec<u64>
}
<commit_msg>refactor: update to use new chrono timestamps<commit_after>use bot::LalafellBot;
use tasks::{RunsTask, FromConfig};
use config::Task;
use discord::GetMessages;
use discord::model::ChannelId;
use chrono::prelude::*;
use chrono::Duration;

use error::*;
use serde_json;

use std::sync::Arc;
use std::thread;

#[derive(Debug)]
pub struct DeleteAllMessagesTask {
  config: DeleteAllMessagesTaskConfig,
  next_sleep: i64
}

impl RunsTask for DeleteAllMessagesTask {
  fn start(mut self, s: Arc<LalafellBot>) {
    loop {
      thread::sleep(Duration::seconds(self.next_sleep).to_std().unwrap());
      info!("Delete messages task running");
      let channel = ChannelId(self.config.channel);
      let messages = match s.discord.get_messages(channel, GetMessages::MostRecent, None) {
        Ok(m) => m,
        Err(e) => {
          warn!("Could not get messages for channel {}: {}", channel, e);
          self.next_sleep = 30;
          continue;
        }
      };
      let mut to_delete = Vec::new();
      for message in messages {
        if self.config.except.contains(&message.id.0) {
          continue;
        }
        if message.timestamp.with_timezone(&UTC) + Duration::seconds(self.config.after) > UTC::now() {
          continue;
        }
        to_delete.push(message);
      }
      for chunk in to_delete.chunks(100) {
        let result = if chunk.len() == 1 {
          s.discord.delete_message(channel, chunk[0].id)
        } else {
          let ids: Vec<_> = chunk.iter().map(|m| m.id).collect();
          s.discord.delete_messages(channel, &ids)
        };
        if let Err(e) = result {
          warn!("Could not delete messages: {}", e);
        }
      }
      self.next_sleep = 60;
      info!("Delete messages task done");
    }
  }
}

impl FromConfig for DeleteAllMessagesTask {
  fn from_config(task: &Task) -> Result<Self> {
    let val = match task.config {
      None => bail!("delete_all_messages task is missing configuration"),
      Some(ref val) => val
    };
    let config: DeleteAllMessagesTaskConfig = serde_json::from_value(val.clone()).chain_err(|| "could not parse delete_all_messages configuration")?;
    Ok(DeleteAllMessagesTask {
      config: config,
      next_sleep: Default::default()
    })
  }
}

#[derive(Debug, Deserialize)]
pub struct DeleteAllMessagesTaskConfig {
  pub channel: u64,
  pub after: i64,
  #[serde(default)]
  pub except: Vec<u64>
}
<|endoftext|>


<commit_before>use std::{env, fs, path};
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::{Arc, RwLock};

use client::{self, ApiClient};

use chrono::{self, DateTime, UTC};
use hyper::{self, Uri};
use hyper::header::ContentType;
use jwt;
use openssl::rsa::Rsa;
use serde_json;
use url::form_urlencoded;

mod gcert;

static APP_DEFAULT_PATH: &'static str = ".config/gcloud/application_default_credentials.json";
static APP_DEFAULT_GRANT_TYPE: &'static str = "refresh_token";
static APP_DEFAULT_URI: &'static str = "https://www.googleapis.com/oauth2/v4/token";

static OAUTH_JWT_EXP_DELTA: i64 = 59 * 60; // 59 minutes (in seconds)
static OAUTH_JWT_GRANT_TYPE: &str = "urn:ietf:params:oauth:grant-type:jwt-bearer";
static OAUTH_JWT_DEFAULT_SCOPE: &str = "https://www.googleapis.com/auth/cloud-platform";

pub type Authorization = hyper::header::Authorization<hyper::header::Bearer>;

pub use self::gcert::PubKey;
use self::gcert::KeyRingType;

#[derive(Deserialize, Clone, Debug, Default)]
pub struct Token {
    pub access_token: String,
    pub token_type: String,
    pub expires_in: i64,

    // set manually after deserialization
    #[serde(skip_deserializing)]
    expires_at: Option<DateTime<UTC>>,
}

impl Token {
    pub fn into_header(self) -> Authorization {
        let bearer = hyper::header::Bearer { token: self.access_token };
        hyper::header::Authorization(bearer)
    }
    fn is_expired(&self) -> bool {
        self.expires_at.map_or(true, |at| UTC::now() > at)
    }
}

#[derive(Clone, Debug)]
pub struct GoogleCloudAuth {
    // XXX(don) we only cache a token for the last set of scopes requested.
    token_scopes: Arc<RwLock<(Token, Vec<String>)>>,
    keyrings: Arc<RwLock<HashMap<KeyRingType, gcert::KeyRing>>>,
    adapter: AuthAdapter,
}

impl GoogleCloudAuth {
    pub fn get_firebase_pkey<C: ApiClient>(&self,
                                           client: &C,
                                           kid: &str)
                                           -> client::Result<gcert::PubKey> {
        self.get_pkey(client, kid, KeyRingType::Firebase)
    }

    pub fn get_google_auth_pkey<C: ApiClient>(&self,
                                              client: &C,
                                              kid: &str)
                                              -> client::Result<gcert::PubKey> {
        self.get_pkey(client, kid, KeyRingType::GoogleAuth)
    }

    fn get_pkey<C: ApiClient>(&self,
                              client: &C,
                              kid: &str,
                              ty: KeyRingType)
                              -> client::Result<gcert::PubKey> {
        {
            let ref keyrings = *self.keyrings.read().expect("lock to not be poisoned");
            if let Some(keyring) = keyrings.get(&ty) {
                if let Some(pkey) = keyring.get(kid).ok() {
                    if !keyring.is_expired() {
                        return Ok(pkey);
                    }
                }
            }
        }

        // check if we were blocked on another writer
        let ref mut keyrings = *self.keyrings.write().expect("lock to not be poisoned");
        if let Some(keyring) = keyrings.get(&ty) {
            return keyring.get(kid);
        }

        let keyring = gcert::fetch(client, ty)?;
        keyrings.insert(ty, keyring);
        keyrings[&ty].get(kid)
    }

    pub fn delegate<C: ApiClient>(&self,
                                  client: &C,
                                  id_token: &str,
                                  scopes: &[String])
                                  -> client::Result<Token> {

        match self.adapter {
            // The application default creds are scoped to a user, and thus are not
            // a service account. As such we can't use them for token delegation.
            AuthAdapter::ApplicationDefault(ref auth) => auth.refresh_token(client, scopes),
            AuthAdapter::ServiceAccount(ref auth) => {
                let kid = get_jwt_kid(id_token)?;
                let cert = self.get_google_auth_pkey(client, &kid)?;

                #[derive(Deserialize)]
                struct TokenInfo {
                    email: Option<String>,
                }

                let mut info = jwt::decode::<TokenInfo>(id_token,
                                                        &*cert,
                                                        &jwt::Validation {
                                                             algorithms:
                                                                 Some(vec![jwt::Algorithm::RS256]),
                                                             leeway: 1000 * 60, // 60 seconds
                                                             ..Default::default()
                                                         })
                        .map_err(|_| client::Error::Unauthorized)?;

                let email = info.claims
                    .email
                    .take()
                    .ok_or(client::Error::Unauthorized)?;

                auth.fetch_token(client, Some(&email), scopes)
            }
        }
    }

    pub fn token<C: ApiClient>(&self, client: &C, scopes: &[String]) -> client::Result<Token> {
        {
            let (ref cached_token, ref cached_scopes) = *self.token_scopes
                                                             .read()
                                                             .expect("lock to not be poisoned");
            if !cached_token.is_expired() && cached_scopes.as_slice() == scopes {
                trace!("reusing cached service account oauth token (cached = {:?}, requested = {:?})",
                       cached_scopes.as_slice(),
                       scopes);
                return Ok((*cached_token).clone());
            }
        }

        let (ref mut cached_token, ref mut cached_scopes) = *self.token_scopes
                                                                 .write()
                                                                 .expect("lock to not be poisoned");

        // check is we were blocked on another writer
        if !cached_token.is_expired() && cached_scopes.as_slice() == scopes {
            return Ok(cached_token.clone());
        }

        // refresh the token and shrink the expiration window by 60s
        let mut up_to_date = self.adapter.refresh_token(client, scopes)?;
        let expires_in = chrono::Duration::seconds(up_to_date.expires_in - 60);
        up_to_date.expires_at = Some(UTC::now() + expires_in);

        *cached_token = up_to_date.clone();
        *cached_scopes = Vec::from(scopes);
        Ok(up_to_date)
    }
}

#[derive(Clone, Debug)]
enum AuthAdapter {
    ServiceAccount(ServiceAccountAuth),
    ApplicationDefault(ApplicationDefaultAuth),
}

impl AuthAdapter {
    fn refresh_token<C: ApiClient>(&self, client: &C, scopes: &[String]) -> client::Result<Token> {
        match *self {
            AuthAdapter::ServiceAccount(ref auth) => auth.fetch_token(client, None, scopes),
            AuthAdapter::ApplicationDefault(ref auth) => auth.refresh_token(client, scopes),
        }
    }
}

#[inline(never)] // for stack traces
pub fn default_credentials() -> GoogleCloudAuth {
    let adapter = if let Some(adapter) = credentials_from_env() {
        debug!("Using Google Cloud credentials from [env]");
        adapter
    } else if let Some(adapter) = credentials_from_app_default() {
        debug!("Using Google Cloud credentials from [application_default_credentials]");
        adapter
    } else {
        println!("
            Unable to obtain Google Cloud credentials. Please ensure you have either:
            A) Set GOOGLE_APPLICATION_CREDENTIALS to a valid service account key file
            B) Run the following command 'gcloud auth application-default login'
        ");
        ::std::process::exit(1)
    };

    GoogleCloudAuth {
        adapter: adapter,
        token_scopes: Arc::default(),
        keyrings: Arc::default(),
    }
}

#[inline(never)] // for stack traces
fn credentials_from_env() -> Option<AuthAdapter> {
    #[derive(Deserialize)]
    #[allow(dead_code)]
    struct RawKey {
        #[serde(rename="type")]
        key_type: String,
        project_id: String,
        private_key_id: String,
        #[serde(rename="private_key")]
        private_key_pem: String,
        client_email: String,
        client_id: String,
        auth_uri: String,
        token_uri: String,
        client_x509_cert_url: String,
        auth_provier_x509_cert_url: Option<String>,
    };

    if let Ok(path) = env::var("GOOGLE_APPLICATION_CREDENTIALS") {
        debug!("GOOGLE_APPLICATION_CREDENTIALS={}", path);

        let file = fs::File::open(path).unwrap();
        let raw = serde_json::from_reader::<_, RawKey>(file).unwrap();

        let private_key = Rsa::private_key_from_pem(raw.private_key_pem.as_bytes()).unwrap();
        let private_key_der = private_key.private_key_to_der().unwrap();

        let meta = ServiceAccountMeta {
            token_uri: Uri::from_str(&raw.token_uri).unwrap(),
            aud: raw.token_uri,
            client_email: raw.client_email,
            private_key_der: private_key_der,
        };

        return Some(AuthAdapter::ServiceAccount(ServiceAccountAuth { meta: meta }));
    }
    None
}

// see https://developers.google.com/identity/protocols/OAuth2WebServer#offline
#[inline(never)] // for stack traces
fn credentials_from_app_default() -> Option<AuthAdapter> {
    let homedir = env::home_dir().unwrap_or("./".into());
    let path = path::Path::new(&homedir).join(APP_DEFAULT_PATH);
    debug!("application-default-credentials={:?}", path);

    if path.exists() {
        let file = fs::File::open(path).unwrap();
        let app_default_auth = serde_json::from_reader::<_, ApplicationDefaultAuth>(file).unwrap();
        return Some(AuthAdapter::ApplicationDefault(app_default_auth));
    }
    None
}

#[derive(Deserialize, Clone, Debug)]
struct ApplicationDefaultAuth {
    client_id: String,
    client_secret: String,
    refresh_token: String,
}

impl ApplicationDefaultAuth {
    fn refresh_token<C: ApiClient>(&self, client: &C, _: &[String]) -> client::Result<Token> {
        trace!("refreshing application default token");

        let body = form_urlencoded::Serializer::new(String::new())
            .append_pair("client_id", &self.client_id)
            .append_pair("client_secret", &self.client_secret)
            .append_pair("refresh_token", &self.refresh_token)
            .append_pair("grant_type", APP_DEFAULT_GRANT_TYPE)
            .finish();

        let uri = Uri::from_str(APP_DEFAULT_URI).expect("app default uri to be valid");
        let mut request = hyper::Request::new(hyper::Method::Post, uri);
        request.set_body(body);
        request
            .headers_mut()
            .set(ContentType::form_url_encoded());

        client.request(request).map(|(_, res)| res)
    }
}

#[derive(Clone, Debug)]
struct ServiceAccountAuth {
    meta: ServiceAccountMeta,
}

#[derive(Clone, Debug)]
struct ServiceAccountMeta {
    aud: String,
    token_uri: Uri,
    client_email: String,
    private_key_der: Vec<u8>,
}

impl ServiceAccountAuth {
    fn fetch_token<C: ApiClient>(&self,
                                 client: &C,
                                 sub: Option<&str>,
                                 scopes: &[String])
                                 -> client::Result<Token> {
        trace!("refreshing service account oauth token");

        let scope = if scopes.is_empty() {
            OAUTH_JWT_DEFAULT_SCOPE.to_string()
        } else {
            scopes.join(" ")
        };

        #[derive(Serialize)]
        struct Claims<'a> {
            iss: &'a str, // email addr of the service account
            aud: &'a str, // always https://www.googleapis.com/oauth2/v4/token
            scope: String, // space delimited list of scopes
            iat: i64, // time issued in seconds since epoch
            exp: i64, // no more than 60 minutes after iat
            sub: Option<&'a str>, // User email address if this is a delegated token
        }

        let iat = UTC::now().timestamp();
        let exp = iat + OAUTH_JWT_EXP_DELTA;
        let claims = Claims {
            iss: self.meta.client_email.as_str(),
            aud: self.meta.aud.as_str(),
            scope: scope,
            iat: iat,
            exp: exp,
            sub: sub,
        };

        let header = jwt::Header::new(jwt::Algorithm::RS256);
        let assertion = jwt::encode(&header, &claims, &self.meta.private_key_der)
            .expect("jwt signing not to fail");

        let body = form_urlencoded::Serializer::new(String::new())
            .append_pair("assertion", &assertion)
            .append_pair("grant_type", OAUTH_JWT_GRANT_TYPE)
            .finish();

        let mut request = hyper::Request::new(hyper::Method::Post, self.meta.token_uri.clone());
        request.set_body(body);
        request
            .headers_mut()
            .set(ContentType::form_url_encoded());

        client.request(request).map(|(_, res)| res)
    }
}

fn get_jwt_kid(token: &str) -> client::Result<String> {
    #[derive(Deserialize)]
    struct Empty {};

    let mut info = jwt::decode::<Empty>(token,
                                        &[],
                                        &jwt::Validation {
                                             validate_signature: false,
                                             validate_exp: false,
                                             ..Default::default()
                                         })
            .map_err(|_| client::Error::Unauthorized)?;

    info.header
        .kid
        .take()
        .ok_or(client::Error::Unauthorized)
}
<commit_msg>auth/mod: don't use an expired keyring<commit_after>use std::{env, fs, path};
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::{Arc, RwLock};

use client::{self, ApiClient};

use chrono::{self, DateTime, UTC};
use hyper::{self, Uri};
use hyper::header::ContentType;
use jwt;
use openssl::rsa::Rsa;
use serde_json;
use url::form_urlencoded;

mod gcert;

static APP_DEFAULT_PATH: &'static str = ".config/gcloud/application_default_credentials.json";
static APP_DEFAULT_GRANT_TYPE: &'static str = "refresh_token";
static APP_DEFAULT_URI: &'static str = "https://www.googleapis.com/oauth2/v4/token";

static OAUTH_JWT_EXP_DELTA: i64 = 59 * 60; // 59 minutes (in seconds)
static OAUTH_JWT_GRANT_TYPE: &str = "urn:ietf:params:oauth:grant-type:jwt-bearer";
static OAUTH_JWT_DEFAULT_SCOPE: &str = "https://www.googleapis.com/auth/cloud-platform";

pub type Authorization = hyper::header::Authorization<hyper::header::Bearer>;

pub use self::gcert::PubKey;
use self::gcert::KeyRingType;

#[derive(Deserialize, Clone, Debug, Default)]
pub struct Token {
    pub access_token: String,
    pub token_type: String,
    pub expires_in: i64,

    // set manually after deserialization
    #[serde(skip_deserializing)]
    expires_at: Option<DateTime<UTC>>,
}

impl Token {
    pub fn into_header(self) -> Authorization {
        let bearer = hyper::header::Bearer { token: self.access_token };
        hyper::header::Authorization(bearer)
    }
    fn is_expired(&self) -> bool {
        self.expires_at.map_or(true, |at| UTC::now() > at)
    }
}

#[derive(Clone, Debug)]
pub struct GoogleCloudAuth {
    // XXX(don) we only cache a token for the last set of scopes requested.
    token_scopes: Arc<RwLock<(Token, Vec<String>)>>,
    keyrings: Arc<RwLock<HashMap<KeyRingType, gcert::KeyRing>>>,
    adapter: AuthAdapter,
}

impl GoogleCloudAuth {
    pub fn get_firebase_pkey<C: ApiClient>(&self,
                                           client: &C,
                                           kid: &str)
                                           -> client::Result<gcert::PubKey> {
        self.get_pkey(client, kid, KeyRingType::Firebase)
    }

    pub fn get_google_auth_pkey<C: ApiClient>(&self,
                                              client: &C,
                                              kid: &str)
                                              -> client::Result<gcert::PubKey> {
        self.get_pkey(client, kid, KeyRingType::GoogleAuth)
    }

    fn get_pkey<C: ApiClient>(&self,
                              client: &C,
                              kid: &str,
                              ty: KeyRingType)
                              -> client::Result<gcert::PubKey> {
        {
            let ref keyrings = *self.keyrings.read().expect("lock to not be poisoned");
            if let Some(keyring) = keyrings.get(&ty) {
                if !keyring.is_expired() {
                    if let Some(pkey) = keyring.get(kid).ok() {
                        return Ok(pkey);
                    }
                }
            }
        }

        // check if we were blocked on another writer
        let ref mut keyrings = *self.keyrings.write().expect("lock to not be poisoned");
        if let Some(keyring) = keyrings.get(&ty) {
            if !keyring.is_expired() {
                return keyring.get(kid);
            }
        }

        let keyring = gcert::fetch(client, ty)?;
        keyrings.insert(ty, keyring);
        keyrings[&ty].get(kid)
    }

    pub fn delegate<C: ApiClient>(&self,
                                  client: &C,
                                  id_token: &str,
                                  scopes: &[String])
                                  -> client::Result<Token> {

        match self.adapter {
            // The application default creds are scoped to a user, and thus are not
            // a service account. As such we can't use them for token delegation.
            AuthAdapter::ApplicationDefault(ref auth) => auth.refresh_token(client, scopes),
            AuthAdapter::ServiceAccount(ref auth) => {
                let kid = get_jwt_kid(id_token)?;
                let cert = self.get_google_auth_pkey(client, &kid)?;

                #[derive(Deserialize)]
                struct TokenInfo {
                    email: Option<String>,
                }

                let mut info = jwt::decode::<TokenInfo>(id_token,
                                                        &*cert,
                                                        &jwt::Validation {
                                                             algorithms:
                                                                 Some(vec![jwt::Algorithm::RS256]),
                                                             leeway: 1000 * 60, // 60 seconds
                                                             ..Default::default()
                                                         })
                        .map_err(|_| client::Error::Unauthorized)?;

                let email = info.claims
                    .email
                    .take()
                    .ok_or(client::Error::Unauthorized)?;

                auth.fetch_token(client, Some(&email), scopes)
            }
        }
    }

    pub fn token<C: ApiClient>(&self, client: &C, scopes: &[String]) -> client::Result<Token> {
        {
            let (ref cached_token, ref cached_scopes) = *self.token_scopes
                                                             .read()
                                                             .expect("lock to not be poisoned");
            if !cached_token.is_expired() && cached_scopes.as_slice() == scopes {
                trace!("reusing cached service account oauth token (cached = {:?}, requested = {:?})",
                       cached_scopes.as_slice(),
                       scopes);
                return Ok((*cached_token).clone());
            }
        }

        let (ref mut cached_token, ref mut cached_scopes) = *self.token_scopes
                                                                 .write()
                                                                 .expect("lock to not be poisoned");

        // check is we were blocked on another writer
        if !cached_token.is_expired() && cached_scopes.as_slice() == scopes {
            return Ok(cached_token.clone());
        }

        // refresh the token and shrink the expiration window by 60s
        let mut up_to_date = self.adapter.refresh_token(client, scopes)?;
        let expires_in = chrono::Duration::seconds(up_to_date.expires_in - 60);
        up_to_date.expires_at = Some(UTC::now() + expires_in);

        *cached_token = up_to_date.clone();
        *cached_scopes = Vec::from(scopes);
        Ok(up_to_date)
    }
}

#[derive(Clone, Debug)]
enum AuthAdapter {
    ServiceAccount(ServiceAccountAuth),
    ApplicationDefault(ApplicationDefaultAuth),
}

impl AuthAdapter {
    fn refresh_token<C: ApiClient>(&self, client: &C, scopes: &[String]) -> client::Result<Token> {
        match *self {
            AuthAdapter::ServiceAccount(ref auth) => auth.fetch_token(client, None, scopes),
            AuthAdapter::ApplicationDefault(ref auth) => auth.refresh_token(client, scopes),
        }
    }
}

#[inline(never)] // for stack traces
pub fn default_credentials() -> GoogleCloudAuth {
    let adapter = if let Some(adapter) = credentials_from_env() {
        debug!("Using Google Cloud credentials from [env]");
        adapter
    } else if let Some(adapter) = credentials_from_app_default() {
        debug!("Using Google Cloud credentials from [application_default_credentials]");
        adapter
    } else {
        println!("
            Unable to obtain Google Cloud credentials. Please ensure you have either:
            A) Set GOOGLE_APPLICATION_CREDENTIALS to a valid service account key file
            B) Run the following command 'gcloud auth application-default login'
        ");
        ::std::process::exit(1)
    };

    GoogleCloudAuth {
        adapter: adapter,
        token_scopes: Arc::default(),
        keyrings: Arc::default(),
    }
}

#[inline(never)] // for stack traces
fn credentials_from_env() -> Option<AuthAdapter> {
    #[derive(Deserialize)]
    #[allow(dead_code)]
    struct RawKey {
        #[serde(rename="type")]
        key_type: String,
        project_id: String,
        private_key_id: String,
        #[serde(rename="private_key")]
        private_key_pem: String,
        client_email: String,
        client_id: String,
        auth_uri: String,
        token_uri: String,
        client_x509_cert_url: String,
        auth_provier_x509_cert_url: Option<String>,
    };

    if let Ok(path) = env::var("GOOGLE_APPLICATION_CREDENTIALS") {
        debug!("GOOGLE_APPLICATION_CREDENTIALS={}", path);

        let file = fs::File::open(path).unwrap();
        let raw = serde_json::from_reader::<_, RawKey>(file).unwrap();

        let private_key = Rsa::private_key_from_pem(raw.private_key_pem.as_bytes()).unwrap();
        let private_key_der = private_key.private_key_to_der().unwrap();

        let meta = ServiceAccountMeta {
            token_uri: Uri::from_str(&raw.token_uri).unwrap(),
            aud: raw.token_uri,
            client_email: raw.client_email,
            private_key_der: private_key_der,
        };

        return Some(AuthAdapter::ServiceAccount(ServiceAccountAuth { meta: meta }));
    }
    None
}

// see https://developers.google.com/identity/protocols/OAuth2WebServer#offline
#[inline(never)] // for stack traces
fn credentials_from_app_default() -> Option<AuthAdapter> {
    let homedir = env::home_dir().unwrap_or("./".into());
    let path = path::Path::new(&homedir).join(APP_DEFAULT_PATH);
    debug!("application-default-credentials={:?}", path);

    if path.exists() {
        let file = fs::File::open(path).unwrap();
        let app_default_auth = serde_json::from_reader::<_, ApplicationDefaultAuth>(file).unwrap();
        return Some(AuthAdapter::ApplicationDefault(app_default_auth));
    }
    None
}

#[derive(Deserialize, Clone, Debug)]
struct ApplicationDefaultAuth {
    client_id: String,
    client_secret: String,
    refresh_token: String,
}

impl ApplicationDefaultAuth {
    fn refresh_token<C: ApiClient>(&self, client: &C, _: &[String]) -> client::Result<Token> {
        trace!("refreshing application default token");

        let body = form_urlencoded::Serializer::new(String::new())
            .append_pair("client_id", &self.client_id)
            .append_pair("client_secret", &self.client_secret)
            .append_pair("refresh_token", &self.refresh_token)
            .append_pair("grant_type", APP_DEFAULT_GRANT_TYPE)
            .finish();

        let uri = Uri::from_str(APP_DEFAULT_URI).expect("app default uri to be valid");
        let mut request = hyper::Request::new(hyper::Method::Post, uri);
        request.set_body(body);
        request
            .headers_mut()
            .set(ContentType::form_url_encoded());

        client.request(request).map(|(_, res)| res)
    }
}

#[derive(Clone, Debug)]
struct ServiceAccountAuth {
    meta: ServiceAccountMeta,
}

#[derive(Clone, Debug)]
struct ServiceAccountMeta {
    aud: String,
    token_uri: Uri,
    client_email: String,
    private_key_der: Vec<u8>,
}

impl ServiceAccountAuth {
    fn fetch_token<C: ApiClient>(&self,
                                 client: &C,
                                 sub: Option<&str>,
                                 scopes: &[String])
                                 -> client::Result<Token> {
        trace!("refreshing service account oauth token");

        let scope = if scopes.is_empty() {
            OAUTH_JWT_DEFAULT_SCOPE.to_string()
        } else {
            scopes.join(" ")
        };

        #[derive(Serialize)]
        struct Claims<'a> {
            iss: &'a str, // email addr of the service account
            aud: &'a str, // always https://www.googleapis.com/oauth2/v4/token
            scope: String, // space delimited list of scopes
            iat: i64, // time issued in seconds since epoch
            exp: i64, // no more than 60 minutes after iat
            sub: Option<&'a str>, // User email address if this is a delegated token
        }

        let iat = UTC::now().timestamp();
        let exp = iat + OAUTH_JWT_EXP_DELTA;
        let claims = Claims {
            iss: self.meta.client_email.as_str(),
            aud: self.meta.aud.as_str(),
            scope: scope,
            iat: iat,
            exp: exp,
            sub: sub,
        };

        let header = jwt::Header::new(jwt::Algorithm::RS256);
        let assertion = jwt::encode(&header, &claims, &self.meta.private_key_der)
            .expect("jwt signing not to fail");

        let body = form_urlencoded::Serializer::new(String::new())
            .append_pair("assertion", &assertion)
            .append_pair("grant_type", OAUTH_JWT_GRANT_TYPE)
            .finish();

        let mut request = hyper::Request::new(hyper::Method::Post, self.meta.token_uri.clone());
        request.set_body(body);
        request
            .headers_mut()
            .set(ContentType::form_url_encoded());

        client.request(request).map(|(_, res)| res)
    }
}

fn get_jwt_kid(token: &str) -> client::Result<String> {
    #[derive(Deserialize)]
    struct Empty {};

    let mut info = jwt::decode::<Empty>(token,
                                        &[],
                                        &jwt::Validation {
                                             validate_signature: false,
                                             validate_exp: false,
                                             ..Default::default()
                                         })
            .map_err(|_| client::Error::Unauthorized)?;

    info.header
        .kid
        .take()
        .ok_or(client::Error::Unauthorized)
}
<|endoftext|>


<commit_before>extern crate array_tool;
use libc::c_char;
use std::ffi::{CStr, CString};
use path_parsing::extract_last_path_segment;
use self::array_tool::string::Squeeze;

#[no_mangle]
pub extern "C" fn basename(c_pth: *const c_char, c_ext: *const c_char) -> *const c_char {
  if c_pth.is_null() || c_ext.is_null() {
    return c_pth;
  }
  let pth = unsafe { CStr::from_ptr(c_pth) }.to_str().unwrap();
  let ext = unsafe { CStr::from_ptr(c_ext) }.to_str().unwrap();

  // Two known edge cases.
  match &pth.squeeze("/")[..] {
    "/" => { return CString::new("/").unwrap().into_raw() }
    _ => {}
  }

  let mut name = extract_last_path_segment(pth);

  if ext == ".*" {
    if let Some(dot_i) = name.rfind('.') {
      name = &name[0..dot_i];
    }
  } else if name.ends_with(ext) {
    name = &name[..name.len() - ext.len()];
  };

  CString::new(name).unwrap().into_raw()
}
<commit_msg>update comment [ci skip]<commit_after>extern crate array_tool;
use libc::c_char;
use std::ffi::{CStr, CString};
use path_parsing::extract_last_path_segment;
use self::array_tool::string::Squeeze;

#[no_mangle]
pub extern "C" fn basename(c_pth: *const c_char, c_ext: *const c_char) -> *const c_char {
  if c_pth.is_null() || c_ext.is_null() {
    return c_pth;
  }
  let pth = unsafe { CStr::from_ptr(c_pth) }.to_str().unwrap();
  let ext = unsafe { CStr::from_ptr(c_ext) }.to_str().unwrap();

  // Known edge case
  match &pth.squeeze("/")[..] {
    "/" => { return CString::new("/").unwrap().into_raw() }
    _ => {}
  }

  let mut name = extract_last_path_segment(pth);

  if ext == ".*" {
    if let Some(dot_i) = name.rfind('.') {
      name = &name[0..dot_i];
    }
  } else if name.ends_with(ext) {
    name = &name[..name.len() - ext.len()];
  };

  CString::new(name).unwrap().into_raw()
}
<|endoftext|>