<commit_before>#![feature(globs)]
#![feature(phase)]
#[phase(plugin, link)]
extern crate log;
extern crate getopts;
extern crate serialize;
extern crate wtftw_core;
extern crate wtftw_xlib;

use std::ops::Fn;
use std::os;
use getopts::{ optopt, getopts };
use serialize::json;
use wtftw_core::config::Config;
use wtftw_core::logger::FileLogger;
use wtftw_core::window_manager::WindowManager;
use wtftw_core::window_system::*;
use wtftw_xlib::XlibWindowSystem;

pub fn parse_window_ids(ids: &str) -> Vec<(Window, u32)> {
    json::decode(ids).unwrap()
}

fn main() {
    // Parse command line arguments
    let args : Vec<String> = os::args();

    let opts = [
        optopt("r", "resume", "list of window IDs to capture in resume", "WINDOW")
    ];

    let matches = match getopts(args.tail(), &opts) {
        Ok(m)  => m,
        Err(f) => panic!(f.to_string())
    };

    // Create a default configuration
    let mut config = Config::initialize();
    log::set_logger(box FileLogger::new(&config.logfile, false));
    // Initialize window system. Use xlib here for now
    let window_system = XlibWindowSystem::new();
    // Create the actual window manager
    let mut window_manager = WindowManager::new(&window_system, &config);

    // If available, compile the config file at ~/.wtftw/config.rs
    // and call the configure method
    let old = log::set_logger(box FileLogger::new(&config.logfile, true));
    config.compile_and_call(&mut window_manager, &window_system);
    config.call(&mut window_manager, &window_system);
    log::set_logger(old.unwrap());

    // Output some initial information
    info!("WTFTW - Window Tiling For The Win");
    info!("Starting wtftw on {} screen(s)", window_system.get_screen_infos().len());

    // Output information about displays
    for (i, &Rectangle(x, y, w, h)) in window_system.get_screen_infos().iter().enumerate() {
        debug!("Display {}: {}x{} ({}, {})", i, w, h, x, y);
    }

    debug!("Size of keyhandlers after configuration: {}", config.key_handlers.len());

    for (command, _) in config.key_handlers.iter() {
        debug!("grabbing command {}", command);
        window_system.grab_keys(vec!(command.clone()));
    }

    let window_ids = if matches.opt_present("r") {
        debug!("found {}", matches.opt_str("r").unwrap());
        parse_window_ids(matches.opt_str("r").unwrap().as_slice())
    } else {
        Vec::new()
    };

    for &(window, workspace) in window_ids.iter() {
        debug!("re-inserting window {}", window);
        window_manager = window_manager.view(&window_system, workspace, &config)
            .manage(&window_system, window, &config);
    }

    // Enter the event loop and just listen for events
    while window_manager.running {
        let event = window_system.get_event();
        match event {
            ClientMessageEvent(_) => {
            },
            // The X11/Wayland configuration changed, so we need to readjust the
            // screen configurations.
            ConfigurationNotification(window) => {
                if window_system.get_root() == window {
                    debug!("screen configuration changed. Rescreen");
                    window_manager = window_manager.rescreen(&window_system);
                }
            },
            // A window asked to be reconfigured (i.e. resized, border change, etc.)
            ConfigurationRequest(window, window_changes, mask) => {
                window_system.configure_window(window, window_changes, mask);
                window_manager = window_manager.windows(&window_system, &config, |x| x.clone());
            },
            // A new window was created, so we need to manage
            // it unless it is already managed by us.
            WindowCreated(window) => {
                if !window_manager.is_window_managed(window) {
                    window_manager = window_manager.manage(&window_system, window, &config);
                    window_manager = window_manager.windows(&window_system, &config,
                                                            |x| config.manage_hook.call((x.clone(),
                                                                         &window_system, window)));
                }
            },
            WindowUnmapped(window, synthetic) => {
                if synthetic && window_manager.is_window_managed(window) {
                    window_manager.unmanage(&window_system, window, &config);
                    // TODO: remove from mapped stack and from waitingUnmap stack
                }
            },
            WindowDestroyed(window) => {
                if window_manager.is_window_managed(window) {
                    window_manager = window_manager.unmanage(&window_system, window, &config);
                }
            },
            // The mouse pointer entered a window's region. If focus following
            // is enabled, we need to set focus to it.
            Enter(window) => {
                if config.focus_follows_mouse && window_manager.is_window_managed(window) {
                    debug!("enter event on {}", window_system.get_window_name(window));
                    window_manager = window_manager.focus(window, &window_system, &config);
                }
            },
            // The mouse pointer left a window's reagion. If focus following is enabled,
            // we need to reset the border color
            //Leave(window) => {
            //    if config.focus_follows_mouse && window_manager.is_window_managed(window) {
            //        window_system.set_window_border_color(window, config.border_color);
            //    }
            //},
            KeyPressed(_, key) => {
                for (command, ref handler) in config.key_handlers.iter() {
                    if command == &key {
                        let local_window_manager = window_manager.clone();
                        debug!("calling handler");
                        window_manager = handler.call((local_window_manager, &window_system, &config));
                        continue;
                    }
                }
            },
            _ => ()
        }
    }
}
<commit_msg>added loghook<commit_after>#![feature(globs)]
#![feature(phase)]
#![feature(if_let)]
#[phase(plugin, link)]
extern crate log;
extern crate getopts;
extern crate serialize;
extern crate wtftw_core;
extern crate wtftw_xlib;

use std::ops::Fn;
use std::os;
use getopts::{ optopt, getopts };
use serialize::json;
use wtftw_core::config::Config;
use wtftw_core::logger::FileLogger;
use wtftw_core::window_manager::WindowManager;
use wtftw_core::window_system::*;
use wtftw_xlib::XlibWindowSystem;

pub fn parse_window_ids(ids: &str) -> Vec<(Window, u32)> {
    json::decode(ids).unwrap()
}

fn main() {
    // Parse command line arguments
    let args : Vec<String> = os::args();

    let opts = [
        optopt("r", "resume", "list of window IDs to capture in resume", "WINDOW")
    ];

    let matches = match getopts(args.tail(), &opts) {
        Ok(m)  => m,
        Err(f) => panic!(f.to_string())
    };

    // Create a default config.generaluration
    let mut config = Config::initialize();
    log::set_logger(box FileLogger::new(&config.general.logfile, false));
    // Initialize window system. Use xlib here for now
    let window_system = XlibWindowSystem::new();
    // Create the actual window manager
    let mut window_manager = WindowManager::new(&window_system, &config.general);

    // If available, compile the config.general file at ~/.wtftw/config.general.rs
    // and call the config.generalure method
    config.compile_and_call(&mut window_manager, &window_system);

    // Output some initial information
    info!("WTFTW - Window Tiling For The Win");
    info!("Starting wtftw on {} screen(s)", window_system.get_screen_infos().len());

    // Output information about displays
    for (i, &Rectangle(x, y, w, h)) in window_system.get_screen_infos().iter().enumerate() {
        debug!("Display {}: {}x{} ({}, {})", i, w, h, x, y);
    }

    debug!("Size of keyhandlers after config.generaluration: {}", config.internal.key_handlers.len());

    for (command, _) in config.internal.key_handlers.iter() {
        debug!("grabbing command {}", command);
        window_system.grab_keys(vec!(command.clone()));
    }

    let window_ids = if matches.opt_present("r") {
        debug!("found {}", matches.opt_str("r").unwrap());
        parse_window_ids(matches.opt_str("r").unwrap().as_slice())
    } else {
        Vec::new()
    };

    for &(window, workspace) in window_ids.iter() {
        debug!("re-inserting window {}", window);
        window_manager = window_manager.view(&window_system, workspace, &config.general)
            .manage(&window_system, window, &config.general);
    }

    // Enter the event loop and just listen for events
    while window_manager.running {
        let event = window_system.get_event();
        match event {
            ClientMessageEvent(_) => {
            },
            // The X11/Wayland config.generaluration changed, so we need to readjust the
            // screen config.generalurations.
            ConfigurationNotification(window) => {
                if window_system.get_root() == window {
                    debug!("screen config.generaluration changed. Rescreen");
                    window_manager = window_manager.rescreen(&window_system);
                }
            },
            // A window asked to be reconfig.generalured (i.e. resized, border change, etc.)
            ConfigurationRequest(window, window_changes, mask) => {
                window_system.configure_window(window, window_changes, mask);
                window_manager = window_manager.windows(&window_system, &config.general, |x| x.clone());
            },
            // A new window was created, so we need to manage
            // it unless it is already managed by us.
            WindowCreated(window) => {
                if !window_manager.is_window_managed(window) {
                    window_manager = window_manager.manage(&window_system, window, &config.general);
                    window_manager = window_manager.windows(&window_system, &config.general,
                                                            |x| config.internal.manage_hook.call((x.clone(),
                                                                         &window_system, window)));
                }
            },
            WindowUnmapped(window, synthetic) => {
                if synthetic && window_manager.is_window_managed(window) {
                    window_manager.unmanage(&window_system, window, &config.general);
                    // TODO: remove from mapped stack and from waitingUnmap stack
                }
            },
            WindowDestroyed(window) => {
                if window_manager.is_window_managed(window) {
                    window_manager = window_manager.unmanage(&window_system, window, &config.general);
                }
            },
            // The mouse pointer entered a window's region. If focus following
            // is enabled, we need to set focus to it.
            Enter(window) => {
                if config.general.focus_follows_mouse && window_manager.is_window_managed(window) {
                    debug!("enter event on {}", window_system.get_window_name(window));
                    window_manager = window_manager.focus(window, &window_system, &config.general);
                }
            },
            // The mouse pointer left a window's reagion. If focus following is enabled,
            // we need to reset the border color
            //Leave(window) => {
            //    if config.general.focus_follows_mouse && window_manager.is_window_managed(window) {
            //        window_system.set_window_border_color(window, config.general.border_color);
            //    }
            //},
            KeyPressed(_, key) => {
                for (command, ref handler) in config.internal.key_handlers.iter() {
                    if command == &key {
                        let local_window_manager = window_manager.clone();
                        debug!("calling handler");
                        window_manager = handler.call((local_window_manager, &window_system, &config.general));
                        continue;
                    }
                }
            },
            _ => ()
        };

        if let Some(ref mut loghook) = config.internal.loghook {
            loghook.call_mut((window_manager.clone(), &window_system));
        }
    }
}
<|endoftext|>


<commit_before>extern crate bytes;
extern crate futures;
extern crate tokio;
extern crate tokio_io;
extern crate tokio_serial;

use std::{env, io, str};
use tokio::io::AsyncRead;
use tokio_io::codec::{Decoder, Encoder};

use bytes::BytesMut;

use futures::{Future, Stream};

#[cfg(unix)]
const DEFAULT_TTY: &str = "/dev/ttyUSB0";
#[cfg(windows)]
const DEFAULT_TTY: &str = "COM1";

struct LineCodec;

impl Decoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        let newline = src.as_ref().iter().position(|b| *b == b'\n');
        if let Some(n) = newline {
            let line = src.split_to(n + 1);
            return match str::from_utf8(line.as_ref()) {
                Ok(s) => Ok(Some(s.to_string())),
                Err(_) => Err(io::Error::new(io::ErrorKind::Other, "Invalid String")),
            };
        }
        Ok(None)
    }
}

impl Encoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn encode(&mut self, _item: Self::Item, _dst: &mut BytesMut) -> Result<(), Self::Error> {
        Ok(())
    }
}

fn main() {
    let mut args = env::args();
    let tty_path = args.nth(1).unwrap_or_else(|| DEFAULT_TTY.into());

    let settings = tokio_serial::SerialPortSettings::default();
    let mut port = tokio_serial::Serial::from_path(tty_path, &settings).unwrap();
    #[cfg(unix)]
    port.set_exclusive(false)
        .expect("Unable to set serial port exlusive");

    let (_, reader) = port.framed(LineCodec).split();

    let printer = reader
        .for_each(|s| {
            println!("{:?}", s);
            Ok(())
        }).map_err(|e| eprintln!("{}", e));

    tokio::run(printer);
}
<commit_msg>Update serial_println.rs<commit_after>extern crate bytes;
extern crate futures;
extern crate tokio;
extern crate tokio_io;
extern crate tokio_serial;

use std::{env, io, str};
use tokio_io::codec::{Decoder, Encoder};

use bytes::BytesMut;

use futures::{Future, Stream};

#[cfg(unix)]
const DEFAULT_TTY: &str = "/dev/ttyUSB0";
#[cfg(windows)]
const DEFAULT_TTY: &str = "COM1";

struct LineCodec;

impl Decoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        let newline = src.as_ref().iter().position(|b| *b == b'\n');
        if let Some(n) = newline {
            let line = src.split_to(n + 1);
            return match str::from_utf8(line.as_ref()) {
                Ok(s) => Ok(Some(s.to_string())),
                Err(_) => Err(io::Error::new(io::ErrorKind::Other, "Invalid String")),
            };
        }
        Ok(None)
    }
}

impl Encoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn encode(&mut self, _item: Self::Item, _dst: &mut BytesMut) -> Result<(), Self::Error> {
        Ok(())
    }
}

fn main() {
    let mut args = env::args();
    let tty_path = args.nth(1).unwrap_or_else(|| DEFAULT_TTY.into());

    let settings = tokio_serial::SerialPortSettings::default();
    let mut port = tokio_serial::Serial::from_path(tty_path, &settings).unwrap();
    #[cfg(unix)]
    port.set_exclusive(false)
        .expect("Unable to set serial port exlusive");

    let (_, reader) = LineCodec.framed(port).split();

    let printer = reader
        .for_each(|s| {
            println!("{:?}", s);
            Ok(())
        }).map_err(|e| eprintln!("{}", e));

    tokio::run(printer);
}
<|endoftext|>


<commit_before>//! Allows dynamic dispatch to object-unsafe traits, with some caveats.
//!
//! `list_of_types` works around Rust's lack of generic/associated statics by requiring the program to specify a single "list of types" at compile time, which must include everything that you want to call into dynamically. This must be globally unique within the program. That is, if a *library* wants to use these features, it must rely on being passed the global list as a generic parameter.
//!
//! Creating a list of types is simple: you wrap each type `T` into `ListedType<T>`, then put the `ListedType`s into tuples (possibly nested tuples). All the traits necessary to use a list for automatically implemented for all nested tuples of `ListedType`s. For instance, ((ListedType<i64>, ListedType<String>, ListedType<Vec<usize>>), ListedType<bool>) is a valid list with 4 types in it.

use std::marker::PhantomData;

#[macro_export]
macro_rules! time_steward_make_sublist {
  (mod $mod: ident visits $T: ident where $($where:tt)*) => {mod $mod {
    use std::marker::PhantomData;
    use std::any::Any;
    use $crate::dynamic::list_of_types::{List, SubListRepresentative, ListedType};
    pub trait Visitor {
      fn visit<$T>(&mut self) where $($where)*;
    }
    pub unsafe trait SubList: List {
      fn visit_all<V: Visitor>(visitor: &mut V);
      fn count()->usize;
      fn count_before<T>()->usize;
    }
    unsafe impl <T: Any> SubList for ListedType<T> {
      #[inline(always)]
      default fn visit_all<V: Visitor>(_: &mut V) {}
      #[inline(always)]
      default fn count()->usize {0}
      #[inline(always)]
      default fn count_before<U>()->usize {panic!("invoked count_before on a list that doesn't contain the type")}
    }
    unsafe impl <$T: Any> SubList for ListedType<$T> where $($where)* {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        visitor.visit::<$T>();
      }
      #[inline(always)]
      fn count()->usize {1}
      #[inline(always)]
      fn count_before<U>()->usize {0}
    }
    __time_steward_internal_sublist_tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

    pub struct Representative <GlobalList: SubList> (PhantomData <GlobalList>,!);
    unsafe impl <GlobalList: SubList> SubListRepresentative for Representative <GlobalList> {
      fn count()->usize {GlobalList::count()}
      fn count_before<T>()->usize {GlobalList::count_before::<T>()}
    }/*{
      fn visit_all<V: Visitor>(visitor: &mut V) {
        GlobalList::visit_all(visitor);
      }
    }*/
  }}
}
pub struct ListedType<T: Any>(PhantomData <T>, !);

#[macro_export]
#[doc(hidden)]
macro_rules! __time_steward_internal_sublist_tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> SubList for ($($T,)* $TL,)
      where $($T: SubList,)* $TL: SubList
    {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        $($T::visit_all(visitor);)*
        $TL::visit_all(visitor);
      }
      #[inline(always)]
      fn count()->usize {
        $($T::count() + )* $TL::count()
      }
      #[inline(always)]
      fn count_before<T>()->usize {
        let count = 0;
        $(if $T::includes::<T> () {return count + $T::count_before::<T>()}
        let count = count + $T::count();)*
        if $TL::includes::<T> () {return count + $TL::count_before::<T>()}
        panic!("invoked count_before on a list that doesn't contain the type")
      }
    }
    __time_steward_internal_sublist_tuple_impls! ($($T),*);
  };
  () => {};
}

pub unsafe trait List: Any {
  fn includes <T> ()->bool;
}
pub unsafe trait SubListRepresentative {
  fn count()->usize;
  fn count_before<T>()->usize;
}

pub unsafe trait AmI <T> {fn am_i()->bool;}
unsafe impl <T, U> AmI <T> for U {default fn am_i()->bool {false}}
unsafe impl <T> AmI <T> for T {fn am_i()->bool {true}}

unsafe impl <T: Any> List for ListedType<T> {
  #[inline(always)]
  fn includes<U>()->bool {<T as AmI<U>>::am_i()}
}

macro_rules! tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> List for ($($T,)* $TL,)
      where $($T: List,)* $TL: List
    {
      #[inline(always)]
      fn includes<T>()->bool {
        $($T::includes::<T>() || )* $TL::includes::<T>()
      }
    }
    tuple_impls! ($($T),*);
  };
  () => {};
}

tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct DeterministicallyRandomlyIdentifiedTypeId(u64);
pub trait DeterministicallyRandomlyIdentifiedType {
  const ID: DeterministicallyRandomlyIdentifiedTypeId;
}

fn assert_unique_global_list <GlobalList: List>() {
  use std::any::TypeId;
  use std::cell::Cell;
  thread_local! {
    static LIST_ID: Cell<Option <TypeId>> = Cell::new (None);
  }
  LIST_ID.with (| id_cell | {
    let id = TypeId::of::<GlobalList>();
    if let Some (existing) = id_cell.get() {
      assert!(id == existing, "invoked dynamic function with two different global lists (see the list_of_types documentation for why this is wrong");
      return
    }
    id_cell.set (Some(id));
  });
}

time_steward_make_sublist! (
mod whatever visits T where T: super::DeterministicallyRandomlyIdentifiedType);
/*
#[macro_export]
macro_rules! time_steward_sublist_fn {
  (static $visitor_data: ident: $VisitorData: ty: $VisitorTrait: ident = $initial_value: expr followed by visit<$T> (&mut $self_hack) $visitation_effect: expr; fn $function_name: ident <$GlobalList: $SubList: ident> ($($argument_name: ident: $argument_type:ty),*)->$return_type:ty $($body:tt)*) => {

    fn $function_name <GlobalList: $List> $($argument_name: $argument_type),*)->$return_type:ty {
      struct Visitor ($VisitorData);
      impl VisitorTrait for Visitor {
        fn visit<$T>(&mut $self_hack) where  {$visitation_effect}
      }
      thread_local! {
        static LIST_ID: TypeId = TypeId::of::<GlobalList>();
        static DATA: $VisitorData = {
          let mut visitor = Visitor ($initial_value);
          <GlobalList as DeterministicallyRandomlyIdentifiedTypesList>::visit_all (&mut visitor);
          visitor.0
        };
      }
      LIST_ID.with (| id | {
        assert!(id, TypeId::of::<GlobalList>(), "invoked dynamic function with two different global lists (see the list_of_types documentation for why this is wrong")
      });
      DATA.with (| $visitor_data | {$($body)*})
  }
}
  */

use std::any::Any ;

fn listed_type_id <GlobalList: whatever::SubList> (index: usize)->Option <DeterministicallyRandomlyIdentifiedTypeId> {
  assert_unique_global_list::<GlobalList>();
  use std::cell::RefCell;
  use std::mem;
  struct Visitor (Vec<DeterministicallyRandomlyIdentifiedTypeId>);
  impl whatever::Visitor for Visitor {
    fn visit<T>(&mut self) where T: DeterministicallyRandomlyIdentifiedType {self.0.push (T::ID);}
  }
  thread_local! {
    static TABLE: RefCell<Vec<DeterministicallyRandomlyIdentifiedTypeId>> = RefCell::new(Vec::new());
  }
  TABLE.with (| table | {
    let mut guard = table.borrow_mut();
    if guard.is_empty() {
      mem::replace (&mut*guard, {
        let mut visitor = Visitor (Vec::with_capacity(whatever::Representative::<GlobalList>::count()));
        <GlobalList as whatever::SubList>::visit_all (&mut visitor);
        visitor.0
      });
    }
    guard.get (index).cloned()
  })
}

<commit_msg>Made a macro to reduce the boilerplate of visiting<commit_after>//! Allows dynamic dispatch to object-unsafe traits, with some caveats.
//!
//! `list_of_types` works around Rust's lack of generic/associated statics by requiring the program to specify a single "list of types" at compile time, which must include everything that you want to call into dynamically. This must be globally unique within the program. That is, if a *library* wants to use these features, it must rely on being passed the global list as a generic parameter.
//!
//! Creating a list of types is simple: you wrap each type `T` into `ListedType<T>`, then put the `ListedType`s into tuples (possibly nested tuples). All the traits necessary to use a list for automatically implemented for all nested tuples of `ListedType`s. For instance, ((ListedType<i64>, ListedType<String>, ListedType<Vec<usize>>), ListedType<bool>) is a valid list with 4 types in it.

use std::marker::PhantomData;

#[macro_export]
macro_rules! time_steward_make_sublist {
  (mod $mod: ident visits $T: ident where $($where:tt)*) => {mod $mod {
    use std::marker::PhantomData;
    use std::any::Any;
    use $crate::dynamic::list_of_types::{List, SubListRepresentative, ListedType};
    pub trait Visitor {
      fn visit<$T>(&mut self) where $($where)*;
    }
    pub unsafe trait SubList: List {
      fn visit_all<V: Visitor>(visitor: &mut V);
      fn count()->usize;
      fn count_before<T>()->usize;
    }
    unsafe impl <T: Any> SubList for ListedType<T> {
      #[inline(always)]
      default fn visit_all<V: Visitor>(_: &mut V) {}
      #[inline(always)]
      default fn count()->usize {0}
      #[inline(always)]
      default fn count_before<U>()->usize {panic!("invoked count_before on a list that doesn't contain the type")}
    }
    unsafe impl <$T: Any> SubList for ListedType<$T> where $($where)* {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        visitor.visit::<$T>();
      }
      #[inline(always)]
      fn count()->usize {1}
      #[inline(always)]
      fn count_before<U>()->usize {0}
    }
    __time_steward_internal_sublist_tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

    pub struct Representative <GlobalList: SubList> (PhantomData <GlobalList>,!);
    unsafe impl <GlobalList: SubList> SubListRepresentative for Representative <GlobalList> {
      fn count()->usize {
        $crate::dynamic::list_of_types::assert_unique_global_list::<GlobalList>();
        GlobalList::count()
      }
      fn count_before<T>()->usize {
        $crate::dynamic::list_of_types::assert_unique_global_list::<GlobalList>();
        GlobalList::count_before::<T>()
      }
    }/*{
      fn visit_all<V: Visitor>(visitor: &mut V) {
        GlobalList::visit_all(visitor);
      }
    }*/
  }}
}
pub struct ListedType<T: Any>(PhantomData <T>, !);

#[macro_export]
#[doc(hidden)]
macro_rules! __time_steward_internal_sublist_tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> SubList for ($($T,)* $TL,)
      where $($T: SubList,)* $TL: SubList
    {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        $($T::visit_all(visitor);)*
        $TL::visit_all(visitor);
      }
      #[inline(always)]
      fn count()->usize {
        $($T::count() + )* $TL::count()
      }
      #[inline(always)]
      fn count_before<T>()->usize {
        let count = 0;
        $(if $T::includes::<T> () {return count + $T::count_before::<T>()}
        let count = count + $T::count();)*
        if $TL::includes::<T> () {return count + $TL::count_before::<T>()}
        panic!("invoked count_before on a list that doesn't contain the type")
      }
    }
    __time_steward_internal_sublist_tuple_impls! ($($T),*);
  };
  () => {};
}

pub unsafe trait List: Any {
  fn includes <T> ()->bool;
}
pub unsafe trait SubListRepresentative {
  fn count()->usize;
  fn count_before<T>()->usize;
}

pub unsafe trait AmI <T> {fn am_i()->bool;}
unsafe impl <T, U> AmI <T> for U {default fn am_i()->bool {false}}
unsafe impl <T> AmI <T> for T {fn am_i()->bool {true}}

unsafe impl <T: Any> List for ListedType<T> {
  #[inline(always)]
  fn includes<U>()->bool {<T as AmI<U>>::am_i()}
}

macro_rules! tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> List for ($($T,)* $TL,)
      where $($T: List,)* $TL: List
    {
      #[inline(always)]
      fn includes<T>()->bool {
        $($T::includes::<T>() || )* $TL::includes::<T>()
      }
    }
    tuple_impls! ($($T),*);
  };
  () => {};
}

tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct DeterministicallyRandomlyIdentifiedTypeId(u64);
pub trait DeterministicallyRandomlyIdentifiedType {
  const ID: DeterministicallyRandomlyIdentifiedTypeId;
}

fn assert_unique_global_list <GlobalList: List>() {
  use std::any::TypeId;
  use std::cell::Cell;
  thread_local! {
    static LIST_ID: Cell<Option <TypeId>> = Cell::new (None);
  }
  LIST_ID.with (| id_cell | {
    let id = TypeId::of::<GlobalList>();
    if let Some (existing) = id_cell.get() {
      assert!(id == existing, "invoked dynamic function with two different global lists (see the list_of_types documentation for why this is wrong");
      return
    }
    id_cell.set (Some(id));
  });
}

time_steward_make_sublist! (
mod whatever visits T where T: super::DeterministicallyRandomlyIdentifiedType);
/*
#[macro_export]
macro_rules! time_steward_sublist_fn {
  (static $visitor_data: ident: $VisitorData: ty: $VisitorTrait: ident = $initial_value: expr followed by visit<$T> (&mut $self_hack) $visitation_effect: expr; fn $function_name: ident <$GlobalList: $SubList: ident> ($($argument_name: ident: $argument_type:ty),*)->$return_type:ty $($body:tt)*) => {

    fn $function_name <GlobalList: $List> $($argument_name: $argument_type),*)->$return_type:ty {
      struct Visitor ($VisitorData);
      impl VisitorTrait for Visitor {
        fn visit<$T>(&mut $self_hack) where  {$visitation_effect}
      }
      thread_local! {
        static DATA: $VisitorData = {
          let mut visitor = Visitor ($initial_value);
          <GlobalList as DeterministicallyRandomlyIdentifiedTypesList>::visit_all (&mut visitor);
          visitor.0
        };
      }
      DATA.with (| $visitor_data | {$($body)*})
  }
}
  */

#[macro_export]
macro_rules! time_steward_visit_sublist {
  (&mut $object: ident: $Object: ty, $GlobalList: ident, $mod: ident, $($method: tt)*) => {
    /*struct Visitor <'a> (&mut 'a $Object);
    impl <'a> $mod::Visitor for Visitor <'a> {
      $method
    }*/
    impl $mod::Visitor for $Object {
      $($method)*
    }
    <$GlobalList as $mod::SubList>::visit_all (&mut $object);
  }
}

use std::any::Any ;

fn listed_type_id <GlobalList: whatever::SubList> (index: usize)->Option <DeterministicallyRandomlyIdentifiedTypeId> {
  assert_unique_global_list::<GlobalList>();
  use std::cell::RefCell;
  use std::mem;
  struct Visitor (Vec<DeterministicallyRandomlyIdentifiedTypeId>);
  impl whatever::Visitor for Visitor {
    fn visit<T>(&mut self) where T: DeterministicallyRandomlyIdentifiedType {self.0.push (T::ID);}
  }
  thread_local! {
    static TABLE: RefCell<Vec<DeterministicallyRandomlyIdentifiedTypeId>> = RefCell::new(Vec::new());
  }
  TABLE.with (| table | {
    let mut guard = table.borrow_mut();
    if guard.is_empty() {
      mem::replace (&mut*guard, {
        let mut result = Vec::with_capacity(whatever::Representative::<GlobalList>::count());
        time_steward_visit_sublist! (&mut result: Vec<DeterministicallyRandomlyIdentifiedTypeId>, GlobalList, whatever, fn visit<T>(&mut self) where T: DeterministicallyRandomlyIdentifiedType {self.push (T::ID);});
        result
      });
    }
    guard.get (index).cloned()
  })
}

<|endoftext|>


<commit_before>use num::Integer;
use euclid::Point2D;
use hex::Dir6;

/// Field of view iterator for a hexagonal map.
///
/// Takes a function that maps cells into user-specified values and indicates when traversal should
/// stop.
pub struct HexFov<F, T> {
    /// Predicate for whether a given point will block the field of view.
    f: F,
    stack: Vec<Sector<T>>,
    /// Returns true if given cell is a wallform and should have fake isometric hack applied.
    is_wall_f: Box<Fn(Point2D<i32>, &T) -> bool>,
    /// Extra values generated by special cases.
    side_channel: Vec<(Point2D<i32>, T)>,
}

impl<F, T> HexFov<F, T>
    where F: Fn(Point2D<i32>, &T) -> Option<T>,
          T: Eq + Clone
{
    pub fn new(init: T, f: F) -> HexFov<F, T> {
        // We could run f for (0, 0) here, but the traditional way for the FOV to work is to only
        // consider your surroundings, not the origin site itself.
        HexFov {
            f: f,
            stack: vec![Sector {
                            begin: PolarPoint::new(0.0, 1),
                            pt: PolarPoint::new(0.0, 1),
                            end: PolarPoint::new(6.0, 1),
                            group_value: init.clone(),
                        }],
            is_wall_f: Box::new(move |_, _| false),
            // The FOV algorithm will not generate the origin point, so we use
            // the side channel to explicitly add it in the beginning.
            side_channel: vec![(Point2D::new(0, 0), init)],
        }
    }

    /// Make wall tiles in acute corners visible when running the algorithm.
    ///
    /// This will ensure that a complete wall rectangle of fake-isometric rooms will appear
    /// in the FOV. Takes a function that queries if a location contains a wall-form tile.
    pub fn fake_isometric<G>(mut self, is_wall_f: G) -> HexFov<F, T>
        where G: Fn(Point2D<i32>, &T) -> bool + 'static
    {
        self.is_wall_f = Box::new(is_wall_f);
        self
    }
}

impl<F, T> Iterator for HexFov<F, T>
    where F: Fn(Point2D<i32>, &T) -> Option<T>,
          T: Eq + Clone
{
    type Item = (Point2D<i32>, T);
    fn next(&mut self) -> Option<(Point2D<i32>, T)> {
        if let Some(ret) = self.side_channel.pop() {
            return Some(ret);
        }

        if let Some(mut current) = self.stack.pop() {
            let current_value = (self.f)(current.pt.to_v2(), &current.group_value);

            if current.pt.is_below(current.end) && current_value.is_some() {
                let pos = current.pt.to_v2();
                let current_value = current_value.unwrap();

                if current_value != current.group_value {
                    if current.pt == current.begin {
                        // Oops, we've got a value mismatch on the very first item, so the entire
                        // sector was mistagged. This happens in the initial cycle when we
                        // guesstimate the value. Let's just quickly fix this before anyone
                        // notices.
                        current.group_value = current_value.clone();
                    } else {
                        // Terrain value changed, branch out.

                        // Add the rest of this sector with the new terrain value.
                        self.stack.push(Sector {
                            begin: current.pt,
                            pt: current.pt,
                            end: current.end,
                            group_value: current_value.clone(),
                        });

                        // Branch further if we still get values there.
                        if let Some(further_value) = (self.f)(current.begin.further().to_v2(),
                                                              &current_value) {
                            self.stack.push(Sector {
                                begin: current.begin.further(),
                                pt: current.begin.further(),
                                end: current.pt.further(),
                                group_value: further_value.clone(),
                            });
                        }
                        return self.next();
                    }
                }

                // Hack for making acute corner tiles of fake-isometric rooms visible.

                // We're moving along a vertical line on the hex circle, so there are side
                // points to check.
                if let Some(side_pos) = current.pt.side_point() {

                    let next = current.pt.next();
                    // If the next cell is within the current span and the current cell is
                    // wallform,
                    if next.is_below(current.end) &&
                       (self.is_wall_f)(current.pt.to_v2(), &current.group_value) {
                        // and if the next cell is visible,
                        if let Some(next_value) = (self.f)(next.to_v2(), &current.group_value) {
                            // and if the current and the next cell are in the same value group,
                            // both the next cell and the third corner point cell are
                            // wallforms, and the side point would not be otherwise
                            // visible:
                            if next_value == current.group_value &&
                               (self.is_wall_f)(next.to_v2(), &next_value) &&
                               (self.f)(side_pos, &current.group_value).is_none() &&
                               (self.is_wall_f)(side_pos, &current.group_value) {
                                // Add the side point to the side channel.
                                self.side_channel.push((side_pos, current.group_value.clone()));
                            }
                        }
                    }
                }

                // Proceed along the current sector.
                current.pt = current.pt.next();
                self.stack.push(current);
                return Some((pos, current_value));
            } else {
                // Hit the end of the sector.

                if let Some(group_value) = (self.f)(current.begin.further().to_v2(),
                                                    &current.group_value) {
                    // Branch out further if things are still visible there.
                    self.stack.push(Sector {
                        begin: current.begin.further(),
                        pt: current.begin.further(),
                        end: current.end.further(),
                        group_value: group_value,
                    });
                }

                self.next()
            }
        } else {
            None
        }
    }
}

struct Sector<T> {
    /// Start point of current sector.
    begin: PolarPoint,
    /// Point currently being processed.
    pt: PolarPoint,
    /// End point of current sector.
    end: PolarPoint,
    /// The user value for this group.
    group_value: T,
}

/// Points on a hex circle expressed in polar coordinates.
#[derive(Copy, Clone, PartialEq)]
struct PolarPoint {
    pos: f32,
    radius: u32,
}

impl PolarPoint {
    pub fn new(pos: f32, radius: u32) -> PolarPoint {
        PolarPoint {
            pos: pos,
            radius: radius,
        }
    }
    /// Index of the discrete hex cell along the circle that corresponds to this point.
    fn winding_index(self) -> i32 {
        (self.pos + 0.5).floor() as i32
    }

    pub fn is_below(self, other: PolarPoint) -> bool {
        self.winding_index() < other.end_index()
    }

    fn end_index(self) -> i32 {
        (self.pos + 0.5).ceil() as i32
    }

    pub fn to_v2(self) -> Point2D<i32> {
        if self.radius == 0 {
            return Point2D::new(0, 0);
        }
        let index = self.winding_index();
        let sector = index.mod_floor(&(self.radius as i32 * 6)) / self.radius as i32;
        let offset = index.mod_floor(&(self.radius as i32));

        let rod = Dir6::from_int(sector).to_v2();
        let tangent = Dir6::from_int((sector + 2) % 6).to_v2();

        rod * (self.radius as i32) + tangent * offset
    }

    /// If this point and the next point are adjacent vertically (along the xy
    /// axis), return the point outside of the circle between the two points.
    ///
    /// This is a helper function for the FOV special case where acute corners
    /// of fake isometric rooms are marked visible even though strict hex FOV
    /// logic would keep them unseen.
    pub fn side_point(self) -> Option<Point2D<i32>> {
        let next = self.next();
        let a = self.to_v2();
        let b = next.to_v2();

        if b.x == a.x + 1 && b.y == a.y + 1 {
            // Going down the right rim.
            Some(Point2D::new(a.x + 1, a.y))
        } else if b.x == a.x - 1 && b.y == a.y - 1 {
            // Going up the left rim.
            Some(Point2D::new(a.x - 1, a.y))
        } else {
            None
        }
    }

    /// The point corresponding to this one on the hex circle with radius +1.
    pub fn further(self) -> PolarPoint {
        PolarPoint::new(self.pos * (self.radius + 1) as f32 / self.radius as f32,
                        self.radius + 1)
    }

    /// The point next to this one along the hex circle.
    pub fn next(self) -> PolarPoint {
        PolarPoint::new((self.pos + 0.5).floor() + 0.5, self.radius)
    }
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;
    use std::iter::FromIterator;
    use euclid::Point2D;
    use super::HexFov;
    use hex::HexGeom;

    #[test]
    fn trivial_fov() {
        // Just draw a small circle.
        let fov = HexFov::new(0i32, |offset, &a| if offset.hex_dist() < 2 {
            Some(a + offset.x + offset.y)
        } else {
            None
        });

        let field: HashMap<Point2D<i32>, i32> = HashMap::from_iter(fov);

        assert!(field.contains_key(&Point2D::new(1, 0)));
        assert!(!field.contains_key(&Point2D::new(1, -1)));

        let fov = HexFov::new(0i32, |offset, &a| if offset.hex_dist() < 2 {
                      Some(a)
                  } else {
                      None
                  })
                      .fake_isometric(|_, _| true);
        let field: HashMap<Point2D<i32>, i32> = HashMap::from_iter(fov);

        assert!(field.contains_key(&Point2D::new(1, 0)));
        assert!(field.contains_key(&Point2D::new(1, -1)));
    }
}
<commit_msg>Give up for now on embedding is_wall function in HexFov<commit_after>use num::Integer;
use euclid::Point2D;
use hex::Dir6;

/// Field of view iterator for a hexagonal map.
///
/// Takes a function that maps cells into user-specified values and indicates when traversal should
/// stop.
pub struct HexFov<F, T> {
    /// Predicate for whether a given point will block the field of view.
    f: F,
    stack: Vec<Sector<T>>,
    /// Extra values generated by special cases.
    side_channel: Vec<(Point2D<i32>, T)>,
}

impl<F, T> HexFov<F, T>
    where F: Fn(Point2D<i32>, &T) -> Option<T>,
          T: Eq + Clone
{
    pub fn new(init: T, f: F) -> HexFov<F, T> {
        // We could run f for (0, 0) here, but the traditional way for the FOV to work is to only
        // consider your surroundings, not the origin site itself.
        HexFov {
            f: f,
            stack: vec![Sector {
                            begin: PolarPoint::new(0.0, 1),
                            pt: PolarPoint::new(0.0, 1),
                            end: PolarPoint::new(6.0, 1),
                            group_value: init.clone(),
                        }],
            // The FOV algorithm will not generate the origin point, so we use
            // the side channel to explicitly add it in the beginning.
            side_channel: vec![(Point2D::new(0, 0), init)],
        }
    }
}

impl<F, T> Iterator for HexFov<F, T>
    where F: Fn(Point2D<i32>, &T) -> Option<T>,
          T: Eq + Clone
{
    type Item = (Point2D<i32>, T);
    fn next(&mut self) -> Option<(Point2D<i32>, T)> {
        if let Some(ret) = self.side_channel.pop() {
            return Some(ret);
        }

        if let Some(mut current) = self.stack.pop() {
            let current_value = (self.f)(current.pt.to_v2(), &current.group_value);

            if current.pt.is_below(current.end) && current_value.is_some() {
                let pos = current.pt.to_v2();
                let current_value = current_value.unwrap();

                if current_value != current.group_value {
                    if current.pt == current.begin {
                        // Oops, we've got a value mismatch on the very first item, so the entire
                        // sector was mistagged. This happens in the initial cycle when we
                        // guesstimate the value. Let's just quickly fix this before anyone
                        // notices.
                        current.group_value = current_value.clone();
                    } else {
                        // Terrain value changed, branch out.

                        // Add the rest of this sector with the new terrain value.
                        self.stack.push(Sector {
                            begin: current.pt,
                            pt: current.pt,
                            end: current.end,
                            group_value: current_value.clone(),
                        });

                        // Branch further if we still get values there.
                        if let Some(further_value) = (self.f)(current.begin.further().to_v2(),
                                                              &current_value) {
                            self.stack.push(Sector {
                                begin: current.begin.further(),
                                pt: current.begin.further(),
                                end: current.pt.further(),
                                group_value: further_value.clone(),
                            });
                        }
                        return self.next();
                    }
                }

                // Proceed along the current sector.
                current.pt = current.pt.next();
                self.stack.push(current);
                return Some((pos, current_value));
            } else {
                // Hit the end of the sector.

                if let Some(group_value) = (self.f)(current.begin.further().to_v2(),
                                                    &current.group_value) {
                    // Branch out further if things are still visible there.
                    self.stack.push(Sector {
                        begin: current.begin.further(),
                        pt: current.begin.further(),
                        end: current.end.further(),
                        group_value: group_value,
                    });
                }

                self.next()
            }
        } else {
            None
        }
    }
}

struct Sector<T> {
    /// Start point of current sector.
    begin: PolarPoint,
    /// Point currently being processed.
    pt: PolarPoint,
    /// End point of current sector.
    end: PolarPoint,
    /// The user value for this group.
    group_value: T,
}

/// Points on a hex circle expressed in polar coordinates.
#[derive(Copy, Clone, PartialEq)]
struct PolarPoint {
    pos: f32,
    radius: u32,
}

impl PolarPoint {
    pub fn new(pos: f32, radius: u32) -> PolarPoint {
        PolarPoint {
            pos: pos,
            radius: radius,
        }
    }
    /// Index of the discrete hex cell along the circle that corresponds to this point.
    fn winding_index(self) -> i32 {
        (self.pos + 0.5).floor() as i32
    }

    pub fn is_below(self, other: PolarPoint) -> bool {
        self.winding_index() < other.end_index()
    }

    fn end_index(self) -> i32 {
        (self.pos + 0.5).ceil() as i32
    }

    pub fn to_v2(self) -> Point2D<i32> {
        if self.radius == 0 {
            return Point2D::new(0, 0);
        }
        let index = self.winding_index();
        let sector = index.mod_floor(&(self.radius as i32 * 6)) / self.radius as i32;
        let offset = index.mod_floor(&(self.radius as i32));

        let rod = Dir6::from_int(sector).to_v2();
        let tangent = Dir6::from_int((sector + 2) % 6).to_v2();

        rod * (self.radius as i32) + tangent * offset
    }

    /// The point corresponding to this one on the hex circle with radius +1.
    pub fn further(self) -> PolarPoint {
        PolarPoint::new(self.pos * (self.radius + 1) as f32 / self.radius as f32,
                        self.radius + 1)
    }

    /// The point next to this one along the hex circle.
    pub fn next(self) -> PolarPoint {
        PolarPoint::new((self.pos + 0.5).floor() + 0.5, self.radius)
    }
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;
    use std::iter::FromIterator;
    use euclid::Point2D;
    use super::HexFov;
    use hex::HexGeom;

    #[test]
    fn trivial_fov() {
        // Just draw a small circle.
        let fov = HexFov::new(0i32, |offset, &a| if offset.hex_dist() < 2 {
            Some(a + offset.x + offset.y)
        } else {
            None
        });

        let field: HashMap<Point2D<i32>, i32> = HashMap::from_iter(fov);

        assert!(field.contains_key(&Point2D::new(1, 0)));
        assert!(!field.contains_key(&Point2D::new(1, -1)));
    }
}
<|endoftext|>


<commit_before>// A port of the simplistic benchmark from
//
//    http://github.com/PaulKeeble/ScalaVErlangAgents
//
// I *think* it's the same, more or less.

extern mod std;
extern mod extra;
extern mod zmq;

use std::comm;
use std::os;
use std::task;

fn server(mut pull_socket: zmq::Socket, mut push_socket: zmq::Socket, mut workers: uint) {
    let mut count = 0u;
    let mut msg = zmq::Message::new();

    while workers != 0 {
        match pull_socket.recv(&mut msg, 0) {
            Err(e) => fail!(e.to_str()),
            Ok(()) => {
                msg.with_str(|s| {
                    if s == "" {
                        workers -= 1;
                    } else {
                        count += from_str::<uint>(s).unwrap();
                    }
                })
            }
        }
    }

    match push_socket.send_str(count.to_str(), 0) {
        Ok(()) => { }
        Err(e) => fail!(e.to_str()),
    }
}

fn spawn_server(ctx: &mut zmq::Context, workers: uint) -> comm::Chan<()> {
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    pull_socket.bind("inproc://server-pull").unwrap();
    push_socket.bind("inproc://server-push").unwrap();

    // Spawn the server.
    let (ready_po, ready_ch) = comm::Chan::new();
    let (start_po, start_ch) = comm::Chan::new();

    // Mutable sockets cannot be implicitly captured.
    let pull_socket = pull_socket;
    let push_socket = push_socket;

    let mut task = task::task();
    task.sched_mode(task::SingleThreaded);
    do task.spawn {
        // Let the main thread know we're ready.
        ready_ch.send(());

        // Wait until we need to start.
        start_po.recv();

        server(pull_socket, push_socket, workers);
    }

    // Wait for the server to start.
    ready_po.recv();

    start_ch
}

fn worker(mut push_socket: zmq::Socket, count: uint) {
    for _ in range(0, count) {
        push_socket.send_str(100u.to_str(), 0).unwrap();
    }

    // Let the server know we're done.
    push_socket.send_str("", 0).unwrap();
}

fn spawn_worker(ctx: &mut zmq::Context, count: uint) -> comm::Port<()> {
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();

    // Mutable sockets cannot be implicitly captured.
    let push_socket = push_socket;

    // Spawn the worker.
    let (po, ch) = comm::Chan::new();
    let mut task = task::task();
    task.sched_mode(task::SingleThreaded);
    do task.spawn {
        // Let the main thread we're ready.
        ch.send(());

        worker(push_socket, count);

        ch.send(());
    }

    // Wait for the worker to start.
    po.recv();

    po
}

fn run(ctx: &mut zmq::Context, size: uint, workers: uint) {
    let start_ch = spawn_server(ctx, workers);

    // Create some command/control sockets.
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    pull_socket.connect("inproc://server-push").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();
    //pull_socket.connect("tcp://127.0.0.1:3457").unwrap();

    // Spawn all the workers.
    let mut worker_results = ~[];
    for _ in range(0, workers) {
        worker_results.push(spawn_worker(ctx, size / workers));
    }

    let start = extra::time::precise_time_s();

    start_ch.send(());

    // Block until all the workers finish.
    for po in worker_results.iter() {
        po.recv();
    }

    // Receive the final count.
    let result = match pull_socket.recv_msg(0) {
        Ok(msg) => msg.with_str(|s| from_str::<uint>(s).unwrap()),
        Err(e) => fail!(e.to_str()),
    };

    let end = extra::time::precise_time_s();
    let elapsed = end - start;

    println!("Count is {}", result);
    println!("Test took {} seconds", elapsed);
    let thruput = ((size / workers * workers) as f64) / (elapsed as f64);
    println!("Throughput={:f} per sec", thruput);
}

fn main() {
    let args = os::args();

    let args = if os::getenv("RUST_BENCH").is_some() {
        ~[~"", ~"1000000", ~"10000"]
    } else if args.len() <= 1u {
        ~[~"", ~"10000", ~"4"]
    } else {
        args
    };

    let size = from_str::<uint>(args[1]).unwrap();
    let workers = from_str::<uint>(args[2]).unwrap();

    let mut ctx = zmq::Context::new();

    run(&mut ctx, size, workers);
}
<commit_msg>Update to rust 0.9-pre (a5fa1d9)<commit_after>// A port of the simplistic benchmark from
//
//    http://github.com/PaulKeeble/ScalaVErlangAgents
//
// I *think* it's the same, more or less.

extern mod std;
extern mod extra;
extern mod native;
extern mod zmq;

use std::comm;
use std::os;

fn server(mut pull_socket: zmq::Socket, mut push_socket: zmq::Socket, mut workers: uint) {
    let mut count = 0u;
    let mut msg = zmq::Message::new();

    while workers != 0 {
        match pull_socket.recv(&mut msg, 0) {
            Err(e) => fail!(e.to_str()),
            Ok(()) => {
                msg.with_str(|s| {
                    if s == "" {
                        workers -= 1;
                    } else {
                        count += from_str::<uint>(s).unwrap();
                    }
                })
            }
        }
    }

    match push_socket.send_str(count.to_str(), 0) {
        Ok(()) => { }
        Err(e) => fail!(e.to_str()),
    }
}

fn spawn_server(ctx: &mut zmq::Context, workers: uint) -> comm::Chan<()> {
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    pull_socket.bind("inproc://server-pull").unwrap();
    push_socket.bind("inproc://server-push").unwrap();

    // Spawn the server.
    let (ready_po, ready_ch) = comm::Chan::new();
    let (start_po, start_ch) = comm::Chan::new();

    // Mutable sockets cannot be implicitly captured.
    let pull_socket = pull_socket;
    let push_socket = push_socket;

    do native::task::spawn {
        // Let the main thread know we're ready.
        ready_ch.send(());

        // Wait until we need to start.
        start_po.recv();

        server(pull_socket, push_socket, workers);
    }

    // Wait for the server to start.
    ready_po.recv();

    start_ch
}

fn worker(mut push_socket: zmq::Socket, count: uint) {
    for _ in range(0, count) {
        push_socket.send_str(100u.to_str(), 0).unwrap();
    }

    // Let the server know we're done.
    push_socket.send_str("", 0).unwrap();
}

fn spawn_worker(ctx: &mut zmq::Context, count: uint) -> comm::Port<()> {
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();

    // Mutable sockets cannot be implicitly captured.
    let push_socket = push_socket;

    // Spawn the worker.
    let (po, ch) = comm::Chan::new();
    do native::task::spawn {
        // Let the main thread we're ready.
        ch.send(());

        worker(push_socket, count);

        ch.send(());
    }

    // Wait for the worker to start.
    po.recv();

    po
}

fn run(ctx: &mut zmq::Context, size: uint, workers: uint) {
    let start_ch = spawn_server(ctx, workers);

    // Create some command/control sockets.
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    pull_socket.connect("inproc://server-push").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();
    //pull_socket.connect("tcp://127.0.0.1:3457").unwrap();

    // Spawn all the workers.
    let mut worker_results = ~[];
    for _ in range(0, workers) {
        worker_results.push(spawn_worker(ctx, size / workers));
    }

    let start = extra::time::precise_time_s();

    start_ch.send(());

    // Block until all the workers finish.
    for po in worker_results.iter() {
        po.recv();
    }

    // Receive the final count.
    let result = match pull_socket.recv_msg(0) {
        Ok(msg) => msg.with_str(|s| from_str::<uint>(s).unwrap()),
        Err(e) => fail!(e.to_str()),
    };

    let end = extra::time::precise_time_s();
    let elapsed = end - start;

    println!("Count is {}", result);
    println!("Test took {} seconds", elapsed);
    let thruput = ((size / workers * workers) as f64) / (elapsed as f64);
    println!("Throughput={:f} per sec", thruput);
}

fn main() {
    let args = os::args();

    let args = if os::getenv("RUST_BENCH").is_some() {
        ~[~"", ~"1000000", ~"10000"]
    } else if args.len() <= 1u {
        ~[~"", ~"10000", ~"4"]
    } else {
        args
    };

    let size = from_str::<uint>(args[1]).unwrap();
    let workers = from_str::<uint>(args[2]).unwrap();

    let mut ctx = zmq::Context::new();

    run(&mut ctx, size, workers);
}
<|endoftext|>


<commit_before>//! Default shaders.

use luminance::M44;
use luminance_gl::gl33::Uniform;
use std::ops::Deref;

use id::Id;
use shader::Program;
use scene::Scene;

pub type ColorUniform = Uniform<[f32; 3]>;
pub type Mat44Uniform = Uniform<M44>;

pub const DEFAULT_2D_COLOR: ColorUniform = Uniform::new(0);

pub struct DefaultProgram2D<'a>(Id<'a, Program>);

impl<'a> Deref for DefaultProgram2D<'a> {
  type Target = Id<'a, Program>;

  fn deref(&self) -> &Self::Target {
    &self.0
  }
}

impl<'a> DefaultProgram2D<'a> {
  pub fn new_from(scene: &mut Scene<'a>) -> Option<Self> {
    get_id!(scene, "spectra/default_2d.glsl", vec![ColorUniform::sem("color")]).map(DefaultProgram2D)
  }
}

pub const DEFAULT_3D_PROJ: Mat44Uniform = Uniform::new(0);
pub const DEFAULT_3D_VIEW: Mat44Uniform = Uniform::new(1);
pub const DEFAULT_3D_INST: Mat44Uniform = Uniform::new(2);

pub struct DefaultProgram3D<'a>(Id<'a, Program>);

impl<'a> Deref for DefaultProgram3D<'a> {
  type Target = Id<'a, Program>;

  fn deref(&self) -> &Self::Target {
    &self.0
  }
}

impl<'a> DefaultProgram3D<'a> {
  pub fn new_from(scene: &mut Scene<'a>) -> Option<Self> {
    get_id!(scene, "spectra/default_3d.glsl", vec![
              Mat44Uniform::sem("proj"),
              Mat44Uniform::sem("view"),
              Mat44Uniform::sem("inst")])
      .map(DefaultProgram3D)
  }
}
<commit_msg>Various new_from to new.<commit_after>//! Default shaders.

use luminance::M44;
use luminance_gl::gl33::Uniform;
use std::ops::Deref;

use id::Id;
use shader::Program;
use scene::Scene;

pub type ColorUniform = Uniform<[f32; 3]>;
pub type Mat44Uniform = Uniform<M44>;

pub const DEFAULT_2D_COLOR: ColorUniform = Uniform::new(0);

pub struct DefaultProgram2D<'a>(Id<'a, Program>);

impl<'a> Deref for DefaultProgram2D<'a> {
  type Target = Id<'a, Program>;

  fn deref(&self) -> &Self::Target {
    &self.0
  }
}

impl<'a> DefaultProgram2D<'a> {
  pub fn new(scene: &mut Scene<'a>) -> Option<Self> {
    get_id!(scene, "spectra/default_2d.glsl", vec![ColorUniform::sem("color")]).map(DefaultProgram2D)
  }
}

pub const DEFAULT_3D_PROJ: Mat44Uniform = Uniform::new(0);
pub const DEFAULT_3D_VIEW: Mat44Uniform = Uniform::new(1);
pub const DEFAULT_3D_INST: Mat44Uniform = Uniform::new(2);

pub struct DefaultProgram3D<'a>(Id<'a, Program>);

impl<'a> Deref for DefaultProgram3D<'a> {
  type Target = Id<'a, Program>;

  fn deref(&self) -> &Self::Target {
    &self.0
  }
}

impl<'a> DefaultProgram3D<'a> {
  pub fn new(scene: &mut Scene<'a>) -> Option<Self> {
    get_id!(scene, "spectra/default_3d.glsl", vec![
              Mat44Uniform::sem("proj"),
              Mat44Uniform::sem("view"),
              Mat44Uniform::sem("inst")])
      .map(DefaultProgram3D)
  }
}
<|endoftext|>


<commit_before>use std::cmp::min;
use std::f64;

use markup5ever::{expanded_name, local_name, namespace_url, ns};
use nalgebra::{DMatrix, Dynamic, VecStorage};

use crate::attributes::Attributes;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::Node;
use crate::parsers::{NumberOptionalNumber, ParseValue};
use crate::rect::IRect;
use crate::surface_utils::{
    shared_surface::{BlurDirection, Horizontal, SharedImageSurface, Vertical},
    EdgeMode,
};

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// The maximum gaussian blur kernel size.
///
/// The value of 500 is used in webkit.
const MAXIMUM_KERNEL_SIZE: usize = 500;

/// The `feGaussianBlur` filter primitive.
pub struct FeGaussianBlur {
    base: PrimitiveWithInput,
    std_deviation: (f64, f64),
}

impl Default for FeGaussianBlur {
    /// Constructs a new `GaussianBlur` with empty properties.
    #[inline]
    fn default() -> FeGaussianBlur {
        FeGaussianBlur {
            base: PrimitiveWithInput::new::<Self>(),
            std_deviation: (0.0, 0.0),
        }
    }
}

impl SetAttributes for FeGaussianBlur {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.set_attributes(attrs)?;
        let result = attrs
            .iter()
            .find(|(attr, _)| attr.expanded() == expanded_name!("", "stdDeviation"))
            .and_then(|(attr, value)| {
                attr.parse_and_validate(value, |v: NumberOptionalNumber<f64>| {
                    if v.0 >= 0.0 && v.1 >= 0.0 {
                        Ok(v)
                    } else {
                        Err(ValueErrorKind::value_error("values can't be negative"))
                    }
                })
                .ok()
            });
        if let Some(tuple) = result {
            self.std_deviation = (tuple.0, tuple.1);
        }

        Ok(())
    }
}

/// Computes a gaussian kernel line for the given standard deviation.
fn gaussian_kernel(std_deviation: f64) -> Vec<f64> {
    assert!(std_deviation > 0.0);

    // Make sure there aren't any infinities.
    let maximal_deviation = (MAXIMUM_KERNEL_SIZE / 2) as f64 / 3.0;

    // Values further away than std_deviation * 3 are too small to contribute anything meaningful.
    let radius = ((std_deviation.min(maximal_deviation) * 3.0) + 0.5) as usize;
    // Clamp the radius rather than diameter because `MAXIMUM_KERNEL_SIZE` might be even and we
    // want an odd-sized kernel.
    let radius = min(radius, (MAXIMUM_KERNEL_SIZE - 1) / 2);
    let diameter = radius * 2 + 1;

    let mut kernel = Vec::with_capacity(diameter);

    let gauss_point = |x: f64| (-x.powi(2) / (2.0 * std_deviation.powi(2))).exp();

    // Fill the matrix by doing numerical integration approximation from -2*std_dev to 2*std_dev,
    // sampling 50 points per pixel. We do the bottom half, mirror it to the top half, then compute
    // the center point. Otherwise asymmetric quantization errors will occur. The formula to
    // integrate is e^-(x^2/2s^2).
    for i in 0..diameter / 2 {
        let base_x = (diameter / 2 + 1 - i) as f64 - 0.5;

        let mut sum = 0.0;
        for j in 1..=50 {
            let r = base_x + 0.02 * f64::from(j);
            sum += gauss_point(r);
        }

        kernel.push(sum / 50.0);
    }

    // We'll compute the middle point later.
    kernel.push(0.0);

    // Mirror the bottom half to the top half.
    for i in 0..diameter / 2 {
        let x = kernel[diameter / 2 - 1 - i];
        kernel.push(x);
    }

    // Find center val -- calculate an odd number of quanta to make it symmetric, even if the
    // center point is weighted slightly higher than others.
    let mut sum = 0.0;
    for j in 0..=50 {
        let r = -0.5 + 0.02 * f64::from(j);
        sum += gauss_point(r);
    }
    kernel[diameter / 2] = sum / 51.0;

    // Normalize the distribution by scaling the total sum to 1.
    let sum = kernel.iter().sum::<f64>();
    kernel.iter_mut().for_each(|x| *x /= sum);

    kernel
}

/// Returns a size of the box blur kernel to approximate the gaussian blur.
fn box_blur_kernel_size(std_deviation: f64) -> usize {
    let d = (std_deviation * 3.0 * (2.0 * f64::consts::PI).sqrt() / 4.0 + 0.5).floor();
    let d = d.min(MAXIMUM_KERNEL_SIZE as f64);
    d as usize
}

/// Applies three box blurs to approximate the gaussian blur.
///
/// This is intended to be used in two steps, horizontal and vertical.
fn three_box_blurs<B: BlurDirection>(
    surface: &SharedImageSurface,
    bounds: IRect,
    std_deviation: f64,
) -> Result<SharedImageSurface, FilterError> {
    let d = box_blur_kernel_size(std_deviation);
    if d == 0 {
        return Ok(surface.clone());
    }

    let surface = if d % 2 == 1 {
        // Odd kernel sizes just get three successive box blurs.
        let mut surface = surface.clone();

        for _ in 0..3 {
            surface = surface.box_blur::<B>(bounds, d, d / 2)?;
        }

        surface
    } else {
        // Even kernel sizes have a more interesting scheme.
        let surface = surface.box_blur::<B>(bounds, d, d / 2)?;
        let surface = surface.box_blur::<B>(bounds, d, d / 2 - 1)?;

        let d = d + 1;
        surface.box_blur::<B>(bounds, d, d / 2)?
    };

    Ok(surface)
}

/// Applies the gaussian blur.
///
/// This is intended to be used in two steps, horizontal and vertical.
fn gaussian_blur(
    input_surface: &SharedImageSurface,
    bounds: IRect,
    std_deviation: f64,
    vertical: bool,
) -> Result<SharedImageSurface, FilterError> {
    let kernel = gaussian_kernel(std_deviation);
    let (rows, cols) = if vertical {
        (kernel.len(), 1)
    } else {
        (1, kernel.len())
    };
    let kernel = DMatrix::from_data(VecStorage::new(
        Dynamic::new(rows),
        Dynamic::new(cols),
        kernel,
    ));

    Ok(input_surface.convolve(
        bounds,
        ((cols / 2) as i32, (rows / 2) as i32),
        &kernel,
        EdgeMode::None,
    )?)
}

impl FilterEffect for FeGaussianBlur {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, acquired_nodes, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx, node.parent().as_ref())?
            .add_input(&input)
            .into_irect(draw_ctx);

        let (std_x, std_y) = self.std_deviation;
        let (std_x, std_y) = ctx.paffine().transform_distance(std_x, std_y);

        // The deviation can become negative here due to the transform.
        let std_x = std_x.abs();
        let std_y = std_y.abs();

        // Performance TODO: gaussian blur is frequently used for shadows, operating on SourceAlpha
        // (so the image is alpha-only). We can use this to not waste time processing the other
        // channels.

        // Horizontal convolution.
        let horiz_result_surface = if std_x >= 2.0 {
            // The spec says for deviation >= 2.0 three box blurs can be used as an optimization.
            three_box_blurs::<Horizontal>(input.surface(), bounds, std_x)?
        } else if std_x != 0.0 {
            gaussian_blur(input.surface(), bounds, std_x, false)?
        } else {
            input.surface().clone()
        };

        // Vertical convolution.
        let output_surface = if std_y >= 2.0 {
            // The spec says for deviation >= 2.0 three box blurs can be used as an optimization.
            three_box_blurs::<Vertical>(&horiz_result_surface, bounds, std_y)?
        } else if std_y != 0.0 {
            gaussian_blur(&horiz_result_surface, bounds, std_y, true)?
        } else {
            horiz_result_surface
        };

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: output_surface,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}
<commit_msg>blur: use NonNegative for parsing<commit_after>use std::cmp::min;
use std::f64;

use markup5ever::{expanded_name, local_name, namespace_url, ns};
use nalgebra::{DMatrix, Dynamic, VecStorage};

use crate::attributes::Attributes;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::node::Node;
use crate::parsers::{NonNegative, NumberOptionalNumber, ParseValue};
use crate::rect::IRect;
use crate::surface_utils::{
    shared_surface::{BlurDirection, Horizontal, SharedImageSurface, Vertical},
    EdgeMode,
};

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// The maximum gaussian blur kernel size.
///
/// The value of 500 is used in webkit.
const MAXIMUM_KERNEL_SIZE: usize = 500;

/// The `feGaussianBlur` filter primitive.
pub struct FeGaussianBlur {
    base: PrimitiveWithInput,
    std_deviation: (f64, f64),
}

impl Default for FeGaussianBlur {
    /// Constructs a new `GaussianBlur` with empty properties.
    #[inline]
    fn default() -> FeGaussianBlur {
        FeGaussianBlur {
            base: PrimitiveWithInput::new::<Self>(),
            std_deviation: (0.0, 0.0),
        }
    }
}

impl SetAttributes for FeGaussianBlur {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.set_attributes(attrs)?;

        for (attr, value) in attrs.iter() {
            if let expanded_name!("", "stdDeviation") = attr.expanded() {
                let NumberOptionalNumber(NonNegative(x), NonNegative(y)) = attr.parse(value)?;
                self.std_deviation = (x, y);
            }
        }

        Ok(())
    }
}

/// Computes a gaussian kernel line for the given standard deviation.
fn gaussian_kernel(std_deviation: f64) -> Vec<f64> {
    assert!(std_deviation > 0.0);

    // Make sure there aren't any infinities.
    let maximal_deviation = (MAXIMUM_KERNEL_SIZE / 2) as f64 / 3.0;

    // Values further away than std_deviation * 3 are too small to contribute anything meaningful.
    let radius = ((std_deviation.min(maximal_deviation) * 3.0) + 0.5) as usize;
    // Clamp the radius rather than diameter because `MAXIMUM_KERNEL_SIZE` might be even and we
    // want an odd-sized kernel.
    let radius = min(radius, (MAXIMUM_KERNEL_SIZE - 1) / 2);
    let diameter = radius * 2 + 1;

    let mut kernel = Vec::with_capacity(diameter);

    let gauss_point = |x: f64| (-x.powi(2) / (2.0 * std_deviation.powi(2))).exp();

    // Fill the matrix by doing numerical integration approximation from -2*std_dev to 2*std_dev,
    // sampling 50 points per pixel. We do the bottom half, mirror it to the top half, then compute
    // the center point. Otherwise asymmetric quantization errors will occur. The formula to
    // integrate is e^-(x^2/2s^2).
    for i in 0..diameter / 2 {
        let base_x = (diameter / 2 + 1 - i) as f64 - 0.5;

        let mut sum = 0.0;
        for j in 1..=50 {
            let r = base_x + 0.02 * f64::from(j);
            sum += gauss_point(r);
        }

        kernel.push(sum / 50.0);
    }

    // We'll compute the middle point later.
    kernel.push(0.0);

    // Mirror the bottom half to the top half.
    for i in 0..diameter / 2 {
        let x = kernel[diameter / 2 - 1 - i];
        kernel.push(x);
    }

    // Find center val -- calculate an odd number of quanta to make it symmetric, even if the
    // center point is weighted slightly higher than others.
    let mut sum = 0.0;
    for j in 0..=50 {
        let r = -0.5 + 0.02 * f64::from(j);
        sum += gauss_point(r);
    }
    kernel[diameter / 2] = sum / 51.0;

    // Normalize the distribution by scaling the total sum to 1.
    let sum = kernel.iter().sum::<f64>();
    kernel.iter_mut().for_each(|x| *x /= sum);

    kernel
}

/// Returns a size of the box blur kernel to approximate the gaussian blur.
fn box_blur_kernel_size(std_deviation: f64) -> usize {
    let d = (std_deviation * 3.0 * (2.0 * f64::consts::PI).sqrt() / 4.0 + 0.5).floor();
    let d = d.min(MAXIMUM_KERNEL_SIZE as f64);
    d as usize
}

/// Applies three box blurs to approximate the gaussian blur.
///
/// This is intended to be used in two steps, horizontal and vertical.
fn three_box_blurs<B: BlurDirection>(
    surface: &SharedImageSurface,
    bounds: IRect,
    std_deviation: f64,
) -> Result<SharedImageSurface, FilterError> {
    let d = box_blur_kernel_size(std_deviation);
    if d == 0 {
        return Ok(surface.clone());
    }

    let surface = if d % 2 == 1 {
        // Odd kernel sizes just get three successive box blurs.
        let mut surface = surface.clone();

        for _ in 0..3 {
            surface = surface.box_blur::<B>(bounds, d, d / 2)?;
        }

        surface
    } else {
        // Even kernel sizes have a more interesting scheme.
        let surface = surface.box_blur::<B>(bounds, d, d / 2)?;
        let surface = surface.box_blur::<B>(bounds, d, d / 2 - 1)?;

        let d = d + 1;
        surface.box_blur::<B>(bounds, d, d / 2)?
    };

    Ok(surface)
}

/// Applies the gaussian blur.
///
/// This is intended to be used in two steps, horizontal and vertical.
fn gaussian_blur(
    input_surface: &SharedImageSurface,
    bounds: IRect,
    std_deviation: f64,
    vertical: bool,
) -> Result<SharedImageSurface, FilterError> {
    let kernel = gaussian_kernel(std_deviation);
    let (rows, cols) = if vertical {
        (kernel.len(), 1)
    } else {
        (1, kernel.len())
    };
    let kernel = DMatrix::from_data(VecStorage::new(
        Dynamic::new(rows),
        Dynamic::new(cols),
        kernel,
    ));

    Ok(input_surface.convolve(
        bounds,
        ((cols / 2) as i32, (rows / 2) as i32),
        &kernel,
        EdgeMode::None,
    )?)
}

impl FilterEffect for FeGaussianBlur {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, acquired_nodes, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx, node.parent().as_ref())?
            .add_input(&input)
            .into_irect(draw_ctx);

        let (std_x, std_y) = self.std_deviation;
        let (std_x, std_y) = ctx.paffine().transform_distance(std_x, std_y);

        // The deviation can become negative here due to the transform.
        let std_x = std_x.abs();
        let std_y = std_y.abs();

        // Performance TODO: gaussian blur is frequently used for shadows, operating on SourceAlpha
        // (so the image is alpha-only). We can use this to not waste time processing the other
        // channels.

        // Horizontal convolution.
        let horiz_result_surface = if std_x >= 2.0 {
            // The spec says for deviation >= 2.0 three box blurs can be used as an optimization.
            three_box_blurs::<Horizontal>(input.surface(), bounds, std_x)?
        } else if std_x != 0.0 {
            gaussian_blur(input.surface(), bounds, std_x, false)?
        } else {
            input.surface().clone()
        };

        // Vertical convolution.
        let output_surface = if std_y >= 2.0 {
            // The spec says for deviation >= 2.0 three box blurs can be used as an optimization.
            three_box_blurs::<Vertical>(&horiz_result_surface, bounds, std_y)?
        } else if std_y != 0.0 {
            gaussian_blur(&horiz_result_surface, bounds, std_y, true)?
        } else {
            horiz_result_surface
        };

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: output_surface,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}
<|endoftext|>


<commit_before>use crate::symbol::Symbol;
use std::cmp;

#[cfg(test)]
mod tests;

/// Finds the Levenshtein distance between two strings
pub fn lev_distance(a: &str, b: &str) -> usize {
    // cases which don't require further computation
    if a.is_empty() {
        return b.chars().count();
    } else if b.is_empty() {
        return a.chars().count();
    }

    let mut dcol: Vec<_> = (0..=b.len()).collect();
    let mut t_last = 0;

    for (i, sc) in a.chars().enumerate() {
        let mut current = i;
        dcol[0] = current + 1;

        for (j, tc) in b.chars().enumerate() {
            let next = dcol[j + 1];
            if sc == tc {
                dcol[j + 1] = current;
            } else {
                dcol[j + 1] = cmp::min(current, next);
                dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
            }
            current = next;
            t_last = j;
        }
    }
    dcol[t_last + 1]
}

/// Finds the best match for a given word in the given iterator
///
/// As a loose rule to avoid the obviously incorrect suggestions, it takes
/// an optional limit for the maximum allowable edit distance, which defaults
/// to one-third of the given word.
///
/// Besides Levenshtein, we use case insensitive comparison to improve accuracy on an edge case with
/// a lower(upper)case letters mismatch.
pub fn find_best_match_for_name<'a, T>(
    iter_names: T,
    lookup: &str,
    dist: Option<usize>,
) -> Option<Symbol>
where
    T: Iterator<Item = &'a Symbol>,
{
    let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d);
    let name_vec: Vec<&Symbol> = iter_names.collect();

    let (case_insensitive_match, levenshtein_match) = name_vec.iter()
        .filter_map(|&name| {
            let dist = lev_distance(lookup, &name.as_str());
            if dist <= max_dist { Some((name, dist)) } else { None }
        })
        // Here we are collecting the next structure:
        // (case_insensitive_match, (levenshtein_match, levenshtein_distance))
        .fold((None, None), |result, (candidate, dist)| {
            (
                if candidate.as_str().to_uppercase() == lookup.to_uppercase() {
                    Some(candidate)
                } else {
                    result.0
                },
                match result.1 {
                    None => Some((candidate, dist)),
                    Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) }),
                },
            )
        });

    // Priority of matches:
    // 1. Exact case insensitive match
    // 2. Levenshtein distance match
    // 3. Sorted word match
    if let Some(candidate) = case_insensitive_match {
        Some(*candidate)
    } else if levenshtein_match.is_some() {
        levenshtein_match.map(|(candidate, _)| *candidate)
    } else {
        find_match_by_sorted_words(name_vec, lookup)
    }
}

fn find_match_by_sorted_words<'a>(iter_names: Vec<&'a Symbol>, lookup: &str) -> Option<Symbol> {
    iter_names.iter().fold(None, |result, candidate| {
        if sort_by_words(&candidate.as_str()) == sort_by_words(lookup) {
            Some(**candidate)
        } else {
            result
        }
    })
}

fn sort_by_words(name: &str) -> String {
    let mut split_words: Vec<&str> = name.split('_').collect();
    split_words.sort();
    split_words.join("_")
}
<commit_msg>missed tidy check<commit_after>use crate::symbol::Symbol;
use std::cmp;

#[cfg(test)]
mod tests;

/// Finds the Levenshtein distance between two strings
pub fn lev_distance(a: &str, b: &str) -> usize {
    // cases which don't require further computation
    if a.is_empty() {
        return b.chars().count();
    } else if b.is_empty() {
        return a.chars().count();
    }

    let mut dcol: Vec<_> = (0..=b.len()).collect();
    let mut t_last = 0;

    for (i, sc) in a.chars().enumerate() {
        let mut current = i;
        dcol[0] = current + 1;

        for (j, tc) in b.chars().enumerate() {
            let next = dcol[j + 1];
            if sc == tc {
                dcol[j + 1] = current;
            } else {
                dcol[j + 1] = cmp::min(current, next);
                dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
            }
            current = next;
            t_last = j;
        }
    }
    dcol[t_last + 1]
}

/// Finds the best match for a given word in the given iterator
///
/// As a loose rule to avoid the obviously incorrect suggestions, it takes
/// an optional limit for the maximum allowable edit distance, which defaults
/// to one-third of the given word.
///
/// Besides Levenshtein, we use case insensitive comparison to improve accuracy on an edge case with
/// a lower(upper)case letters mismatch.
pub fn find_best_match_for_name<'a, T>(
    iter_names: T,
    lookup: &str,
    dist: Option<usize>,
) -> Option<Symbol>
where
    T: Iterator<Item = &'a Symbol>,
{
    let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d);
    let name_vec: Vec<&Symbol> = iter_names.collect();

    let (case_insensitive_match, levenshtein_match) = name_vec
        .iter()
        .filter_map(|&name| {
            let dist = lev_distance(lookup, &name.as_str());
            if dist <= max_dist { Some((name, dist)) } else { None }
        })
        // Here we are collecting the next structure:
        // (case_insensitive_match, (levenshtein_match, levenshtein_distance))
        .fold((None, None), |result, (candidate, dist)| {
            (
                if candidate.as_str().to_uppercase() == lookup.to_uppercase() {
                    Some(candidate)
                } else {
                    result.0
                },
                match result.1 {
                    None => Some((candidate, dist)),
                    Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) }),
                },
            )
        });
    // Priority of matches:
    // 1. Exact case insensitive match
    // 2. Levenshtein distance match
    // 3. Sorted word match
    if let Some(candidate) = case_insensitive_match {
        Some(*candidate)
    } else if levenshtein_match.is_some() {
        levenshtein_match.map(|(candidate, _)| *candidate)
    } else {
        find_match_by_sorted_words(name_vec, lookup)
    }
}

fn find_match_by_sorted_words<'a>(iter_names: Vec<&'a Symbol>, lookup: &str) -> Option<Symbol> {
    iter_names.iter().fold(None, |result, candidate| {
        if sort_by_words(&candidate.as_str()) == sort_by_words(lookup) {
            Some(**candidate)
        } else {
            result
        }
    })
}

fn sort_by_words(name: &str) -> String {
    let mut split_words: Vec<&str> = name.split('_').collect();
    split_words.sort();
    split_words.join("_")
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

use std::sync::{Arc, Mutex};
use std::thread::Thread;
// use std::sync::atomic::{AtomicOption, SeqCst};
use std::io::net::addrinfo::get_host_addresses;
use std::io::net::ip::IpAddr;

use collect::LruCache;

use config::DEFAULT_DNS_CACHE_CAPACITY;

struct DnsLruCache {
    cache: LruCache<String, Vec<IpAddr>>,
    totally_matched: usize,
    totally_missed: usize,
}

pub struct CachedDns {
    lru_cache: Arc<Mutex<DnsLruCache>>,
}

impl CachedDns {
    pub fn new() -> CachedDns {
        CachedDns {
            lru_cache: Arc::new(Mutex::new(DnsLruCache {
                cache: LruCache::new(DEFAULT_DNS_CACHE_CAPACITY),
                totally_missed: 0,
                totally_matched: 0,
            })),
        }
    }

    pub fn with_capacity(cache_capacity: usize) -> CachedDns {
        CachedDns {
            lru_cache: Arc::new(Mutex::new(DnsLruCache {
                cache: LruCache::new(cache_capacity),
                totally_missed: 0,
                totally_matched: 0,
            })),
        }
    }

    pub fn resolve(&self, addr: &str) -> Option<Vec<IpAddr>> {
        let addr_string = addr.to_string();

        {
            let mut cache = self.lru_cache.lock().unwrap();
            match cache.cache.get(&addr_string).map(|x| x.clone()) {
                Some(addrs) => {
                    cache.totally_matched += 1;
                    debug!("DNS cache matched!: {}", addr_string);
                    debug!("DNS cache matched: {}, missed: {}", cache.totally_matched, cache.totally_missed);
                    return Some(addrs)
                },
                None => {
                    cache.totally_missed += 1;
                    debug!("DNS cache missed!: {}", addr_string);
                    debug!("DNS cache matched: {}, missed: {}", cache.totally_matched, cache.totally_missed);
                }
            }
        }

        let addrs = match get_host_addresses(addr) {
            Ok(addrs) => addrs,
            Err(err) => {
                error!("Failed to resolve {}: {}", addr, err);
                return None;
            }
        };

        let cloned_mutex = self.lru_cache.clone();
        let cloned_addr = addrs.clone();
        Thread::spawn(move || {
            let mut cache = cloned_mutex.lock().unwrap();
            cache.cache.insert(addr_string, cloned_addr);
        });
        Some(addrs)
    }
}

unsafe impl Send for CachedDns {}
<commit_msg>use task pool<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

use std::sync::{Arc, Mutex, TaskPool};
use std::thread::Thread;
// use std::sync::atomic::{AtomicOption, SeqCst};
use std::io::net::addrinfo::get_host_addresses;
use std::io::net::ip::IpAddr;

use collect::LruCache;

use config::DEFAULT_DNS_CACHE_CAPACITY;

const TASK_POOL_SIZE: usize = 4;

struct DnsLruCache {
    cache: LruCache<String, Vec<IpAddr>>,
    totally_matched: usize,
    totally_missed: usize,
}

pub struct CachedDns {
    lru_cache: Arc<Mutex<DnsLruCache>>,
    pool: TaskPool,
}

impl CachedDns {
    pub fn new() -> CachedDns {
        CachedDns {
            lru_cache: Arc::new(Mutex::new(DnsLruCache {
                cache: LruCache::new(DEFAULT_DNS_CACHE_CAPACITY),
                totally_missed: 0,
                totally_matched: 0,
            })),
            pool: TaskPool::new(TASK_POOL_SIZE),
        }
    }

    pub fn with_capacity(cache_capacity: usize) -> CachedDns {
        CachedDns {
            lru_cache: Arc::new(Mutex::new(DnsLruCache {
                cache: LruCache::new(cache_capacity),
                totally_missed: 0,
                totally_matched: 0,
            })),
            pool: TaskPool::new(TASK_POOL_SIZE),
        }
    }

    pub fn resolve(&self, addr: &str) -> Option<Vec<IpAddr>> {
        let addr_string = addr.to_string();

        {
            let mut cache = self.lru_cache.lock().unwrap();
            match cache.cache.get(&addr_string).map(|x| x.clone()) {
                Some(addrs) => {
                    cache.totally_matched += 1;
                    debug!("DNS cache matched!: {}", addr_string);
                    debug!("DNS cache matched: {}, missed: {}", cache.totally_matched, cache.totally_missed);
                    return Some(addrs)
                },
                None => {
                    cache.totally_missed += 1;
                    debug!("DNS cache missed!: {}", addr_string);
                    debug!("DNS cache matched: {}, missed: {}", cache.totally_matched, cache.totally_missed);
                }
            }
        }

        let addrs = match get_host_addresses(addr) {
            Ok(addrs) => addrs,
            Err(err) => {
                error!("Failed to resolve {}: {}", addr, err);
                return None;
            }
        };

        let cloned_mutex = self.lru_cache.clone();
        let cloned_addr = addrs.clone();
        self.pool.execute(move || {
            let mut cache = cloned_mutex.lock().unwrap();
            cache.cache.insert(addr_string, cloned_addr);
        });
        Some(addrs)
    }
}

unsafe impl Send for CachedDns {}
unsafe impl Sync for CachedDns {}
<|endoftext|>


<commit_before>use lyon::path;
use lyon::path_builder::BaseBuilder;
use lyon::path_iterator::PathIterator;
use lyon::tessellation;
use lyon::tessellation::basic_shapes;
use lyon::tessellation::math;
use lyon::tessellation::path_stroke;
use lyon::tessellation::path_fill;
use lyon::tessellation::geometry_builder;

use super::{Point, Vertex};
use GameError;
use GameResult;

pub type Buffer = geometry_builder::VertexBuffers<Vertex>;

pub struct VertexConstructor {
    stroke_width: f32,
}

impl geometry_builder::VertexConstructor<tessellation::StrokeVertex, Vertex> for VertexConstructor {
    fn new_vertex(&mut self, input: tessellation::StrokeVertex) -> Vertex {
        let c = input.position + input.normal * self.stroke_width;
        Vertex {
            pos: [c.x, c.y],
            uv: [c.x, c.y],
        }
    }
}

impl geometry_builder::VertexConstructor<tessellation::FillVertex, Vertex> for VertexConstructor {
    fn new_vertex(&mut self, input: tessellation::FillVertex) -> Vertex {
        let p = input.position;
        Vertex {
            pos: [p.x, p.y],
            uv: [p.x, p.y],
        }
    }
}

fn build_path(points: &[Point], closed: bool) -> path::Path {
    let mut path_builder = path::Builder::with_capacity(points.len());
    path_builder.move_to(math::point(points[0].x, points[0].y));

    for p in &points[1..] {
        path_builder.line_to(math::point(p.x, p.y));
    }

    if closed {
        path_builder.close();
    }

    path_builder.build()
}

fn build_geometry<F, V, E>(line_width: f32, f: F) -> GameResult<Buffer>
    where F: for<'a> FnOnce(&mut geometry_builder::BuffersBuilder<'a, Vertex, V, VertexConstructor>)
                            -> Result<geometry_builder::Count, E>,
        VertexConstructor: geometry_builder::VertexConstructor<V, Vertex>,
{
    let mut buffers = geometry_builder::VertexBuffers::new();
    let vertex_ctor = VertexConstructor { stroke_width: line_width };
    {
        let mut builder = geometry_builder::BuffersBuilder::new(&mut buffers, vertex_ctor);
        if let Err(_) = f(&mut builder) {
            return Err(GameError::RenderError(String::from("geometry tessellation failed")));
        }
    }
    Ok(buffers)
}

pub fn build_line(points: &[Point], line_width: f32) -> GameResult<Buffer> {
    let path = build_path(points, false);
    let opts = path_stroke::StrokeOptions::default();
    let mut tessellator = path_stroke::StrokeTessellator::new();
    build_geometry(line_width, |builder| {
                       tessellator.tessellate(path.path_iter().flattened(0.5), &opts, builder)
                   })
}

/// Build a closed polygon.  Identical to build_line but closes the path,
/// which makes sure the two endpoints actually line up.
pub fn build_polygon(points: &[Point], line_width: f32) -> GameResult<Buffer> {

    let path = build_path(points, true);
    let opts = path_stroke::StrokeOptions::default();
    let mut tessellator = path_stroke::StrokeTessellator::new();
    build_geometry(line_width, |builder| {
                       tessellator.tessellate(path.path_iter().flattened(0.5), &opts, builder)
                   })
}

 pub fn build_polygon_fill(points: &[Point]) -> GameResult<Buffer> {
     let path = build_path(points, true);
     let path_iter = path.path_iter().flattened(0.5);
     let opts = path_fill::FillOptions::default();
     let mut tessellator = path_fill::FillTessellator::new();
     build_geometry(0.0, |builder| tessellator.tessellate_path(path_iter, &opts, builder))
 }

pub fn build_ellipse_fill(point: Point, r1: f32, r2: f32, segments: u32) -> GameResult<Buffer> {
    let center = math::point(point.x, point.y);
    let radii = math::point(r1, r2);
    build_geometry(0.0, |builder| Ok::<_, ()>(basic_shapes::fill_ellipse(center, radii, segments, builder)))
}
<commit_msg>Reduce code duplication.<commit_after>use lyon::path;
use lyon::path_builder::BaseBuilder;
use lyon::path_iterator::PathIterator;
use lyon::tessellation;
use lyon::tessellation::basic_shapes;
use lyon::tessellation::math;
use lyon::tessellation::path_stroke;
use lyon::tessellation::path_fill;
use lyon::tessellation::geometry_builder;

use super::{Point, Vertex};
use GameError;
use GameResult;

pub type Buffer = geometry_builder::VertexBuffers<Vertex>;

const FLATTEN_TOLERANCE: f32 = 0.5;

pub struct VertexConstructor {
    stroke_width: f32,
}

impl geometry_builder::VertexConstructor<tessellation::StrokeVertex, Vertex> for VertexConstructor {
    fn new_vertex(&mut self, input: tessellation::StrokeVertex) -> Vertex {
        let c = input.position + input.normal * self.stroke_width;
        Vertex {
            pos: [c.x, c.y],
            uv: [c.x, c.y],
        }
    }
}

impl geometry_builder::VertexConstructor<tessellation::FillVertex, Vertex> for VertexConstructor {
    fn new_vertex(&mut self, input: tessellation::FillVertex) -> Vertex {
        let p = input.position;
        Vertex {
            pos: [p.x, p.y],
            uv: [p.x, p.y],
        }
    }
}

fn build_path(points: &[Point], closed: bool) -> path::Path {
    let mut path_builder = path::Builder::with_capacity(points.len());
    path_builder.move_to(math::point(points[0].x, points[0].y));

    for p in &points[1..] {
        path_builder.line_to(math::point(p.x, p.y));
    }

    if closed {
        path_builder.close();
    }

    path_builder.build()
}

fn build_geometry<F, V, E>(line_width: f32, f: F) -> GameResult<Buffer>
    where F: for<'a> FnOnce(&mut geometry_builder::BuffersBuilder<'a, Vertex, V, VertexConstructor>)
                            -> Result<geometry_builder::Count, E>,
        VertexConstructor: geometry_builder::VertexConstructor<V, Vertex>,
{
    let mut buffers = geometry_builder::VertexBuffers::new();
    let vertex_ctor = VertexConstructor { stroke_width: line_width };
    {
        let mut builder = geometry_builder::BuffersBuilder::new(&mut buffers, vertex_ctor);
        if let Err(_) = f(&mut builder) {
            return Err(GameError::RenderError(String::from("geometry tessellation failed")));
        }
    }
    Ok(buffers)
}

fn build_stroke(points: &[Point], close: bool, line_width: f32) -> GameResult<Buffer> {
    let path = build_path(points, close);
    let path_iter = path.path_iter().flattened(FLATTEN_TOLERANCE);
    let opts = path_stroke::StrokeOptions::default();
    let mut tessellator = path_stroke::StrokeTessellator::new();
    build_geometry(line_width, |builder| tessellator.tessellate(path_iter, &opts, builder))
}

pub fn build_line(points: &[Point], line_width: f32) -> GameResult<Buffer> {
    build_stroke(points, false, line_width)
}

/// Build a closed polygon.  Identical to build_line but closes the path,
/// which makes sure the two endpoints actually line up.
pub fn build_polygon(points: &[Point], line_width: f32) -> GameResult<Buffer> {
    build_stroke(points, true, line_width)
}

 pub fn build_polygon_fill(points: &[Point]) -> GameResult<Buffer> {
     let path = build_path(points, true);
     let path_iter = path.path_iter().flattened(FLATTEN_TOLERANCE);
     let opts = path_fill::FillOptions::default();
     let mut tessellator = path_fill::FillTessellator::new();
     build_geometry(0.0, |builder| tessellator.tessellate_path(path_iter, &opts, builder))
 }

pub fn build_ellipse_fill(point: Point, r1: f32, r2: f32, segments: u32) -> GameResult<Buffer> {
    let center = math::point(point.x, point.y);
    let radii = math::point(r1, r2);
    build_geometry(0.0, |builder| Ok::<_, ()>(basic_shapes::fill_ellipse(center, radii, segments, builder)))
}
<|endoftext|>