<commit_before>macro_rules! cstr {
    ($s:expr) => ($s as *const _ as *const ::libc::c_char)
}

macro_rules! real {
    ($f:ident) => ({
        ::hooks::hw::POINTERS.read().unwrap().$f.get()
    })
}

macro_rules! find {
    ($pointers:expr, $handle:expr, $f:ident, $symbol:tt) => ({
        let ptr = $handle.sym($symbol)
            .chain_err(|| concat!("couldn't find ", stringify!($f), "()"))?;
        $pointers.$f.set_from_raw(ptr);
    })
}

macro_rules! command {
    ($name:ident, $callback:expr) => (
        #[allow(non_camel_case_types)]
        pub struct $name;

        impl $name {
            // This will get called by the engine, in main game thread.
            unsafe extern "C" fn callback() {
                const F: &Fn(::engine::Engine) = &$callback;

                // We know this is the main game thread.
                let engine = ::engine::Engine::new();

                F(engine);
            }
        }

        impl ::command::Command for $name {
            fn name(&self) -> &'static [u8] {
                lazy_static! {
                    static ref NAME: ::std::ffi::CString = {
                        ::std::ffi::CString::new(stringify!($name)).unwrap()
                    };
                }

                NAME.as_bytes_with_nul()
            }

            fn callback(&self) -> unsafe extern "C" fn() {
                Self::callback
            }
        }
    )
}

macro_rules! gen_function_impls {
    (@make_impl ($($extern_type:tt)*) ($($arg_name:ident : $arg_type:ident),*)) => (
        impl<R $(, $arg_type)*> Default for Function<$($extern_type)* fn($($arg_type),*) -> R> {
            #[inline(always)]
            fn default() -> Self {
                Function {
                    ptr: Self::default_func as $($extern_type)* fn($($arg_type),*) -> R,
                }
            }
        }

        #[allow(dead_code)]
        impl<R $(, $arg_type)*> Function<$($extern_type)* fn($($arg_type),*) -> R> {
            #[inline(always)]
            pub fn is_default(&self) -> bool {
                self.ptr as *const usize == Self::default_func as *const usize
            }

            #[inline(always)]
            pub unsafe fn call(&self $(, $arg_name : $arg_type)*) -> R {
                (self.ptr)($($arg_name),*)
            }

            #[inline(always)]
            pub fn get(&self) -> $($extern_type)* fn($($arg_type),*) -> R {
                self.ptr
            }

            #[inline(always)]
            pub fn set(&mut self, f: $($extern_type)* fn($($arg_type),*) -> R) {
                self.ptr = f;
            }

            #[inline(always)]
            pub unsafe fn set_from_raw(&mut self, f: *const ::libc::c_void) {
                self.set(*(&f as *const _ as *const _));
            }

            // This should never be called.
            $($extern_type)* fn default_func($(_: $arg_type),*) -> R {
                unreachable!();
            }
        }
    );

    (@gen_impls $($arg_name:ident : $arg_type:ident),*) => (
        gen_function_impls!(@make_impl (unsafe                  ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (unsafe extern "C"       ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (unsafe extern "system"  ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (unsafe extern "fastcall") ($($arg_name : $arg_type),*));
    );

    () => (
        gen_function_impls!(@gen_impls);
    );

    ($first_arg_name:ident : $first_arg_type:ident $(, $arg_name:ident : $arg_type:ident)*) => (
        gen_function_impls!(@gen_impls $first_arg_name : $first_arg_type $(, $arg_name : $arg_type)*);
        gen_function_impls!($($arg_name : $arg_type),*);
    );
}
<commit_msg>Document command!<commit_after>macro_rules! cstr {
    ($s:expr) => ($s as *const _ as *const ::libc::c_char)
}

macro_rules! real {
    ($f:ident) => ({
        ::hooks::hw::POINTERS.read().unwrap().$f.get()
    })
}

macro_rules! find {
    ($pointers:expr, $handle:expr, $f:ident, $symbol:tt) => ({
        let ptr = $handle.sym($symbol)
            .chain_err(|| concat!("couldn't find ", stringify!($f), "()"))?;
        $pointers.$f.set_from_raw(ptr);
    })
}

/// Defines console commands.
///
/// Commands defined by this macro will be automatically added
/// to the console command list and registered in the game.
macro_rules! command {
    ($name:ident, $callback:expr) => (
        #[allow(non_camel_case_types)]
        pub struct $name;

        impl $name {
            // This will get called by the engine, in main game thread.
            unsafe extern "C" fn callback() {
                const F: &Fn(::engine::Engine) = &$callback;

                // We know this is the main game thread.
                let engine = ::engine::Engine::new();

                F(engine);
            }
        }

        impl ::command::Command for $name {
            fn name(&self) -> &'static [u8] {
                lazy_static! {
                    static ref NAME: ::std::ffi::CString = {
                        ::std::ffi::CString::new(stringify!($name)).unwrap()
                    };
                }

                NAME.as_bytes_with_nul()
            }

            fn callback(&self) -> unsafe extern "C" fn() {
                Self::callback
            }
        }
    )
}

macro_rules! gen_function_impls {
    (@make_impl ($($extern_type:tt)*) ($($arg_name:ident : $arg_type:ident),*)) => (
        impl<R $(, $arg_type)*> Default for Function<$($extern_type)* fn($($arg_type),*) -> R> {
            #[inline(always)]
            fn default() -> Self {
                Function {
                    ptr: Self::default_func as $($extern_type)* fn($($arg_type),*) -> R,
                }
            }
        }

        #[allow(dead_code)]
        impl<R $(, $arg_type)*> Function<$($extern_type)* fn($($arg_type),*) -> R> {
            #[inline(always)]
            pub fn is_default(&self) -> bool {
                self.ptr as *const usize == Self::default_func as *const usize
            }

            #[inline(always)]
            pub unsafe fn call(&self $(, $arg_name : $arg_type)*) -> R {
                (self.ptr)($($arg_name),*)
            }

            #[inline(always)]
            pub fn get(&self) -> $($extern_type)* fn($($arg_type),*) -> R {
                self.ptr
            }

            #[inline(always)]
            pub fn set(&mut self, f: $($extern_type)* fn($($arg_type),*) -> R) {
                self.ptr = f;
            }

            #[inline(always)]
            pub unsafe fn set_from_raw(&mut self, f: *const ::libc::c_void) {
                self.set(*(&f as *const _ as *const _));
            }

            // This should never be called.
            $($extern_type)* fn default_func($(_: $arg_type),*) -> R {
                unreachable!();
            }
        }
    );

    (@gen_impls $($arg_name:ident : $arg_type:ident),*) => (
        gen_function_impls!(@make_impl (unsafe                  ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (unsafe extern "C"       ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (unsafe extern "system"  ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (unsafe extern "fastcall") ($($arg_name : $arg_type),*));
    );

    () => (
        gen_function_impls!(@gen_impls);
    );

    ($first_arg_name:ident : $first_arg_type:ident $(, $arg_name:ident : $arg_type:ident)*) => (
        gen_function_impls!(@gen_impls $first_arg_name : $first_arg_type $(, $arg_name : $arg_type)*);
        gen_function_impls!($($arg_name : $arg_type),*);
    );
}
<|endoftext|>


<commit_before>//use Tensor;
//use tensor;

/// Macro for creating vectors and matrices.
///
/// To use this macro, import Numeric as follows:
///
/// ```text
/// #[macro_use(tensor)]
/// extern crate numeric;
/// ```
///
/// # Examples
///
/// 1D tensor (vector):
///
/// ```
/// # #[macro_use] extern crate numeric; fn main() {
/// let x = tensor![1.0, 2.0, 3.0];
/// # assert!(x == numeric::Tensor::new(vec![1.0, 2.0, 3.0]));
/// # }
/// ```
///
/// 2D tensor (matrix):
///
/// ```
/// # #[macro_use] extern crate numeric; use numeric::tensor; fn main() {
/// let x = tensor![1, 0; 3, 2; 5, 4];
/// # assert!(x == numeric::Tensor::new(vec![1, 0, 3, 2, 5, 4]).reshape(&[3, 2]));
/// # }
/// ```
///
/// 1D tensor filled with a single value:
///
/// ```
/// # #[macro_use] extern crate numeric; use numeric::tensor; fn main() {
/// let x = tensor![2.0; 5];
/// # assert!(x == numeric::Tensor::new(vec![2.0, 2.0, 2.0, 2.0, 2.0]));
/// # }
/// ```
#[macro_export]
macro_rules! tensor {
    ($elem:expr; $n:expr) => (
        $crate::Tensor::filled(&[$n], $elem)
    );
    ($($x:expr),*) => (
        $crate::Tensor::new(vec![$($x),*])
    );
    ($($x:expr,)*) => (
        tensor![$($x),*]
    );
    ($($($x:expr),*;)*) => ({
        let mut v = Vec::new();
        let mut n = 0;
        $(
            n += 1;
            $(v.push($x);)*
        )*
        $crate::Tensor::new(v).reshape(&[n, -1])
    });
    ($($($x:expr),*);*) => (
        tensor![$($($x),*;)*]
    );
}

#[cfg(test)]
mod tests {
    use Tensor;

    #[test]
    fn tensor_1d() {
        let x = Tensor::new(vec![1, 2, 3, 4, 5, 6]);
        assert!(x == tensor![1, 2, 3, 4, 5, 6]);
        assert!(x == tensor![1, 2, 3, 4, 5, 6,]);
    }

    #[test]
    fn tensor_2d() {
        let x = Tensor::new(vec![1, 2, 3, 4, 5, 6]).reshape(&[3, 2]);
        assert!(x == tensor![1, 2; 3, 4; 5, 6]);
        assert!(x == tensor![1, 2; 3, 4; 5, 6;]);
    }
}
<commit_msg>Make tensor! avoid calling filled<commit_after>//use Tensor;
//use tensor;

/// Macro for creating vectors and matrices.
///
/// To use this macro, import Numeric as follows:
///
/// ```text
/// #[macro_use(tensor)]
/// extern crate numeric;
/// ```
///
/// # Examples
///
/// 1D tensor (vector):
///
/// ```
/// # #[macro_use] extern crate numeric; fn main() {
/// let x = tensor![1.0, 2.0, 3.0];
/// # assert!(x == numeric::Tensor::new(vec![1.0, 2.0, 3.0]));
/// # }
/// ```
///
/// 2D tensor (matrix):
///
/// ```
/// # #[macro_use] extern crate numeric; use numeric::tensor; fn main() {
/// let x = tensor![1, 0; 3, 2; 5, 4];
/// # assert!(x == numeric::Tensor::new(vec![1, 0, 3, 2, 5, 4]).reshape(&[3, 2]));
/// # }
/// ```
///
/// 1D tensor filled with a single value:
///
/// ```
/// # #[macro_use] extern crate numeric; use numeric::tensor; fn main() {
/// let x = tensor![2.0; 5];
/// # assert!(x == numeric::Tensor::new(vec![2.0, 2.0, 2.0, 2.0, 2.0]));
/// # }
/// ```
#[macro_export]
macro_rules! tensor {
    ($elem:expr; $n:expr) => (
        $crate::Tensor::new(vec![$elem; $n])
    );
    ($($x:expr),*) => (
        $crate::Tensor::new(vec![$($x),*])
    );
    ($($x:expr,)*) => (
        tensor![$($x),*]
    );
    ($($($x:expr),*;)*) => ({
        let mut v = Vec::new();
        let mut n = 0;
        $(
            n += 1;
            $(v.push($x);)*
        )*
        $crate::Tensor::new(v).reshape(&[n, -1])
    });
    ($($($x:expr),*);*) => (
        tensor![$($($x),*;)*]
    );
}

#[cfg(test)]
mod tests {
    use Tensor;

    #[test]
    fn tensor_1d() {
        let x = Tensor::new(vec![1, 2, 3, 4, 5, 6]);
        assert!(x == tensor![1, 2, 3, 4, 5, 6]);
        assert!(x == tensor![1, 2, 3, 4, 5, 6,]);
    }

    #[test]
    fn tensor_2d() {
        let x = Tensor::new(vec![1, 2, 3, 4, 5, 6]).reshape(&[3, 2]);
        assert!(x == tensor![1, 2; 3, 4; 5, 6]);
        assert!(x == tensor![1, 2; 3, 4; 5, 6;]);
    }
}
<|endoftext|>


<commit_before>//! Responsible for orchestrating all the different library components into
//! something cohesive. It effectively hides the rest of the library,
//! and all commands are meant to pass through this instead.

use std::path::Path;
use std::ops::Range;

use client::Client;
use render::Renderer;
use resman::ResMan;
use routing::{Edge, Effect, NodeData, NodeHandle, RouteGraph, EffectId};
use routing::{effect, routegraph};

#[derive(Default)]
pub struct Dispatch<R, C> {
    /// Contains the toplevel description of the audio being generated.
    routegraph: RouteGraph,
    renderer: R,
    /// Resource manager. Knows where to find all data that might be stored
    /// outside the application.
    resman: ResMan,
    /// Where to send notifications of state changes,
    /// results from the renderer, etc.
    client: C,
}

/// OSC message to /<...>
#[derive(OscMessage)]
pub enum OscToplevel {
    /// Send a message to the primary RouteGraph
    #[osc_address(address="routegraph")]
    RouteGraph((), OscRouteGraph),
    /// Send a message to one of the Renderers.
    #[osc_address(address="renderer")]
    Renderer((), OscRenderer),
    /// Send a message to the resource manager
    #[osc_address(address="resman")]
    ResMan((), OscResMan),
}

/// OSC message to /routegraph/<...>
#[derive(OscMessage)]
pub enum OscRouteGraph {
    #[osc_address(address="add_node")]
    AddNode((), (NodeHandle, EffectId)),
    #[osc_address(address="add_edge")]
    AddEdge((), (Edge,)),
    #[osc_address(address="del_node")]
    DelNode((), (NodeHandle,)),
    #[osc_address(address="del_edge")]
    DelEdge((), (Edge,)),
    /// Query a node's metadata: it's I/Os, etc.
    #[osc_address(address="query_meta")]
    QueryMeta((), (NodeHandle,)),
    /// Query a node's id: it's SHA, name, etc.
    #[osc_address(address="query_id")]
    QueryId((), (NodeHandle,)),
}

/// OSC message to /renderer/<...>
#[derive(OscMessage)]
pub enum OscRenderer {
    /// Render a range of samples from [a, b)
    /// Last argument indicates the number of slots to render.
    /// TODO: The slot count should become a property of the RouteGraph.
    #[osc_address(address="render")]
    RenderRange((), (Range<u64>, u32)),
}

/// OOSC message to /resman/<...>
#[derive(OscMessage)]
pub enum OscResMan {
    /// Add another directory to watch when loading resources.
    #[osc_address(address="add_dir")]
    AddDir((), (String,)),
}

#[derive(Debug)]
pub enum Error {
    RouteGraphError(routegraph::Error),
    EffectError(effect::Error),
}

type ResultE<T> = Result<T, Error>;

impl<R, C> Dispatch<R, C> {
    pub fn new(renderer: R, client: C) -> Self {
        Self {
            routegraph: Default::default(),
            renderer,
            resman: Default::default(),
            client,
        }
    }
}

impl<R: Renderer, C: Client> Dispatch<R, C> {
    /// Process the OSC message.
    pub fn dispatch(&mut self, msg: OscToplevel) -> ResultE<()> {
        match msg {
            OscToplevel::RouteGraph((), rg_msg) => match rg_msg {
                OscRouteGraph::AddNode((), (handle, id)) => {
                    let node_data = Effect::from_id(id, &self.resman)?;
                    self.routegraph.add_node(handle, node_data.clone())?;
                    self.on_add_node(&handle, &node_data);
                }
                OscRouteGraph::AddEdge((), (edge,)) => {
                    self.routegraph.add_edge(edge.clone())?;
                    self.on_add_edge(&edge);
                }
                OscRouteGraph::DelNode((), (handle,)) => {
                    self.routegraph.del_node(handle)?;
                    self.on_del_node(&handle);
                }
                OscRouteGraph::DelEdge((), (edge,)) => {
                    self.routegraph.del_edge(edge.clone());
                    self.on_del_edge(&edge);
                }
                OscRouteGraph::QueryMeta((), (handle,)) => {
                    // TODO: probably log something on failure.
                    if let Some(effect) = self.routegraph.get_data(&handle) {
                        self.client.node_meta(&handle, effect.meta());
                    }
                }
                OscRouteGraph::QueryId((), (handle,)) => {
                    // TODO: probably log something on failure.
                    if let Some(effect) = self.routegraph.get_data(&handle) {
                        self.client.node_id(&handle, &effect.id());
                    }
                }
            },
            OscToplevel::Renderer((), rend_msg) => match rend_msg {
                OscRenderer::RenderRange((), (range, slot)) => {
                    let mut buff: Vec<f32> = range.clone().map(|_| { 0f32 }).collect();
                    self.renderer.fill_buffer(&mut buff, range.start, slot);
                    self.client.audio_rendered(&buff, range.start, slot);
                }
            },
            OscToplevel::ResMan((), res_msg) => match res_msg {
                OscResMan::AddDir((), (dir,)) => {
                    self.resman.add_dir(Path::new(&dir).to_path_buf());
                }
            }
        }
        Ok(())
    }
}

/// Conversion from `routegraph::Error` for use with the `?` operator
impl From<routegraph::Error> for Error {
    fn from(e: routegraph::Error) -> Self {
        Error::RouteGraphError(e)
    }
}

/// Conversion from `effect::Error` for use with the `?` operator
impl From<effect::Error> for Error {
    fn from(e: effect::Error) -> Self {
        Error::EffectError(e)
    }
}

/// Deterministic mapping from one OSC message to a container OSC message
impl From<OscRouteGraph> for OscToplevel {
    fn from(m: OscRouteGraph) -> Self {
        OscToplevel::RouteGraph((), m)
    }
}

/// Deterministic mapping from one OSC message to a container OSC message
impl From<OscRenderer> for OscToplevel {
    fn from(m: OscRenderer) -> Self {
        OscToplevel::Renderer((), m)
    }
}

/// Deterministic mapping from one OSC message to a container OSC message
impl From<OscResMan> for OscToplevel {
    fn from(m: OscResMan) -> Self {
        OscToplevel::ResMan((), m)
    }
}

/// Route callbacks to wherever they need to go
impl<R: Renderer, C> Dispatch<R, C> {
    fn on_add_node(&mut self, node: &NodeHandle, data: &NodeData) {
        self.renderer.on_add_node(node, data);
    }
    fn on_del_node(&mut self, node: &NodeHandle) {
        self.renderer.on_del_node(node);
    }
    fn on_add_edge(&mut self, edge: &Edge) {
        self.renderer.on_add_edge(edge);
    }
    fn on_del_edge(&mut self, edge: &Edge) {
        self.renderer.on_del_edge(edge);
    }
}
<commit_msg>Log messages on effect lookup failure.<commit_after>//! Responsible for orchestrating all the different library components into
//! something cohesive. It effectively hides the rest of the library,
//! and all commands are meant to pass through this instead.

use std::path::Path;
use std::ops::Range;

use client::Client;
use render::Renderer;
use resman::ResMan;
use routing::{Edge, Effect, NodeData, NodeHandle, RouteGraph, EffectId};
use routing::{effect, routegraph};

#[derive(Default)]
pub struct Dispatch<R, C> {
    /// Contains the toplevel description of the audio being generated.
    routegraph: RouteGraph,
    renderer: R,
    /// Resource manager. Knows where to find all data that might be stored
    /// outside the application.
    resman: ResMan,
    /// Where to send notifications of state changes,
    /// results from the renderer, etc.
    client: C,
}

/// OSC message to /<...>
#[derive(OscMessage)]
pub enum OscToplevel {
    /// Send a message to the primary RouteGraph
    #[osc_address(address="routegraph")]
    RouteGraph((), OscRouteGraph),
    /// Send a message to one of the Renderers.
    #[osc_address(address="renderer")]
    Renderer((), OscRenderer),
    /// Send a message to the resource manager
    #[osc_address(address="resman")]
    ResMan((), OscResMan),
}

/// OSC message to /routegraph/<...>
#[derive(OscMessage)]
pub enum OscRouteGraph {
    #[osc_address(address="add_node")]
    AddNode((), (NodeHandle, EffectId)),
    #[osc_address(address="add_edge")]
    AddEdge((), (Edge,)),
    #[osc_address(address="del_node")]
    DelNode((), (NodeHandle,)),
    #[osc_address(address="del_edge")]
    DelEdge((), (Edge,)),
    /// Query a node's metadata: it's I/Os, etc.
    #[osc_address(address="query_meta")]
    QueryMeta((), (NodeHandle,)),
    /// Query a node's id: it's SHA, name, etc.
    #[osc_address(address="query_id")]
    QueryId((), (NodeHandle,)),
}

/// OSC message to /renderer/<...>
#[derive(OscMessage)]
pub enum OscRenderer {
    /// Render a range of samples from [a, b)
    /// Last argument indicates the number of slots to render.
    #[osc_address(address="render")]
    RenderRange((), (Range<u64>, u32)),
}

/// OOSC message to /resman/<...>
#[derive(OscMessage)]
pub enum OscResMan {
    /// Add another directory to watch when loading resources.
    #[osc_address(address="add_dir")]
    AddDir((), (String,)),
}

#[derive(Debug)]
pub enum Error {
    RouteGraphError(routegraph::Error),
    EffectError(effect::Error),
}

type ResultE<T> = Result<T, Error>;

impl<R, C> Dispatch<R, C> {
    pub fn new(renderer: R, client: C) -> Self {
        Self {
            routegraph: Default::default(),
            renderer,
            resman: Default::default(),
            client,
        }
    }
}

impl<R: Renderer, C: Client> Dispatch<R, C> {
    /// Process the OSC message.
    pub fn dispatch(&mut self, msg: OscToplevel) -> ResultE<()> {
        match msg {
            OscToplevel::RouteGraph((), rg_msg) => match rg_msg {
                OscRouteGraph::AddNode((), (handle, id)) => {
                    let node_data = Effect::from_id(id, &self.resman)?;
                    self.routegraph.add_node(handle, node_data.clone())?;
                    self.on_add_node(&handle, &node_data);
                }
                OscRouteGraph::AddEdge((), (edge,)) => {
                    self.routegraph.add_edge(edge.clone())?;
                    self.on_add_edge(&edge);
                }
                OscRouteGraph::DelNode((), (handle,)) => {
                    self.routegraph.del_node(handle)?;
                    self.on_del_node(&handle);
                }
                OscRouteGraph::DelEdge((), (edge,)) => {
                    self.routegraph.del_edge(edge.clone());
                    self.on_del_edge(&edge);
                }
                OscRouteGraph::QueryMeta((), (handle,)) => {
                    if let Some(effect) = self.routegraph.get_data(&handle) {
                        self.client.node_meta(&handle, effect.meta());
                    } else {
                        warn!("QueryMeta: no such effect with handle: {:?}", handle);
                    }
                }
                OscRouteGraph::QueryId((), (handle,)) => {
                    if let Some(effect) = self.routegraph.get_data(&handle) {
                        self.client.node_id(&handle, &effect.id());
                    } else {
                        warn!("QueryId: no such effect with handle: {:?}", handle);
                    }
                }
            },
            OscToplevel::Renderer((), rend_msg) => match rend_msg {
                OscRenderer::RenderRange((), (range, slot)) => {
                    let mut buff: Vec<f32> = range.clone().map(|_| { 0f32 }).collect();
                    self.renderer.fill_buffer(&mut buff, range.start, slot);
                    self.client.audio_rendered(&buff, range.start, slot);
                }
            },
            OscToplevel::ResMan((), res_msg) => match res_msg {
                OscResMan::AddDir((), (dir,)) => {
                    self.resman.add_dir(Path::new(&dir).to_path_buf());
                }
            }
        }
        Ok(())
    }
}

/// Conversion from `routegraph::Error` for use with the `?` operator
impl From<routegraph::Error> for Error {
    fn from(e: routegraph::Error) -> Self {
        Error::RouteGraphError(e)
    }
}

/// Conversion from `effect::Error` for use with the `?` operator
impl From<effect::Error> for Error {
    fn from(e: effect::Error) -> Self {
        Error::EffectError(e)
    }
}

/// Deterministic mapping from one OSC message to a container OSC message
impl From<OscRouteGraph> for OscToplevel {
    fn from(m: OscRouteGraph) -> Self {
        OscToplevel::RouteGraph((), m)
    }
}

/// Deterministic mapping from one OSC message to a container OSC message
impl From<OscRenderer> for OscToplevel {
    fn from(m: OscRenderer) -> Self {
        OscToplevel::Renderer((), m)
    }
}

/// Deterministic mapping from one OSC message to a container OSC message
impl From<OscResMan> for OscToplevel {
    fn from(m: OscResMan) -> Self {
        OscToplevel::ResMan((), m)
    }
}

/// Route callbacks to wherever they need to go
impl<R: Renderer, C> Dispatch<R, C> {
    fn on_add_node(&mut self, node: &NodeHandle, data: &NodeData) {
        self.renderer.on_add_node(node, data);
    }
    fn on_del_node(&mut self, node: &NodeHandle) {
        self.renderer.on_del_node(node);
    }
    fn on_add_edge(&mut self, edge: &Edge) {
        self.renderer.on_add_edge(edge);
    }
    fn on_del_edge(&mut self, edge: &Edge) {
        self.renderer.on_del_edge(edge);
    }
}
<|endoftext|>


<commit_before>use std::time::Duration;
use std::str::FromStr;
use std::error::Error;
use serde::de;

use num::FromPrimitive;

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct SerializableDuration(pub Duration);

pub struct Visitor;

impl de::Visitor for Visitor {
    type Value = SerializableDuration;

    fn visit_u64<E>(&mut self, v: u64) -> Result<SerializableDuration, E>
        where E: de::Error
    {
        match FromPrimitive::from_u64(v) {
            Some(v) => Ok(SerializableDuration(Duration::from_millis(v))),
            None => Err(E::type_mismatch(de::Type::U64)),
        }
    }

    fn visit_str<E>(&mut self, s: &str) -> Result<SerializableDuration, E>
        where E: de::Error
    {
        match FromStr::from_str(s) {
            Ok(value) => Ok(SerializableDuration(Duration::from_millis(value))),
            Err(error) => Err(E::syntax(error.description())),
        }
    }
}

impl de::Deserialize for SerializableDuration {
    fn deserialize<D>(deserializer: &mut D) -> Result<SerializableDuration, D::Error>
        where D: de::Deserializer
    {
        deserializer.visit_str(Visitor)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json;
    use std::time::Duration;

    fn assert_serialized_value_eq(input: &str, expected: Duration) {
        let result = serde_json::from_str::<SerializableDuration>(input);
        println!("{:?}", &result);
        let duration = result.expect("Failed to deserialize a valid SerializableDuration value");
        assert_eq!(expected, duration.0);
    }

    #[test]
    fn test_given_valid_duration_when_it_is_deserialized_then_we_get_the_right_result() {
        assert_serialized_value_eq("100", Duration::from_millis(100));
    }

    #[test]
    fn test_given_valid_duration_as_str_when_it_is_deserialized_then_we_get_the_right_result() {
        assert_serialized_value_eq(r#""100""#, Duration::from_millis(100));
    }

    #[test]
    fn test_given_invalid_duration_when_it_is_deserialized_then_we_get_error() {
        let result = serde_json::from_str::<SerializableDuration>("word");
        println!("{:?}", &result);
        assert_eq!(true, result.is_err());
    }
}
<commit_msg>SerializableDuration: add a new unit test<commit_after>use std::time::Duration;
use std::str::FromStr;
use std::error::Error;
use serde::de;

use num::FromPrimitive;

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct SerializableDuration(pub Duration);

pub struct Visitor;

impl de::Visitor for Visitor {
    type Value = SerializableDuration;

    fn visit_u64<E>(&mut self, v: u64) -> Result<SerializableDuration, E>
        where E: de::Error
    {
        match FromPrimitive::from_u64(v) {
            Some(v) => Ok(SerializableDuration(Duration::from_millis(v))),
            None => Err(E::type_mismatch(de::Type::U64)),
        }
    }

    fn visit_str<E>(&mut self, s: &str) -> Result<SerializableDuration, E>
        where E: de::Error
    {
        match FromStr::from_str(s) {
            Ok(value) => Ok(SerializableDuration(Duration::from_millis(value))),
            Err(error) => Err(E::syntax(error.description())),
        }
    }
}

impl de::Deserialize for SerializableDuration {
    fn deserialize<D>(deserializer: &mut D) -> Result<SerializableDuration, D::Error>
        where D: de::Deserializer
    {
        deserializer.visit_str(Visitor)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json;
    use std::time::Duration;

    fn assert_serialized_value_eq(input: &str, expected: Duration) {
        let result = serde_json::from_str::<SerializableDuration>(input);
        println!("{:?}", &result);
        let duration = result.expect("Failed to deserialize a valid SerializableDuration value");
        assert_eq!(expected, duration.0);
    }

    #[test]
    fn test_given_valid_duration_when_it_is_deserialized_then_we_get_the_right_result() {
        assert_serialized_value_eq("100", Duration::from_millis(100));
    }

    #[test]
    fn test_given_valid_duration_as_str_when_it_is_deserialized_then_we_get_the_right_result() {
        assert_serialized_value_eq(r#""100""#, Duration::from_millis(100));
    }

    #[test]
    fn test_given_invalid_duration_when_it_is_deserialized_then_we_get_error() {
        let result = serde_json::from_str::<SerializableDuration>("word");
        println!("{:?}", &result);
        assert_eq!(true, result.is_err());
    }

    #[test]
    fn test_given_a_word_starting_with_numbers_when_it_is_deserialized_then_we_get_error() {
        let result = serde_json::from_str::<SerializableDuration>(r#""42word""#);
        println!("{:?}", &result);
        assert_eq!(true, result.is_err());
    }
}
<|endoftext|>


<commit_before>//! A module for wrappers that encode / decode data.

use std::borrow::Cow;

#[cfg(feature = "encoding")]
use encoding_rs::{Encoding, UTF_16BE, UTF_16LE, UTF_8};

use crate::{Error, Result};

/// Decoder of byte slices into strings.
///
/// If feature `encoding` is enabled, this encoding taken from the `"encoding"`
/// XML declaration or assumes UTF-8, if XML has no <?xml ?> declaration, encoding
/// key is not defined or contains unknown encoding.
///
/// The library supports any UTF-8 compatible encodings that crate `encoding_rs`
/// is supported. [*UTF-16 is not supported at the present*][utf16].
///
/// If feature `encoding` is disabled, the decoder is always UTF-8 decoder:
/// any XML declarations are ignored.
///
/// [utf16]: https://github.com/tafia/quick-xml/issues/158
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Decoder {
    #[cfg(feature = "encoding")]
    pub(crate) encoding: &'static Encoding,
}

impl Decoder {
    pub(crate) fn utf8() -> Self {
        Decoder {
            #[cfg(feature = "encoding")]
            encoding: UTF_8,
        }
    }

    #[cfg(all(test, feature = "encoding", feature = "serialize"))]
    pub(crate) fn utf16() -> Self {
        Decoder { encoding: UTF_16LE }
    }
}

#[cfg(not(feature = "encoding"))]
impl Decoder {
    /// Decodes a UTF8 slice regardless of XML declaration and ignoring BOM if
    /// it is present in the `bytes`.
    ///
    /// Returns an error in case of malformed sequences in the `bytes`.
    ///
    /// If you instead want to use XML declared encoding, use the `encoding` feature
    #[inline]
    pub fn decode<'b>(&self, bytes: &'b [u8]) -> Result<Cow<'b, str>> {
        Ok(Cow::Borrowed(std::str::from_utf8(bytes)?))
    }

    /// Decodes a slice regardless of XML declaration with BOM removal if
    /// it is present in the `bytes`.
    ///
    /// Returns an error in case of malformed sequences in the `bytes`.
    ///
    /// If you instead want to use XML declared encoding, use the `encoding` feature
    pub fn decode_with_bom_removal<'b>(&self, bytes: &'b [u8]) -> Result<Cow<'b, str>> {
        let bytes = if bytes.starts_with(&[0xEF, 0xBB, 0xBF]) {
            &bytes[3..]
        } else {
            bytes
        };
        self.decode(bytes)
    }
}

#[cfg(feature = "encoding")]
impl Decoder {
    /// Returns the `Reader`s encoding.
    ///
    /// This encoding will be used by [`decode`].
    ///
    /// [`decode`]: Self::decode
    pub fn encoding(&self) -> &'static Encoding {
        self.encoding
    }

    /// Decodes specified bytes using encoding, declared in the XML, if it was
    /// declared there, or UTF-8 otherwise, and ignoring BOM if it is present
    /// in the `bytes`.
    ///
    /// Returns an error in case of malformed sequences in the `bytes`.
    pub fn decode<'b>(&self, bytes: &'b [u8]) -> Result<Cow<'b, str>> {
        decode(bytes, self.encoding)
    }

    /// Decodes a slice with BOM removal if it is present in the `bytes` using
    /// the reader encoding.
    ///
    /// If this method called after reading XML declaration with the `"encoding"`
    /// key, then this encoding is used, otherwise UTF-8 is used.
    ///
    /// If XML declaration is absent in the XML, UTF-8 is used.
    ///
    /// Returns an error in case of malformed sequences in the `bytes`.
    pub fn decode_with_bom_removal<'b>(&self, bytes: &'b [u8]) -> Result<Cow<'b, str>> {
        self.decode(remove_bom(bytes, self.encoding))
    }
}

/// Decodes the provided bytes using the specified encoding, ignoring the BOM
/// if it is present in the `bytes`.
///
/// Returns an error in case of malformed sequences in the `bytes`.
#[cfg(feature = "encoding")]
pub fn decode<'b>(bytes: &'b [u8], encoding: &'static Encoding) -> Result<Cow<'b, str>> {
    encoding
        .decode_without_bom_handling_and_without_replacement(bytes)
        .ok_or(Error::NonDecodable(None))
}

/// Decodes a slice with an unknown encoding, removing the BOM if it is present
/// in the bytes.
///
/// Returns an error in case of malformed sequences in the `bytes`.
#[cfg(feature = "encoding")]
pub fn decode_with_bom_removal<'b>(bytes: &'b [u8]) -> Result<Cow<'b, str>> {
    if let Some(encoding) = detect_encoding(bytes) {
        let bytes = remove_bom(bytes, encoding);
        decode(bytes, encoding)
    } else {
        decode(bytes, UTF_8)
    }
}

#[cfg(feature = "encoding")]
fn split_at_bom<'b>(bytes: &'b [u8], encoding: &'static Encoding) -> (&'b [u8], &'b [u8]) {
    if encoding == UTF_8 && bytes.starts_with(&[0xEF, 0xBB, 0xBF]) {
        bytes.split_at(3)
    } else if encoding == UTF_16LE && bytes.starts_with(&[0xFF, 0xFE]) {
        bytes.split_at(2)
    } else if encoding == UTF_16BE && bytes.starts_with(&[0xFE, 0xFF]) {
        bytes.split_at(2)
    } else {
        (&[], bytes)
    }
}

#[cfg(feature = "encoding")]
fn remove_bom<'b>(bytes: &'b [u8], encoding: &'static Encoding) -> &'b [u8] {
    let (_, bytes) = split_at_bom(bytes, encoding);
    bytes
}

/// Automatic encoding detection of XML files based using the
/// [recommended algorithm](https://www.w3.org/TR/xml11/#sec-guessing).
///
/// If encoding is detected, `Some` is returned, otherwise `None` is returned.
///
/// Because the [`encoding_rs`] crate supports only subset of those encodings, only
/// the supported subset are detected, which is UTF-8, UTF-16 BE and UTF-16 LE.
///
/// The algorithm suggests examine up to the first 4 bytes to determine encoding
/// according to the following table:
///
/// | Bytes       |Detected encoding
/// |-------------|------------------------------------------
/// |`FE FF ## ##`|UTF-16, big-endian
/// |`FF FE ## ##`|UTF-16, little-endian
/// |`EF BB BF`   |UTF-8
/// |-------------|------------------------------------------
/// |`00 3C 00 3F`|UTF-16 BE or ISO-10646-UCS-2 BE or similar 16-bit BE (use declared encoding to find the exact one)
/// |`3C 00 3F 00`|UTF-16 LE or ISO-10646-UCS-2 LE or similar 16-bit LE (use declared encoding to find the exact one)
/// |`3C 3F 78 6D`|UTF-8, ISO 646, ASCII, some part of ISO 8859, Shift-JIS, EUC, or any other 7-bit, 8-bit, or mixed-width encoding which ensures that the characters of ASCII have their normal positions, width, and values; the actual encoding declaration must be read to detect which of these applies, but since all of these encodings use the same bit patterns for the relevant ASCII characters, the encoding declaration itself may be read reliably
#[cfg(feature = "encoding")]
pub fn detect_encoding(bytes: &[u8]) -> Option<&'static Encoding> {
    match bytes {
        // with BOM
        _ if bytes.starts_with(&[0xFE, 0xFF]) => Some(UTF_16BE),
        _ if bytes.starts_with(&[0xFF, 0xFE]) => Some(UTF_16LE),
        _ if bytes.starts_with(&[0xEF, 0xBB, 0xBF]) => Some(UTF_8),

        // without BOM
        _ if bytes.starts_with(&[0x00, b'<', 0x00, b'?']) => Some(UTF_16BE), // Some BE encoding, for example, UTF-16 or ISO-10646-UCS-2
        _ if bytes.starts_with(&[b'<', 0x00, b'?', 0x00]) => Some(UTF_16LE), // Some LE encoding, for example, UTF-16 or ISO-10646-UCS-2
        _ if bytes.starts_with(&[b'<', b'?', b'x', b'm']) => Some(UTF_8), // Some ASCII compatible

        _ => None,
    }
}

// TODO: add some tests for functions
<commit_msg>Fix a warning when compile without `encoding` feature<commit_after>//! A module for wrappers that encode / decode data.

use std::borrow::Cow;

#[cfg(feature = "encoding")]
use encoding_rs::{Encoding, UTF_16BE, UTF_16LE, UTF_8};

#[cfg(feature = "encoding")]
use crate::Error;
use crate::Result;

/// Decoder of byte slices into strings.
///
/// If feature `encoding` is enabled, this encoding taken from the `"encoding"`
/// XML declaration or assumes UTF-8, if XML has no <?xml ?> declaration, encoding
/// key is not defined or contains unknown encoding.
///
/// The library supports any UTF-8 compatible encodings that crate `encoding_rs`
/// is supported. [*UTF-16 is not supported at the present*][utf16].
///
/// If feature `encoding` is disabled, the decoder is always UTF-8 decoder:
/// any XML declarations are ignored.
///
/// [utf16]: https://github.com/tafia/quick-xml/issues/158
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Decoder {
    #[cfg(feature = "encoding")]
    pub(crate) encoding: &'static Encoding,
}

impl Decoder {
    pub(crate) fn utf8() -> Self {
        Decoder {
            #[cfg(feature = "encoding")]
            encoding: UTF_8,
        }
    }

    #[cfg(all(test, feature = "encoding", feature = "serialize"))]
    pub(crate) fn utf16() -> Self {
        Decoder { encoding: UTF_16LE }
    }
}

#[cfg(not(feature = "encoding"))]
impl Decoder {
    /// Decodes a UTF8 slice regardless of XML declaration and ignoring BOM if
    /// it is present in the `bytes`.
    ///
    /// Returns an error in case of malformed sequences in the `bytes`.
    ///
    /// If you instead want to use XML declared encoding, use the `encoding` feature
    #[inline]
    pub fn decode<'b>(&self, bytes: &'b [u8]) -> Result<Cow<'b, str>> {
        Ok(Cow::Borrowed(std::str::from_utf8(bytes)?))
    }

    /// Decodes a slice regardless of XML declaration with BOM removal if
    /// it is present in the `bytes`.
    ///
    /// Returns an error in case of malformed sequences in the `bytes`.
    ///
    /// If you instead want to use XML declared encoding, use the `encoding` feature
    pub fn decode_with_bom_removal<'b>(&self, bytes: &'b [u8]) -> Result<Cow<'b, str>> {
        let bytes = if bytes.starts_with(&[0xEF, 0xBB, 0xBF]) {
            &bytes[3..]
        } else {
            bytes
        };
        self.decode(bytes)
    }
}

#[cfg(feature = "encoding")]
impl Decoder {
    /// Returns the `Reader`s encoding.
    ///
    /// This encoding will be used by [`decode`].
    ///
    /// [`decode`]: Self::decode
    pub fn encoding(&self) -> &'static Encoding {
        self.encoding
    }

    /// Decodes specified bytes using encoding, declared in the XML, if it was
    /// declared there, or UTF-8 otherwise, and ignoring BOM if it is present
    /// in the `bytes`.
    ///
    /// Returns an error in case of malformed sequences in the `bytes`.
    pub fn decode<'b>(&self, bytes: &'b [u8]) -> Result<Cow<'b, str>> {
        decode(bytes, self.encoding)
    }

    /// Decodes a slice with BOM removal if it is present in the `bytes` using
    /// the reader encoding.
    ///
    /// If this method called after reading XML declaration with the `"encoding"`
    /// key, then this encoding is used, otherwise UTF-8 is used.
    ///
    /// If XML declaration is absent in the XML, UTF-8 is used.
    ///
    /// Returns an error in case of malformed sequences in the `bytes`.
    pub fn decode_with_bom_removal<'b>(&self, bytes: &'b [u8]) -> Result<Cow<'b, str>> {
        self.decode(remove_bom(bytes, self.encoding))
    }
}

/// Decodes the provided bytes using the specified encoding, ignoring the BOM
/// if it is present in the `bytes`.
///
/// Returns an error in case of malformed sequences in the `bytes`.
#[cfg(feature = "encoding")]
pub fn decode<'b>(bytes: &'b [u8], encoding: &'static Encoding) -> Result<Cow<'b, str>> {
    encoding
        .decode_without_bom_handling_and_without_replacement(bytes)
        .ok_or(Error::NonDecodable(None))
}

/// Decodes a slice with an unknown encoding, removing the BOM if it is present
/// in the bytes.
///
/// Returns an error in case of malformed sequences in the `bytes`.
#[cfg(feature = "encoding")]
pub fn decode_with_bom_removal<'b>(bytes: &'b [u8]) -> Result<Cow<'b, str>> {
    if let Some(encoding) = detect_encoding(bytes) {
        let bytes = remove_bom(bytes, encoding);
        decode(bytes, encoding)
    } else {
        decode(bytes, UTF_8)
    }
}

#[cfg(feature = "encoding")]
fn split_at_bom<'b>(bytes: &'b [u8], encoding: &'static Encoding) -> (&'b [u8], &'b [u8]) {
    if encoding == UTF_8 && bytes.starts_with(&[0xEF, 0xBB, 0xBF]) {
        bytes.split_at(3)
    } else if encoding == UTF_16LE && bytes.starts_with(&[0xFF, 0xFE]) {
        bytes.split_at(2)
    } else if encoding == UTF_16BE && bytes.starts_with(&[0xFE, 0xFF]) {
        bytes.split_at(2)
    } else {
        (&[], bytes)
    }
}

#[cfg(feature = "encoding")]
fn remove_bom<'b>(bytes: &'b [u8], encoding: &'static Encoding) -> &'b [u8] {
    let (_, bytes) = split_at_bom(bytes, encoding);
    bytes
}

/// Automatic encoding detection of XML files based using the
/// [recommended algorithm](https://www.w3.org/TR/xml11/#sec-guessing).
///
/// If encoding is detected, `Some` is returned, otherwise `None` is returned.
///
/// Because the [`encoding_rs`] crate supports only subset of those encodings, only
/// the supported subset are detected, which is UTF-8, UTF-16 BE and UTF-16 LE.
///
/// The algorithm suggests examine up to the first 4 bytes to determine encoding
/// according to the following table:
///
/// | Bytes       |Detected encoding
/// |-------------|------------------------------------------
/// |`FE FF ## ##`|UTF-16, big-endian
/// |`FF FE ## ##`|UTF-16, little-endian
/// |`EF BB BF`   |UTF-8
/// |-------------|------------------------------------------
/// |`00 3C 00 3F`|UTF-16 BE or ISO-10646-UCS-2 BE or similar 16-bit BE (use declared encoding to find the exact one)
/// |`3C 00 3F 00`|UTF-16 LE or ISO-10646-UCS-2 LE or similar 16-bit LE (use declared encoding to find the exact one)
/// |`3C 3F 78 6D`|UTF-8, ISO 646, ASCII, some part of ISO 8859, Shift-JIS, EUC, or any other 7-bit, 8-bit, or mixed-width encoding which ensures that the characters of ASCII have their normal positions, width, and values; the actual encoding declaration must be read to detect which of these applies, but since all of these encodings use the same bit patterns for the relevant ASCII characters, the encoding declaration itself may be read reliably
#[cfg(feature = "encoding")]
pub fn detect_encoding(bytes: &[u8]) -> Option<&'static Encoding> {
    match bytes {
        // with BOM
        _ if bytes.starts_with(&[0xFE, 0xFF]) => Some(UTF_16BE),
        _ if bytes.starts_with(&[0xFF, 0xFE]) => Some(UTF_16LE),
        _ if bytes.starts_with(&[0xEF, 0xBB, 0xBF]) => Some(UTF_8),

        // without BOM
        _ if bytes.starts_with(&[0x00, b'<', 0x00, b'?']) => Some(UTF_16BE), // Some BE encoding, for example, UTF-16 or ISO-10646-UCS-2
        _ if bytes.starts_with(&[b'<', 0x00, b'?', 0x00]) => Some(UTF_16LE), // Some LE encoding, for example, UTF-16 or ISO-10646-UCS-2
        _ if bytes.starts_with(&[b'<', b'?', b'x', b'm']) => Some(UTF_8), // Some ASCII compatible

        _ => None,
    }
}

// TODO: add some tests for functions
<|endoftext|>


<commit_before>#![feature(proc_macro)]
#![feature(proc_macro_lib)]
#![recursion_limit = "128"]

#[macro_use] extern crate quote;

extern crate proc_macro;
extern crate syn;

use proc_macro::TokenStream;

// Yield mock generated code for template
//     Hello, {{name}} ({{age}})
#[proc_macro_derive(StacheDisplay)]
pub fn stache_display(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();

    let type_name = &ast.ident;
    let generics = &ast.generics;

    let gen = quote! {
        impl #generics std::fmt::Display for #type_name #generics {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                use display_html_safe::DisplayHtmlSafe;

                f.write_str("Hello, ")?;
                DisplayHtmlSafe::fmt(&self.name, f)?;
                f.write_str(" (")?;
                DisplayHtmlSafe::fmt(&self.age, f)?;
                f.write_str(")\n")?;
                Ok(())
            }
        }
    };

    gen.parse().unwrap()
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Use ast.generics.split_for_impl() to correctly generate impl with any generic parameters<commit_after>#![feature(proc_macro)]
#![feature(proc_macro_lib)]
#![recursion_limit = "128"]

#[macro_use] extern crate quote;

extern crate proc_macro;
extern crate syn;

use proc_macro::TokenStream;

// Yield mock generated code for template
//     Hello, {{name}} ({{age}})
#[proc_macro_derive(StacheDisplay)]
pub fn stache_display(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();

    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

    let gen = quote! {
        impl #impl_generics std::fmt::Display for #name #ty_generics #where_clause {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                use display_html_safe::DisplayHtmlSafe;

                f.write_str("Hello, ")?;
                DisplayHtmlSafe::fmt(&self.name, f)?;
                f.write_str(" (")?;
                DisplayHtmlSafe::fmt(&self.age, f)?;
                f.write_str(")\n")?;
                Ok(())
            }
        }
    };

    gen.parse().unwrap()
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>


<commit_before>use super::coordinates::{Point, CoordinateSystem};
use super::tensors::{TwoForm, InvTwoForm, Tensor, CovariantIndex, ContravariantIndex, InnerProduct};
use typenum::{Pow, Exp};
use typenum::consts::{U1, U2, U3};
use generic_array::ArrayLength;

pub trait MetricSystem: CoordinateSystem
	where <Self as CoordinateSystem>::Dimension: Pow<U2> + Pow<U3>,
	      Exp<<Self as CoordinateSystem>::Dimension, U2>: ArrayLength<f64>,
	      Exp<<Self as CoordinateSystem>::Dimension, U3>: ArrayLength<f64>
{
    fn g(point: &Point<Self>) -> TwoForm<Self>;
    fn inv_g(point: &Point<Self>) -> InvTwoForm<Self> { Self::g(point).inverse().unwrap() }

    fn dg(point: &Point<Self>) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))> {
    	let d = Self::dimension();
        let mut result = Tensor::new(point.clone());
        let h = Self::small(point);

        for j in 0..d {
            let mut x = point.clone();
            x[j] = x[j] - h;
            let g1 = Self::g(&x);

            x[j] = x[j] + h * 2.0;
            let g2 = Self::g(&x);

            for coord in g1.iter_coords() {
                // calculate dg_i/dx^j
                let index = [coord[0], coord[1], j];
                result[&index[..]] = (g2[&*coord] - g1[&*coord]) / (2.0 * h);
            }
        }

    	result
    }

    fn covariant_christoffel(point: &Point<Self>) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))> {
    	let dg = Self::dg(point);
    	let mut result = Tensor::<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>::new(point.clone());

    	for i in result.iter_coords() {
    	    result[&*i] = 0.5*(dg[&*i] + dg[&[i[0],i[2],i[1]][..]] - dg[&[i[1], i[2], i[0]][..]]);
    	}

    	result
    }

    fn christoffel(point: &Point<Self>) -> Tensor<Self, (ContravariantIndex, (CovariantIndex, CovariantIndex))> {
        let ig = Self::inv_g(point);
        let gamma = Self::covariant_christoffel(point);

        <InvTwoForm<Self> as InnerProduct<Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>, U1, U2>>::inner_product(ig, gamma)
    }
}
<commit_msg>Added some documentation<commit_after>use super::coordinates::{Point, CoordinateSystem};
use super::tensors::{TwoForm, InvTwoForm, Tensor, CovariantIndex, ContravariantIndex, InnerProduct};
use typenum::{Pow, Exp};
use typenum::consts::{U1, U2, U3};
use generic_array::ArrayLength;

/// Trait representing the metric properties of the coordinate system
pub trait MetricSystem: CoordinateSystem
	where <Self as CoordinateSystem>::Dimension: Pow<U2> + Pow<U3>,
	      Exp<<Self as CoordinateSystem>::Dimension, U2>: ArrayLength<f64>,
	      Exp<<Self as CoordinateSystem>::Dimension, U3>: ArrayLength<f64>
{
    /// Returns the metric tensor at a given point.
    fn g(point: &Point<Self>) -> TwoForm<Self>;

    /// Returns the inverse metric tensor at a given point.
    ///
    /// The default implementation calculates the metric and then inverts it. A direct implementation
    /// may be desirable for more performance.
    fn inv_g(point: &Point<Self>) -> InvTwoForm<Self> { Self::g(point).inverse().unwrap() }

    /// Returns the partial derivatives of the metric at a given point.
    ///
    /// The default implementation calculates them numerically. A direct implementation
    /// may be desirable for performance.
    fn dg(point: &Point<Self>) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))> {
    	let d = Self::dimension();
        let mut result = Tensor::new(point.clone());
        let h = Self::small(point);

        for j in 0..d {
            let mut x = point.clone();
            x[j] = x[j] - h;
            let g1 = Self::g(&x);

            x[j] = x[j] + h * 2.0;
            let g2 = Self::g(&x);

            for coord in g1.iter_coords() {
                // calculate dg_i/dx^j
                let index = [coord[0], coord[1], j];
                result[&index[..]] = (g2[&*coord] - g1[&*coord]) / (2.0 * h);
            }
        }

    	result
    }

    /// Returns the covariant Christoffel symbols (with three lower indices).
    ///
    /// The default implementation calculates them from the metric. A direct implementation
    /// may be desirable for performance.
    fn covariant_christoffel(point: &Point<Self>) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))> {
    	let dg = Self::dg(point);
    	let mut result = Tensor::<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>::new(point.clone());

    	for i in result.iter_coords() {
    	    result[&*i] = 0.5*(dg[&*i] + dg[&[i[0],i[2],i[1]][..]] - dg[&[i[1], i[2], i[0]][..]]);
    	}

    	result
    }

	/// Returns the Christoffel symbols.
	///
    /// The default implementation calculates them from the metric. A direct implementation
    /// may be desirable for performance.
    fn christoffel(point: &Point<Self>) -> Tensor<Self, (ContravariantIndex, (CovariantIndex, CovariantIndex))> {
        let ig = Self::inv_g(point);
        let gamma = Self::covariant_christoffel(point);

        <InvTwoForm<Self> as InnerProduct<Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>, U1, U2>>::inner_product(ig, gamma)
    }
}
<|endoftext|>


<commit_before>use dungeon::{Dungeon};

pub trait GenoType {
    fn mutate();
    fn generate() -> Dungeon;

    fn evaluate<F: Fn(&Dungeon) -> f64>(dungeon: &Dungeon, strategies: &[F]) -> f64 {
        strategies.iter().fold(1.0, |accum, f| accum * f(dungeon))
    }
}
<commit_msg>Added RandomSeed.<commit_after>use dungeon::{Dungeon};
use celloption::{CellOptions, Tile, Item, Occupant};

pub trait GenoType {
    fn mutate(&mut self);
    fn generate(&self) -> Dungeon;

    fn evaluate<F: Fn(&Dungeon) -> f64>(&self, dungeon: &Dungeon, strategies: &[F]) -> f64 {
        strategies.iter().fold(1.0, |accum, f| accum * f(dungeon))
    }
}

use std::rand::{thread_rng};

struct RandomSeed {
    fitness: f64,
    width: usize,
    height: usize,
    tiles: CellOptions<Tile>,
    items: CellOptions<Item>,
    occupants: CellOptions<Occupant>
}

impl RandomSeed {
    pub fn new(width: usize,
               height: usize,
               tiles: CellOptions<Tile>,
               items: CellOptions<Item>,
               occupants: CellOptions<Occupant>) -> RandomSeed {
        RandomSeed {
            fitness: 0.0,
            width: width,
            height: height,
            tiles: tiles,
            items: items,
            occupants: occupants
        }
    }
}

impl GenoType for RandomSeed {
    fn mutate(&mut self) { /* no-op */ }

    fn generate(&self) -> Dungeon {
        let mut rng = thread_rng();
        let mut dungeon = Dungeon::new(self.width, self.height);
        for i in 0..dungeon.width {
            for j in 0..dungeon.height {
                let tile = self.tiles.choose(&mut rng).clone();
                dungeon.cells[i][j].tile = Some(tile);

                // TODO: add possibility (0.05% per occupant)
                let occupants = self.occupants.sample(&mut rng, 2);
                for occupant in occupants.iter() {
                    dungeon.cells[i][j].add(*occupant);
                }
            }
        }
        dungeon
    }
}
<|endoftext|>


<commit_before>#![cfg(target_os = "windows")]

pub mod ffi {
   #![allow(non_snake_case)]

   pub use libc::{
      c_int, c_uint, c_void, uintptr_t, c_long, c_ulong
   };
   pub use libc::types::os::arch::extra::{
      HANDLE, LONG_PTR, LRESULT, HINSTANCE, LPCWSTR, HMODULE, LPVOID, BOOL
   };
   use std::mem;

   pub type HWND = HANDLE;
   pub type HICON = HANDLE;
   pub type HBRUSH = HANDLE;
   pub type HMENU = HANDLE;
   pub type HCURSOR = HICON;

   pub type WPARAM = uintptr_t;
   pub type LPARAM = LONG_PTR;

   pub type ATOM = u16;

   pub type WNDPROC = Option<unsafe extern "system" fn(HWND, c_uint, WPARAM, LPARAM) -> LRESULT>;

   pub const CS_VREDRAW:                 c_ulong = 0x00000001;
   pub const CS_HREDRAW:                 c_ulong = 0x00000002;
   pub const CS_DBLCLKS:                 c_ulong = 0x00000008;
   pub const CS_OWNDC:                   c_ulong = 0x00000020;
   pub const CS_CLASSDC:                 c_ulong = 0x00000040;
   pub const CS_PARENTDC:                c_ulong = 0x00000080;
   pub const CS_NOCLOSE:                 c_ulong = 0x00000200;
   pub const CS_SAVEBITS:                c_ulong = 0x00000800;
   pub const CS_BYTEALIGNCLIENT:         c_ulong = 0x00001000;
   pub const CS_BYTEALIGNWINDOW:         c_ulong = 0x00002000;
   pub const CS_GLOBALCLASS:             c_ulong = 0x00004000;
   pub const CS_IME:                     c_ulong = 0x00010000;
   pub const CS_DROPSHADOW:              c_ulong = 0x00020000;

   pub const WS_OVERLAPPED:              c_ulong = 0x00000000;
   pub const WS_POPUP:                   c_ulong = 0x80000000;
   pub const WS_CHILD:                   c_ulong = 0x40000000;
   pub const WS_MINIMIZE:                c_ulong = 0x20000000;
   pub const WS_VISIBLE:                 c_ulong = 0x10000000;
   pub const WS_DISABLED:                c_ulong = 0x08000000;
   pub const WS_CLIPSIBLINGS:            c_ulong = 0x04000000;
   pub const WS_CLIPCHILDREN:            c_ulong = 0x02000000;
   pub const WS_MAXIMIZE:                c_ulong = 0x01000000;
   pub const WS_CAPTION:                 c_ulong = 0x00C00000;
   pub const WS_BORDER:                  c_ulong = 0x00800000;
   pub const WS_DLGFRAME:                c_ulong = 0x00400000;
   pub const WS_VSCROLL:                 c_ulong = 0x00200000;
   pub const WS_HSCROLL:                 c_ulong = 0x00100000;
   pub const WS_SYSMENU:                 c_ulong = 0x00080000;
   pub const WS_THICKFRAME:              c_ulong = 0x00040000;
   pub const WS_GROUP:                   c_ulong = 0x00020000;
   pub const WS_TABSTOP:                 c_ulong = 0x00010000;
   pub const WS_MINIMIZEBOX:             c_ulong = 0x00020000;
   pub const WS_MAXIMIZEBOX:             c_ulong = 0x00010000;
   pub const WS_TILED:                   c_ulong = WS_OVERLAPPED;
   pub const WS_ICONIC:                  c_ulong = WS_MINIMIZE;
   pub const WS_SIZEBOX:                 c_ulong = WS_THICKFRAME;
   pub const WS_TILEDWINDOW:             c_ulong = WS_OVERLAPPEDWINDOW;
   pub const WS_OVERLAPPEDWINDOW:        c_ulong = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
   pub const WS_POPUPWINDOW:             c_ulong = WS_POPUP | WS_BORDER | WS_SYSMENU;
   pub const WS_CHILDWINDOW:             c_ulong = WS_CHILD;

   pub const WS_EX_DLGMODALFRAME:        c_ulong = 0x00000001;
   pub const WS_EX_NOPARENTNOTIFY:       c_ulong = 0x00000004;
   pub const WS_EX_TOPMOST:              c_ulong = 0x00000008;
   pub const WS_EX_ACCEPTFILES:          c_ulong = 0x00000010;
   pub const WS_EX_TRANSPARENT:          c_ulong = 0x00000020;
   pub const WS_EX_MDICHILD:             c_ulong = 0x00000040;
   pub const WS_EX_TOOLWINDOW:           c_ulong = 0x00000080;
   pub const WS_EX_WINDOWEDGE:           c_ulong = 0x00000100;
   pub const WS_EX_CLIENTEDGE:           c_ulong = 0x00000200;
   pub const WS_EX_CONTEXTHELP:          c_ulong = 0x00000400;
   pub const WS_EX_RIGHT:                c_ulong = 0x00001000;
   pub const WS_EX_LEFT:                 c_ulong = 0x00000000;
   pub const WS_EX_RTLREADING:           c_ulong = 0x00002000;
   pub const WS_EX_LTRREADING:           c_ulong = 0x00000000;
   pub const WS_EX_LEFTSCROLLBAR:        c_ulong = 0x00004000;
   pub const WS_EX_RIGHTSCROLLBAR:       c_ulong = 0x00000000;
   pub const WS_EX_CONTROLPARENT:        c_ulong = 0x00010000;
   pub const WS_EX_STATICEDGE:           c_ulong = 0x00020000;
   pub const WS_EX_APPWINDOW:            c_ulong = 0x00040000;
   pub const WS_EX_OVERLAPPEDWINDOW:     c_ulong = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE;
   pub const WS_EX_PALETTEWINDOW:        c_ulong = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
   pub const WS_EX_LAYERED:              c_ulong = 0x00080000;
   pub const WS_EX_NOINHERITLAYOUT:      c_ulong = 0x00100000;
   pub const WS_EX_NOREDIRECTIONBITMAP:  c_ulong = 0x00200000;
   pub const WS_EX_LAYOUTRTL:            c_ulong = 0x00400000;
   pub const WS_EX_COMPOSITED:           c_ulong = 0x02000000;
   pub const WS_EX_NOACTIVATE:           c_ulong = 0x08000000;

   pub const CW_USEDEFAULT:                c_int = 0x80000000u32 as c_int;

   pub const WM_CLOSE:                    c_uint = 16;

   #[repr(C)]
   #[derive(Copy)]
   pub struct WNDCLASSEXW {
      pub cbSize: c_uint,
      pub style: c_uint,
      pub lpfnWndProc: WNDPROC,
      pub cbClsExtra: c_int,
      pub cbWndExtra: c_int,
      pub hInstance: HINSTANCE,
      pub hIcon: HICON,
      pub hCursor: HCURSOR,
      pub hbrBackground: HBRUSH,
      pub lpszMenuName: LPCWSTR,
      pub lpszClassName: LPCWSTR,
      pub hIconSm: HICON,
   }
   impl Clone for WNDCLASSEXW {
      fn clone(&self) -> Self { *self }
   }
   impl Default for WNDCLASSEXW {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct POINT {
      pub x: c_long,
      pub y: c_long,
   }
   impl Clone for POINT {
      fn clone(&self) -> Self { *self }
   }
   impl Default for POINT {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct MSG {
      pub hwnd: HWND,
      pub message: c_uint,
      pub wParam: WPARAM,
      pub lParam: LPARAM,
      pub time: c_ulong,
      pub pt: POINT,
   }
   impl Clone for MSG {
      fn clone(&self) -> Self { *self }
   }
   impl Default for MSG {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   extern "system" {
      pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;

      pub fn RegisterClassExW(lpWndClass: *const WNDCLASSEXW) -> ATOM;

      pub fn PostQuitMessage(nExitCode: c_int);

      pub fn TranslateMessage(lpmsg: *const MSG) -> BOOL;

      pub fn DispatchMessageW(lpmsg: *const MSG) -> LRESULT;

      pub fn DefWindowProcW(
         hWnd: HWND,
         Msg: c_uint,
         wParam: WPARAM,
         lParam: LPARAM
      ) -> LRESULT;

      pub fn CreateWindowExW(
         dwExStyle: c_ulong,
         lpClassName: LPCWSTR,
         lpWindowName: LPCWSTR,
         dwStyle: c_ulong,
         x: c_int,
         y: c_int,
         nWidth: c_int,
         nHeight: c_int,
         hWndParent: HWND,
         hMenu: HMENU,
         hInstance: HINSTANCE,
         lpParam: LPVOID,
      ) -> HWND;

      pub fn GetMessageW(
         lpMsg: *const MSG,
         hWnd: HWND,
         wMsgFilterMin: c_uint,
         wMsgFilterMax: c_uint
      ) -> BOOL;
   }
}

use std::ptr;
use std::mem;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;

fn to_utf16_os<S: AsRef<OsStr> + ?Sized>(s: &S) -> Vec<u16> {
   let mut v: Vec<_> = OsStr::new(s).encode_wide().collect();
   v.push(0);
   v
}

pub fn register_window_class<S: AsRef<OsStr> + ?Sized>(class_name: &S) {
   unsafe extern "system" fn wnd_proc(
      hwnd: ffi::HWND,
      msg: ffi::c_uint,
      wparam: ffi::WPARAM,
      lparam: ffi::LPARAM
   ) -> ffi::LRESULT {
      match msg {
         ffi::WM_CLOSE => {
            ffi::PostQuitMessage(0);
         },
         _ => {
            return ffi::DefWindowProcW(hwnd, msg, wparam, lparam);
         }
      }

      return 0;
   }

   unsafe {
      let wnd_class = ffi::WNDCLASSEXW {
         cbSize: mem::size_of::<ffi::WNDCLASSEXW>() as ffi::c_uint,
         style: ffi::CS_HREDRAW | ffi::CS_VREDRAW | ffi::CS_OWNDC,
         lpfnWndProc: Some(wnd_proc),
         cbClsExtra: 0,
         cbWndExtra: 0,
         hInstance: ffi::GetModuleHandleW(ptr::null()),
         hIcon: ptr::null_mut(),
         hCursor: ptr::null_mut(),
         hbrBackground: ptr::null_mut(),
         lpszMenuName: ptr::null(),
         lpszClassName: to_utf16_os(class_name).as_ptr(),
         hIconSm: ptr::null_mut(),
      };

      ffi::RegisterClassExW(&wnd_class);
   }
}

pub struct Window {
   hwnd: ffi::HWND
}

impl Window {
   pub fn create<S: AsRef<OsStr> + ?Sized>(width: ffi::c_int, height: ffi::c_int, title: &S, class_name: &S) -> Window {
      let hwnd = unsafe {
         ffi::CreateWindowExW(
            ffi::WS_EX_CLIENTEDGE,
            to_utf16_os(class_name).as_ptr(),
            to_utf16_os(title).as_ptr(),
            ffi::WS_OVERLAPPEDWINDOW | ffi::WS_VISIBLE,
            ffi::CW_USEDEFAULT, ffi::CW_USEDEFAULT,
            width, height,
            ptr::null_mut(),
            ptr::null_mut(),
            ffi::GetModuleHandleW(ptr::null()),
            ptr::null_mut()
         )
      };

      Window {
         hwnd: hwnd
      }
   }
}

pub struct Message {
   msg: ffi::MSG
}

impl Message {
   pub fn get() -> Option<Self> {
      let mut msg = unsafe { mem::uninitialized() };

      match unsafe { ffi::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) } {
         0 => None,
         _ => Some(Message {
            msg: msg
         })
      }
   }

   pub fn translate(&self) {
      unsafe {
         ffi::TranslateMessage(&self.msg)
      };
   }

   pub fn dispatch(&self) {
      unsafe {
         ffi::DispatchMessageW(&self.msg)
      };
   }
}
<commit_msg>Make hwnd a public attribute<commit_after>#![cfg(target_os = "windows")]

pub mod ffi {
   #![allow(non_snake_case)]

   pub use libc::{
      c_int, c_uint, c_void, uintptr_t, c_long, c_ulong
   };
   pub use libc::types::os::arch::extra::{
      HANDLE, LONG_PTR, LRESULT, HINSTANCE, LPCWSTR, HMODULE, LPVOID, BOOL
   };
   use std::mem;

   pub type HWND = HANDLE;
   pub type HICON = HANDLE;
   pub type HBRUSH = HANDLE;
   pub type HMENU = HANDLE;
   pub type HCURSOR = HICON;

   pub type WPARAM = uintptr_t;
   pub type LPARAM = LONG_PTR;

   pub type ATOM = u16;

   pub type WNDPROC = Option<unsafe extern "system" fn(HWND, c_uint, WPARAM, LPARAM) -> LRESULT>;

   pub const CS_VREDRAW:                 c_ulong = 0x00000001;
   pub const CS_HREDRAW:                 c_ulong = 0x00000002;
   pub const CS_DBLCLKS:                 c_ulong = 0x00000008;
   pub const CS_OWNDC:                   c_ulong = 0x00000020;
   pub const CS_CLASSDC:                 c_ulong = 0x00000040;
   pub const CS_PARENTDC:                c_ulong = 0x00000080;
   pub const CS_NOCLOSE:                 c_ulong = 0x00000200;
   pub const CS_SAVEBITS:                c_ulong = 0x00000800;
   pub const CS_BYTEALIGNCLIENT:         c_ulong = 0x00001000;
   pub const CS_BYTEALIGNWINDOW:         c_ulong = 0x00002000;
   pub const CS_GLOBALCLASS:             c_ulong = 0x00004000;
   pub const CS_IME:                     c_ulong = 0x00010000;
   pub const CS_DROPSHADOW:              c_ulong = 0x00020000;

   pub const WS_OVERLAPPED:              c_ulong = 0x00000000;
   pub const WS_POPUP:                   c_ulong = 0x80000000;
   pub const WS_CHILD:                   c_ulong = 0x40000000;
   pub const WS_MINIMIZE:                c_ulong = 0x20000000;
   pub const WS_VISIBLE:                 c_ulong = 0x10000000;
   pub const WS_DISABLED:                c_ulong = 0x08000000;
   pub const WS_CLIPSIBLINGS:            c_ulong = 0x04000000;
   pub const WS_CLIPCHILDREN:            c_ulong = 0x02000000;
   pub const WS_MAXIMIZE:                c_ulong = 0x01000000;
   pub const WS_CAPTION:                 c_ulong = 0x00C00000;
   pub const WS_BORDER:                  c_ulong = 0x00800000;
   pub const WS_DLGFRAME:                c_ulong = 0x00400000;
   pub const WS_VSCROLL:                 c_ulong = 0x00200000;
   pub const WS_HSCROLL:                 c_ulong = 0x00100000;
   pub const WS_SYSMENU:                 c_ulong = 0x00080000;
   pub const WS_THICKFRAME:              c_ulong = 0x00040000;
   pub const WS_GROUP:                   c_ulong = 0x00020000;
   pub const WS_TABSTOP:                 c_ulong = 0x00010000;
   pub const WS_MINIMIZEBOX:             c_ulong = 0x00020000;
   pub const WS_MAXIMIZEBOX:             c_ulong = 0x00010000;
   pub const WS_TILED:                   c_ulong = WS_OVERLAPPED;
   pub const WS_ICONIC:                  c_ulong = WS_MINIMIZE;
   pub const WS_SIZEBOX:                 c_ulong = WS_THICKFRAME;
   pub const WS_TILEDWINDOW:             c_ulong = WS_OVERLAPPEDWINDOW;
   pub const WS_OVERLAPPEDWINDOW:        c_ulong = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
   pub const WS_POPUPWINDOW:             c_ulong = WS_POPUP | WS_BORDER | WS_SYSMENU;
   pub const WS_CHILDWINDOW:             c_ulong = WS_CHILD;

   pub const WS_EX_DLGMODALFRAME:        c_ulong = 0x00000001;
   pub const WS_EX_NOPARENTNOTIFY:       c_ulong = 0x00000004;
   pub const WS_EX_TOPMOST:              c_ulong = 0x00000008;
   pub const WS_EX_ACCEPTFILES:          c_ulong = 0x00000010;
   pub const WS_EX_TRANSPARENT:          c_ulong = 0x00000020;
   pub const WS_EX_MDICHILD:             c_ulong = 0x00000040;
   pub const WS_EX_TOOLWINDOW:           c_ulong = 0x00000080;
   pub const WS_EX_WINDOWEDGE:           c_ulong = 0x00000100;
   pub const WS_EX_CLIENTEDGE:           c_ulong = 0x00000200;
   pub const WS_EX_CONTEXTHELP:          c_ulong = 0x00000400;
   pub const WS_EX_RIGHT:                c_ulong = 0x00001000;
   pub const WS_EX_LEFT:                 c_ulong = 0x00000000;
   pub const WS_EX_RTLREADING:           c_ulong = 0x00002000;
   pub const WS_EX_LTRREADING:           c_ulong = 0x00000000;
   pub const WS_EX_LEFTSCROLLBAR:        c_ulong = 0x00004000;
   pub const WS_EX_RIGHTSCROLLBAR:       c_ulong = 0x00000000;
   pub const WS_EX_CONTROLPARENT:        c_ulong = 0x00010000;
   pub const WS_EX_STATICEDGE:           c_ulong = 0x00020000;
   pub const WS_EX_APPWINDOW:            c_ulong = 0x00040000;
   pub const WS_EX_OVERLAPPEDWINDOW:     c_ulong = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE;
   pub const WS_EX_PALETTEWINDOW:        c_ulong = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
   pub const WS_EX_LAYERED:              c_ulong = 0x00080000;
   pub const WS_EX_NOINHERITLAYOUT:      c_ulong = 0x00100000;
   pub const WS_EX_NOREDIRECTIONBITMAP:  c_ulong = 0x00200000;
   pub const WS_EX_LAYOUTRTL:            c_ulong = 0x00400000;
   pub const WS_EX_COMPOSITED:           c_ulong = 0x02000000;
   pub const WS_EX_NOACTIVATE:           c_ulong = 0x08000000;

   pub const CW_USEDEFAULT:                c_int = 0x80000000u32 as c_int;

   pub const WM_CLOSE:                    c_uint = 16;

   #[repr(C)]
   #[derive(Copy)]
   pub struct WNDCLASSEXW {
      pub cbSize: c_uint,
      pub style: c_uint,
      pub lpfnWndProc: WNDPROC,
      pub cbClsExtra: c_int,
      pub cbWndExtra: c_int,
      pub hInstance: HINSTANCE,
      pub hIcon: HICON,
      pub hCursor: HCURSOR,
      pub hbrBackground: HBRUSH,
      pub lpszMenuName: LPCWSTR,
      pub lpszClassName: LPCWSTR,
      pub hIconSm: HICON,
   }
   impl Clone for WNDCLASSEXW {
      fn clone(&self) -> Self { *self }
   }
   impl Default for WNDCLASSEXW {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct POINT {
      pub x: c_long,
      pub y: c_long,
   }
   impl Clone for POINT {
      fn clone(&self) -> Self { *self }
   }
   impl Default for POINT {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct MSG {
      pub hwnd: HWND,
      pub message: c_uint,
      pub wParam: WPARAM,
      pub lParam: LPARAM,
      pub time: c_ulong,
      pub pt: POINT,
   }
   impl Clone for MSG {
      fn clone(&self) -> Self { *self }
   }
   impl Default for MSG {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   extern "system" {
      pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;

      pub fn RegisterClassExW(lpWndClass: *const WNDCLASSEXW) -> ATOM;

      pub fn PostQuitMessage(nExitCode: c_int);

      pub fn TranslateMessage(lpmsg: *const MSG) -> BOOL;

      pub fn DispatchMessageW(lpmsg: *const MSG) -> LRESULT;

      pub fn DefWindowProcW(
         hWnd: HWND,
         Msg: c_uint,
         wParam: WPARAM,
         lParam: LPARAM
      ) -> LRESULT;

      pub fn CreateWindowExW(
         dwExStyle: c_ulong,
         lpClassName: LPCWSTR,
         lpWindowName: LPCWSTR,
         dwStyle: c_ulong,
         x: c_int,
         y: c_int,
         nWidth: c_int,
         nHeight: c_int,
         hWndParent: HWND,
         hMenu: HMENU,
         hInstance: HINSTANCE,
         lpParam: LPVOID,
      ) -> HWND;

      pub fn GetMessageW(
         lpMsg: *const MSG,
         hWnd: HWND,
         wMsgFilterMin: c_uint,
         wMsgFilterMax: c_uint
      ) -> BOOL;
   }
}

use std::ptr;
use std::mem;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;

fn to_utf16_os<S: AsRef<OsStr> + ?Sized>(s: &S) -> Vec<u16> {
   let mut v: Vec<_> = OsStr::new(s).encode_wide().collect();
   v.push(0);
   v
}

pub fn register_window_class<S: AsRef<OsStr> + ?Sized>(class_name: &S) {
   unsafe extern "system" fn wnd_proc(
      hwnd: ffi::HWND,
      msg: ffi::c_uint,
      wparam: ffi::WPARAM,
      lparam: ffi::LPARAM
   ) -> ffi::LRESULT {
      match msg {
         ffi::WM_CLOSE => {
            ffi::PostQuitMessage(0);
         },
         _ => {
            return ffi::DefWindowProcW(hwnd, msg, wparam, lparam);
         }
      }

      return 0;
   }

   unsafe {
      let wnd_class = ffi::WNDCLASSEXW {
         cbSize: mem::size_of::<ffi::WNDCLASSEXW>() as ffi::c_uint,
         style: ffi::CS_HREDRAW | ffi::CS_VREDRAW | ffi::CS_OWNDC,
         lpfnWndProc: Some(wnd_proc),
         cbClsExtra: 0,
         cbWndExtra: 0,
         hInstance: ffi::GetModuleHandleW(ptr::null()),
         hIcon: ptr::null_mut(),
         hCursor: ptr::null_mut(),
         hbrBackground: ptr::null_mut(),
         lpszMenuName: ptr::null(),
         lpszClassName: to_utf16_os(class_name).as_ptr(),
         hIconSm: ptr::null_mut(),
      };

      ffi::RegisterClassExW(&wnd_class);
   }
}

pub struct Window {
   pub hwnd: ffi::HWND
}

impl Window {
   pub fn create<S: AsRef<OsStr> + ?Sized>(width: ffi::c_int, height: ffi::c_int, title: &S, class_name: &S) -> Window {
      let hwnd = unsafe {
         ffi::CreateWindowExW(
            ffi::WS_EX_CLIENTEDGE,
            to_utf16_os(class_name).as_ptr(),
            to_utf16_os(title).as_ptr(),
            ffi::WS_OVERLAPPEDWINDOW | ffi::WS_VISIBLE,
            ffi::CW_USEDEFAULT, ffi::CW_USEDEFAULT,
            width, height,
            ptr::null_mut(),
            ptr::null_mut(),
            ffi::GetModuleHandleW(ptr::null()),
            ptr::null_mut()
         )
      };

      Window {
         hwnd: hwnd
      }
   }
}

pub struct Message {
   msg: ffi::MSG
}

impl Message {
   pub fn get() -> Option<Self> {
      let mut msg = unsafe { mem::uninitialized() };

      match unsafe { ffi::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) } {
         0 => None,
         _ => Some(Message {
            msg: msg
         })
      }
   }

   pub fn translate(&self) {
      unsafe {
         ffi::TranslateMessage(&self.msg)
      };
   }

   pub fn dispatch(&self) {
      unsafe {
         ffi::DispatchMessageW(&self.msg)
      };
   }
}
<|endoftext|>


<commit_before>use nom::{IResult, alphanumeric, digit, eof, line_ending, multispace, space};
use std::str;
use std::str::FromStr;

use select::*;

#[derive(Debug, PartialEq)]
pub enum SqlQuery {
    Select(SelectStatement),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ConditionBase {
    Field(String),
    Literal(String),
    Placeholder,
}

#[derive(Clone, Debug, PartialEq)]
pub struct ConditionTree {
    pub operator: String,
    pub left: Option<Box<ConditionExpression>>,
    pub right: Option<Box<ConditionExpression>>,
}

#[derive(Clone, Debug, PartialEq)]
pub enum ConditionExpression {
    ComparisonOp(ConditionTree),
    LogicalOp(ConditionTree),
    Expr(ConditionBase),
}

/// Parse an unsigned integer.
named!(pub unsigned_number<&[u8], u64>,
    map_res!(
        map_res!(digit, str::from_utf8),
        FromStr::from_str
    )
);

/// Parse a terminator that ends a SQL statement.
named!(pub statement_terminator,
    delimited!(opt!(multispace),
               alt_complete!(tag!(";") | line_ending | eof),
               opt!(multispace)
    )
);

/// Parse binary comparison operators
named!(pub binary_comparison_operator<&[u8], &str>,
    dbg_dmp!(map_res!(
        dbg_dmp!(alt_complete!(  tag_s!(b"=")
             | tag_s!(b"<")
             | tag_s!(b">")
             | tag_s!(b"<>")
             | tag_s!(b">=")
             | tag_s!(b"<=")
             | tag_s!(b"LIKE")
             | tag_s!(b"NOT_LIKE")
        )),
        str::from_utf8
    )
));

/// Parse logical operators
named!(pub binary_logical_operator<&[u8], &str>,
    map_res!(
        alt_complete!(
               tag_s!(b"and")
             | tag_s!(b"or")
        ),
        str::from_utf8
    )
);

/// Parse unary comparison operators
named!(pub unary_comparison_operator<&[u8], &str>,
    map_res!(
        alt_complete!(
               tag_s!(b"NOT")
             | tag_s!(b"-") // ??? (number neg)
             | tag_s!(b"ISNULL")
        ),
        str::from_utf8
    )
);

/// Parse unary comparison operators
named!(pub unary_negation_operator<&[u8], &str>,
    map_res!(
        alt_complete!(
              tag_s!(b"not")
            | tag_s!(b"!")
        ),
        str::from_utf8
    )
);

/// Parse rule for a comma-separated list.
named!(pub csvlist<&[u8], Vec<&str> >,
       many0!(
           map_res!(
               chain!(
                   fieldname: alphanumeric ~
                   opt!(
                       chain!(
                           tag!(",") ~
                           space?,
                           ||{}
                       )
                   ),
                   ||{ fieldname }
               ),
               str::from_utf8
           )
       )
);

/// Parse list of columns/fields.
/// XXX(malte): add support for named table notation
named!(pub fieldlist<&[u8], Vec<&str> >,
       alt_complete!(
           tag!("*") => { |_| vec!["ALL".into()] }
         | csvlist
       )
);

/// Parse sequence of SQL statements, divided by semicolons or newlines
// named!(pub query_list<&[u8], Vec<SqlQuery> >,
//    many1!(map_res!(selection, |s| { SqlQuery::Select(s) }))
// );

pub fn parse_query(input: &str) -> Result<SqlQuery, &str> {
    // we process all queries in lowercase to avoid having to deal with capitalization in the
    // parser.
    let q_lower = input.to_lowercase();

    // TODO(malte): appropriately pass through errors from nom
    match selection(&q_lower.into_bytes()) {
        IResult::Done(_, o) => Ok(SqlQuery::Select(o)),
        IResult::Error(_) => Err("parse error"),
        IResult::Incomplete(_) => Err("incomplete query"),
    }
}
<commit_msg>SqlQuery ought to derive Clone.<commit_after>use nom::{IResult, alphanumeric, digit, eof, line_ending, multispace, space};
use std::str;
use std::str::FromStr;

use select::*;

#[derive(Clone, Debug, PartialEq)]
pub enum SqlQuery {
    Select(SelectStatement),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ConditionBase {
    Field(String),
    Literal(String),
    Placeholder,
}

#[derive(Clone, Debug, PartialEq)]
pub struct ConditionTree {
    pub operator: String,
    pub left: Option<Box<ConditionExpression>>,
    pub right: Option<Box<ConditionExpression>>,
}

#[derive(Clone, Debug, PartialEq)]
pub enum ConditionExpression {
    ComparisonOp(ConditionTree),
    LogicalOp(ConditionTree),
    Expr(ConditionBase),
}

/// Parse an unsigned integer.
named!(pub unsigned_number<&[u8], u64>,
    map_res!(
        map_res!(digit, str::from_utf8),
        FromStr::from_str
    )
);

/// Parse a terminator that ends a SQL statement.
named!(pub statement_terminator,
    delimited!(opt!(multispace),
               alt_complete!(tag!(";") | line_ending | eof),
               opt!(multispace)
    )
);

/// Parse binary comparison operators
named!(pub binary_comparison_operator<&[u8], &str>,
    dbg_dmp!(map_res!(
        dbg_dmp!(alt_complete!(  tag_s!(b"=")
             | tag_s!(b"<")
             | tag_s!(b">")
             | tag_s!(b"<>")
             | tag_s!(b">=")
             | tag_s!(b"<=")
             | tag_s!(b"LIKE")
             | tag_s!(b"NOT_LIKE")
        )),
        str::from_utf8
    )
));

/// Parse logical operators
named!(pub binary_logical_operator<&[u8], &str>,
    map_res!(
        alt_complete!(
               tag_s!(b"and")
             | tag_s!(b"or")
        ),
        str::from_utf8
    )
);

/// Parse unary comparison operators
named!(pub unary_comparison_operator<&[u8], &str>,
    map_res!(
        alt_complete!(
               tag_s!(b"NOT")
             | tag_s!(b"-") // ??? (number neg)
             | tag_s!(b"ISNULL")
        ),
        str::from_utf8
    )
);

/// Parse unary comparison operators
named!(pub unary_negation_operator<&[u8], &str>,
    map_res!(
        alt_complete!(
              tag_s!(b"not")
            | tag_s!(b"!")
        ),
        str::from_utf8
    )
);

/// Parse rule for a comma-separated list.
named!(pub csvlist<&[u8], Vec<&str> >,
       many0!(
           map_res!(
               chain!(
                   fieldname: alphanumeric ~
                   opt!(
                       chain!(
                           tag!(",") ~
                           space?,
                           ||{}
                       )
                   ),
                   ||{ fieldname }
               ),
               str::from_utf8
           )
       )
);

/// Parse list of columns/fields.
/// XXX(malte): add support for named table notation
named!(pub fieldlist<&[u8], Vec<&str> >,
       alt_complete!(
           tag!("*") => { |_| vec!["ALL".into()] }
         | csvlist
       )
);

/// Parse sequence of SQL statements, divided by semicolons or newlines
// named!(pub query_list<&[u8], Vec<SqlQuery> >,
//    many1!(map_res!(selection, |s| { SqlQuery::Select(s) }))
// );

pub fn parse_query(input: &str) -> Result<SqlQuery, &str> {
    // we process all queries in lowercase to avoid having to deal with capitalization in the
    // parser.
    let q_lower = input.to_lowercase();

    // TODO(malte): appropriately pass through errors from nom
    match selection(&q_lower.into_bytes()) {
        IResult::Done(_, o) => Ok(SqlQuery::Select(o)),
        IResult::Error(_) => Err("parse error"),
        IResult::Incomplete(_) => Err("incomplete query"),
    }
}
<|endoftext|>


<commit_before>//! A parser for lambda expressions with [De Bruijn indices](https://en.wikipedia.org/wiki/De_Bruijn_index)

use term::*;
use term::Term::*;
use self::Token::*;
use self::Error::*;
use self::Expression::*;

/// A type to represent a parsing error.
#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidCharacter((usize, char)),
    InvalidExpression
}

#[derive(Debug, PartialEq, Clone, Copy)]
enum Token {
    Lambda,
    Lparen,
    Rparen,
    Number(usize)
}

fn tokenize(input: &str) -> Result<Vec<Token>, Error> {
    let mut chars = input.chars();
    let mut tokens = Vec::new();
    let mut position = 0;

    while let Some(c) = chars.next() {
        match c {
            'λ' => { tokens.push(Lambda) },
            '(' => { tokens.push(Lparen) },
            ')' => { tokens.push(Rparen) },
             x  => {
                if let Some(n) = x.to_digit(16) {
                    tokens.push(Number(n as usize))
                } else if x.is_whitespace() {
                    ()
                } else {
                    return Err(InvalidCharacter((position, x)))
                }
            }
        }
        position += if c == 'λ' { 2 } else { 1 };
    }

    Ok(tokens)
}

#[derive(Debug, PartialEq, Clone)]
enum Expression {
    Abstraction,
    Sequence(Vec<Expression>),
    Variable(usize)
}

fn _get_ast(tokens: &[Token], pos: &mut usize) -> Expression {
    let mut expr = Vec::new();

    while *pos < tokens.len() {
        match tokens[*pos] {
            Lambda => {
                expr.push(Abstraction)
            },
            Number(i) => {
                expr.push(Variable(i))
            },
            Lparen => {
                *pos += 1;
                expr.push(_get_ast(&tokens, pos));
            },
            Rparen => {
                return Sequence(expr)
            }
        }
        *pos += 1;
    }

    Sequence(expr)
}

fn get_ast(tokens: &[Token]) -> Expression {
    let mut pos = 0;

    _get_ast(tokens, &mut pos)
}

/// Parses the input lambda expression to a `Term`.
///
/// # Example
/// ```
/// use lambda_calculus::parser::parse;
/// use lambda_calculus::arithmetic::{succ, pred};
///
/// assert_eq!(parse(&"λ λ λ 2 (3 2 1)"), Ok(succ()));
/// assert_eq!(parse(&"λλλ3(λλ1(24))(λ2)(λ1)"), Ok(pred()));
/// ```
pub fn parse(input: &str) -> Result<Term, Error> {
    let tokens = try!(tokenize(input));
    let ast = get_ast(&tokens);

    let exprs = if let Sequence(exprs) = ast { Ok(exprs) } else { Err(InvalidExpression) };

    let mut stack = Vec::new();
    let mut output = Vec::new();
    let term = fold_exprs(&exprs.unwrap(), &mut stack, &mut output);

    Ok(term)
}

fn fold_exprs(exprs: &[Expression], stack: &mut Vec<Expression>, output: &mut Vec<Term>) -> Term {
    let mut iter = exprs.iter();

    while let Some(ref expr) = iter.next() {
        match **expr {
            Variable(i) => output.push(Var(i)),
            Abstraction => stack.push(Abstraction),
            Sequence(ref exprs) => {
                let mut stack2 = Vec::new();
                let mut output2 = Vec::new();
                output.push(fold_exprs(&exprs, &mut stack2, &mut output2))
            }
        }
    }

    let mut ret = fold_terms(output.clone());

    while let Some(Abstraction) = stack.pop() {
        ret = abs(ret);
    }

    ret
}

fn fold_terms(mut terms: Vec<Term>) -> Term {
    if terms.len() > 1 {
        terms.reverse();
        let fst = terms.pop().unwrap();
        terms.reverse();
        terms.into_iter().fold(fst, |acc, t| app(acc, t))
    } else {
        terms.pop().expect("attempted to fold an empty term vector")
    }
}

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

    #[test]
    fn tokenization_error() {
        assert_eq!(tokenize(&"λλx2"), Err(InvalidCharacter((4, 'x'))))
    }

    #[test]
    fn tokenization_success() {
        let quine = "λ 1 ( (λ 1 1) (λ λ λ λ λ 1 4 (3 (5 5) 2) ) ) 1";
        let tokens = tokenize(&quine);

        assert!(tokens.is_ok());
        assert_eq!(tokens.unwrap(), vec![Lambda, Number(1), Lparen, Lparen, Lambda, Number(1), Number(1), Rparen, Lparen, Lambda, Lambda, Lambda, Lambda,
            Lambda, Number(1), Number(4), Lparen, Number(3), Lparen, Number(5), Number(5), Rparen, Number(2), Rparen, Rparen, Rparen, Number(1)]);
    }

    #[test]
    fn succ_ast() {
        let tokens = tokenize(&"λλλ2(321)").unwrap();
        let ast = get_ast(&tokens);

        assert_eq!(ast,
            Sequence(vec![
                Abstraction,
                Abstraction,
                Abstraction,
                Variable(2),
                Sequence(vec![
                    Variable(3),
                    Variable(2),
                    Variable(1)
                ])
            ])
        );
    }

    #[test]
    fn parse_y() {
        let y = "λ(λ2(11))(λ2(11))";
        assert_eq!(&*format!("{}", parse(&y).unwrap()), y);
    }

    #[test]
    fn parse_quine() {
        let quine = "λ1((λ11)(λλλλλ14(3(55)2)))1";
        assert_eq!(&*format!("{}", parse(&quine).unwrap()), quine);
    }

    #[test]
    fn parse_blc() {
        let blc = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))(λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        assert_eq!(&*format!("{}", parse(&blc).unwrap()), blc);
    }
}
<commit_msg>Remove Clone from parser objects<commit_after>//! A parser for lambda expressions with [De Bruijn indices](https://en.wikipedia.org/wiki/De_Bruijn_index)

use term::*;
use term::Term::*;
use self::Token::*;
use self::Error::*;
use self::Expression::*;

/// A type to represent a parsing error.
#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidCharacter((usize, char)),
    InvalidExpression
}

#[derive(Debug, PartialEq)]
enum Token {
    Lambda,
    Lparen,
    Rparen,
    Number(usize)
}

fn tokenize(input: &str) -> Result<Vec<Token>, Error> {
    let mut chars = input.chars();
    let mut tokens = Vec::new();
    let mut position = 0;

    while let Some(c) = chars.next() {
        match c {
            'λ' => { tokens.push(Lambda) },
            '(' => { tokens.push(Lparen) },
            ')' => { tokens.push(Rparen) },
             x  => {
                if let Some(n) = x.to_digit(16) {
                    tokens.push(Number(n as usize))
                } else if x.is_whitespace() {
                    ()
                } else {
                    return Err(InvalidCharacter((position, x)))
                }
            }
        }
        position += if c == 'λ' { 2 } else { 1 };
    }

    Ok(tokens)
}

#[derive(Debug, PartialEq)]
enum Expression {
    Abstraction,
    Sequence(Vec<Expression>),
    Variable(usize)
}

fn _get_ast(tokens: &[Token], pos: &mut usize) -> Expression {
    let mut expr = Vec::new();

    while *pos < tokens.len() {
        match tokens[*pos] {
            Lambda => {
                expr.push(Abstraction)
            },
            Number(i) => {
                expr.push(Variable(i))
            },
            Lparen => {
                *pos += 1;
                expr.push(_get_ast(&tokens, pos));
            },
            Rparen => {
                return Sequence(expr)
            }
        }
        *pos += 1;
    }

    Sequence(expr)
}

fn get_ast(tokens: &[Token]) -> Expression {
    let mut pos = 0;

    _get_ast(tokens, &mut pos)
}

/// Parses the input lambda expression to a `Term`.
///
/// # Example
/// ```
/// use lambda_calculus::parser::parse;
/// use lambda_calculus::arithmetic::{succ, pred};
///
/// assert_eq!(parse(&"λ λ λ 2 (3 2 1)"), Ok(succ()));
/// assert_eq!(parse(&"λλλ3(λλ1(24))(λ2)(λ1)"), Ok(pred()));
/// ```
pub fn parse(input: &str) -> Result<Term, Error> {
    let tokens = try!(tokenize(input));
    let ast = get_ast(&tokens);

    let exprs = if let Sequence(exprs) = ast { Ok(exprs) } else { Err(InvalidExpression) };

    let mut stack = Vec::new();
    let mut output = Vec::new();
    let term = fold_exprs(&exprs.unwrap(), &mut stack, &mut output);

    Ok(term)
}

fn fold_exprs(exprs: &[Expression], stack: &mut Vec<Expression>, output: &mut Vec<Term>) -> Term {
    let mut iter = exprs.iter();

    while let Some(ref expr) = iter.next() {
        match **expr {
            Variable(i) => output.push(Var(i)),
            Abstraction => stack.push(Abstraction),
            Sequence(ref exprs) => {
                let mut stack2 = Vec::new();
                let mut output2 = Vec::new();
                output.push(fold_exprs(&exprs, &mut stack2, &mut output2))
            }
        }
    }

    let mut ret = fold_terms(output.drain(..).collect());

    while let Some(Abstraction) = stack.pop() {
        ret = abs(ret);
    }

    ret
}

fn fold_terms(mut terms: Vec<Term>) -> Term {
    if terms.len() > 1 {
        terms.reverse();
        let fst = terms.pop().unwrap();
        terms.reverse();
        terms.into_iter().fold(fst, |acc, t| app(acc, t))
    } else {
        terms.pop().expect("attempted to fold an empty term vector")
    }
}

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

    #[test]
    fn tokenization_error() {
        assert_eq!(tokenize(&"λλx2"), Err(InvalidCharacter((4, 'x'))))
    }

    #[test]
    fn tokenization_success() {
        let quine = "λ 1 ( (λ 1 1) (λ λ λ λ λ 1 4 (3 (5 5) 2) ) ) 1";
        let tokens = tokenize(&quine);

        assert!(tokens.is_ok());
        assert_eq!(tokens.unwrap(), vec![Lambda, Number(1), Lparen, Lparen, Lambda, Number(1), Number(1), Rparen, Lparen, Lambda, Lambda, Lambda, Lambda,
            Lambda, Number(1), Number(4), Lparen, Number(3), Lparen, Number(5), Number(5), Rparen, Number(2), Rparen, Rparen, Rparen, Number(1)]);
    }

    #[test]
    fn succ_ast() {
        let tokens = tokenize(&"λλλ2(321)").unwrap();
        let ast = get_ast(&tokens);

        assert_eq!(ast,
            Sequence(vec![
                Abstraction,
                Abstraction,
                Abstraction,
                Variable(2),
                Sequence(vec![
                    Variable(3),
                    Variable(2),
                    Variable(1)
                ])
            ])
        );
    }

    #[test]
    fn parse_y() {
        let y = "λ(λ2(11))(λ2(11))";
        assert_eq!(&*format!("{}", parse(&y).unwrap()), y);
    }

    #[test]
    fn parse_quine() {
        let quine = "λ1((λ11)(λλλλλ14(3(55)2)))1";
        assert_eq!(&*format!("{}", parse(&quine).unwrap()), quine);
    }

    #[test]
    fn parse_blc() {
        let blc = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))(λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        assert_eq!(&*format!("{}", parse(&blc).unwrap()), blc);
    }
}
<|endoftext|>


<commit_before>/*
 Copyright 2021 Google LLC

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      https://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

use pyo3::prelude::*;
use pyo3::wrap_pyfunction;

use crate::query::QueryTree;
use crate::result::QueryResult;

#[pyclass]
struct QueryTreePy {
    qt: QueryTree,
}

#[pyclass]
struct QueryResultPy {
    qr: QueryResult,
}

#[pyfunction]
fn parse_query(q: &str) -> PyResult<QueryTreePy> {
    let tree = crate::parse(q, false);
    let mut c = tree.walk();

    let qt = crate::builder::build_querytree(q, &mut c, 0, false);
    Ok(QueryTreePy { qt })
}

#[pyfunction]
fn identifiers(p: &QueryTreePy) -> PyResult<Vec<String>> {
    Ok(p.qt.identifiers())
}

#[pyfunction]
fn matches(p: &QueryTreePy, source: &str) -> PyResult<Vec<QueryResultPy>> {
    let source_tree = crate::parse(source, false);

    let matches = p.qt.matches(source_tree.root_node(), source);

    let r = matches.into_iter().map(|qr| QueryResultPy { qr }).collect();

    Ok(r)
}

#[pyfunction]
fn display(p: &QueryResultPy, source: &str) -> PyResult<String> {
    let r = p.qr.display(source, 10, 10);
    println!("{}", r.as_bytes().len());
    Ok(r)
}

#[pymodule]
fn weggli(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<QueryTreePy>()?;
    m.add_function(wrap_pyfunction!(parse_query, m)?)?;
    m.add_function(wrap_pyfunction!(identifiers, m)?)?;
    m.add_function(wrap_pyfunction!(matches, m)?)?;
    m.add_function(wrap_pyfunction!(display, m)?)?;

    Ok(())
}
<commit_msg>Fix python API build error<commit_after>/*
 Copyright 2021 Google LLC

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      https://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

use pyo3::prelude::*;
use pyo3::wrap_pyfunction;

use crate::query::QueryTree;
use crate::result::QueryResult;

#[pyclass]
struct QueryTreePy {
    qt: QueryTree,
}

#[pyclass]
struct QueryResultPy {
    qr: QueryResult,
}

#[pyfunction]
fn parse_query(q: &str) -> PyResult<QueryTreePy> {
    let tree = crate::parse(q, false);
    let mut c = tree.walk();

    let qt = crate::builder::build_query_tree(q, &mut c, false);
    Ok(QueryTreePy { qt })
}

#[pyfunction]
fn identifiers(p: &QueryTreePy) -> PyResult<Vec<String>> {
    Ok(p.qt.identifiers())
}

#[pyfunction]
fn matches(p: &QueryTreePy, source: &str) -> PyResult<Vec<QueryResultPy>> {
    let source_tree = crate::parse(source, false);

    let matches = p.qt.matches(source_tree.root_node(), source);

    let r = matches.into_iter().map(|qr| QueryResultPy { qr }).collect();

    Ok(r)
}

#[pyfunction]
fn display(p: &QueryResultPy, source: &str) -> PyResult<String> {
    let r = p.qr.display(source, 10, 10);
    println!("{}", r.as_bytes().len());
    Ok(r)
}

#[pymodule]
fn weggli(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<QueryTreePy>()?;
    m.add_function(wrap_pyfunction!(parse_query, m)?)?;
    m.add_function(wrap_pyfunction!(identifiers, m)?)?;
    m.add_function(wrap_pyfunction!(matches, m)?)?;
    m.add_function(wrap_pyfunction!(display, m)?)?;

    Ok(())
}
<|endoftext|>