<commit_before>use rustc_serialize::{ json, Encodable };

use std::error::Error;
use std::fs::File;
use std::io::{ Read, Write };
use std::path::Path;

use package::pkg::{ Package, Version };

pub fn get_list(path: &Path) -> Result<Vec<(String, Version)>, String> {
    let mut buffer = String::new();
    let mut file = get!(File::open(path), "An error occured while opening file");

    get!(file.read_to_string(&mut buffer), "An error occured while reading file");
    return Ok(get!(json::decode(&buffer), "An error occured while decoding JSON"))
}

fn raw_update<T: Encodable>(object: &T, path: &Path) -> Result<(), String> {
    let mut file = get!(File::open(path), "An error occured while opening file");
    return match file.write(get!(json::encode(&object), "An error occured while encoding list").as_bytes()) {
        Ok(_) => Ok(()),
        Err(why) => Err(why.description().to_string())
    }
}

pub fn update_list(package: &Package, path: &Path) -> Result<(), String> {
    let mut list: Vec<(String, Version)> = try!(get_list(path));
    for x in 0..(list.len() - 1) {
        if &list[x].0 == &package.name {
            list[x].1 = package.version.clone();
            return raw_update(&list, path)
        }
    };

    list.push((package.name.clone(), package.version.clone()));
    return raw_update(&list, path)
}<commit_msg>Newline<commit_after>use rustc_serialize::{ json, Encodable };

use std::error::Error;
use std::fs::File;
use std::io::{ Read, Write };
use std::path::Path;

use package::pkg::{ Package, Version };

pub fn get_list(path: &Path) -> Result<Vec<(String, Version)>, String> {
    let mut buffer = String::new();
    let mut file = get!(File::open(path), "An error occured while opening file");

    get!(file.read_to_string(&mut buffer), "An error occured while reading file");
    return Ok(get!(json::decode(&buffer), "An error occured while decoding JSON"))
}

fn raw_update<T: Encodable>(object: &T, path: &Path) -> Result<(), String> {
    let mut file = get!(File::open(path), "An error occured while opening file");
    return match file.write(get!(json::encode(&object), "An error occured while encoding list").as_bytes()) {
        Ok(_) => Ok(()),
        Err(why) => Err(why.description().to_string())
    }
}

pub fn update_list(package: &Package, path: &Path) -> Result<(), String> {
    let mut list: Vec<(String, Version)> = try!(get_list(path));
    for x in 0..(list.len() - 1) {
        if &list[x].0 == &package.name {
            list[x].1 = package.version.clone();
            return raw_update(&list, path)
        }
    };

    list.push((package.name.clone(), package.version.clone()));
    return raw_update(&list, path)
}
<|endoftext|>


<commit_before>/// unit creates a type representing a single unit.
///
/// # Examples
///
/// ```
/// #[macro_use(unit)]
/// extern crate fiz_math;
/// use std::fmt::Debug;
///
/// // GoldCoins are golden!
/// unit!(GoldCoins);
///
/// // SilverCoins are like gold coins, only worse!
/// unit!(SilverCoins);
///
/// fn collect<T: Debug>(coins: GoldCoins<T>) {
///     println!("We've collected {:?} golden coins!", coins.0);
/// }
///
/// fn main() {
///     let x = GoldCoins(5);
///     collect(x);
///
///     let y = SilverCoins(6);
///
///     // Try uncommenting the line below and see:
///     //
///     // error: mismatched types: expected `GoldCoins<_>`, found `SilverCoins<_>`"
///     //
///     //collect(y);
///
///     // add, subtract, multiply, divide:
///     assert_eq!(y + SilverCoins(4), SilverCoins(10));
///     assert_eq!(y - SilverCoins(3), SilverCoins(3));
///     assert_eq!(y * SilverCoins(3), SilverCoins(18));
///     assert_eq!(y / SilverCoins(2), SilverCoins(3));
///
///     // ordering and equality:
///     assert!(y < SilverCoins(7));
///     assert!(y > SilverCoins(5));
///     assert!(y <= SilverCoins(6));
///     assert!(y >= SilverCoins(6));
///     assert!(y == SilverCoins(6));
/// }
/// ```
///
#[macro_export]
macro_rules! unit {
    ( $ident:ident ) => {
        #[derive(Copy, Clone, Debug)]
        pub struct $ident<T>(pub T);

        // addition
        impl<T: ::std::ops::Add<Output = T>> ::std::ops::Add for $ident<T> {
            type Output = Self;

            fn add(self, _rhs: Self) -> Self {
                $ident(self.0 + _rhs.0)
            }
        }

        // subtraction
        impl<T: ::std::ops::Sub<Output = T>> ::std::ops::Sub for $ident<T> {
            type Output = Self;

            fn sub(self, _rhs: Self) -> Self {
                $ident(self.0 - _rhs.0)
            }
        }

        // multiplication
        impl<T: ::std::ops::Mul<Output = T>> ::std::ops::Mul for $ident<T> {
            type Output = Self;

            fn mul(self, _rhs: Self) -> Self {
                $ident(self.0 * _rhs.0)
            }
        }

        // division
        impl<T: ::std::ops::Div<Output = T>> ::std::ops::Div for $ident<T> {
            type Output = Self;

            fn div(self, _rhs: Self) -> Self {
                $ident(self.0 / _rhs.0)
            }
        }

        // remainder
        impl<T: ::std::ops::Rem<Output = T>> ::std::ops::Rem for $ident<T> {
            type Output = Self;

            fn rem(self, rhs: Self) -> Self { $ident(self.0 % rhs.0) }
        }

        // negation
        impl<T: ::std::ops::Neg<Output = T>> ::std::ops::Neg for $ident<T> {
            type Output = Self;

            fn neg(self) -> Self::Output { $ident(-self.0) }
        }

        // not
        impl<T: ::std::ops::Not<Output = T>> ::std::ops::Not for $ident<T> {
            type Output = Self;

            fn not(self) -> Self::Output { $ident(!self.0) }
        }

        // bitwise and
        impl<T: ::std::ops::BitAnd<Output = T>> ::std::ops::BitAnd for $ident<T> {
            type Output = Self;

            fn bitand(self, rhs: Self) -> Self::Output { $ident(self.0 & rhs.0) }
        }

        // bitwise or
        impl<T: ::std::ops::BitOr<Output = T>> ::std::ops::BitOr for $ident<T> {
            type Output = Self;

            fn bitor(self, rhs: Self) -> Self::Output { $ident(self.0 | rhs.0) }
        }

        // bitwise xor
        impl<T: ::std::ops::BitXor<Output = T>> ::std::ops::BitXor for $ident<T> {
            type Output = Self;

            fn bitxor(self, rhs: Self) -> Self::Output { $ident(self.0 ^ rhs.0) }
        }

        // shift left
        impl<T: ::std::ops::Shl<usize>> ::std::ops::Shl<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shl(self, rhs: usize) -> Self::Output { $ident(self.0 << rhs) }
        }

        // shift right
        impl<T: ::std::ops::Shr<usize>> ::std::ops::Shr<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shr(self, rhs: usize) -> Self::Output { $ident(self.0 >> rhs) }
        }

        // partial equality
        impl<T: ::std::cmp::PartialEq> ::std::cmp::PartialEq for $ident<T> {
            fn eq(&self, _rhs: &Self) -> bool {
                self.0 == _rhs.0
            }
        }

        // equality
        impl<T: ::std::cmp::Eq> ::std::cmp::Eq for $ident<T> {}

        // partial ordering
        impl<T: ::std::cmp::PartialOrd> ::std::cmp::PartialOrd for $ident<T> {
            fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
                if self.0 < other.0 {
                    Some(::std::cmp::Ordering::Less)
                } else if self.0 > other.0 {
                    Some(::std::cmp::Ordering::Greater)
                } else if self == other {
                    Some(::std::cmp::Ordering::Equal)
                } else {
                    None
                }
            }
        }

        // total ordering
        impl<T: ::std::cmp::Ord> ::std::cmp::Ord for $ident<T> {
            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
                if self.0 < other.0 {
                    ::std::cmp::Ordering::Less
                } else if self.0 > other.0 {
                    ::std::cmp::Ordering::Greater
                } else {
                    ::std::cmp::Ordering::Equal
                }
            }
        }
    };
}
<commit_msg>unit! move std::ops::* and std::cmp::* impl to separate macro patterns<commit_after>/// unit creates a type representing a single unit.
///
/// # Examples
///
/// ```
/// #[macro_use(unit)]
/// extern crate fiz_math;
/// use std::fmt::Debug;
///
/// // GoldCoins are golden!
/// unit!(GoldCoins);
///
/// // SilverCoins are like gold coins, only worse!
/// unit!(SilverCoins);
///
/// fn collect<T: Debug>(coins: GoldCoins<T>) {
///     println!("We've collected {:?} golden coins!", coins.0);
/// }
///
/// fn main() {
///     let x = GoldCoins(5);
///     collect(x);
///
///     let y = SilverCoins(6);
///
///     // Try uncommenting the line below and see:
///     //
///     // error: mismatched types: expected `GoldCoins<_>`, found `SilverCoins<_>`"
///     //
///     //collect(y);
///
///     // add, subtract, multiply, divide:
///     assert_eq!(y + SilverCoins(4), SilverCoins(10));
///     assert_eq!(y - SilverCoins(3), SilverCoins(3));
///     assert_eq!(y * SilverCoins(3), SilverCoins(18));
///     assert_eq!(y / SilverCoins(2), SilverCoins(3));
///
///     // ordering and equality:
///     assert!(y < SilverCoins(7));
///     assert!(y > SilverCoins(5));
///     assert!(y <= SilverCoins(6));
///     assert!(y >= SilverCoins(6));
///     assert!(y == SilverCoins(6));
/// }
/// ```
///
#[macro_export]
macro_rules! unit {
    ( $ident:ident ) => {
        #[derive(Copy, Clone, Debug)]
        pub struct $ident<T>(pub T);

        unit!(impl_std_ops, $ident);
        unit!(impl_std_cmp, $ident);
    };

    (impl_std_ops, $ident:ident ) => {
        // addition
        impl<T: ::std::ops::Add<Output = T>> ::std::ops::Add for $ident<T> {
            type Output = Self;

            fn add(self, _rhs: Self) -> Self {
                $ident(self.0 + _rhs.0)
            }
        }

        // subtraction
        impl<T: ::std::ops::Sub<Output = T>> ::std::ops::Sub for $ident<T> {
            type Output = Self;

            fn sub(self, _rhs: Self) -> Self {
                $ident(self.0 - _rhs.0)
            }
        }

        // multiplication
        impl<T: ::std::ops::Mul<Output = T>> ::std::ops::Mul for $ident<T> {
            type Output = Self;

            fn mul(self, _rhs: Self) -> Self {
                $ident(self.0 * _rhs.0)
            }
        }

        // division
        impl<T: ::std::ops::Div<Output = T>> ::std::ops::Div for $ident<T> {
            type Output = Self;

            fn div(self, _rhs: Self) -> Self {
                $ident(self.0 / _rhs.0)
            }
        }

        // remainder
        impl<T: ::std::ops::Rem<Output = T>> ::std::ops::Rem for $ident<T> {
            type Output = Self;

            fn rem(self, rhs: Self) -> Self { $ident(self.0 % rhs.0) }
        }

        // negation
        impl<T: ::std::ops::Neg<Output = T>> ::std::ops::Neg for $ident<T> {
            type Output = Self;

            fn neg(self) -> Self::Output { $ident(-self.0) }
        }

        // not
        impl<T: ::std::ops::Not<Output = T>> ::std::ops::Not for $ident<T> {
            type Output = Self;

            fn not(self) -> Self::Output { $ident(!self.0) }
        }

        // bitwise and
        impl<T: ::std::ops::BitAnd<Output = T>> ::std::ops::BitAnd for $ident<T> {
            type Output = Self;

            fn bitand(self, rhs: Self) -> Self::Output { $ident(self.0 & rhs.0) }
        }

        // bitwise or
        impl<T: ::std::ops::BitOr<Output = T>> ::std::ops::BitOr for $ident<T> {
            type Output = Self;

            fn bitor(self, rhs: Self) -> Self::Output { $ident(self.0 | rhs.0) }
        }

        // bitwise xor
        impl<T: ::std::ops::BitXor<Output = T>> ::std::ops::BitXor for $ident<T> {
            type Output = Self;

            fn bitxor(self, rhs: Self) -> Self::Output { $ident(self.0 ^ rhs.0) }
        }

        // shift left
        impl<T: ::std::ops::Shl<usize>> ::std::ops::Shl<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shl(self, rhs: usize) -> Self::Output { $ident(self.0 << rhs) }
        }

        // shift right
        impl<T: ::std::ops::Shr<usize>> ::std::ops::Shr<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shr(self, rhs: usize) -> Self::Output { $ident(self.0 >> rhs) }
        }
    };

    (impl_std_cmp, $ident:ident ) => {
        // partial equality
        impl<T: ::std::cmp::PartialEq> ::std::cmp::PartialEq for $ident<T> {
            fn eq(&self, _rhs: &Self) -> bool {
                self.0 == _rhs.0
            }
        }

        // equality
        impl<T: ::std::cmp::Eq> ::std::cmp::Eq for $ident<T> {}

        // partial ordering
        impl<T: ::std::cmp::PartialOrd> ::std::cmp::PartialOrd for $ident<T> {
            fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
                if self.0 < other.0 {
                    Some(::std::cmp::Ordering::Less)
                } else if self.0 > other.0 {
                    Some(::std::cmp::Ordering::Greater)
                } else if self == other {
                    Some(::std::cmp::Ordering::Equal)
                } else {
                    None
                }
            }
        }

        // total ordering
        impl<T: ::std::cmp::Ord> ::std::cmp::Ord for $ident<T> {
            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
                if self.0 < other.0 {
                    ::std::cmp::Ordering::Less
                } else if self.0 > other.0 {
                    ::std::cmp::Ordering::Greater
                } else {
                    ::std::cmp::Ordering::Equal
                }
            }
        }
    };
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

// Imported from clap, to avoid to depend directly to the crate
macro_rules! _clap_count_exprs {
    () => { 0 };
    ($e:expr) => { 1 };
    ($e:expr, $($es:expr),+) => { 1 + _clap_count_exprs!($($es),*) };
}
macro_rules! arg_enum {
    (@as_item $($i:item)*) => ($($i)*);
    (@impls ( $($tts:tt)* ) -> ($e:ident, $($v:ident),+)) => {
        arg_enum!(@as_item
        $($tts)*

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> ::std::result::Result<Self,Self::Err> {
                #[allow(deprecated, unused_imports)]
                use ::std::ascii::AsciiExt;
                match s {
                    $(stringify!($v) |
                    _ if s.eq_ignore_ascii_case(stringify!($v)) => Ok($e::$v)),+,
                    _ => Err({
                        let v = vec![
                            $(stringify!($v),)+
                        ];
                        format!("valid values: {}",
                            v.join(" ,"))
                    }),
                }
            }
        }
        impl ::std::fmt::Display for $e {
            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                match *self {
                    $($e::$v => write!(f, stringify!($v)),)+
                }
            }
        }
        impl $e {
            #[allow(dead_code)]
            pub fn variants() -> [&'static str; _clap_count_exprs!($(stringify!($v)),+)] {
                [
                    $(stringify!($v),)+
                ]
            }
        });
    };
    ($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
        arg_enum!(@impls
            ($(#[$($m),+])+
            pub enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    ($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
        arg_enum!(@impls
            ($(#[$($m),+])+
            pub enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    ($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
        arg_enum!(@impls
            ($(#[$($m),+])+
             enum $e {
                 $($v$(=$val)*),+
             }) -> ($e, $($v),+)
        );
    };
    ($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
        arg_enum!(@impls
            ($(#[$($m),+])+
            enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    (pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
        arg_enum!(@impls
            (pub enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    (pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
        arg_enum!(@impls
            (pub enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    (enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
        arg_enum!(@impls
            (enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    (enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
        arg_enum!(@impls
            (enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
}

//TODO: Nice to have (although I wasnt able to find a way to do it yet in rust): zero-fill arrays that are
// shorter than required.  Need const fn (Rust Issue #24111) or const generics (Rust RFC #2000)
macro_rules! cdf {
    ($($x:expr),+) =>  {[$(32768 - $x),+, 0, 0]}
}

macro_rules! cdf_size {
    ($x:expr) => ($x+1);
}

#[repr(align(16))]
struct Align16;

/// A 16 byte aligned array.
/// # Examples
/// ```
/// extern crate rav1e;
/// use rav1e::util::*;
///
/// let mut x: AlignedArray<[i16; 64 * 64]> = AlignedArray([0; 64 * 64]);
/// assert!(x.array.as_ptr() as usize % 16 == 0);
///
/// let mut x: AlignedArray<[i16; 64 * 64]> = UninitializedAlignedArray();
/// assert!(x.array.as_ptr() as usize % 16 == 0);
/// ```
pub struct AlignedArray<ARRAY>
where
  ARRAY: ?Sized
{
  _alignment: [Align16; 0],
  pub array: ARRAY
}

#[allow(non_snake_case)]
pub fn AlignedArray<ARRAY>(array: ARRAY) -> AlignedArray<ARRAY> {
  AlignedArray { _alignment: [], array }
}

#[allow(non_snake_case)]
pub fn UninitializedAlignedArray<ARRAY>() -> AlignedArray<ARRAY> {
  use std::mem;
  AlignedArray(unsafe { mem::uninitialized() })
}

#[test]
fn sanity() {
  let a: AlignedArray<_> = AlignedArray([0u8; 3]);
  assert!(is_aligned(a.array.as_ptr(), 4));
}

pub trait Fixed {
  fn floor_log2(&self, n: usize) -> usize;
  fn ceil_log2(&self, n: usize) -> usize;
  fn align_power_of_two(&self, n: usize) -> usize;
  fn align_power_of_two_and_shift(&self, n: usize) -> usize;
}

impl Fixed for usize {
  #[inline]
  fn floor_log2(&self, n: usize) -> usize {
    self & !((1 << n) - 1)
  }
  #[inline]
  fn ceil_log2(&self, n: usize) -> usize {
    (self + (1 << n) - 1).floor_log2(n)
  }
  #[inline]
  fn align_power_of_two(&self, n: usize) -> usize {
    self.ceil_log2(n)
  }
  #[inline]
  fn align_power_of_two_and_shift(&self, n: usize) -> usize {
    (self + (1 << n) - 1) >> n
  }
}

/// Check alignment.
pub fn is_aligned<T>(ptr: *const T, n: usize) -> bool {
  ((ptr as usize) & ((1 << n) - 1)) == 0
}

pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
  if input < min {
    min
  } else if input > max {
    max
  } else {
    input
  }
}

use num_traits::PrimInt;
use std::mem::size_of;

pub trait Pixel: PrimInt + Into<u32> + Into<i32> + 'static {}
impl<T> Pixel for T where T: PrimInt + Into<u32> + Into<i32> + 'static {}

pub trait ILog: PrimInt {
  fn ilog(self) -> Self {
    Self::from(size_of::<Self>() * 8 - self.leading_zeros() as usize).unwrap()
  }
}

impl<T> ILog for T where T: PrimInt {}

pub fn msb(x: i32) -> i32 {
  debug_assert!(x > 0);
  31 ^ (x.leading_zeros() as i32)
}
<commit_msg>Impl Pixel only for u8 and u16.<commit_after>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

// Imported from clap, to avoid to depend directly to the crate
macro_rules! _clap_count_exprs {
    () => { 0 };
    ($e:expr) => { 1 };
    ($e:expr, $($es:expr),+) => { 1 + _clap_count_exprs!($($es),*) };
}
macro_rules! arg_enum {
    (@as_item $($i:item)*) => ($($i)*);
    (@impls ( $($tts:tt)* ) -> ($e:ident, $($v:ident),+)) => {
        arg_enum!(@as_item
        $($tts)*

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> ::std::result::Result<Self,Self::Err> {
                #[allow(deprecated, unused_imports)]
                use ::std::ascii::AsciiExt;
                match s {
                    $(stringify!($v) |
                    _ if s.eq_ignore_ascii_case(stringify!($v)) => Ok($e::$v)),+,
                    _ => Err({
                        let v = vec![
                            $(stringify!($v),)+
                        ];
                        format!("valid values: {}",
                            v.join(" ,"))
                    }),
                }
            }
        }
        impl ::std::fmt::Display for $e {
            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                match *self {
                    $($e::$v => write!(f, stringify!($v)),)+
                }
            }
        }
        impl $e {
            #[allow(dead_code)]
            pub fn variants() -> [&'static str; _clap_count_exprs!($(stringify!($v)),+)] {
                [
                    $(stringify!($v),)+
                ]
            }
        });
    };
    ($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
        arg_enum!(@impls
            ($(#[$($m),+])+
            pub enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    ($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
        arg_enum!(@impls
            ($(#[$($m),+])+
            pub enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    ($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
        arg_enum!(@impls
            ($(#[$($m),+])+
             enum $e {
                 $($v$(=$val)*),+
             }) -> ($e, $($v),+)
        );
    };
    ($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
        arg_enum!(@impls
            ($(#[$($m),+])+
            enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    (pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
        arg_enum!(@impls
            (pub enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    (pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
        arg_enum!(@impls
            (pub enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    (enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
        arg_enum!(@impls
            (enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
    (enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
        arg_enum!(@impls
            (enum $e {
                $($v$(=$val)*),+
            }) -> ($e, $($v),+)
        );
    };
}

//TODO: Nice to have (although I wasnt able to find a way to do it yet in rust): zero-fill arrays that are
// shorter than required.  Need const fn (Rust Issue #24111) or const generics (Rust RFC #2000)
macro_rules! cdf {
    ($($x:expr),+) =>  {[$(32768 - $x),+, 0, 0]}
}

macro_rules! cdf_size {
    ($x:expr) => ($x+1);
}

#[repr(align(16))]
struct Align16;

/// A 16 byte aligned array.
/// # Examples
/// ```
/// extern crate rav1e;
/// use rav1e::util::*;
///
/// let mut x: AlignedArray<[i16; 64 * 64]> = AlignedArray([0; 64 * 64]);
/// assert!(x.array.as_ptr() as usize % 16 == 0);
///
/// let mut x: AlignedArray<[i16; 64 * 64]> = UninitializedAlignedArray();
/// assert!(x.array.as_ptr() as usize % 16 == 0);
/// ```
pub struct AlignedArray<ARRAY>
where
  ARRAY: ?Sized
{
  _alignment: [Align16; 0],
  pub array: ARRAY
}

#[allow(non_snake_case)]
pub fn AlignedArray<ARRAY>(array: ARRAY) -> AlignedArray<ARRAY> {
  AlignedArray { _alignment: [], array }
}

#[allow(non_snake_case)]
pub fn UninitializedAlignedArray<ARRAY>() -> AlignedArray<ARRAY> {
  use std::mem;
  AlignedArray(unsafe { mem::uninitialized() })
}

#[test]
fn sanity() {
  let a: AlignedArray<_> = AlignedArray([0u8; 3]);
  assert!(is_aligned(a.array.as_ptr(), 4));
}

pub trait Fixed {
  fn floor_log2(&self, n: usize) -> usize;
  fn ceil_log2(&self, n: usize) -> usize;
  fn align_power_of_two(&self, n: usize) -> usize;
  fn align_power_of_two_and_shift(&self, n: usize) -> usize;
}

impl Fixed for usize {
  #[inline]
  fn floor_log2(&self, n: usize) -> usize {
    self & !((1 << n) - 1)
  }
  #[inline]
  fn ceil_log2(&self, n: usize) -> usize {
    (self + (1 << n) - 1).floor_log2(n)
  }
  #[inline]
  fn align_power_of_two(&self, n: usize) -> usize {
    self.ceil_log2(n)
  }
  #[inline]
  fn align_power_of_two_and_shift(&self, n: usize) -> usize {
    (self + (1 << n) - 1) >> n
  }
}

/// Check alignment.
pub fn is_aligned<T>(ptr: *const T, n: usize) -> bool {
  ((ptr as usize) & ((1 << n) - 1)) == 0
}

pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
  if input < min {
    min
  } else if input > max {
    max
  } else {
    input
  }
}

use num_traits::PrimInt;
use std::mem::size_of;

pub trait Pixel: PrimInt + Into<u32> + Into<i32> + 'static {}
impl Pixel for u8 {}
impl Pixel for u16 {}

pub trait ILog: PrimInt {
  fn ilog(self) -> Self {
    Self::from(size_of::<Self>() * 8 - self.leading_zeros() as usize).unwrap()
  }
}

impl<T> ILog for T where T: PrimInt {}

pub fn msb(x: i32) -> i32 {
  debug_assert!(x > 0);
  31 ^ (x.leading_zeros() as i32)
}
<|endoftext|>


<commit_before>use std::string::ToString;
use std::collections::BTreeMap;
use std::error::Error;
use std::fmt;
use rustc_serialize::json::{Json,ToJson};

use util::Presence::*;

#[derive(Clone, PartialEq, Debug)]
pub enum ParseError {
    InvalidJsonType(String),
    InvalidStructure(String),
    MissingField(String),
    UnknownMethod(String),
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::InvalidJsonType(_)  => "invalid JSON type for conversion",
            ParseError::InvalidStructure(_) => "invalid value structure for conversion",
            ParseError::MissingField(_)     => "missing field",
            ParseError::UnknownMethod(_)    => "unknown method",
        }
    }
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match *self {
            ParseError::InvalidJsonType(ref e)  => format!("invalid JSON type for conversion to {}", e),
            ParseError::InvalidStructure(ref e) => format!("invalid value structure for conversion to {}", e),
            ParseError::MissingField(ref e)     => format!("missing field \"{}\"", e),
            ParseError::UnknownMethod(ref e)    => format!("unknown method \"{}\"", e),
        }.to_string())
    }
}

#[derive(Clone, PartialEq, Debug)]
pub enum Presence<T> {
    Present(T),
    Absent,
}

// trait for things that can be created from a JSON fragment
pub trait FromJson {
    fn from_json(json: &Json) -> Result<Self,ParseError>;
}

// conversions for system types
impl FromJson for String {
    fn from_json(json: &Json) -> Result<String,ParseError> {
        match *json {
            Json::String(ref s) => Ok(s.to_string()),
            _                   => Err(ParseError::InvalidJsonType("String".to_string())),
        }
    }
}
impl FromJson for u64 {
    fn from_json(json: &Json) -> Result<u64,ParseError> {
        match *json {
            Json::U64(n) => Ok(n),
            Json::I64(n) => Ok(n as u64),
            _            => Err(ParseError::InvalidJsonType("u64".to_string())),
        }
    }
}
impl FromJson for bool {
    fn from_json(json: &Json) -> Result<bool,ParseError> {
        match *json {
            Json::Boolean(b) => Ok(b),
            _                => Err(ParseError::InvalidJsonType("bool".to_string())),
        }
    }
}

impl<T> FromJson for Vec<T> where T: FromJson {
    fn from_json(json: &Json) -> Result<Vec<T>,ParseError> {
        match *json {
            Json::Array(ref a) => {
                let (ok, mut err): (Vec<_>,Vec<_>)  = a.iter().map(|ref j| T::from_json(j)).partition(|ref r| match **r { Ok(_) => true, Err(_) => false });
                match err.len() {
                    0 => Ok(ok.into_iter().map(|r| r.ok().unwrap()).collect()),
                    _ => Err(err.remove(0).err().unwrap()),
                }
            }
            _ => Err(ParseError::InvalidJsonType("Vec".to_string())),
        }
    }
}

impl<T> FromJson for BTreeMap<String,T> where T: FromJson {
    fn from_json(json: &Json) -> Result<Self,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut m = BTreeMap::<String,T>::new();
                for (k, v) in o.iter() {
                    let vv = try!(T::from_json(v));
                    m.insert(k.clone(), vv);
                }
                Ok(m)
            },
            _ => Err(ParseError::InvalidJsonType("BTreeMap".to_string()))
        }
    }
}

pub trait FromJsonField {
    fn from_json_field(json: &BTreeMap<String,Json>, field: &str) -> Result<Self,ParseError>;
}

impl<T> FromJsonField for T where T: FromJson {
    fn from_json_field(json: &BTreeMap<String,Json>, field: &str) -> Result<Self,ParseError> {
        match json.get(field) {
            Some(ref v) => T::from_json(&v),
            None        => Err(ParseError::MissingField(field.to_string())),
        }
    }
}
impl<T> FromJsonField for Option<T> where T: FromJson {
    fn from_json_field(json: &BTreeMap<String,Json>, field: &str) -> Result<Self,ParseError> {
        match json.get(field) {
            Some(v) => {
                match *v {
                    Json::Null => Ok(None),
                    _ => match T::from_json(&v) {
                        Ok(j)  => Ok(Some(j)),
                        Err(e) => Err(e),
                    }
                }
            }
            None => Ok(None),
        }
    }
}
impl<T> FromJsonField for Presence<T> where T: FromJson {
    fn from_json_field(json: &BTreeMap<String,Json>, field: &str) -> Result<Self,ParseError> {
        match json.get(field) {
            Some(ref v) => {
                match T::from_json(&v) {
                    Ok(j)  => Ok(Present(j)),
                    Err(e) => Err(e),
                }
            }
            None => Ok(Absent),
        }
    }
}
impl <T> FromJsonField for Presence<Option<T>> where T: FromJson {
    fn from_json_field(json: &BTreeMap<String,Json>, field: &str) -> Result<Self,ParseError> {
        match json.get(field) {
            Some(v) => {
                match *v {
                    Json::Null => Ok(Present(None)),
                    _ => match T::from_json(&v) {
                        Ok(j)  => Ok(Present(Some(j))),
                        Err(e) => Err(e),
                    }
                }
            }
            None => Ok(Absent),
        }
    }
}

pub trait ToJsonField {
    fn to_json_field(&self, json: &mut BTreeMap<String,Json>, field: &str);
}

impl<T> ToJsonField for T where T: ToJson {
    fn to_json_field(&self, json: &mut BTreeMap<String,Json>, field: &str) {
        json.insert(field.to_string(), self.to_json());
    }
}

impl<T> ToJsonField for Presence<T> where T: ToJson {
    fn to_json_field(&self, json: &mut BTreeMap<String,Json>, field: &str) {
        if let Present(ref v) = *self {
            json.insert(field.to_string(), v.to_json());
        }
    }
}
<commit_msg>Make Presence convertible to Option<commit_after>use std::string::ToString;
use std::collections::BTreeMap;
use std::error::Error;
use std::fmt;
use rustc_serialize::json::{Json,ToJson};

use util::Presence::*;

#[derive(Clone, PartialEq, Debug)]
pub enum ParseError {
    InvalidJsonType(String),
    InvalidStructure(String),
    MissingField(String),
    UnknownMethod(String),
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::InvalidJsonType(_)  => "invalid JSON type for conversion",
            ParseError::InvalidStructure(_) => "invalid value structure for conversion",
            ParseError::MissingField(_)     => "missing field",
            ParseError::UnknownMethod(_)    => "unknown method",
        }
    }
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match *self {
            ParseError::InvalidJsonType(ref e)  => format!("invalid JSON type for conversion to {}", e),
            ParseError::InvalidStructure(ref e) => format!("invalid value structure for conversion to {}", e),
            ParseError::MissingField(ref e)     => format!("missing field \"{}\"", e),
            ParseError::UnknownMethod(ref e)    => format!("unknown method \"{}\"", e),
        }.to_string())
    }
}

#[derive(Clone, PartialEq, Debug)]
pub enum Presence<T> {
    Present(T),
    Absent,
}
impl<T> Presence<T> {
    pub fn as_option<'a>(&'a self) -> Option<&'a T> {
        match *self {
            Present(ref tt) => Some(&tt),
            Absent          => None,
        }
    }
}

// trait for things that can be created from a JSON fragment
pub trait FromJson {
    fn from_json(json: &Json) -> Result<Self,ParseError>;
}

// conversions for system types
impl FromJson for String {
    fn from_json(json: &Json) -> Result<String,ParseError> {
        match *json {
            Json::String(ref s) => Ok(s.to_string()),
            _                   => Err(ParseError::InvalidJsonType("String".to_string())),
        }
    }
}
impl FromJson for u64 {
    fn from_json(json: &Json) -> Result<u64,ParseError> {
        match *json {
            Json::U64(n) => Ok(n),
            Json::I64(n) => Ok(n as u64),
            _            => Err(ParseError::InvalidJsonType("u64".to_string())),
        }
    }
}
impl FromJson for bool {
    fn from_json(json: &Json) -> Result<bool,ParseError> {
        match *json {
            Json::Boolean(b) => Ok(b),
            _                => Err(ParseError::InvalidJsonType("bool".to_string())),
        }
    }
}

impl<T> FromJson for Vec<T> where T: FromJson {
    fn from_json(json: &Json) -> Result<Vec<T>,ParseError> {
        match *json {
            Json::Array(ref a) => {
                let (ok, mut err): (Vec<_>,Vec<_>)  = a.iter().map(|ref j| T::from_json(j)).partition(|ref r| match **r { Ok(_) => true, Err(_) => false });
                match err.len() {
                    0 => Ok(ok.into_iter().map(|r| r.ok().unwrap()).collect()),
                    _ => Err(err.remove(0).err().unwrap()),
                }
            }
            _ => Err(ParseError::InvalidJsonType("Vec".to_string())),
        }
    }
}

impl<T> FromJson for BTreeMap<String,T> where T: FromJson {
    fn from_json(json: &Json) -> Result<Self,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut m = BTreeMap::<String,T>::new();
                for (k, v) in o.iter() {
                    let vv = try!(T::from_json(v));
                    m.insert(k.clone(), vv);
                }
                Ok(m)
            },
            _ => Err(ParseError::InvalidJsonType("BTreeMap".to_string()))
        }
    }
}

pub trait FromJsonField {
    fn from_json_field(json: &BTreeMap<String,Json>, field: &str) -> Result<Self,ParseError>;
}

impl<T> FromJsonField for T where T: FromJson {
    fn from_json_field(json: &BTreeMap<String,Json>, field: &str) -> Result<Self,ParseError> {
        match json.get(field) {
            Some(ref v) => T::from_json(&v),
            None        => Err(ParseError::MissingField(field.to_string())),
        }
    }
}
impl<T> FromJsonField for Option<T> where T: FromJson {
    fn from_json_field(json: &BTreeMap<String,Json>, field: &str) -> Result<Self,ParseError> {
        match json.get(field) {
            Some(v) => {
                match *v {
                    Json::Null => Ok(None),
                    _ => match T::from_json(&v) {
                        Ok(j)  => Ok(Some(j)),
                        Err(e) => Err(e),
                    }
                }
            }
            None => Ok(None),
        }
    }
}
impl<T> FromJsonField for Presence<T> where T: FromJson {
    fn from_json_field(json: &BTreeMap<String,Json>, field: &str) -> Result<Self,ParseError> {
        match json.get(field) {
            Some(ref v) => {
                match T::from_json(&v) {
                    Ok(j)  => Ok(Present(j)),
                    Err(e) => Err(e),
                }
            }
            None => Ok(Absent),
        }
    }
}
impl <T> FromJsonField for Presence<Option<T>> where T: FromJson {
    fn from_json_field(json: &BTreeMap<String,Json>, field: &str) -> Result<Self,ParseError> {
        match json.get(field) {
            Some(v) => {
                match *v {
                    Json::Null => Ok(Present(None)),
                    _ => match T::from_json(&v) {
                        Ok(j)  => Ok(Present(Some(j))),
                        Err(e) => Err(e),
                    }
                }
            }
            None => Ok(Absent),
        }
    }
}

pub trait ToJsonField {
    fn to_json_field(&self, json: &mut BTreeMap<String,Json>, field: &str);
}

impl<T> ToJsonField for T where T: ToJson {
    fn to_json_field(&self, json: &mut BTreeMap<String,Json>, field: &str) {
        json.insert(field.to_string(), self.to_json());
    }
}

impl<T> ToJsonField for Presence<T> where T: ToJson {
    fn to_json_field(&self, json: &mut BTreeMap<String,Json>, field: &str) {
        if let Present(ref v) = *self {
            json.insert(field.to_string(), v.to_json());
        }
    }
}
<|endoftext|>


<commit_before>#![allow(unused_variables)]
#![allow(bad_style)]

use std::path::Path;
use std::{fs, io};
use FileTime;

pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    unimplemented!()
}

pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    unimplemented!()
}

pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
    unimplemented!()
}

pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
    unimplemented!()
}

pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
    unimplemented!()
}
<commit_msg>Return an Err instead of panicking<commit_after>#![allow(unused_variables)]
#![allow(bad_style)]

use std::path::Path;
use std::{fs, io};
use FileTime;

pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    Err(io::Error::new(io::ErrorKind::Other, "Wasm not implemented"))
}

pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    Err(io::Error::new(io::ErrorKind::Other, "Wasm not implemented"))
}

pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
    unimplemented!()
}

pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
    unimplemented!()
}

pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
    unimplemented!()
}
<|endoftext|>


<commit_before>mod test_signal;
mod test_socket;
mod test_sockopt;
mod test_termios;
mod test_ioctl;
mod test_wait;
mod test_select;
mod test_uio;
mod test_epoll;
<commit_msg>test/mod.rs: only test epoll on linux.<commit_after>mod test_signal;
mod test_socket;
mod test_sockopt;
mod test_termios;
mod test_ioctl;
mod test_wait;
mod test_select;
mod test_uio;

#[cfg(target_os = "linux")]
mod test_epoll;
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerNonNull, EventHandlerNonNull};
use dom::bindings::codegen::Bindings::WindowBinding;
use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable};
use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::browsercontext::BrowserContext;
use dom::console::Console;
use dom::document::Document;
use dom::eventtarget::{EventTarget, WindowTypeId, EventTargetHelpers};
use dom::location::Location;
use dom::navigator::Navigator;
use dom::performance::Performance;

use layout_interface::{ReflowForDisplay, DocumentDamageLevel};
use script_task::{ExitWindowMsg, FireTimerMsg, Page, ScriptChan, TriggerLoadMsg, TriggerFragmentMsg};
use servo_msg::compositor_msg::ScriptListener;
use servo_net::image_cache_task::ImageCacheTask;
use servo_util::str::DOMString;
use servo_util::task::{spawn_named};
use servo_util::url::parse_url;

use js::jsapi::JSContext;
use js::jsapi::{JS_GC, JS_GetRuntime};
use js::jsval::JSVal;

use collections::hashmap::HashMap;
use std::cell::{Cell, RefCell};
use std::cmp;
use std::comm::{channel, Sender};
use std::comm::Select;
use std::hash::{Hash, sip};
use std::io::timer::Timer;
use std::rc::Rc;

use time;

use serialize::{Encoder, Encodable};
use url::Url;

#[deriving(Eq, Encodable, TotalEq)]
pub struct TimerId(i32);

#[deriving(Encodable)]
pub struct TimerHandle {
    pub handle: TimerId,
    pub data: TimerData,
    pub cancel_chan: Untraceable<Option<Sender<()>>>,
}

impl Hash for TimerId {
    fn hash(&self, state: &mut sip::SipState) {
        let TimerId(id) = *self;
        id.hash(state);
    }
}

impl TimerHandle {
    fn cancel(&mut self) {
        self.cancel_chan.as_ref().map(|chan| chan.send(()));
    }
}

#[deriving(Encodable)]
pub struct Window {
    pub eventtarget: EventTarget,
    pub script_chan: ScriptChan,
    pub console: Cell<Option<JS<Console>>>,
    pub location: Cell<Option<JS<Location>>>,
    pub navigator: Cell<Option<JS<Navigator>>>,
    pub image_cache_task: ImageCacheTask,
    pub active_timers: Traceable<RefCell<HashMap<TimerId, TimerHandle>>>,
    pub next_timer_handle: Untraceable<Cell<i32>>,
    pub compositor: Untraceable<Box<ScriptListener>>,
    pub browser_context: Traceable<RefCell<Option<BrowserContext>>>,
    pub page: Rc<Page>,
    pub performance: Cell<Option<JS<Performance>>>,
    pub navigationStart: u64,
    pub navigationStartPrecise: f64,
}

impl Window {
    pub fn get_cx(&self) -> *mut JSContext {
        let js_info = self.page().js_info();
        (**js_info.get_ref().js_context).ptr
    }

    pub fn page<'a>(&'a self) -> &'a Page {
        &*self.page
    }
    pub fn get_url(&self) -> Url {
        self.page().get_url()
    }
}

#[unsafe_destructor]
impl Drop for Window {
    fn drop(&mut self) {
        for (_, timer_handle) in self.active_timers.borrow_mut().mut_iter() {
            timer_handle.cancel();
        }
    }
}

// Holder for the various JS values associated with setTimeout
// (ie. function value to invoke and all arguments to pass
//      to the function when calling it)
#[deriving(Encodable)]
pub struct TimerData {
    pub is_interval: bool,
    pub funval: Traceable<JSVal>,
}

pub trait WindowMethods {
    fn Alert(&self, s: DOMString);
    fn Close(&self);
    fn Document(&self) -> Temporary<Document>;
    fn Location(&self) -> Temporary<Location>;
    fn Console(&self) -> Temporary<Console>;
    fn Navigator(&self) -> Temporary<Navigator>;
    fn SetTimeout(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32;
    fn ClearTimeout(&self, handle: i32);
    fn SetInterval(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32;
    fn ClearInterval(&self, handle: i32);
    fn Window(&self) -> Temporary<Window>;
    fn Self(&self) -> Temporary<Window>;
    fn Performance(&self) -> Temporary<Performance>;
    fn GetOnclick(&self) -> Option<EventHandlerNonNull>;
    fn SetOnclick(&self, listener: Option<EventHandlerNonNull>);
    fn GetOnload(&self) -> Option<EventHandlerNonNull>;
    fn SetOnload(&self, listener: Option<EventHandlerNonNull>);
    fn GetOnunload(&self) -> Option<EventHandlerNonNull>;
    fn SetOnunload(&self, listener: Option<EventHandlerNonNull>);
    fn GetOnerror(&self) -> Option<OnErrorEventHandlerNonNull>;
    fn SetOnerror(&self, listener: Option<OnErrorEventHandlerNonNull>);
    fn Debug(&self, message: DOMString);
    fn Gc(&self);
}

impl<'a> WindowMethods for JSRef<'a, Window> {
    fn Alert(&self, s: DOMString) {
        // Right now, just print to the console
        println!("ALERT: {:s}", s);
    }

    fn Close(&self) {
        let ScriptChan(ref chan) = self.script_chan;
        chan.send(ExitWindowMsg(self.page.id.clone()));
    }

    fn Document(&self) -> Temporary<Document> {
        let frame = self.page().frame();
        Temporary::new(frame.get_ref().document.clone())
    }

    fn Location(&self) -> Temporary<Location> {
        if self.location.get().is_none() {
            let page = self.deref().page.clone();
            let location = Location::new(self, page);
            self.location.assign(Some(location));
        }
        Temporary::new(self.location.get().get_ref().clone())
    }

    fn Console(&self) -> Temporary<Console> {
        if self.console.get().is_none() {
            let console = Console::new(self);
            self.console.assign(Some(console));
        }
        Temporary::new(self.console.get().get_ref().clone())
    }

    fn Navigator(&self) -> Temporary<Navigator> {
        if self.navigator.get().is_none() {
            let navigator = Navigator::new(self);
            self.navigator.assign(Some(navigator));
        }
        Temporary::new(self.navigator.get().get_ref().clone())
    }

    fn SetTimeout(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
        self.set_timeout_or_interval(callback, timeout, false)
    }

    fn ClearTimeout(&self, handle: i32) {
        let mut timers = self.active_timers.deref().borrow_mut();
        let mut timer_handle = timers.pop(&TimerId(handle));
        match timer_handle {
            Some(ref mut handle) => handle.cancel(),
            None => { }
        }
        timers.remove(&TimerId(handle));
    }

    fn SetInterval(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
        self.set_timeout_or_interval(callback, timeout, true)
    }

    fn ClearInterval(&self, handle: i32) {
        self.ClearTimeout(handle);
    }

    fn Window(&self) -> Temporary<Window> {
        Temporary::from_rooted(self)
    }

    fn Self(&self) -> Temporary<Window> {
        self.Window()
    }

    fn Performance(&self) -> Temporary<Performance> {
        if self.performance.get().is_none() {
            let performance = Performance::new(self);
            self.performance.assign(Some(performance));
        }
        Temporary::new(self.performance.get().get_ref().clone())
    }

    fn GetOnclick(&self) -> Option<EventHandlerNonNull> {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.get_event_handler_common("click")
    }

    fn SetOnclick(&self, listener: Option<EventHandlerNonNull>) {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.set_event_handler_common("click", listener)
    }

    fn GetOnload(&self) -> Option<EventHandlerNonNull> {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.get_event_handler_common("load")
    }

    fn SetOnload(&self, listener: Option<EventHandlerNonNull>) {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.set_event_handler_common("load", listener)
    }

    fn GetOnunload(&self) -> Option<EventHandlerNonNull> {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.get_event_handler_common("unload")
    }

    fn SetOnunload(&self, listener: Option<EventHandlerNonNull>) {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.set_event_handler_common("unload", listener)
    }

    fn GetOnerror(&self) -> Option<OnErrorEventHandlerNonNull> {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.get_event_handler_common("error")
    }

    fn SetOnerror(&self, listener: Option<OnErrorEventHandlerNonNull>) {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.set_event_handler_common("error", listener)
    }

    fn Debug(&self, message: DOMString) {
        debug!("{:s}", message);
    }

    fn Gc(&self) {
        unsafe {
            JS_GC(JS_GetRuntime(self.get_cx()));
        }
    }
}

impl Reflectable for Window {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.eventtarget.reflector()
    }

    fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
        self.eventtarget.mut_reflector()
    }
}

pub trait WindowHelpers {
    fn damage_and_reflow(&self, damage: DocumentDamageLevel);
    fn wait_until_safe_to_modify_dom(&self);
    fn init_browser_context(&self, doc: &JSRef<Document>);
    fn load_url(&self, href: DOMString);
}

trait PrivateWindowHelpers {
    fn set_timeout_or_interval(&self, callback: JSVal, timeout: i32, is_interval: bool) -> i32;
}

impl<'a> WindowHelpers for JSRef<'a, Window> {
    fn damage_and_reflow(&self, damage: DocumentDamageLevel) {
        // FIXME This should probably be ReflowForQuery, not Display. All queries currently
        // currently rely on the display list, which means we can't destroy it by
        // doing a query reflow.
        self.page().damage(damage);
        self.page().reflow(ReflowForDisplay, self.script_chan.clone(), *self.compositor);
    }

    fn wait_until_safe_to_modify_dom(&self) {
        // FIXME: This disables concurrent layout while we are modifying the DOM, since
        //        our current architecture is entirely unsafe in the presence of races.
        self.page().join_layout();
    }

    fn init_browser_context(&self, doc: &JSRef<Document>) {
        *self.browser_context.deref().borrow_mut() = Some(BrowserContext::new(doc));
    }

    /// Commence a new URL load which will either replace this window or scroll to a fragment.
    fn load_url(&self, href: DOMString) {
        let base_url = Some(self.page().get_url());
        debug!("current page url is {:?}", base_url);
        let url = parse_url(href.as_slice(), base_url);
        let ScriptChan(ref script_chan) = self.script_chan;
        if href.as_slice().starts_with("#") {
            script_chan.send(TriggerFragmentMsg(self.page.id, url));
        } else {
            script_chan.send(TriggerLoadMsg(self.page.id, url));
        }
    }
}

impl<'a> PrivateWindowHelpers for JSRef<'a, Window> {
    fn set_timeout_or_interval(&self, callback: JSVal, timeout: i32, is_interval: bool) -> i32 {
        let timeout = cmp::max(0, timeout) as u64;
        let handle = self.next_timer_handle.deref().get();
        self.next_timer_handle.deref().set(handle + 1);

        // Post a delayed message to the per-window timer task; it will dispatch it
        // to the relevant script handler that will deal with it.
        let tm = Timer::new().unwrap();
        let (cancel_chan, cancel_port) = channel();
        let chan = self.script_chan.clone();
        let page_id = self.page.id.clone();
        let spawn_name = if is_interval {
            "Window:SetInterval"
        } else {
            "Window:SetTimeout"
        };
        spawn_named(spawn_name, proc() {
            let mut tm = tm;
            let timeout_port = if is_interval {
                tm.periodic(timeout)
            } else {
                tm.oneshot(timeout)
            };
            let cancel_port = cancel_port;

            let select = Select::new();
            let mut timeout_handle = select.handle(&timeout_port);
            unsafe { timeout_handle.add() };
            let mut cancel_handle = select.handle(&cancel_port);
            unsafe { cancel_handle.add() };

            loop {
                let id = select.wait();
                if id == timeout_handle.id() {
                    timeout_port.recv();
                    let ScriptChan(ref chan) = chan;
                    chan.send(FireTimerMsg(page_id, TimerId(handle)));
                    if !is_interval {
                        break;
                    }
                } else if id == cancel_handle.id() {
                    break;
                }
            }
        });
        let timer_id = TimerId(handle);
        let timer = TimerHandle {
            handle: timer_id,
            cancel_chan: Untraceable::new(Some(cancel_chan)),
            data: TimerData {
                is_interval: is_interval,
                funval: Traceable::new(callback),
            }
        };
        self.active_timers.deref().borrow_mut().insert(timer_id, timer);
        handle
    }
}

impl Window {
    pub fn new(cx: *mut JSContext,
               page: Rc<Page>,
               script_chan: ScriptChan,
               compositor: Box<ScriptListener>,
               image_cache_task: ImageCacheTask)
               -> JS<Window> {
        let win = box Window {
            eventtarget: EventTarget::new_inherited(WindowTypeId),
            script_chan: script_chan,
            console: Cell::new(None),
            compositor: Untraceable::new(compositor),
            page: page,
            location: Cell::new(None),
            navigator: Cell::new(None),
            image_cache_task: image_cache_task,
            active_timers: Traceable::new(RefCell::new(HashMap::new())),
            next_timer_handle: Untraceable::new(Cell::new(0)),
            browser_context: Traceable::new(RefCell::new(None)),
            performance: Cell::new(None),
            navigationStart: time::get_time().sec as u64,
            navigationStartPrecise: time::precise_time_s(),
        };

        WindowBinding::Wrap(cx, win)
    }
}
<commit_msg>Don't fail on clearing nonexistant timeouts<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerNonNull, EventHandlerNonNull};
use dom::bindings::codegen::Bindings::WindowBinding;
use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable};
use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::browsercontext::BrowserContext;
use dom::console::Console;
use dom::document::Document;
use dom::eventtarget::{EventTarget, WindowTypeId, EventTargetHelpers};
use dom::location::Location;
use dom::navigator::Navigator;
use dom::performance::Performance;

use layout_interface::{ReflowForDisplay, DocumentDamageLevel};
use script_task::{ExitWindowMsg, FireTimerMsg, Page, ScriptChan, TriggerLoadMsg, TriggerFragmentMsg};
use servo_msg::compositor_msg::ScriptListener;
use servo_net::image_cache_task::ImageCacheTask;
use servo_util::str::DOMString;
use servo_util::task::{spawn_named};
use servo_util::url::parse_url;

use js::jsapi::JSContext;
use js::jsapi::{JS_GC, JS_GetRuntime};
use js::jsval::JSVal;

use collections::hashmap::HashMap;
use std::cell::{Cell, RefCell};
use std::cmp;
use std::comm::{channel, Sender};
use std::comm::Select;
use std::hash::{Hash, sip};
use std::io::timer::Timer;
use std::rc::Rc;

use time;

use serialize::{Encoder, Encodable};
use url::Url;

#[deriving(Eq, Encodable, TotalEq)]
pub struct TimerId(i32);

#[deriving(Encodable)]
pub struct TimerHandle {
    pub handle: TimerId,
    pub data: TimerData,
    pub cancel_chan: Untraceable<Option<Sender<()>>>,
}

impl Hash for TimerId {
    fn hash(&self, state: &mut sip::SipState) {
        let TimerId(id) = *self;
        id.hash(state);
    }
}

impl TimerHandle {
    fn cancel(&mut self) {
        self.cancel_chan.as_ref().map(|chan| chan.send_opt(()).ok());
    }
}

#[deriving(Encodable)]
pub struct Window {
    pub eventtarget: EventTarget,
    pub script_chan: ScriptChan,
    pub console: Cell<Option<JS<Console>>>,
    pub location: Cell<Option<JS<Location>>>,
    pub navigator: Cell<Option<JS<Navigator>>>,
    pub image_cache_task: ImageCacheTask,
    pub active_timers: Traceable<RefCell<HashMap<TimerId, TimerHandle>>>,
    pub next_timer_handle: Untraceable<Cell<i32>>,
    pub compositor: Untraceable<Box<ScriptListener>>,
    pub browser_context: Traceable<RefCell<Option<BrowserContext>>>,
    pub page: Rc<Page>,
    pub performance: Cell<Option<JS<Performance>>>,
    pub navigationStart: u64,
    pub navigationStartPrecise: f64,
}

impl Window {
    pub fn get_cx(&self) -> *mut JSContext {
        let js_info = self.page().js_info();
        (**js_info.get_ref().js_context).ptr
    }

    pub fn page<'a>(&'a self) -> &'a Page {
        &*self.page
    }
    pub fn get_url(&self) -> Url {
        self.page().get_url()
    }
}

#[unsafe_destructor]
impl Drop for Window {
    fn drop(&mut self) {
        for (_, timer_handle) in self.active_timers.borrow_mut().mut_iter() {
            timer_handle.cancel();
        }
    }
}

// Holder for the various JS values associated with setTimeout
// (ie. function value to invoke and all arguments to pass
//      to the function when calling it)
#[deriving(Encodable)]
pub struct TimerData {
    pub is_interval: bool,
    pub funval: Traceable<JSVal>,
}

pub trait WindowMethods {
    fn Alert(&self, s: DOMString);
    fn Close(&self);
    fn Document(&self) -> Temporary<Document>;
    fn Location(&self) -> Temporary<Location>;
    fn Console(&self) -> Temporary<Console>;
    fn Navigator(&self) -> Temporary<Navigator>;
    fn SetTimeout(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32;
    fn ClearTimeout(&self, handle: i32);
    fn SetInterval(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32;
    fn ClearInterval(&self, handle: i32);
    fn Window(&self) -> Temporary<Window>;
    fn Self(&self) -> Temporary<Window>;
    fn Performance(&self) -> Temporary<Performance>;
    fn GetOnclick(&self) -> Option<EventHandlerNonNull>;
    fn SetOnclick(&self, listener: Option<EventHandlerNonNull>);
    fn GetOnload(&self) -> Option<EventHandlerNonNull>;
    fn SetOnload(&self, listener: Option<EventHandlerNonNull>);
    fn GetOnunload(&self) -> Option<EventHandlerNonNull>;
    fn SetOnunload(&self, listener: Option<EventHandlerNonNull>);
    fn GetOnerror(&self) -> Option<OnErrorEventHandlerNonNull>;
    fn SetOnerror(&self, listener: Option<OnErrorEventHandlerNonNull>);
    fn Debug(&self, message: DOMString);
    fn Gc(&self);
}

impl<'a> WindowMethods for JSRef<'a, Window> {
    fn Alert(&self, s: DOMString) {
        // Right now, just print to the console
        println!("ALERT: {:s}", s);
    }

    fn Close(&self) {
        let ScriptChan(ref chan) = self.script_chan;
        chan.send(ExitWindowMsg(self.page.id.clone()));
    }

    fn Document(&self) -> Temporary<Document> {
        let frame = self.page().frame();
        Temporary::new(frame.get_ref().document.clone())
    }

    fn Location(&self) -> Temporary<Location> {
        if self.location.get().is_none() {
            let page = self.deref().page.clone();
            let location = Location::new(self, page);
            self.location.assign(Some(location));
        }
        Temporary::new(self.location.get().get_ref().clone())
    }

    fn Console(&self) -> Temporary<Console> {
        if self.console.get().is_none() {
            let console = Console::new(self);
            self.console.assign(Some(console));
        }
        Temporary::new(self.console.get().get_ref().clone())
    }

    fn Navigator(&self) -> Temporary<Navigator> {
        if self.navigator.get().is_none() {
            let navigator = Navigator::new(self);
            self.navigator.assign(Some(navigator));
        }
        Temporary::new(self.navigator.get().get_ref().clone())
    }

    fn SetTimeout(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
        self.set_timeout_or_interval(callback, timeout, false)
    }

    fn ClearTimeout(&self, handle: i32) {
        let mut timers = self.active_timers.deref().borrow_mut();
        let mut timer_handle = timers.pop(&TimerId(handle));
        match timer_handle {
            Some(ref mut handle) => handle.cancel(),
            None => { }
        }
        timers.remove(&TimerId(handle));
    }

    fn SetInterval(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
        self.set_timeout_or_interval(callback, timeout, true)
    }

    fn ClearInterval(&self, handle: i32) {
        self.ClearTimeout(handle);
    }

    fn Window(&self) -> Temporary<Window> {
        Temporary::from_rooted(self)
    }

    fn Self(&self) -> Temporary<Window> {
        self.Window()
    }

    fn Performance(&self) -> Temporary<Performance> {
        if self.performance.get().is_none() {
            let performance = Performance::new(self);
            self.performance.assign(Some(performance));
        }
        Temporary::new(self.performance.get().get_ref().clone())
    }

    fn GetOnclick(&self) -> Option<EventHandlerNonNull> {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.get_event_handler_common("click")
    }

    fn SetOnclick(&self, listener: Option<EventHandlerNonNull>) {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.set_event_handler_common("click", listener)
    }

    fn GetOnload(&self) -> Option<EventHandlerNonNull> {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.get_event_handler_common("load")
    }

    fn SetOnload(&self, listener: Option<EventHandlerNonNull>) {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.set_event_handler_common("load", listener)
    }

    fn GetOnunload(&self) -> Option<EventHandlerNonNull> {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.get_event_handler_common("unload")
    }

    fn SetOnunload(&self, listener: Option<EventHandlerNonNull>) {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.set_event_handler_common("unload", listener)
    }

    fn GetOnerror(&self) -> Option<OnErrorEventHandlerNonNull> {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.get_event_handler_common("error")
    }

    fn SetOnerror(&self, listener: Option<OnErrorEventHandlerNonNull>) {
        let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
        eventtarget.set_event_handler_common("error", listener)
    }

    fn Debug(&self, message: DOMString) {
        debug!("{:s}", message);
    }

    fn Gc(&self) {
        unsafe {
            JS_GC(JS_GetRuntime(self.get_cx()));
        }
    }
}

impl Reflectable for Window {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.eventtarget.reflector()
    }

    fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
        self.eventtarget.mut_reflector()
    }
}

pub trait WindowHelpers {
    fn damage_and_reflow(&self, damage: DocumentDamageLevel);
    fn wait_until_safe_to_modify_dom(&self);
    fn init_browser_context(&self, doc: &JSRef<Document>);
    fn load_url(&self, href: DOMString);
}

trait PrivateWindowHelpers {
    fn set_timeout_or_interval(&self, callback: JSVal, timeout: i32, is_interval: bool) -> i32;
}

impl<'a> WindowHelpers for JSRef<'a, Window> {
    fn damage_and_reflow(&self, damage: DocumentDamageLevel) {
        // FIXME This should probably be ReflowForQuery, not Display. All queries currently
        // currently rely on the display list, which means we can't destroy it by
        // doing a query reflow.
        self.page().damage(damage);
        self.page().reflow(ReflowForDisplay, self.script_chan.clone(), *self.compositor);
    }

    fn wait_until_safe_to_modify_dom(&self) {
        // FIXME: This disables concurrent layout while we are modifying the DOM, since
        //        our current architecture is entirely unsafe in the presence of races.
        self.page().join_layout();
    }

    fn init_browser_context(&self, doc: &JSRef<Document>) {
        *self.browser_context.deref().borrow_mut() = Some(BrowserContext::new(doc));
    }

    /// Commence a new URL load which will either replace this window or scroll to a fragment.
    fn load_url(&self, href: DOMString) {
        let base_url = Some(self.page().get_url());
        debug!("current page url is {:?}", base_url);
        let url = parse_url(href.as_slice(), base_url);
        let ScriptChan(ref script_chan) = self.script_chan;
        if href.as_slice().starts_with("#") {
            script_chan.send(TriggerFragmentMsg(self.page.id, url));
        } else {
            script_chan.send(TriggerLoadMsg(self.page.id, url));
        }
    }
}

impl<'a> PrivateWindowHelpers for JSRef<'a, Window> {
    fn set_timeout_or_interval(&self, callback: JSVal, timeout: i32, is_interval: bool) -> i32 {
        let timeout = cmp::max(0, timeout) as u64;
        let handle = self.next_timer_handle.deref().get();
        self.next_timer_handle.deref().set(handle + 1);

        // Post a delayed message to the per-window timer task; it will dispatch it
        // to the relevant script handler that will deal with it.
        let tm = Timer::new().unwrap();
        let (cancel_chan, cancel_port) = channel();
        let chan = self.script_chan.clone();
        let page_id = self.page.id.clone();
        let spawn_name = if is_interval {
            "Window:SetInterval"
        } else {
            "Window:SetTimeout"
        };
        spawn_named(spawn_name, proc() {
            let mut tm = tm;
            let timeout_port = if is_interval {
                tm.periodic(timeout)
            } else {
                tm.oneshot(timeout)
            };
            let cancel_port = cancel_port;

            let select = Select::new();
            let mut timeout_handle = select.handle(&timeout_port);
            unsafe { timeout_handle.add() };
            let mut cancel_handle = select.handle(&cancel_port);
            unsafe { cancel_handle.add() };

            loop {
                let id = select.wait();
                if id == timeout_handle.id() {
                    timeout_port.recv();
                    let ScriptChan(ref chan) = chan;
                    chan.send(FireTimerMsg(page_id, TimerId(handle)));
                    if !is_interval {
                        break;
                    }
                } else if id == cancel_handle.id() {
                    break;
                }
            }
        });
        let timer_id = TimerId(handle);
        let timer = TimerHandle {
            handle: timer_id,
            cancel_chan: Untraceable::new(Some(cancel_chan)),
            data: TimerData {
                is_interval: is_interval,
                funval: Traceable::new(callback),
            }
        };
        self.active_timers.deref().borrow_mut().insert(timer_id, timer);
        handle
    }
}

impl Window {
    pub fn new(cx: *mut JSContext,
               page: Rc<Page>,
               script_chan: ScriptChan,
               compositor: Box<ScriptListener>,
               image_cache_task: ImageCacheTask)
               -> JS<Window> {
        let win = box Window {
            eventtarget: EventTarget::new_inherited(WindowTypeId),
            script_chan: script_chan,
            console: Cell::new(None),
            compositor: Untraceable::new(compositor),
            page: page,
            location: Cell::new(None),
            navigator: Cell::new(None),
            image_cache_task: image_cache_task,
            active_timers: Traceable::new(RefCell::new(HashMap::new())),
            next_timer_handle: Untraceable::new(Cell::new(0)),
            browser_context: Traceable::new(RefCell::new(None)),
            performance: Cell::new(None),
            navigationStart: time::get_time().sec as u64,
            navigationStartPrecise: time::precise_time_s(),
        };

        WindowBinding::Wrap(cx, win)
    }
}
<|endoftext|>


<commit_before>mod renderer_server_process;

pub use renderer_server_process::*;

use std::sync::Arc;

use ipc_channel::ipc::IpcError;
use serde::{Serialize, Deserialize};
use tokio::sync::{mpsc, RwLock, Mutex};

use crate::ipc_protocol::{ClientConnection, ConnectionError, ClientRequest, ServerResponse};

/// A unique ID used to multiplex responses on the client side
///
/// Treated as an opaque value on the server that is returned back to the client with the response
/// to a request.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ClientId(usize);

/// Spawns the server, and manages the IPC connection
///
/// Messages are sent though IPC and responses are dispatched back to the correct client based on
/// the received client ID.
#[derive(Debug)]
struct ClientDispatcher {
    /// The spawned server process
    ///
    /// When dropped, this will block until the server process has quit
    proc: RendererServerProcess,

    /// The IPC connection to the server process
    conn: Arc<ClientConnection>,

    /// Each `ClientId` indexes into this field
    ///
    /// Using `RwLock` allows sending multiple times concurrently using `read()` and also allows
    /// more clients to be added using `write()`.
    clients: Arc<RwLock<Vec<mpsc::UnboundedSender<ServerResponse>>>>,
}

impl ClientDispatcher {
    async fn new() -> Result<Self, ConnectionError> {
        let mut proc = RendererServerProcess::spawn().await?;
        let conn = Arc::new(ClientConnection::new(&mut proc).await?);
        let clients = Arc::new(RwLock::new(Vec::<mpsc::UnboundedSender<_>>::new()));

        let task_conn = conn.clone();
        let task_clients = clients.clone();
        tokio::spawn(async move {
            loop {
                let (id, response) = match task_conn.recv().await {
                    Ok(res) => res,
                    Err(IpcError::Disconnected) => {
                        panic!("Window closed. Cannot continue to run turtle commands. Stopping.");
                    },
                    Err(err) => panic!("Error while receiving IPC message: {:?}", err),
                };

                let clients = task_clients.read().await;

                let ClientId(index) = id;
                clients[index].send(response)
                    .expect("server process shutdown");
            }
        });

        Ok(Self {proc, conn, clients})
    }

    async fn add_client(&self) -> (ClientId, mpsc::UnboundedReceiver<ServerResponse>) {
        let mut clients = self.clients.write().await;

        let id = ClientId(clients.len());
        let (sender, receiver) = mpsc::unbounded_channel();
        clients.push(sender);

        (id, receiver)
    }

    async fn send(&self, id: ClientId, req: ClientRequest) -> Result<(), ipc_channel::Error> {
        self.conn.send(id, req).await
    }
}

/// Represents a single connection to the server
#[derive(Debug)]
pub struct RendererClient {
    dispatcher: Arc<ClientDispatcher>,
    id: ClientId,
    receiver: Mutex<mpsc::UnboundedReceiver<ServerResponse>>,
}

impl RendererClient {
    /// Spawns a new server process and creates a connection to it
    pub async fn new() -> Result<Self, ConnectionError> {
        let dispatcher = Arc::new(ClientDispatcher::new().await?);
        let (id, receiver) = dispatcher.add_client().await;
        let receiver = Mutex::new(receiver);

        Ok(Self {dispatcher, id, receiver})
    }

    /// Creates a new renderer client that can also communicate to the same server
    pub async fn split(&self) -> Self {
        let dispatcher = self.dispatcher.clone();
        let (id, receiver) = dispatcher.add_client().await;
        let receiver = Mutex::new(receiver);

        Self {dispatcher, id, receiver}
    }

    /// Sends a message to the server process
    ///
    /// When possible, prefer using methods from `ProtocolClient` instead of using this directly
    pub async fn send(&self, req: ClientRequest) -> Result<(), ipc_channel::Error> {
        self.dispatcher.send(self.id, req).await
    }

    /// Receives a response from the server process
    ///
    /// When possible, prefer using methods from `ProtocolClient` instead of using this directly
    pub async fn recv(&self) -> ServerResponse {
        let mut receiver = self.receiver.lock().await;
        receiver.recv().await
            .expect("bug: unable to receive response from server process")
    }
}
<commit_msg>Do not panic if unable to send response back to a particular client<commit_after>mod renderer_server_process;

pub use renderer_server_process::*;

use std::sync::Arc;

use ipc_channel::ipc::IpcError;
use serde::{Serialize, Deserialize};
use tokio::sync::{mpsc, RwLock, Mutex};

use crate::ipc_protocol::{ClientConnection, ConnectionError, ClientRequest, ServerResponse};

/// A unique ID used to multiplex responses on the client side
///
/// Treated as an opaque value on the server that is returned back to the client with the response
/// to a request.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ClientId(usize);

/// Spawns the server, and manages the IPC connection
///
/// Messages are sent though IPC and responses are dispatched back to the correct client based on
/// the received client ID.
#[derive(Debug)]
struct ClientDispatcher {
    /// The spawned server process
    ///
    /// When dropped, this will block until the server process has quit
    proc: RendererServerProcess,

    /// The IPC connection to the server process
    conn: Arc<ClientConnection>,

    /// Each `ClientId` indexes into this field
    ///
    /// Using `RwLock` allows sending multiple times concurrently using `read()` and also allows
    /// more clients to be added using `write()`.
    clients: Arc<RwLock<Vec<mpsc::UnboundedSender<ServerResponse>>>>,
}

impl ClientDispatcher {
    async fn new() -> Result<Self, ConnectionError> {
        let mut proc = RendererServerProcess::spawn().await?;
        let conn = Arc::new(ClientConnection::new(&mut proc).await?);
        let clients = Arc::new(RwLock::new(Vec::<mpsc::UnboundedSender<_>>::new()));

        let task_conn = conn.clone();
        let task_clients = clients.clone();
        tokio::spawn(async move {
            loop {
                let (id, response) = match task_conn.recv().await {
                    Ok(res) => res,
                    Err(IpcError::Disconnected) => {
                        panic!("Window closed. Cannot continue to run turtle commands. Stopping.");
                    },
                    Err(err) => panic!("Error while receiving IPC message: {:?}", err),
                };

                let clients = task_clients.read().await;

                let ClientId(index) = id;
                match clients[index].send(response) {
                    Ok(()) => {},
                    // This particular client connection must have gotten dropped
                    Err(_) => {},
                }
            }
        });

        Ok(Self {proc, conn, clients})
    }

    async fn add_client(&self) -> (ClientId, mpsc::UnboundedReceiver<ServerResponse>) {
        let mut clients = self.clients.write().await;

        let id = ClientId(clients.len());
        let (sender, receiver) = mpsc::unbounded_channel();
        clients.push(sender);

        (id, receiver)
    }

    async fn send(&self, id: ClientId, req: ClientRequest) -> Result<(), ipc_channel::Error> {
        self.conn.send(id, req).await
    }
}

/// Represents a single connection to the server
#[derive(Debug)]
pub struct RendererClient {
    dispatcher: Arc<ClientDispatcher>,
    id: ClientId,
    receiver: Mutex<mpsc::UnboundedReceiver<ServerResponse>>,
}

impl RendererClient {
    /// Spawns a new server process and creates a connection to it
    pub async fn new() -> Result<Self, ConnectionError> {
        let dispatcher = Arc::new(ClientDispatcher::new().await?);
        let (id, receiver) = dispatcher.add_client().await;
        let receiver = Mutex::new(receiver);

        Ok(Self {dispatcher, id, receiver})
    }

    /// Creates a new renderer client that can also communicate to the same server
    pub async fn split(&self) -> Self {
        let dispatcher = self.dispatcher.clone();
        let (id, receiver) = dispatcher.add_client().await;
        let receiver = Mutex::new(receiver);

        Self {dispatcher, id, receiver}
    }

    /// Sends a message to the server process
    ///
    /// When possible, prefer using methods from `ProtocolClient` instead of using this directly
    pub async fn send(&self, req: ClientRequest) -> Result<(), ipc_channel::Error> {
        self.dispatcher.send(self.id, req).await
    }

    /// Receives a response from the server process
    ///
    /// When possible, prefer using methods from `ProtocolClient` instead of using this directly
    pub async fn recv(&self) -> ServerResponse {
        let mut receiver = self.receiver.lock().await;
        receiver.recv().await
            .expect("bug: unable to receive response from server process")
    }
}
<|endoftext|>


<commit_before>extern crate rsoundio;

use std::os::raw::c_int;

#[test]
fn test_outstream() {
    println!("test: OutStream");
    let sio = rsoundio::SoundIo::new();
    assert!(sio.connect().is_none());
    // assert!(sio.connect_backend(rsoundio::ffi::SioBackend::Alsa).is_none());
    println!("current backend: {}", sio.current_backend().unwrap());
    sio.flush_events();
    let mut fmt;
    let dev_idx = sio.default_output_device_index().unwrap();
    let dev = sio.get_output_device(dev_idx).unwrap();
    println!("device: {}, ref_count: {}", dev, dev.ref_count());
    let mut stream = dev.create_outstream().unwrap();
    assert!(stream.open().is_none());
    fmt = stream.current_format().unwrap();
    println!("current format: {}", fmt);
    let cb = |out: rsoundio::OutStream, min: i32, max: i32| {
        println!("Closure: {}, {} using format: {}", min, max, fmt);
    };
    stream.register_write_callback(Box::new(cb));
    let ucb = | out: rsoundio::OutStream | {
        println!("Underflow!")
    };
    stream.register_underflow_callback(Box::new(ucb));
    let ecb = | out: rsoundio::OutStream, err: rsoundio::ffi::SioError| {
        println!("Error: {}", err)
    };
    stream.register_error_callback(Box::new(ecb));
    assert!(stream.start().is_none());
    loop {
        sio.wait_events();
    }
    assert!(stream.clear_buffer().is_none());
    assert!(stream.pause(true).is_none());
    assert!(stream.pause(false).is_none());
    println!("latency: {}", stream.get_latency().unwrap());
    stream.destroy();
}

unsafe extern "C" fn write_callback(raw_out: *mut rsoundio::ffi::SoundIoOutStream,
                                    min_frame_count: c_int,
                                    max_frame_count: c_int) {
    let out = rsoundio::OutStream::new(raw_out);
    let sr = out.get_sample_rate();
    let layout = out.get_layout();
    let channels = layout.channel_count();
    // osc stuff:
    let mut f = 8_000.0f32;
    // let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
    let mut sample = 0.0f32;

    let mut raw_areas: *mut rsoundio::ffi::SoundIoChannelArea = ::std::ptr::null_mut();
    let mut frames_left = max_frame_count;
    let mut block_size = frames_left;
    while frames_left > 0 {
        if let Some(err) = out.begin_write(&mut raw_areas, &mut block_size) {
            panic!("{}", err);
        }
        if block_size <= 0 {
            break;
        }

        let areas = unsafe { ::std::slice::from_raw_parts_mut(raw_areas, channels as usize) };
        let mut dir = 1.0;
        for idx in 0..block_size {
            if f >= 8_000.0 || f <= 60.0 {
                dir *= -1.0
            };
            f += dir * 1.0;
            let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
            sample = (phi * (idx as f32)).sin();
            assert!(sample.abs() < 1.001);
            for ch_idx in 0..channels {
                let addr = (areas[ch_idx as usize].ptr as usize +
                            areas[ch_idx as usize].step as usize *
                            idx as usize) as *mut f32;
                unsafe { *addr = sample };
            }
        }
        assert!(out.end_write().is_none());
        frames_left -= block_size;
    }
}
<commit_msg>Remove unnecessary `mut`<commit_after>extern crate rsoundio;

use std::os::raw::c_int;

#[test]
fn test_outstream() {
    println!("test: OutStream");
    let sio = rsoundio::SoundIo::new();
    assert!(sio.connect().is_none());
    // assert!(sio.connect_backend(rsoundio::ffi::SioBackend::Alsa).is_none());
    println!("current backend: {}", sio.current_backend().unwrap());
    sio.flush_events();
    let fmt;
    let dev_idx = sio.default_output_device_index().unwrap();
    let dev = sio.get_output_device(dev_idx).unwrap();
    println!("device: {}, ref_count: {}", dev, dev.ref_count());
    let mut stream = dev.create_outstream().unwrap();
    assert!(stream.open().is_none());
    fmt = stream.current_format().unwrap();
    println!("current format: {}", fmt);
    let cb = |out: rsoundio::OutStream, min: i32, max: i32| {
        println!("Closure: {}, {} using format: {}", min, max, fmt);
    };
    stream.register_write_callback(Box::new(cb));
    let ucb = | out: rsoundio::OutStream | {
        println!("Underflow!")
    };
    stream.register_underflow_callback(Box::new(ucb));
    let ecb = | out: rsoundio::OutStream, err: rsoundio::ffi::SioError| {
        println!("Error: {}", err)
    };
    stream.register_error_callback(Box::new(ecb));
    assert!(stream.start().is_none());
    loop {
        sio.wait_events();
    }
    assert!(stream.clear_buffer().is_none());
    assert!(stream.pause(true).is_none());
    assert!(stream.pause(false).is_none());
    println!("latency: {}", stream.get_latency().unwrap());
    stream.destroy();
}

unsafe extern "C" fn write_callback(raw_out: *mut rsoundio::ffi::SoundIoOutStream,
                                    min_frame_count: c_int,
                                    max_frame_count: c_int) {
    let out = rsoundio::OutStream::new(raw_out);
    let sr = out.get_sample_rate();
    let layout = out.get_layout();
    let channels = layout.channel_count();
    // osc stuff:
    let mut f = 8_000.0f32;
    // let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
    let mut sample = 0.0f32;

    let mut raw_areas: *mut rsoundio::ffi::SoundIoChannelArea = ::std::ptr::null_mut();
    let mut frames_left = max_frame_count;
    let mut block_size = frames_left;
    while frames_left > 0 {
        if let Some(err) = out.begin_write(&mut raw_areas, &mut block_size) {
            panic!("{}", err);
        }
        if block_size <= 0 {
            break;
        }

        let areas = unsafe { ::std::slice::from_raw_parts_mut(raw_areas, channels as usize) };
        let mut dir = 1.0;
        for idx in 0..block_size {
            if f >= 8_000.0 || f <= 60.0 {
                dir *= -1.0
            };
            f += dir * 1.0;
            let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
            sample = (phi * (idx as f32)).sin();
            assert!(sample.abs() < 1.001);
            for ch_idx in 0..channels {
                let addr = (areas[ch_idx as usize].ptr as usize +
                            areas[ch_idx as usize].step as usize *
                            idx as usize) as *mut f32;
                unsafe { *addr = sample };
            }
        }
        assert!(out.end_write().is_none());
        frames_left -= block_size;
    }
}
<|endoftext|>


<commit_before>use std::ffi::{CString, NulError};
use std::ptr;
use libc::c_char;

use video::Window;
use get_error;

use sys::messagebox as ll;

bitflags! {
    flags MessageBoxFlag: u32 {
        const MESSAGEBOX_ERROR = ll::SDL_MESSAGEBOX_ERROR,
        const MESSAGEBOX_WARNING = ll::SDL_MESSAGEBOX_WARNING,
        const MESSAGEBOX_INFORMATION = ll::SDL_MESSAGEBOX_INFORMATION
    }
}

pub enum ShowMessageError {
    InvalidTitle(NulError),
    InvalidMessage(NulError),
    SdlError(String),
}

pub fn show_simple_message_box(flags: MessageBoxFlag, title: &str,
        message: &str, window: Option<&WindowRef>)
        -> Result<(), ShowMessageError> {
    use self::ShowMessageError::*;
    let result = unsafe {
        let title = match CString::new(title) {
            Ok(s) => s,
            Err(err) => return Err(InvalidTitle(err)),
        };
        let message = match CString::new(message) {
            Ok(s) => s,
            Err(err) => return Err(InvalidMessage(err)),
        };
        ll::SDL_ShowSimpleMessageBox(
            flags.bits(),
            title.as_ptr() as *const c_char,
            message.as_ptr() as *const c_char,
            window.map_or(ptr::null_mut(), |win| win.raw())
        )
    } == 0;

    if result {
        Ok(())
    } else {
        Err(SdlError(get_error()))
    }
}
<commit_msg>whoops, CI failed - fix the use<commit_after>use std::ffi::{CString, NulError};
use std::ptr;
use libc::c_char;

use video::WindowRef;
use get_error;

use sys::messagebox as ll;

bitflags! {
    flags MessageBoxFlag: u32 {
        const MESSAGEBOX_ERROR = ll::SDL_MESSAGEBOX_ERROR,
        const MESSAGEBOX_WARNING = ll::SDL_MESSAGEBOX_WARNING,
        const MESSAGEBOX_INFORMATION = ll::SDL_MESSAGEBOX_INFORMATION
    }
}

pub enum ShowMessageError {
    InvalidTitle(NulError),
    InvalidMessage(NulError),
    SdlError(String),
}

pub fn show_simple_message_box(flags: MessageBoxFlag, title: &str,
        message: &str, window: Option<&WindowRef>)
        -> Result<(), ShowMessageError> {
    use self::ShowMessageError::*;
    let result = unsafe {
        let title = match CString::new(title) {
            Ok(s) => s,
            Err(err) => return Err(InvalidTitle(err)),
        };
        let message = match CString::new(message) {
            Ok(s) => s,
            Err(err) => return Err(InvalidMessage(err)),
        };
        ll::SDL_ShowSimpleMessageBox(
            flags.bits(),
            title.as_ptr() as *const c_char,
            message.as_ptr() as *const c_char,
            window.map_or(ptr::null_mut(), |win| win.raw())
        )
    } == 0;

    if result {
        Ok(())
    } else {
        Err(SdlError(get_error()))
    }
}
<|endoftext|>