<commit_before>// Copyright 2016 Kyle Mayes
//
// 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
//
//     http://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.

//================================================
// Macros
//================================================

// link! _________________________________________

#[cfg(feature="runtime")]
macro_rules! link {
    (@IMPL: #[cfg($cfg:meta)] fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        #[cfg($cfg)]
        pub fn $name(library: &mut super::SharedLibrary) -> Result<(), String> {
            let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.map_err(|_| {
                format!("could not load `{}`", stringify!($name))
            });
            library.functions.$name = *try!(symbol);
            Ok(())
        }

        #[cfg(not($cfg))]
        pub fn $name(_: &mut super::SharedLibrary) -> Result<(), String> {
            Ok(())
        }
    );

    (@IMPL: fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        pub fn $name(library: &mut super::SharedLibrary) -> Result<(), String> {
            let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.map_err(|_| {
                format!("could not load `{}`", stringify!($name))
            });
            library.functions.$name = *try!(symbol);
            Ok(())
        }
    );

    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        use std::cell::{RefCell};
        use std::sync::{Mutex};

        #[doc(hidden)]
        pub struct Functions {
            $($(#[cfg($cfg)])* $name: extern fn($($pname: $pty), *) $(-> $ret)*), +
        }

        impl Default for Functions {
            fn default() -> Functions {
                unsafe { std::mem::zeroed() }
            }
        }

        #[doc(hidden)]
        pub struct SharedLibrary {
            library: libloading::Library,
            functions: Functions,
        }

        impl SharedLibrary {
            //- Constructors -----------------------------

            fn new(library: libloading::Library) -> SharedLibrary {
                SharedLibrary { library: library, functions: Functions::default() }
            }
        }

        lazy_static!(static ref LOADED: Mutex<bool> = Mutex::new(false););
        thread_local!(static LIBRARY: RefCell<Option<SharedLibrary>> = RefCell::new(None));

        $($(#[cfg($cfg)])* pub unsafe fn $name($($pname: $pty), *) $(-> $ret)* {
            let f = LIBRARY.with(|l| l.borrow().as_ref().map(|l| l.functions.$name));
            (f.expect("a `libclang` shared library was not loaded on this thread"))($($pname), *)
        })+

        /// Loads a `libclang` shared library for use in the current thread.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library has already been loaded
        /// * a `libclang` shared library could not be found
        /// * a `libclang` shared library symbol could not be loaded
        #[allow(dead_code)]
        pub fn load() -> Result<(), String> {
            #[path="../build.rs"]
            mod build;

            mod load {
                $(link!(@IMPL: $(#[cfg($cfg)])* fn $name($($pname: $pty), *) $(-> $ret)*);)+
            }

            let mut loaded = LOADED.lock().unwrap();
            if *loaded {
                return Err("a `libclang` shared library has already been loaded".into());
            }

            let file = try!(build::find_shared_library());
            let library = libloading::Library::new(&file).map_err(|_| {
                format!("'{}' could not be opened", file.display())
            });
            let mut library = SharedLibrary::new(try!(library));
            $(try!(load::$name(&mut library));)+
            LIBRARY.with(|l| *l.borrow_mut() = Some(library));
            *loaded = true;
            Ok(())
        }

        /// Unloads the `libclang` shared library in use in the current thread.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library is not in use in the current thread
        pub fn unload() -> Result<(), String> {
            let mut loaded = LOADED.lock().unwrap();
            LIBRARY.with(|l| {
                let mut library = l.borrow_mut();
                if library.is_some() {
                    *library = None;
                    *loaded = false;
               	    Ok(())
                } else {
                    Err("a `libclang` shared library is not in use in the current thread".into())
                }
            })
        }
    )
}

#[cfg(not(feature="runtime"))]
macro_rules! link {
    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        extern { $($(#[cfg($cfg)])* pub fn $name($($pname: $pty), *) $(-> $ret)*;)+ }
    )
}
<commit_msg>Improve the runtime linking API (#45)<commit_after>// Copyright 2016 Kyle Mayes
//
// 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
//
//     http://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.

//================================================
// Macros
//================================================

// link! _________________________________________

#[cfg(feature="runtime")]
macro_rules! link {
    (@LOAD: #[cfg($cfg:meta)] fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        #[cfg($cfg)]
        pub fn $name(library: &mut super::SharedLibrary) {
            let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
            library.functions.$name = symbol.map(|s| *s);
        }

        #[cfg(not($cfg))]
        pub fn $name(_: &mut super::SharedLibrary) {}
    );

    (@LOAD: fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        link!(@LOAD: #[cfg(feature="runtime")] fn $name($($pname: $pty), *) $(-> $ret)*);
    );

    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        use std::cell::{RefCell};
        use std::sync::{Arc};

        /// The set of functions loaded dynamically.
        #[derive(Debug)]
        pub struct Functions {
            $($(#[cfg($cfg)])* pub $name: Option<extern fn($($pname: $pty), *) $(-> $ret)*>,)+
        }

        impl Default for Functions {
            fn default() -> Functions {
                unsafe { std::mem::zeroed() }
            }
        }

        /// A dynamically loaded instance of the libclang library.
        #[derive(Debug)]
        pub struct SharedLibrary {
            library: libloading::Library,
            pub functions: Functions,
        }

        impl SharedLibrary {
            //- Constructors -----------------------------

            fn new(library: libloading::Library) -> SharedLibrary {
                SharedLibrary { library: library, functions: Functions::default() }
            }
        }

        thread_local!(static LIBRARY: RefCell<Option<Arc<SharedLibrary>>> = RefCell::new(None));

        /// Whether `libclang` is loaded on this thread.
        pub fn is_loaded() -> bool {
            LIBRARY.with(|l| l.borrow().is_some())
        }

        $(
            $(#[cfg($cfg)])* pub unsafe fn $name($($pname: $pty), *) $(-> $ret)* {
                let f = LIBRARY.with(|l| l.borrow().as_ref().map(|l| {
                    match l.functions.$name {
                        Some(f) => f,
                        None => panic!("Function not loaded: {}!", stringify!($name)),
                    }
                }));
                (f.expect("a `libclang` shared library was not loaded on this thread"))($($pname), *)
            }

            $(#[cfg($cfg)])* pub mod $name {
                use super::LIBRARY;
                pub fn is_loaded() -> bool {
                    LIBRARY.with(|l| l.borrow().as_ref().map_or(false, |l| {
                        l.functions.$name.is_some()
                    }))
                }
            }
        )+

        #[path="../build.rs"]
        mod build;

        mod load {
            $(link!(@LOAD: $(#[cfg($cfg)])* fn $name($($pname: $pty), *) $(-> $ret)*);)+
        }

        /// Loads a `libclang` shared library for use in the current thread.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library has already been loaded
        /// * a `libclang` shared library could not be found
        ///
        /// Note that this tries to find all the symbols. To check if a symbol
        /// has been found or not, you can use `clang_Foo::is_loaded()`.
        #[allow(dead_code)]
        pub fn load() -> Result<(), String> {
            let lib = Arc::new(try!(load_manually()));
            LIBRARY.with(|l| *l.borrow_mut() = Some(lib));
            Ok(())
        }

        /// Gets the library from tls. This, along with `set_library`, allows
        /// reusing the same library across threads.
        pub fn get_library() -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| {
                l.borrow_mut().clone()
            })
        }

        /// Sets the current library from tls, and returns the previous one.
        pub fn set_library(lib: Option<Arc<SharedLibrary>>) -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| {
                let mut l = l.borrow_mut();
                mem::replace(&mut *l, lib)
            })
        }

        /// Tries to load a libclang library manually, returning the
        /// corresponding `SharedLibrary`.
        ///
        /// Only returns an error when the library couldn't be found or opened,
        /// and the caller is responsible handle the functions manually.
        pub fn load_manually() -> Result<SharedLibrary, String> {
            let file = try!(build::find_shared_library());
            let library = libloading::Library::new(&file).map_err(|_| {
                format!("'{}' could not be opened", file.display())
            });
            let mut library = SharedLibrary::new(try!(library));
            $(load::$name(&mut library);)+

            Ok(library)
        }

        /// Unloads the `libclang` shared library in use in the current thread.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library is not in use in the current thread
        pub fn unload() -> Result<(), String> {
            let l = set_library(None);

            if l.is_some() {
                Ok(())
            } else {
                Err("a `libclang` shared library is not in use in the current thread".into())
            }
        }
    )
}

#[cfg(not(feature="runtime"))]
macro_rules! link {
    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        extern { $($(#[cfg($cfg)])* pub fn $name($($pname: $pty), *) $(-> $ret)*;)+ }
    )
}
<|endoftext|>


<commit_before><commit_msg>Improve error error message when calling Herbie<commit_after><|endoftext|>


<commit_before>//! Functions to perform numerical integration using Shapes
//!
//! # Definitions
//!
//! * `n_integ_point` -- number of integration (Gauss) points
//! * `|J|` -- the determinant of the Jacobian dx/dξ
//! * `||J||` -- the norm of the Jacobian vector for lines in multi-dimensions
//! * `ξ` -- ksi (or xi) -- coordinates in the reference space
//! * `ιᵖ := ξᵖ` -- (**iota**-p gets ksi-p (or xi-p)) --
//!    the coordinate of the integration point on the reference (natural) space
//! * `wᵖ` -- the weight of the p-th integration point
//! * Xᵀ -- Transposed matrix of coordinates
//! * N -- Shape functions
//! * L -- Derivatives of shape functions
//! * J -- Jacobian tensor
//! * J⁻¹ -- Inverse Jacobian matrix (only available if geo_ndim = space_ndim)
//! * G -- Gradients of shape functions (derivatives w.r.t real coordinates x)
//! * see also the subsection named **Expressions** below
//!
//! # Integration of scalar field over a geometric shape
//!
//! Function [scalar_field()]
//!
//! ```text
//!     ⌠   → →
//! I = │ s(x(ξ)) dΩ
//!     ⌡
//!     Ωₑ
//! ```
//!
//! # Vector results: Integration of some combinations involving N and G resulting in vectors
//!
//! ## VEC 01: Interpolation functions times scalar field [vec_01_ns()]:
//!
//! ```text
//!      ⌠    → →     →
//! aᵐ = │ Nᵐ(x(ξ)) s(x) dΩ
//!      ⌡
//!      Ωₑ
//! ```
//!
//! ## VEC 02: Interpolation functions times vector field [vec_02_nv()]:
//!
//! ```text
//! →    ⌠    → →   → →
//! bᵐ = │ Nᵐ(x(ξ)) v(x) dΩ
//!      ⌡
//!      Ωₑ
//! ```
//!
//! ## VEC 03: Vector dot gradient [vec_03_vg()]:
//!
//! ```text
//!      ⌠ → →    →  → →
//! cᵐ = │ w(x) · Gᵐ(x(ξ)) dΩ
//!      ⌡
//!      Ωₑ
//! ```
//!
//! ## VEC 04: Tensor dot gradient [vec_04_tg()]:
//!
//! ```text
//! →    ⌠   →    →  → →
//! dᵐ = │ σ(x) · Gᵐ(x(ξ)) dΩ
//!      ⌡ ▔
//!      Ωₑ
//! ```
//!
//! # Matrix results: Integration of some combinations involving N, tensors, and G, resulting in matrices
//!
//! ![cases](https://github.com/cpmech/gemlab/raw/main/data/figures/integ-matrix-cases.png)
//!
//! ## MAT 01: Shape(N) times scalar(S) times shape(N) (e.g., diffusion matrix)
//!
//! [mat_01_nsn()]
//!
//! ```text
//!       ⌠
//! Kᵐⁿ = │ Nᵐ s Nⁿ dΩ
//!       ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 02: Gradient(G) dot vector(V) times shape(N) (e.g., compressibility matrix)
//!
//! [mat_02_gvn()]
//!
//! ```text
//!       ⌠ →    →
//! Kᵐⁿ = │ Gᵐ ⋅ v Nⁿ dΩ
//!       ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 03: Gradient(G) dot tensor(T) dot gradient(G) (e.g., conductivity matrix)
//!
//! [mat_03_gtg()]
//!
//! ```text
//!       ⌠ →        →
//! Kᵐⁿ = │ Gᵐ ⋅ T ⋅ Gⁿ dΩ
//!       ⌡      ▔
//!       Ωₑ
//! ```
//!
//! ## MAT 04: shape(Nb) time scalar(S) time gradient(G) (e.g., coupling matrix)
//!
//! [mat_04_nsg()]
//!
//! ```text
//! →     ⌠       →
//! Kᵐⁿ = │ Nbᵐ s Gⁿ dΩ
//!       ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 05: Gradient(Gb) time tensor(T) time shape(N) (e.g., coupling matrix)
//!
//! [mat_05_gtn()]
//!
//! ```text
//! →     ⌠ →
//! Kᵐⁿ = │ Gbᵐ ⋅ T Nⁿ dΩ
//!       ⌡       ▔
//!       Ωₑ
//! ```
//!
//! ## MAT 06: Shape(N) time vector(V) time shape(Nb) (e.g., coupling matrix)
//!
//! [mat_06_nvn()]
//!
//! ```text
//! →     ⌠    →
//! Kᵐⁿ = │ Nᵐ v Nbⁿ dΩ
//!       ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 07: Gradient(G) time scalar(S) time shape(Nb) (e.g., coupling matrix)
//!
//! [mat_07_gsn()]
//!
//! ```text
//! →     ⌠ →
//! Kᵐⁿ = │ Gᵐ s Nbⁿ dΩ
//!       ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 08: Shape(N) times tensor(T) times shape(N) (e.g., mass matrix)
//!
//! [mat_08_ntn()]
//!
//! ```text
//!       ⌠
//! Kᵐⁿ = │ Nᵐ T Nⁿ dΩ
//! ▔     ⌡    ▔
//!       Ωₑ
//! ```
//!
//! ## MAT 09: Shape(N) times vector(V) dot gradient(G) (e.g., variable density matrix)
//!
//! [mat_09_nvg()]
//!
//! ```text
//!       ⌠    →   →
//! Kᵐⁿ = │ Nᵐ v ⊗ Gⁿ dΩ
//! ▔     ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 10: Gradient(G) dot 4th-tensor(D) dot gradient(G) (e.g., stiffness matrix)
//!
//! [mat_10_gdg()]
//!
//! ```text
//!       ⌠                       →    →
//! Kᵐⁿ = │ Σ Σ Σ Σ Gᵐₖ Dᵢₖⱼₗ Gⁿₗ eᵢ ⊗ eⱼ dΩ
//! ▔     ⌡ i j k l
//!       Ωₑ
//! ```
//!
//! # Expressions
//!
//! See also [crate::shapes]
//!
//! ## Xᵀ: Transposed matrix of coordinates
//!
//! ```text
//!      ┌                              ┐  superscript = node
//!      | x⁰₀  x¹₀  x²₀  x³₀       xᴹ₀ |  subscript = space dimension
//! Xᵀ = | x⁰₁  x¹₁  x²₁  x³₁  ...  xᴹ₁ |
//!      | x⁰₂  x¹₂  x²₂  x³₂       xᴹ₂ |
//!      └                              ┘_(space_ndim,nnode)
//! where `M = nnode - 1`
//! ```
//!
//! ## N: Shape functions
//!
//! Shape function of node m at ξ (ksi; i.e., xi):
//!
//! ```text
//! Nᵐ(ξ)
//! matrix notation: N is an (nnode) vector
//! ```
//!
//! ## L: Derivatives of shape functions
//!
//! Derivatives of shape functions with respect to the natural coordinates:
//!
//! ```text
//!             →
//! →  →    dNᵐ(ξ)
//! Lᵐ(ξ) = ——————
//!            →
//!           dξ
//! matrix notation: L is an (nnode,geo_ndim) matrix
//! ```
//!
//! ## Isoparametric formula
//!
//! ```text
//! → →         →  →
//! x(ξ) = Σ Nᵐ(ξ) xᵐ
//!        m
//! matrix notation: x = Xᵀ ⋅ N
//! ```
//!
//! ## J: Jacobian tensor (SOLID case with geo_ndim = space_ndim = 2 or 3)
//!
//! ```text
//!         →
//!   →    dx     →    →
//! J(ξ) = —— = Σ xᵐ ⊗ Lᵐ
//!         →   m
//!        dξ
//! matrix notation: J = Xᵀ · L
//! J is a (space_ndim,geo_ndim) matrix
//! ```
//!
//! ## J: Jacobian vector (CABLE case with geo_ndim = 1 and space_ndim = 2 or 3)
//!
//! ```text
//!                           →
//! →    →      →    →  →    dx
//! J := Jcable(ξ) = g₁(ξ) = ——
//!                          dξ
//! matrix notation: J = Jcable = Xᵀ · L
//! J is a (space_ndim,1) matrix; i.e., a vector
//! ```
//!
//! ## J: Jacobian matrix (SHELL case with geo_ndim = 2 and space_ndim = 3)
//!
//! ```text
//!                 dx
//! J(ξ) = Jshell = ——
//!                 dξ
//! matrix notation: J = Jshell = Xᵀ · L
//! J is a (3,2) matrix
//! ```
//!
//! ## G: Gradients of shape functions (derivatives w.r.t real coordinates x) (only for SOLID case)
//!
//! ```text
//!             →
//! →  →    dNᵐ(ξ)
//! Gᵐ(ξ) = ——————
//!            →
//!           dx
//! matrix notation: G = L · J⁻¹
//! G is an (nnode,space_ndim) matrix
//! ```

mod analytical_qua4;
mod analytical_qua8;
mod analytical_tet4;
mod analytical_tri3;
mod integ_points;
mod mat_01_nsn;
mod mat_02_gvn;
mod mat_03_gtg;
mod mat_04_nsg;
mod mat_05_gtn;
mod mat_06_nvn;
mod mat_07_gsn;
mod mat_08_ntn;
mod mat_09_nvg;
mod mat_10_gdg;
mod point_coords;
mod scalar_field;
mod testing;
mod vec_01_ns;
mod vec_02_nv;
mod vec_03_vg;
mod vec_04_tg;
mod vector_cases_boundary;
pub use crate::integ::analytical_qua4::*;
pub use crate::integ::analytical_qua8::*;
pub use crate::integ::analytical_tet4::*;
pub use crate::integ::analytical_tri3::*;
pub use crate::integ::integ_points::*;
pub use crate::integ::mat_01_nsn::*;
pub use crate::integ::mat_02_gvn::*;
pub use crate::integ::mat_03_gtg::*;
pub use crate::integ::mat_04_nsg::*;
pub use crate::integ::mat_05_gtn::*;
pub use crate::integ::mat_06_nvn::*;
pub use crate::integ::mat_07_gsn::*;
pub use crate::integ::mat_08_ntn::*;
pub use crate::integ::mat_09_nvg::*;
pub use crate::integ::mat_10_gdg::*;
pub use crate::integ::point_coords::*;
pub use crate::integ::scalar_field::*;
pub use crate::integ::vec_01_ns::*;
pub use crate::integ::vec_02_nv::*;
pub use crate::integ::vec_03_vg::*;
pub use crate::integ::vec_04_tg::*;
pub use crate::integ::vector_cases_boundary::*;
<commit_msg>Improve doc<commit_after>//! Functions to perform numerical integration using Shapes
//!
//! # Definitions
//!
//! * `n_integ_point` -- number of integration (Gauss) points
//! * `|J|` -- the determinant of the Jacobian dx/dξ
//! * `||J||` -- the norm of the Jacobian vector for lines in multi-dimensions
//! * `ξ` -- ksi (or xi) -- coordinates in the reference space
//! * `ιᵖ := ξᵖ` -- (**iota**-p gets ksi-p (or xi-p)) --
//!    the coordinate of the integration point on the reference (natural) space
//! * `wᵖ` -- the weight of the p-th integration point
//! * Xᵀ -- Transposed matrix of coordinates
//! * N -- Shape functions
//! * L -- Derivatives of shape functions
//! * J -- Jacobian tensor
//! * J⁻¹ -- Inverse Jacobian matrix (only available if geo_ndim = space_ndim)
//! * G -- Gradients of shape functions (derivatives w.r.t real coordinates x)
//! * see also the subsection named **Expressions** below
//!
//! # Integration of scalar field over a geometric shape
//!
//! Function [scalar_field()]
//!
//! ```text
//!     ⌠   → →
//! I = │ s(x(ξ)) dΩ
//!     ⌡
//!     Ωₑ
//! ```
//!
//! # Vector results: Integration of some combinations involving N and G resulting in vectors
//!
//! ## VEC 01: Interpolation functions times scalar field
//!
//! Function [vec_01_ns()]
//!
//! ```text
//!      ⌠    → →     →
//! aᵐ = │ Nᵐ(x(ξ)) s(x) dΩ
//!      ⌡
//!      Ωₑ
//! ```
//!
//! ## VEC 02: Interpolation functions times vector field
//!
//! Function [vec_02_nv()]
//!
//! ```text
//! →    ⌠    → →   → →
//! bᵐ = │ Nᵐ(x(ξ)) v(x) dΩ
//!      ⌡
//!      Ωₑ
//! ```
//!
//! ## VEC 03: Vector dot gradient
//!
//! Function [vec_03_vg()]
//!
//! ```text
//!      ⌠ → →    →  → →
//! cᵐ = │ w(x) · Gᵐ(x(ξ)) dΩ
//!      ⌡
//!      Ωₑ
//! ```
//!
//! ## VEC 04: Tensor dot gradient
//!
//! Function [vec_04_tg()]
//!
//! ```text
//! →    ⌠   →    →  → →
//! dᵐ = │ σ(x) · Gᵐ(x(ξ)) dΩ
//!      ⌡ ▔
//!      Ωₑ
//! ```
//!
//! # Matrix results: Integration of some combinations involving N, tensors, and G, resulting in matrices
//!
//! ![cases](https://github.com/cpmech/gemlab/raw/main/data/figures/integ-matrix-cases.png)
//!
//! ## MAT 01: Shape(N) times scalar(S) times shape(N) (e.g., diffusion matrix)
//!
//! Function [mat_01_nsn()]
//!
//! ```text
//!       ⌠
//! Kᵐⁿ = │ Nᵐ s Nⁿ dΩ
//!       ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 02: Gradient(G) dot vector(V) times shape(N) (e.g., compressibility matrix)
//!
//! Function [mat_02_gvn()]
//!
//! ```text
//!       ⌠ →    →
//! Kᵐⁿ = │ Gᵐ ⋅ v Nⁿ dΩ
//!       ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 03: Gradient(G) dot tensor(T) dot gradient(G) (e.g., conductivity matrix)
//!
//! Function [mat_03_gtg()]
//!
//! ```text
//!       ⌠ →        →
//! Kᵐⁿ = │ Gᵐ ⋅ T ⋅ Gⁿ dΩ
//!       ⌡      ▔
//!       Ωₑ
//! ```
//!
//! ## MAT 04: shape(Nb) time scalar(S) time gradient(G) (e.g., coupling matrix)
//!
//! Function [mat_04_nsg()]
//!
//! ```text
//! →     ⌠       →
//! Kᵐⁿ = │ Nbᵐ s Gⁿ dΩ
//!       ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 05: Gradient(Gb) time tensor(T) time shape(N) (e.g., coupling matrix)
//!
//! Function [mat_05_gtn()]
//!
//! ```text
//! →     ⌠ →
//! Kᵐⁿ = │ Gbᵐ ⋅ T Nⁿ dΩ
//!       ⌡       ▔
//!       Ωₑ
//! ```
//!
//! ## MAT 06: Shape(N) time vector(V) time shape(Nb) (e.g., coupling matrix)
//!
//! Function [mat_06_nvn()]
//!
//! ```text
//! →     ⌠    →
//! Kᵐⁿ = │ Nᵐ v Nbⁿ dΩ
//!       ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 07: Gradient(G) time scalar(S) time shape(Nb) (e.g., coupling matrix)
//!
//! Function [mat_07_gsn()]
//!
//! ```text
//! →     ⌠ →
//! Kᵐⁿ = │ Gᵐ s Nbⁿ dΩ
//!       ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 08: Shape(N) times tensor(T) times shape(N) (e.g., mass matrix)
//!
//! Function [mat_08_ntn()]
//!
//! ```text
//!       ⌠
//! Kᵐⁿ = │ Nᵐ T Nⁿ dΩ
//! ▔     ⌡    ▔
//!       Ωₑ
//! ```
//!
//! ## MAT 09: Shape(N) times vector(V) dot gradient(G) (e.g., variable density matrix)
//!
//! Function [mat_09_nvg()]
//!
//! ```text
//!       ⌠    →   →
//! Kᵐⁿ = │ Nᵐ v ⊗ Gⁿ dΩ
//! ▔     ⌡
//!       Ωₑ
//! ```
//!
//! ## MAT 10: Gradient(G) dot 4th-tensor(D) dot gradient(G) (e.g., stiffness matrix)
//!
//! Function [mat_10_gdg()]
//!
//! ```text
//!       ⌠                       →    →
//! Kᵐⁿ = │ Σ Σ Σ Σ Gᵐₖ Dᵢₖⱼₗ Gⁿₗ eᵢ ⊗ eⱼ dΩ
//! ▔     ⌡ i j k l
//!       Ωₑ
//! ```
//!
//! # Expressions
//!
//! See also [crate::shapes]
//!
//! ## Xᵀ: Transposed matrix of coordinates
//!
//! ```text
//!      ┌                              ┐  superscript = node
//!      | x⁰₀  x¹₀  x²₀  x³₀       xᴹ₀ |  subscript = space dimension
//! Xᵀ = | x⁰₁  x¹₁  x²₁  x³₁  ...  xᴹ₁ |
//!      | x⁰₂  x¹₂  x²₂  x³₂       xᴹ₂ |
//!      └                              ┘_(space_ndim,nnode)
//! where `M = nnode - 1`
//! ```
//!
//! ## N: Shape functions
//!
//! Shape function of node m at ξ (ksi; i.e., xi):
//!
//! ```text
//! Nᵐ(ξ)
//! matrix notation: N is an (nnode) vector
//! ```
//!
//! ## L: Derivatives of shape functions
//!
//! Derivatives of shape functions with respect to the natural coordinates:
//!
//! ```text
//!             →
//! →  →    dNᵐ(ξ)
//! Lᵐ(ξ) = ——————
//!            →
//!           dξ
//! matrix notation: L is an (nnode,geo_ndim) matrix
//! ```
//!
//! ## Isoparametric formula
//!
//! ```text
//! → →         →  →
//! x(ξ) = Σ Nᵐ(ξ) xᵐ
//!        m
//! matrix notation: x = Xᵀ ⋅ N
//! ```
//!
//! ## J: Jacobian tensor (SOLID case with geo_ndim = space_ndim = 2 or 3)
//!
//! ```text
//!         →
//!   →    dx     →    →
//! J(ξ) = —— = Σ xᵐ ⊗ Lᵐ
//!         →   m
//!        dξ
//! matrix notation: J = Xᵀ · L
//! J is a (space_ndim,geo_ndim) matrix
//! ```
//!
//! ## J: Jacobian vector (CABLE case with geo_ndim = 1 and space_ndim = 2 or 3)
//!
//! ```text
//!                           →
//! →    →      →    →  →    dx
//! J := Jcable(ξ) = g₁(ξ) = ——
//!                          dξ
//! matrix notation: J = Jcable = Xᵀ · L
//! J is a (space_ndim,1) matrix; i.e., a vector
//! ```
//!
//! ## J: Jacobian matrix (SHELL case with geo_ndim = 2 and space_ndim = 3)
//!
//! ```text
//!                 dx
//! J(ξ) = Jshell = ——
//!                 dξ
//! matrix notation: J = Jshell = Xᵀ · L
//! J is a (3,2) matrix
//! ```
//!
//! ## G: Gradients of shape functions (derivatives w.r.t real coordinates x) (only for SOLID case)
//!
//! ```text
//!             →
//! →  →    dNᵐ(ξ)
//! Gᵐ(ξ) = ——————
//!            →
//!           dx
//! matrix notation: G = L · J⁻¹
//! G is an (nnode,space_ndim) matrix
//! ```

mod analytical_qua4;
mod analytical_qua8;
mod analytical_tet4;
mod analytical_tri3;
mod integ_points;
mod mat_01_nsn;
mod mat_02_gvn;
mod mat_03_gtg;
mod mat_04_nsg;
mod mat_05_gtn;
mod mat_06_nvn;
mod mat_07_gsn;
mod mat_08_ntn;
mod mat_09_nvg;
mod mat_10_gdg;
mod point_coords;
mod scalar_field;
mod testing;
mod vec_01_ns;
mod vec_02_nv;
mod vec_03_vg;
mod vec_04_tg;
mod vector_cases_boundary;
pub use crate::integ::analytical_qua4::*;
pub use crate::integ::analytical_qua8::*;
pub use crate::integ::analytical_tet4::*;
pub use crate::integ::analytical_tri3::*;
pub use crate::integ::integ_points::*;
pub use crate::integ::mat_01_nsn::*;
pub use crate::integ::mat_02_gvn::*;
pub use crate::integ::mat_03_gtg::*;
pub use crate::integ::mat_04_nsg::*;
pub use crate::integ::mat_05_gtn::*;
pub use crate::integ::mat_06_nvn::*;
pub use crate::integ::mat_07_gsn::*;
pub use crate::integ::mat_08_ntn::*;
pub use crate::integ::mat_09_nvg::*;
pub use crate::integ::mat_10_gdg::*;
pub use crate::integ::point_coords::*;
pub use crate::integ::scalar_field::*;
pub use crate::integ::vec_01_ns::*;
pub use crate::integ::vec_02_nv::*;
pub use crate::integ::vec_03_vg::*;
pub use crate::integ::vec_04_tg::*;
pub use crate::integ::vector_cases_boundary::*;
<|endoftext|>


<commit_before>//! Utilities for lifting functions into signals.

use crate::signal::Signal;
use crate::types::{SharedImpl, SharedSignal, Storage};

/// Maps a function over the value of signals.
///
/// This converts a function `Fn(A, B, ...) -> R` and the signals `Signal<A>, Signal<B>, ...`
/// into a `Signal<R>` that computes it's value by sampling the input signals and then
/// calling the supplied function.
#[macro_export]
macro_rules! signal_lift
{
    ($($sig:expr),+ => $f:expr) => ( signal_lift!($f, $($sig),+) );

    ($f:expr) => ($crate::Signal::from_fn($f));

    ($f:expr, $sig1:expr) => ( $crate::Signal::map(&$sig1, $f) );

    ($f:expr, $sig1:expr, $sig2:expr) =>
        ($crate::lift::lift2($f, $sig1, $sig2));

    ($f:expr, $sig1:expr, $sig2:expr, $sig3:expr) =>
        ($crate::lift::lift3($f, $sig1, $sig2, $sig3));

    ($f:expr, $sig1:expr, $sig2:expr, $sig3:expr, $sig4:expr) =>
        ($crate::lift::lift4($f, $sig1, $sig2, $sig3, $sig4));

    ($f:expr, $sig1:expr, $sig2:expr, $sig3:expr, $sig4:expr, $sig5:expr) =>
        ($crate::lift::lift5($f, $sig1, $sig2, $sig3, $sig4, $sig5));

    ($f:expr, $sig1:expr, $sig2:expr, $sig3:expr, $sig4:expr, $sig5:expr, $sig6:expr) =>
        ($crate::lift::lift6($f, $sig1, $sig2, $sig3, $sig4, $sig5, $sig6));
}

macro_rules! lift_impl
{
    ($fname:ident ( $($vname:ident : $tname:ident),+ ) $($idx:tt)+) => (
        impl<T, $($tname,)+ F> SharedSignal<T> for SharedImpl<T, ($(Signal<$tname>),+), F>
            where F: Fn($($tname),+) -> T + 'static,
            $($tname: Clone + 'static),+
        {
            fn update(&self)
            {
                if !self.storage.must_update() && ($(self.source.$idx.has_changed())||+)
                {
                    self.storage.inc_root();
                }
            }

            fn get_storage(&self) -> &Storage<T>
            {
                &self.storage
            }

            fn sample(&self) -> &Storage<T>
            {
                if self.storage.must_update()
                {
                    let val = (self.f)($(self.source.$idx.sample()),+);
                    self.storage.set_local(val);
                }
                &self.storage
            }
        }

        /// Lifts a function into a signal.
        pub fn $fname<T, F, $($tname),+>(f: F, $($vname: Signal<$tname>),+) -> Signal<T>
            where F: Fn($($tname),+) -> T + Send + Sync + 'static,
            T: Send + 'static, $($tname: Clone + Send + Sync + 'static),+
        {
            Signal::shared(SharedImpl{
                storage: Default::default(),
                source: ($($vname),+),
                f: f,
            }.wrap())
        }
    );
}

lift_impl!(lift2(s1: S1, s2: S2)                                 0 1);
lift_impl!(lift3(s1: S1, s2: S2, s3: S3)                         0 1 2);
lift_impl!(lift4(s1: S1, s2: S2, s3: S3, s4: S4)                 0 1 2 3);
lift_impl!(lift5(s1: S1, s2: S2, s3: S3, s4: S4, s5: S5)         0 1 2 3 4);
lift_impl!(lift6(s1: S1, s2: S2, s3: S3, s4: S4, s5: S5, s6: S6) 0 1 2 3 4 5);
<commit_msg>rustfmt seems to ignore this file<commit_after>//! Utilities for lifting functions into signals.

use crate::signal::Signal;
use crate::types::{SharedImpl, SharedSignal, Storage};

/// Maps a function over the value of signals.
///
/// This converts a function `Fn(A, B, ...) -> R` and the signals `Signal<A>, Signal<B>, ...`
/// into a `Signal<R>` that computes it's value by sampling the input signals and then
/// calling the supplied function.
#[macro_export]
macro_rules! signal_lift {
    ($($sig:expr),+ => $f:expr) => {
        signal_lift!($f, $($sig),+)
    };

    ($f:expr) => {
        $crate::Signal::from_fn($f)
    };

    ($f:expr, $sig1:expr) => {
        $crate::Signal::map(&$sig1, $f)
    };

    ($f:expr, $sig1:expr, $sig2:expr) => {
        $crate::lift::lift2($f, $sig1, $sig2)
    };

    ($f:expr, $sig1:expr, $sig2:expr, $sig3:expr) => {
        $crate::lift::lift3($f, $sig1, $sig2, $sig3)
    };

    ($f:expr, $sig1:expr, $sig2:expr, $sig3:expr, $sig4:expr) => {
        $crate::lift::lift4($f, $sig1, $sig2, $sig3, $sig4)
    };

    ($f:expr, $sig1:expr, $sig2:expr, $sig3:expr, $sig4:expr, $sig5:expr) => {
        $crate::lift::lift5($f, $sig1, $sig2, $sig3, $sig4, $sig5)
    };

    ($f:expr, $sig1:expr, $sig2:expr, $sig3:expr, $sig4:expr, $sig5:expr, $sig6:expr) => {
        $crate::lift::lift6($f, $sig1, $sig2, $sig3, $sig4, $sig5, $sig6)
    };
}

macro_rules! lift_impl {
    ($fname:ident ( $($vname:ident : $tname:ident),+ ) $($idx:tt)+) => (
        impl<T, $($tname,)+ F> SharedSignal<T> for SharedImpl<T, ($(Signal<$tname>),+), F>
        where
            F: Fn($($tname),+) -> T + 'static,
            $($tname: Clone + 'static),+
        {
            fn update(&self) {
                if !self.storage.must_update() && ($(self.source.$idx.has_changed())||+) {
                    self.storage.inc_root();
                }
            }

            fn get_storage(&self) -> &Storage<T> {
                &self.storage
            }

            fn sample(&self) -> &Storage<T> {
                if self.storage.must_update() {
                    let val = (self.f)($(self.source.$idx.sample()),+);
                    self.storage.set_local(val);
                }
                &self.storage
            }
        }

        /// Lifts a function into a signal.
        pub fn $fname<T, F, $($tname),+>(f: F, $($vname: Signal<$tname>),+) -> Signal<T>
        where
            F: Fn($($tname),+) -> T + Send + Sync + 'static,
            T: Send + 'static, $($tname: Clone + Send + Sync + 'static),+
        {
            Signal::shared(SharedImpl{
                storage: Default::default(),
                source: ($($vname),+),
                f: f,
            }.wrap())
        }
    );
}

lift_impl!(lift2(s1: S1, s2: S2)                                 0 1);
lift_impl!(lift3(s1: S1, s2: S2, s3: S3)                         0 1 2);
lift_impl!(lift4(s1: S1, s2: S2, s3: S3, s4: S4)                 0 1 2 3);
lift_impl!(lift5(s1: S1, s2: S2, s3: S3, s4: S4, s5: S5)         0 1 2 3 4);
lift_impl!(lift6(s1: S1, s2: S2, s3: S3, s4: S4, s5: S5, s6: S6) 0 1 2 3 4 5);
<|endoftext|>


<commit_before>extern crate iron;
extern crate staticfile;

use iron::Iron;

use staticfile::Static;

use std::env;

fn main() {
    let port = env::args().nth(1).unwrap_or("80".to_string());
    let addr = format!("localhost:{}", port);

    println!("Listening on port {}", port);
    Iron::new(Static::new(".")).http(&*addr).unwrap();
}
<commit_msg>Change default port to 8080<commit_after>extern crate iron;
extern crate staticfile;

use iron::Iron;

use staticfile::Static;

use std::env;

fn main() {
    let default_port = "8080".to_string();
    let port = env::args().nth(1).unwrap_or(default_port);
    let addr = format!("localhost:{}", port);

    println!("Listening on port {}", port);
    Iron::new(Static::new(".")).http(&*addr).unwrap();
}
<|endoftext|>


<commit_before>/* main.rs - Main source file for mymdb
 * (c) 2016 Zack Hixon under MIT license.
 * See LICENSE.txt for more details. */

extern crate rusqlite;
extern crate time;
extern crate rand;
extern crate regex;

use time::Timespec;
use rusqlite::Connection;
use std::io;
use std::path::Path;
use std::env;
use regex::Regex;

// movie struct
#[derive(Debug)]
struct Movie {
    id: i32,
    name: String,
    time_created: Timespec,
    opinion: String,
    rating: i32
}

// movie impl: possibly add search functions
impl Movie {
    // create new movie
    fn new(id: i32, name: String, time_created: Timespec, opinion: String, rating: i32) -> Movie {
        Movie {
            id: id,
            name: name,
            time_created: time_created,
            opinion: opinion,
            rating: rating,
        }
    }
}

fn main() {
    // open connection to .movies.db in current directory: possibly change to
    // ~/.movies.db for simplicity
    let conn = Connection::open(Path::new(".movies.db")).unwrap();

    // create a table in movies database that maps to a movie struct
    conn.execute("CREATE TABLE IF NOT EXISTS movies (
        id INTEGER UNIQUE NOT NULL,
        name TEXT NOT NULL,
        time_created TEXT NOT NULL,
        opinion TEXT NOT NULL,
        rating INTEGER)", &[]).unwrap();

    // get args
    let args: Vec<String> = env::args().collect();
    let length = args.len();

    if length == 1 {
        println!("for help, use \"mymdb help\"");
    }
    else if length == 2 {
        for i in &args {
            if i == "help" { print_help(); }
            else if i == "add" {
                // prompt user for new movie
                let new_movie = new_movie();

                // insert new movie into database
                conn.execute("INSERT INTO movies VALUES ($1, $2, $3, $4, $5)",
                    &[&new_movie.id, &new_movie.name, &new_movie.time_created,
                    &new_movie.opinion, &new_movie.rating]).unwrap();

                println!("Your movie has been added. ID# {}", &new_movie.id);
            }
            else if i == "remove" {
                // get movie id
                println!("ID of movie to be removed: (number)");
                let id: i32 = number_input();

                // find movie by id: TODO: make more efficient
                let mut stmt = conn.prepare("SELECT * FROM movies WHERE id=$1").unwrap();
                let movie_iter = stmt.query_map(&[&id,], |row| {
                    Movie {
                        id: row.get(0),
                        name: row.get(1),
                        time_created: row.get(2),
                        opinion: row.get(3),
                        rating: row.get(4)
                    }
                }).unwrap();

                // get last movie with id because shitty API or I don't know how to use it
                // probably the latter honestly
                let mut q = Movie::new(0, String::new(), time::get_time(), String::new(), 0);
                for i in movie_iter {
                    q = i.unwrap();
                }

                if q.name.is_empty() {
                    println!("Cannot find movie with ID of {}", id);
                    return
                }

                println!("Are you sure you want to remove {}?", q.name.trim());

                let resp = get_input().to_lowercase().trim();

                // remove from database
                if resp == String::from("yes") {
                    conn.execute("DELETE FROM movies WHERE id=$1", &[&id,]).unwrap();
                    println!("{} has been removed from the database.", q.name.trim());
                } else if resp == String::from("y") {
                    conn.execute("DELETE FROM movies WHERE id=$1", &[&id,]).unwrap();
                    println!("{} has been removed from the database.", q.name.trim());
                } else {
                    println!("Movie will not be removed.");
                }
            }
            // show movies in database
            else if i == "show" {
                // select all movies, conver to iterator
                let mut stmt = conn.prepare("SELECT * FROM movies").unwrap();
                let movie_iter = stmt.query_map(&[], |row| {
                    Movie {
                        id: row.get(0),
                        name: row.get(1),
                        time_created: row.get(2),
                        opinion: row.get(3),
                        rating: row.get(4)
                    }
                }).unwrap();

                // convert list of movies to vector
                let mut count = 0;
                let mut movies: Vec<Movie> = vec![];
                for movie in movie_iter {
                    movies.push(movie.unwrap());
                    count = count + 1;
                }

                println!("Found {} movie(s)", count);

                // print movies
                for z in movies {
                    println!("Name:    {}\nOpinion: {}\nRating:  {}\nID:      {}\nTime:    {}\n",
                             z.name.trim(),
                             z.opinion.trim(),
                             z.rating,
                             z.id,
                             time(z.time_created));
                }
            }
            else {
                // TODO: make this not ridiculous
                let re = Regex::new(r"mymdb").unwrap();
                if !re.is_match(&i) {
                    println!("Not an option: {}", i);
                } else {
                    continue;
                }
            }
        }
    }
    else {
        // TODO: get argparse or something like that
        let mut arg3: &String = &String::from("");
        let mut arg4: &String = &String::from("");
        let mut arg5: i32 = 0;
        if length >= 3 {
            arg3 = &args[2];
        }
        if length == 5 {
            arg4 = &args[3];
            arg5 = args[4].trim().parse().expect("3rd arg must be a number");
        }
        for i in &args {
            if i == "-a" {
                // add movie
                let id = rand::random::<i32>().abs() / 1000;
                conn.execute("INSERT INTO movies VALUES ($1, $2, $3, $4, $5)",
                    &[&id, arg3, &(time::get_time()),
                    arg4, &arg5]).unwrap();
                println!("Your movie has been added. ID# {}", id);
            }
            else if i == "-r" {
                // remove movie
                let id: i32 = arg3.trim().parse().expect("arg must be a number");

                let mut stmt = conn.prepare("SELECT * FROM movies WHERE id=$1").unwrap();
                let movie_iter = stmt.query_map(&[&id,], |row| {
                    Movie {
                        id: row.get(0),
                        name: row.get(1),
                        time_created: row.get(2),
                        opinion: row.get(3),
                        rating: row.get(4)
                    }
                }).unwrap();

                let mut q = Movie::new(0, String::new(), time::get_time(), String::new(), 0);
                for i in movie_iter {
                    q = i.unwrap();
                }

                if q.name.is_empty() {
                    println!("Cannot find movie with ID of {}", id);
                    return
                }

                conn.execute("DELETE FROM movies WHERE id=$1", &[&id,]).unwrap();
                println!("{} has been removed from the database.", q.name.trim());
            }
        }
    }
}

// create new movie struct using input
fn new_movie() -> Movie {
    println!("Name of movie:");
    let name: String = get_input();

    println!("Thoughts:");
    let opinion: String = get_input();

    println!("Rating: (number)");
    let rating: i32 = number_input();

    // TODO: non-retarded ID numbers, like autoincrement
    Movie::new(rand::random::<i32>().abs() / 1000, name,
        time::get_time(), opinion, rating)
}

// return time as string
fn time(t: Timespec) -> String {
    let real_time = time::at(t);
    String::from(format!("{}-{}-{} {}:{}", (real_time.tm_year + 1900), real_time.tm_mon,
                 real_time.tm_mday, real_time.tm_hour, real_time.tm_min))
}

fn print_help() {
    println!("mymdb - personal movie database");
    println!("usage:");
    println!("mymdb <command> [options]");
    println!("commands:");
    println!("\tshow - lists movies in database");
    println!("\tadd - adds movie to database (interactively)");
    println!("\tremove - removes movie from database (interactively)");
    println!("options:");
    println!("\t-r <movie ID> - removes movie from database");
    println!("\t-a <movie name> <opinion> <rating>");
    println!("mymdb creates a movie database that the program is run in.");
    println!("It looks for a sqlite file called .movies.db, and if it does");
    println!("not exist, it is created automatically.");
}

// get input as number
fn number_input() -> i32 {
    let n = match get_input().trim().parse::<i32>() {
        Ok(n) => n,
        Err(e) => { println!("Not a number"); 0 },
    };

    n
}

// get input as string
fn get_input() -> String {
    let mut i = String::new();
    let handle = io::stdin();

    match handle.read_line(&mut i) {
        Ok(n) => {},
        Err(e) => println!("What's your problem?")
    }

    i
}
<commit_msg>huh, that was actually needed<commit_after>/* main.rs - Main source file for mymdb
 * (c) 2016 Zack Hixon under MIT license.
 * See LICENSE.txt for more details. */

extern crate rusqlite;
extern crate time;
extern crate rand;
extern crate regex;

use time::Timespec;
use rusqlite::Connection;
use std::io;
use std::path::Path;
use std::env;
use regex::Regex;

// movie struct
#[derive(Debug)]
struct Movie {
    id: i32,
    name: String,
    time_created: Timespec,
    opinion: String,
    rating: i32
}

// movie impl: possibly add search functions
impl Movie {
    // create new movie
    fn new(id: i32, name: String, time_created: Timespec, opinion: String, rating: i32) -> Movie {
        Movie {
            id: id,
            name: name,
            time_created: time_created,
            opinion: opinion,
            rating: rating,
        }
    }
}

fn main() {
    // open connection to .movies.db in current directory: possibly change to
    // ~/.movies.db for simplicity
    let conn = Connection::open(Path::new(".movies.db")).unwrap();

    // create a table in movies database that maps to a movie struct
    conn.execute("CREATE TABLE IF NOT EXISTS movies (
        id INTEGER UNIQUE NOT NULL,
        name TEXT NOT NULL,
        time_created TEXT NOT NULL,
        opinion TEXT NOT NULL,
        rating INTEGER)", &[]).unwrap();

    // get args
    let args: Vec<String> = env::args().collect();
    let length = args.len();

    if length == 1 {
        println!("for help, use \"mymdb help\"");
    }
    else if length == 2 {
        for i in &args {
            if i == "help" { print_help(); }
            else if i == "add" {
                // prompt user for new movie
                let new_movie = new_movie();

                // insert new movie into database
                conn.execute("INSERT INTO movies VALUES ($1, $2, $3, $4, $5)",
                    &[&new_movie.id, &new_movie.name, &new_movie.time_created,
                    &new_movie.opinion, &new_movie.rating]).unwrap();

                println!("Your movie has been added. ID# {}", &new_movie.id);
            }
            else if i == "remove" {
                // get movie id
                println!("ID of movie to be removed: (number)");
                let id: i32 = number_input();

                // find movie by id: TODO: make more efficient
                let mut stmt = conn.prepare("SELECT * FROM movies WHERE id=$1").unwrap();
                let movie_iter = stmt.query_map(&[&id,], |row| {
                    Movie {
                        id: row.get(0),
                        name: row.get(1),
                        time_created: row.get(2),
                        opinion: row.get(3),
                        rating: row.get(4)
                    }
                }).unwrap();

                // get last movie with id because shitty API or I don't know how to use it
                // probably the latter honestly
                let mut q = Movie::new(0, String::new(), time::get_time(), String::new(), 0);
                for i in movie_iter {
                    q = i.unwrap();
                }

                if q.name.is_empty() {
                    println!("Cannot find movie with ID of {}", id);
                    return
                }

                println!("Are you sure you want to remove {}?", q.name.trim());

                // get_input() does not last long enough and I don't know how
                // to extend lifetimes so yeah
                let resp_upper = get_input();
                let resp_trim = resp_upper.to_lowercase();
                let resp = resp_trim.trim();

                // remove from database
                if resp == String::from("yes") {
                    conn.execute("DELETE FROM movies WHERE id=$1", &[&id,]).unwrap();
                    println!("{} has been removed from the database.", q.name.trim());
                } else if resp == String::from("y") {
                    conn.execute("DELETE FROM movies WHERE id=$1", &[&id,]).unwrap();
                    println!("{} has been removed from the database.", q.name.trim());
                } else {
                    println!("Movie will not be removed.");
                }
            }
            // show movies in database
            else if i == "show" {
                // select all movies, conver to iterator
                let mut stmt = conn.prepare("SELECT * FROM movies").unwrap();
                let movie_iter = stmt.query_map(&[], |row| {
                    Movie {
                        id: row.get(0),
                        name: row.get(1),
                        time_created: row.get(2),
                        opinion: row.get(3),
                        rating: row.get(4)
                    }
                }).unwrap();

                // convert list of movies to vector
                let mut count = 0;
                let mut movies: Vec<Movie> = vec![];
                for movie in movie_iter {
                    movies.push(movie.unwrap());
                    count = count + 1;
                }

                println!("Found {} movie(s)", count);

                // print movies
                for z in movies {
                    println!("Name:    {}\nOpinion: {}\nRating:  {}\nID:      {}\nTime:    {}\n",
                             z.name.trim(),
                             z.opinion.trim(),
                             z.rating,
                             z.id,
                             time(z.time_created));
                }
            }
            else {
                // TODO: make this not ridiculous
                let re = Regex::new(r"mymdb").unwrap();
                if !re.is_match(&i) {
                    println!("Not an option: {}", i);
                } else {
                    continue;
                }
            }
        }
    }
    else {
        // TODO: get argparse or something like that
        let mut arg3: &String = &String::from("");
        let mut arg4: &String = &String::from("");
        let mut arg5: i32 = 0;
        if length >= 3 {
            arg3 = &args[2];
        }
        if length == 5 {
            arg4 = &args[3];
            arg5 = args[4].trim().parse().expect("3rd arg must be a number");
        }
        for i in &args {
            if i == "-a" {
                // add movie
                let id = rand::random::<i32>().abs() / 1000;
                conn.execute("INSERT INTO movies VALUES ($1, $2, $3, $4, $5)",
                    &[&id, arg3, &(time::get_time()),
                    arg4, &arg5]).unwrap();
                println!("Your movie has been added. ID# {}", id);
            }
            else if i == "-r" {
                // remove movie
                let id: i32 = arg3.trim().parse().expect("arg must be a number");

                let mut stmt = conn.prepare("SELECT * FROM movies WHERE id=$1").unwrap();
                let movie_iter = stmt.query_map(&[&id,], |row| {
                    Movie {
                        id: row.get(0),
                        name: row.get(1),
                        time_created: row.get(2),
                        opinion: row.get(3),
                        rating: row.get(4)
                    }
                }).unwrap();

                let mut q = Movie::new(0, String::new(), time::get_time(), String::new(), 0);
                for i in movie_iter {
                    q = i.unwrap();
                }

                if q.name.is_empty() {
                    println!("Cannot find movie with ID of {}", id);
                    return
                }

                conn.execute("DELETE FROM movies WHERE id=$1", &[&id,]).unwrap();
                println!("{} has been removed from the database.", q.name.trim());
            }
        }
    }
}

// create new movie struct using input
fn new_movie() -> Movie {
    println!("Name of movie:");
    let name: String = get_input();

    println!("Thoughts:");
    let opinion: String = get_input();

    println!("Rating: (number)");
    let rating: i32 = number_input();

    // TODO: non-retarded ID numbers, like autoincrement
    Movie::new(rand::random::<i32>().abs() / 1000, name,
        time::get_time(), opinion, rating)
}

// return time as string
fn time(t: Timespec) -> String {
    let real_time = time::at(t);
    String::from(format!("{}-{}-{} {}:{}", (real_time.tm_year + 1900), real_time.tm_mon,
                 real_time.tm_mday, real_time.tm_hour, real_time.tm_min))
}

fn print_help() {
    println!("mymdb - personal movie database");
    println!("usage:");
    println!("mymdb <command> [options]");
    println!("commands:");
    println!("\tshow - lists movies in database");
    println!("\tadd - adds movie to database (interactively)");
    println!("\tremove - removes movie from database (interactively)");
    println!("options:");
    println!("\t-r <movie ID> - removes movie from database");
    println!("\t-a <movie name> <opinion> <rating>");
    println!("mymdb creates a movie database that the program is run in.");
    println!("It looks for a sqlite file called .movies.db, and if it does");
    println!("not exist, it is created automatically.");
}

// get input as number
fn number_input() -> i32 {
    let n = match get_input().trim().parse::<i32>() {
        Ok(n) => n,
        Err(e) => { println!("Not a number"); 0 },
    };

    n
}

// get input as string
fn get_input() -> String {
    let mut i = String::new();
    let handle = io::stdin();

    match handle.read_line(&mut i) {
        Ok(n) => {},
        Err(e) => println!("What's your problem?")
    }

    i
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::OsString;
use std::fs::File;
use std::io::{self, BufRead, Write};
use std::path::PathBuf;
use std::process::{self, Command, Stdio};

extern crate isatty;
use isatty::{stderr_isatty, stdout_isatty};

extern crate tempfile;

fn main() {
    let result = cargo_expand_or_run_nightly();
    process::exit(match result {
        Ok(code) => code,
        Err(err) => {
            let _ = writeln!(&mut io::stderr(), "{}", err);
            1
        }
    });
}

fn cargo_expand_or_run_nightly() -> io::Result<i32> {
    const NO_RUN_NIGHTLY: &str = "CARGO_EXPAND_NO_RUN_NIGHTLY";

    let maybe_nightly = !definitely_not_nightly();
    if maybe_nightly || env::var_os(NO_RUN_NIGHTLY).is_some() {
        return cargo_expand();
    }

    let mut nightly = Command::new("cargo");
    nightly.arg("+nightly");
    nightly.arg("expand");
    nightly.args(env::args_os().skip(1));

    // Hopefully prevent infinite re-run loop.
    nightly.env(NO_RUN_NIGHTLY, "");

    let status = nightly.status()?;

    Ok(match status.code() {
        Some(code) => code,
        None => if status.success() { 0 } else { 1 },
    })
}

fn definitely_not_nightly() -> bool {
    let mut cmd = Command::new(cargo_binary());
    cmd.arg("--version");

    let output = match cmd.output() {
        Ok(output) => output,
        Err(_) => return false,
    };

    let version = match String::from_utf8(output.stdout) {
        Ok(version) => version,
        Err(_) => return false,
    };

    version.starts_with("cargo 1") && !version.contains("nightly")
}

fn cargo_binary() -> OsString {
    env::var_os("CARGO").unwrap_or_else(|| "cargo".to_owned().into())
}

fn cargo_expand() -> io::Result<i32> {
    let args: Vec<_> = env::args_os().collect();

    let which_rustfmt = which(&["rustfmt"]);
    let which_pygmentize = if !color_never(&args) && stdout_isatty() {
        which(&["pygmentize", "-l", "rust"])
    } else {
        None
    };

    let outdir = if which_rustfmt.is_some() || which_pygmentize.is_some() {
        let mut builder = tempfile::Builder::new();
        builder.prefix("cargo-expand");
        Some(builder.tempdir().expect("failed to create tmp file"))
    } else {
        None
    };
    let outfile = outdir.as_ref().map(|dir| dir.path().join("expanded"));

    // Run cargo
    let mut cmd = Command::new(cargo_binary());
    cmd.args(&wrap_args(args.clone(), outfile.as_ref()));
    let code = filter_err(&mut cmd, ignore_cargo_err)?;
    if code != 0 {
        return Ok(code);
    }

    // Run rustfmt
    if let Some(fmt) = which_rustfmt {
        // Ignore any errors.
        let _status = Command::new(fmt)
            .arg(outfile.as_ref().unwrap())
            .stderr(Stdio::null())
            .status();
    }

    // Run pygmentize
    if let Some(pyg) = which_pygmentize {
        let _status = Command::new(pyg)
            .args(&["-l", "rust", "-O", "encoding=utf8"])
            .arg(outfile.as_ref().unwrap())
            .status();
    } else if let Some(outfile) = outfile {
        // Cat outfile if rustfmt was used.
        let mut reader = File::open(outfile)?;
        io::copy(&mut reader, &mut io::stdout())?;
    }
    Ok(0)
}

// Based on https://github.com/rsolomo/cargo-check
fn wrap_args<I>(it: I, outfile: Option<&PathBuf>) -> Vec<OsString>
where
    I: IntoIterator<Item = OsString>,
{
    let mut args = vec!["rustc".into(), "--profile=check".into()];
    let mut ends_with_test = false;
    let mut ends_with_example = false;
    let mut has_color = false;

    let mut it = it.into_iter().skip(2);
    for arg in &mut it {
        if arg == *"--" {
            break;
        }
        ends_with_test = arg == *"--test";
        ends_with_example = arg == *"--example";
        has_color |= arg.to_str().unwrap_or("").starts_with("--color");
        args.push(arg.into());
    }

    if ends_with_test {
        // Expand the `test.rs` test by default.
        args.push("test".into());
    }

    if ends_with_example {
        // Expand the `example.rs` example by default.
        args.push("example".into());
    }

    if !has_color {
        let color = stderr_isatty();
        let setting = if color { "always" } else { "never" };
        args.push(format!("--color={}", setting).into());
    }

    args.push("--".into());
    if let Some(path) = outfile {
        args.push("-o".into());
        args.push(path.into());
    }
    args.push("-Zunstable-options".into());
    args.push("--pretty=expanded".into());
    args.extend(it);
    args
}

fn color_never(args: &Vec<OsString>) -> bool {
    args.windows(2).any(|pair| pair[0] == *"--color" && pair[1] == *"never")
        || args.iter().any(|arg| *arg == *"--color=never")
}

fn which(cmd: &[&str]) -> Option<OsString> {
    if env::args_os().find(|arg| arg == "--help").is_some() {
        return None;
    }

    if let Some(which) = env::var_os(&cmd[0].to_uppercase()) {
        return if which.is_empty() { None } else { Some(which) };
    }

    let spawn = Command::new(cmd[0])
        .args(&cmd[1..])
        .stdin(Stdio::null())
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .spawn();
    let mut child = match spawn {
        Ok(child) => child,
        Err(_) => {
            return None;
        }
    };

    let exit = match child.wait() {
        Ok(exit) => exit,
        Err(_) => {
            return None;
        }
    };

    if exit.success() {
        Some(cmd[0].into())
    } else {
        None
    }
}

fn filter_err(cmd: &mut Command, ignore: fn(&str) -> bool) -> io::Result<i32> {
    let mut child = cmd.stderr(Stdio::piped()).spawn()?;
    let mut stderr = io::BufReader::new(child.stderr.take().unwrap());
    let mut line = String::new();
    while let Ok(n) = stderr.read_line(&mut line) {
        if n == 0 {
            break;
        }
        if !ignore(&line) {
            let _ = write!(&mut io::stderr(), "{}", line);
        }
        line.clear();
    }
    let code = child.wait()?.code().unwrap_or(1);
    Ok(code)
}

fn ignore_cargo_err(line: &str) -> bool {
    if line.trim().is_empty() {
        return true;
    }

    let blacklist = [
        "ignoring specified output filename because multiple outputs were \
         requested",
        "ignoring specified output filename for 'link' output because multiple \
         outputs were requested",
        "ignoring --out-dir flag due to -o flag",
        "ignoring -C extra-filename flag due to -o flag",
        "due to multiple output types requested, the explicitly specified \
         output file name will be adapted for each output type",
    ];
    for s in &blacklist {
        if line.contains(s) {
            return true;
        }
    }

    false
}
<commit_msg>Fix multiple input filenames provided<commit_after>use std::env;
use std::ffi::OsString;
use std::fs::File;
use std::io::{self, BufRead, Write};
use std::path::PathBuf;
use std::process::{self, Command, Stdio};

extern crate isatty;
use isatty::{stderr_isatty, stdout_isatty};

extern crate tempfile;

fn main() {
    let result = cargo_expand_or_run_nightly();
    process::exit(match result {
        Ok(code) => code,
        Err(err) => {
            let _ = writeln!(&mut io::stderr(), "{}", err);
            1
        }
    });
}

fn cargo_expand_or_run_nightly() -> io::Result<i32> {
    const NO_RUN_NIGHTLY: &str = "CARGO_EXPAND_NO_RUN_NIGHTLY";

    let maybe_nightly = !definitely_not_nightly();
    if maybe_nightly || env::var_os(NO_RUN_NIGHTLY).is_some() {
        return cargo_expand();
    }

    let mut nightly = Command::new("cargo");
    nightly.arg("+nightly");
    nightly.arg("expand");

    let mut args = env::args_os().peekable();
    args.next().unwrap(); // cargo
    if args.peek().and_then(|arg| arg.to_str()) == Some("expand") {
        args.next().unwrap(); // expand
    }
    nightly.args(args);

    // Hopefully prevent infinite re-run loop.
    nightly.env(NO_RUN_NIGHTLY, "");

    let status = nightly.status()?;

    Ok(match status.code() {
        Some(code) => code,
        None => if status.success() { 0 } else { 1 },
    })
}

fn definitely_not_nightly() -> bool {
    let mut cmd = Command::new(cargo_binary());
    cmd.arg("--version");

    let output = match cmd.output() {
        Ok(output) => output,
        Err(_) => return false,
    };

    let version = match String::from_utf8(output.stdout) {
        Ok(version) => version,
        Err(_) => return false,
    };

    version.starts_with("cargo 1") && !version.contains("nightly")
}

fn cargo_binary() -> OsString {
    env::var_os("CARGO").unwrap_or_else(|| "cargo".to_owned().into())
}

fn cargo_expand() -> io::Result<i32> {
    let args: Vec<_> = env::args_os().collect();

    let which_rustfmt = which(&["rustfmt"]);
    let which_pygmentize = if !color_never(&args) && stdout_isatty() {
        which(&["pygmentize", "-l", "rust"])
    } else {
        None
    };

    let outdir = if which_rustfmt.is_some() || which_pygmentize.is_some() {
        let mut builder = tempfile::Builder::new();
        builder.prefix("cargo-expand");
        Some(builder.tempdir().expect("failed to create tmp file"))
    } else {
        None
    };
    let outfile = outdir.as_ref().map(|dir| dir.path().join("expanded"));

    // Run cargo
    let mut cmd = Command::new(cargo_binary());
    cmd.args(&wrap_args(args.clone(), outfile.as_ref()));
    let code = filter_err(&mut cmd, ignore_cargo_err)?;
    if code != 0 {
        return Ok(code);
    }

    // Run rustfmt
    if let Some(fmt) = which_rustfmt {
        // Ignore any errors.
        let _status = Command::new(fmt)
            .arg(outfile.as_ref().unwrap())
            .stderr(Stdio::null())
            .status();
    }

    // Run pygmentize
    if let Some(pyg) = which_pygmentize {
        let _status = Command::new(pyg)
            .args(&["-l", "rust", "-O", "encoding=utf8"])
            .arg(outfile.as_ref().unwrap())
            .status();
    } else if let Some(outfile) = outfile {
        // Cat outfile if rustfmt was used.
        let mut reader = File::open(outfile)?;
        io::copy(&mut reader, &mut io::stdout())?;
    }
    Ok(0)
}

// Based on https://github.com/rsolomo/cargo-check
fn wrap_args<I>(it: I, outfile: Option<&PathBuf>) -> Vec<OsString>
where
    I: IntoIterator<Item = OsString>,
{
    let mut args = vec!["rustc".into(), "--profile=check".into()];
    let mut ends_with_test = false;
    let mut ends_with_example = false;
    let mut has_color = false;

    let mut it = it.into_iter().skip(2);
    for arg in &mut it {
        if arg == *"--" {
            break;
        }
        ends_with_test = arg == *"--test";
        ends_with_example = arg == *"--example";
        has_color |= arg.to_str().unwrap_or("").starts_with("--color");
        args.push(arg.into());
    }

    if ends_with_test {
        // Expand the `test.rs` test by default.
        args.push("test".into());
    }

    if ends_with_example {
        // Expand the `example.rs` example by default.
        args.push("example".into());
    }

    if !has_color {
        let color = stderr_isatty();
        let setting = if color { "always" } else { "never" };
        args.push(format!("--color={}", setting).into());
    }

    args.push("--".into());
    if let Some(path) = outfile {
        args.push("-o".into());
        args.push(path.into());
    }
    args.push("-Zunstable-options".into());
    args.push("--pretty=expanded".into());
    args.extend(it);
    args
}

fn color_never(args: &Vec<OsString>) -> bool {
    args.windows(2).any(|pair| pair[0] == *"--color" && pair[1] == *"never")
        || args.iter().any(|arg| *arg == *"--color=never")
}

fn which(cmd: &[&str]) -> Option<OsString> {
    if env::args_os().find(|arg| arg == "--help").is_some() {
        return None;
    }

    if let Some(which) = env::var_os(&cmd[0].to_uppercase()) {
        return if which.is_empty() { None } else { Some(which) };
    }

    let spawn = Command::new(cmd[0])
        .args(&cmd[1..])
        .stdin(Stdio::null())
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .spawn();
    let mut child = match spawn {
        Ok(child) => child,
        Err(_) => {
            return None;
        }
    };

    let exit = match child.wait() {
        Ok(exit) => exit,
        Err(_) => {
            return None;
        }
    };

    if exit.success() {
        Some(cmd[0].into())
    } else {
        None
    }
}

fn filter_err(cmd: &mut Command, ignore: fn(&str) -> bool) -> io::Result<i32> {
    let mut child = cmd.stderr(Stdio::piped()).spawn()?;
    let mut stderr = io::BufReader::new(child.stderr.take().unwrap());
    let mut line = String::new();
    while let Ok(n) = stderr.read_line(&mut line) {
        if n == 0 {
            break;
        }
        if !ignore(&line) {
            let _ = write!(&mut io::stderr(), "{}", line);
        }
        line.clear();
    }
    let code = child.wait()?.code().unwrap_or(1);
    Ok(code)
}

fn ignore_cargo_err(line: &str) -> bool {
    if line.trim().is_empty() {
        return true;
    }

    let blacklist = [
        "ignoring specified output filename because multiple outputs were \
         requested",
        "ignoring specified output filename for 'link' output because multiple \
         outputs were requested",
        "ignoring --out-dir flag due to -o flag",
        "ignoring -C extra-filename flag due to -o flag",
        "due to multiple output types requested, the explicitly specified \
         output file name will be adapted for each output type",
    ];
    for s in &blacklist {
        if line.contains(s) {
            return true;
        }
    }

    false
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate schemamama;
extern crate schemamama_postgres;
extern crate postgres;
mod schema;

#[macro_use]
extern crate log;
extern crate log4rs;

extern crate iron;
extern crate router;
extern crate logger;

use iron::prelude::*;
use iron::status;
use router::Router;
use logger::Logger;
use std::io::Read;
use iron::modifiers::Redirect;

use std::env;
use std::ops::Deref;

extern crate uuid;
use uuid::Uuid;
extern crate serde_json;
use serde_json::{Map, Value};

extern crate r2d2;
extern crate r2d2_postgres;
extern crate persistent;
use persistent::Read as PRead;
use postgres::rows::{Row, RowIndex};
use postgres::types::FromSql;

#[macro_use]mod db;
#[macro_use]mod server_id;

use std::error::Error;
use std::fmt::{self, Debug};
#[derive(Debug)]
struct StringError(String);

impl Error for StringError {
    fn description(&self) -> &str {
        &*self.0
    }
}

impl fmt::Display for StringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self, f)
    }
}

struct Log {
    id: Uuid,
    owner: Uuid,
    next: Option<Uuid>,
    prev: Option<Uuid>,
    data: Value,
}

fn log_status(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "Hello World!")))
}

fn new_log(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    let body_string = {
        let mut body = String::new();
        req.body.read_to_string(&mut body).expect("could read from body");
        body
    };
    let json: Value = match serde_json::de::from_str(&body_string) {
        Ok(val) => val,
        Err(err) => return Err(IronError::new(err, (status::BadRequest, "Bad JSON"))),
    };
    let id = Uuid::new_v4();
    let hyphenated = id.hyphenated().to_string();
    let server_id = get_server_id!(&req).deref();
    let stmt = conn.prepare("SELECT id from log WHERE next is null LIMIT 1").expect("prepare failure");
    let results = stmt.query(&[]).expect("last select works");
    let previous = if results.is_empty() {
        None
    } else {
        let row = results.get(0);
        let id: Uuid = row.get("id");
        Some(id)
    };
    conn.execute("UPDATE log set next = $1 where owner = $2 and next is null",
                 &[&id, server_id])
        .expect("update worked");
    conn.execute("INSERT INTO log (id, owner, data, prev) VALUES ($1, $2, $3, $4)",
                 &[&id, server_id, &json, &previous])
        .expect("insert worked");
    let new_url = {
        let req_url = req.url.clone();
        let base_url = req_url.into_generic_url();
        base_url.join(&format!("/log/{}", &hyphenated)).expect("join url works")
    };
    Ok(Response::with((status::Found,
                       Redirect(iron::Url::from_generic_url(new_url).expect("URL parsed ok")))))
}

fn get_with_null<I, T>(row: &Row, index: I) -> Option<T>
    where I: RowIndex,
          T: FromSql
{
    match row.get_opt(index) {
        Some(val) => {
            match val {
                Ok(val) => Some(val),
                Err(_) => None,
            }
        }
        None => None,
    }
}

fn get_log(req: &mut Request) -> IronResult<Response> {
    let ref query = req.extensions
        .get::<Router>()
        .unwrap()
        .find("entry_id")
        .unwrap_or("/");
    let query_id = Uuid::parse_str(&query).expect("Dodgy UUID");
    let conn = get_pg_connection!(&req);
    let stmt = conn.prepare("SELECT owner, next, prev, data from log where id=$1").expect("prepare failure");
    let results = stmt.query(&[&query_id]).expect("bad query");
    if results.is_empty() {
        Ok(Response::with((status::NotFound, format!("No log {}", query))))
    } else {
        let row = results.get(0);
        let data: Value = row.get("data");
        let mut map = Map::new();
        let owner: Uuid = row.get("owner");
        let next: Option<Uuid> = get_with_null(&row, "next");
        let prev: Option<Uuid> = get_with_null(&row, "prev");
        map.insert(String::from("owner"),
                   serde_json::to_value(&owner.to_string()));
        map.insert(String::from("prev"),
                   serde_json::to_value(&prev.map(|x| x.to_string())));
        map.insert(String::from("next"),
                   serde_json::to_value(&next.map(|x| x.to_string())));
        map.insert(String::from("data"), data);
        let value = Value::Object(map);
        Ok(Response::with((status::Ok, serde_json::ser::to_string(&value).unwrap())))
    }
}

fn main() {
    log4rs::init_file("log.yaml", Default::default()).unwrap();
    let db_url: &str = &env::var("DATABASE_URL").expect("Needed DATABASE_URL");
    let pool = db::get_pool(db_url);
    let conn = pool.get().unwrap();
    schema::up(&conn).unwrap();
    let (logger_before, logger_after) = Logger::new(None);
    let mut router = Router::new();
    router.get("/log", log_status);
    router.post("/log", new_log);
    router.get("/log/:entry_id", get_log);
    let mut chain = Chain::new(router);
    chain.link_before(logger_before);
    chain.link_after(logger_after);
    chain.link_before(PRead::<server_id::ServerId>::one(server_id::setup()));
    chain.link(PRead::<db::PostgresDB>::both(pool));
    info!("Potboiler booted");
    Iron::new(chain).http("localhost:8000").unwrap();
}
<commit_msg>Allow for listing all logs<commit_after>#[macro_use]
extern crate schemamama;
extern crate schemamama_postgres;
extern crate postgres;
mod schema;

#[macro_use]
extern crate log;
extern crate log4rs;

extern crate iron;
extern crate router;
extern crate logger;

use iron::prelude::*;
use iron::status;
use router::Router;
use logger::Logger;
use std::io::Read;
use iron::modifiers::Redirect;

use std::env;
use std::ops::Deref;

extern crate uuid;
use uuid::Uuid;
extern crate serde_json;
use serde_json::{Map, Value};

extern crate r2d2;
extern crate r2d2_postgres;
extern crate persistent;
use persistent::Read as PRead;
use postgres::rows::{Row, RowIndex};
use postgres::types::FromSql;

#[macro_use]mod db;
#[macro_use]mod server_id;

use std::error::Error;
use std::fmt::{self, Debug};
#[derive(Debug)]
struct StringError(String);

impl Error for StringError {
    fn description(&self) -> &str {
        &*self.0
    }
}

impl fmt::Display for StringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self, f)
    }
}

fn log_status(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    let stmt = conn.prepare("SELECT id, owner from log WHERE next is null").expect("prepare failure");
    let mut logs = Map::new();
    for row in &stmt.query(&[]).expect("last select works") {
        let id: Uuid = row.get("id");
        let owner: Uuid = row.get("owner");
        logs.insert(owner.to_string(), serde_json::to_value(&id.to_string()));
    };
    let value = Value::Object(logs);
    Ok(Response::with((status::Ok, serde_json::ser::to_string(&value).unwrap())))
}

fn new_log(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    let body_string = {
        let mut body = String::new();
        req.body.read_to_string(&mut body).expect("could read from body");
        body
    };
    let json: Value = match serde_json::de::from_str(&body_string) {
        Ok(val) => val,
        Err(err) => return Err(IronError::new(err, (status::BadRequest, "Bad JSON"))),
    };
    let id = Uuid::new_v4();
    let hyphenated = id.hyphenated().to_string();
    let server_id = get_server_id!(&req).deref();
    let stmt = conn.prepare("SELECT id from log WHERE next is null and owner = $1 LIMIT 1").expect("prepare failure");
    let results = stmt.query(&[server_id]).expect("last select works");
    let previous = if results.is_empty() {
        None
    } else {
        let row = results.get(0);
        let id: Uuid = row.get("id");
        Some(id)
    };
    conn.execute("UPDATE log set next = $1 where owner = $2 and next is null",
                 &[&id, server_id])
        .expect("update worked");
    conn.execute("INSERT INTO log (id, owner, data, prev) VALUES ($1, $2, $3, $4)",
                 &[&id, server_id, &json, &previous])
        .expect("insert worked");
    let new_url = {
        let req_url = req.url.clone();
        let base_url = req_url.into_generic_url();
        base_url.join(&format!("/log/{}", &hyphenated)).expect("join url works")
    };
    Ok(Response::with((status::Found,
                       Redirect(iron::Url::from_generic_url(new_url).expect("URL parsed ok")))))
}

fn get_with_null<I, T>(row: &Row, index: I) -> Option<T>
    where I: RowIndex,
          T: FromSql
{
    match row.get_opt(index) {
        Some(val) => {
            match val {
                Ok(val) => Some(val),
                Err(_) => None,
            }
        }
        None => None,
    }
}

fn get_log(req: &mut Request) -> IronResult<Response> {
    let ref query = req.extensions
        .get::<Router>()
        .unwrap()
        .find("entry_id")
        .unwrap_or("/");
    let query_id = Uuid::parse_str(&query).expect("Dodgy UUID");
    let conn = get_pg_connection!(&req);
    let stmt = conn.prepare("SELECT owner, next, prev, data from log where id=$1").expect("prepare failure");
    let results = stmt.query(&[&query_id]).expect("bad query");
    if results.is_empty() {
        Ok(Response::with((status::NotFound, format!("No log {}", query))))
    } else {
        let row = results.get(0);
        let data: Value = row.get("data");
        let mut map = Map::new();
        let owner: Uuid = row.get("owner");
        let next: Option<Uuid> = get_with_null(&row, "next");
        let prev: Option<Uuid> = get_with_null(&row, "prev");
        map.insert(String::from("owner"),
                   serde_json::to_value(&owner.to_string()));
        map.insert(String::from("prev"),
                   serde_json::to_value(&prev.map(|x| x.to_string())));
        map.insert(String::from("next"),
                   serde_json::to_value(&next.map(|x| x.to_string())));
        map.insert(String::from("data"), data);
        let value = Value::Object(map);
        Ok(Response::with((status::Ok, serde_json::ser::to_string(&value).unwrap())))
    }
}

fn main() {
    log4rs::init_file("log.yaml", Default::default()).unwrap();
    let db_url: &str = &env::var("DATABASE_URL").expect("Needed DATABASE_URL");
    let pool = db::get_pool(db_url);
    let conn = pool.get().unwrap();
    schema::up(&conn).unwrap();
    let (logger_before, logger_after) = Logger::new(None);
    let mut router = Router::new();
    router.get("/log", log_status);
    router.post("/log", new_log);
    router.get("/log/:entry_id", get_log);
    let mut chain = Chain::new(router);
    chain.link_before(logger_before);
    chain.link_after(logger_after);
    chain.link_before(PRead::<server_id::ServerId>::one(server_id::setup()));
    chain.link(PRead::<db::PostgresDB>::both(pool));
    info!("Potboiler booted");
    Iron::new(chain).http("localhost:8000").unwrap();
}
<|endoftext|>


<commit_before>extern crate raytracer;
extern crate rand;

use raytracer::vec3::Vec3;
use raytracer::ray::Ray;
use raytracer::hitable::*;
use raytracer::camera::Camera;

use rand::{thread_rng, Rng};

use std::io::{self, Write};

const NX: i32 = 200;
const NY: i32 = 100;
const NUM_SAMPLES: i32 = 32;
const MAX_DISTANCE: f64 = 1000.0;

fn color<T: Hitable>(r: &Ray, world: &HitableList<T>) -> Vec3 {
    match world.hit(r, 0.0, MAX_DISTANCE) {
        Some(h) => {
            // Sphere color
            Vec3::new(h.normal.x+1.0, h.normal.y+1.0, h.normal.z+1.0).mul_scalar(0.5)
        }
        None => {
            // Background
            let unit_dir = r.dir.normalized();
            let t = 0.5 * (unit_dir.y + 1.0);
            Vec3::new(1.0,1.0,1.0).mul_scalar(1.0-t) + Vec3::new(0.5, 0.7, 1.0).mul_scalar(t)
        }
    }
}

fn main() {
    io::stdout().write_fmt(format_args!("P3\n{} {}\n{}\n", NX, NY, 255)).unwrap();

    let camera = Camera {
        lower_left_corner: Vec3::new(-2.0, -1.0, -1.0),
        horizontal: Vec3::new(4.0, 0.0, 0.0),
        vertical: Vec3::new(0.0, 2.0, 0.0),
        origin: Vec3::new(0.0, 0.0, 0.0),
    };

    let world: HitableList<Sphere> = HitableList {
        items: vec![
            Sphere { center: Vec3::new(0.0,0.0,-1.0), radius: 0.5 },
            Sphere { center: Vec3::new(0.0,-100.5,-1.0), radius: 100.0 },
        ]
    };

    let mut rng = thread_rng();

    for j in (0..NY).rev() {
        for i in 0..NX {
            let mut c = Vec3::new(0.0, 0.0, 0.0);

            for s in 0..NUM_SAMPLES {
                // Get percent offset from bottom left corner
                let u = (i as f64 + rng.next_f64()) / (NX as f64);
                let v = (j as f64 + rng.next_f64()) / (NY as f64);

                // Make ray
                let r = camera.get_ray(u, v);

                // Get color
                c += color(&r, &world);
            }
            let c = c.div_scalar(NUM_SAMPLES as f64);

            // Output for PPM
            let c = c.mul_scalar(255.99);
            println!("{} {} {}", c.x as i32, c.y as i32, c.z as i32);
        }
    }
}
<commit_msg>Chapter 7: Diffuse materials<commit_after>extern crate raytracer;
extern crate rand;

use raytracer::vec3::Vec3;
use raytracer::ray::Ray;
use raytracer::hitable::*;
use raytracer::camera::Camera;

use rand::{thread_rng, Rng};

use std::io::{self, Write};

const NX: i32 = 200;
const NY: i32 = 100;
const NUM_SAMPLES: i32 = 64;
const MAX_DISTANCE: f64 = 1000.0;

fn random_in_unit_sphere() -> Vec3 {
    let mut rng = thread_rng();
    loop {
        let p = Vec3::new(rng.next_f64(), rng.next_f64(), rng.next_f64()).mul_scalar(2.0).sub_scalar(1.0);
        if p.dot(p) >=  1.0 {
            return p
        }
    }
}

fn color<T: Hitable>(r: &Ray, world: &HitableList<T>) -> Vec3 {
    match world.hit(r, 0.0, MAX_DISTANCE) {
        Some(h) => {
            // Sphere color
            let target = h.p + h.normal + random_in_unit_sphere();
            color(&Ray::new(h.p, target-h.p), world).mul_scalar(0.5)
        }
        None => {
            // Background
            let unit_dir = r.dir.normalized();
            let t = 0.5 * (unit_dir.y + 1.0);
            Vec3::new(1.0,1.0,1.0).mul_scalar(1.0-t) + Vec3::new(0.5, 0.7, 1.0).mul_scalar(t)
        }
    }
}

fn main() {
    io::stdout().write_fmt(format_args!("P3\n{} {}\n{}\n", NX, NY, 255)).unwrap();

    let camera = Camera {
        lower_left_corner: Vec3::new(-2.0, -1.0, -1.0),
        horizontal: Vec3::new(4.0, 0.0, 0.0),
        vertical: Vec3::new(0.0, 2.0, 0.0),
        origin: Vec3::new(0.0, 0.0, 0.0),
    };

    let world: HitableList<Sphere> = HitableList {
        items: vec![
            Sphere { center: Vec3::new(0.0,0.0,-1.0), radius: 0.5 },
            Sphere { center: Vec3::new(0.0,-100.5,-1.0), radius: 100.0 },
        ]
    };

    let mut rng = thread_rng();

    for j in (0..NY).rev() {
        for i in 0..NX {
            let mut c = Vec3::new(0.0, 0.0, 0.0);

            for s in 0..NUM_SAMPLES {
                // Get percent offset from bottom left corner
                let u = (i as f64 + rng.next_f64()) / (NX as f64);
                let v = (j as f64 + rng.next_f64()) / (NY as f64);

                // Make ray
                let r = camera.get_ray(u, v);

                // Get color
                c += color(&r, &world);
            }
            let c = c.div_scalar(NUM_SAMPLES as f64);

            // Output for PPM
            let c = c.mul_scalar(255.99);
            println!("{} {} {}", c.x as i32, c.y as i32, c.z as i32);
        }
    }
}
<|endoftext|>


<commit_before>// TEMPORARY Test with asmjs
// TODO Replace with examples in /examples once Windows builds are fixed
// so that the manual `cargo rustc ... --linker="emcc.bat"` workaround is
// unnecessary

extern crate domafic;
use domafic::{DOMNode, DOMValue, IntoNode};
use domafic::tags::{button, div, h1};
use domafic::events::EventType::Click;
use domafic::listener::on;

#[macro_use] extern crate webplatform;
extern crate libc;

type State = usize;

enum Msg {
    Increment,
    Decrement,
}

fn main() {
    let update = |state: &mut State, msg: Msg| match msg {
        Msg::Increment => *state += 1,
        Msg::Decrement => *state -= 1,
    };

    let render = |state: &State| {
        div ((
            h1("Hello from rust!".into_node()),
            button ((
                on(Click, |_| Msg::Decrement),
                "-".into_node(),
            )),
            state.to_string().into_node(),
            button ((
                on(Click, |_| Msg::Increment),
                "+".into_node(),
            )),
        ))
    };

    run("body", update, render, 0);
}

trait Updater<State, Message> {
    fn update(&self, &mut State, Message) -> ();
}
impl<F, S, M> Updater<S, M> for F where F: Fn(&mut S, M) -> () {
    fn update(&self, state: &mut S, msg: M) -> () {
        (self)(state, msg)
    }
}

trait Renderer<State> {
    type Rendered: DOMNode;
    fn render(&self, &State) -> Self::Rendered;
}
impl<F, S, R> Renderer<S> for F where F: Fn(&S) -> R, R: DOMNode {
    type Rendered = R;
    fn render(&self, state: &S) -> Self::Rendered {
        (self)(state)
    }
}

fn run<U, R, S>(element_selector: &str, updater: U, renderer: R, initial_state: S) -> !
    where
    U: Updater<S, <<R as Renderer<S>>::Rendered as DOMNode>::Message>,
    R: Renderer<S>
{
    let document = webplatform::init();
    let body = document.element_query(element_selector).unwrap();

    // Lives forever on the stack, referenced and mutated in callbacks
    let mut app_system = (updater, renderer, initial_state);
    let app_system_mut_ref = &mut app_system;
    let app_system_mut_ptr = app_system_mut_ref as *mut (U, R, S);

    unsafe {
        (*app_system_mut_ptr).1.render(&(*app_system_mut_ptr).2)
            .process_all::<WebPlatformWriter<U, R, S>>(
                &mut (app_system_mut_ptr, &document, &body)
            )
            .unwrap();

        webplatform::spin();
    }

    // Prevent boxed_system from being freed so it can be used in callbacks
    // (drop occurs after system loop, aka never)
    std::mem::drop(app_system_mut_ptr);
    std::mem::drop(app_system_mut_ref);

    panic!("webplatform::spin() returned");
}

use std::marker::PhantomData;
use domafic::listener::Listener;
use domafic::processors::{DOMNodes, DOMNodeProcessor, Listeners, ListenerProcessor};
use webplatform::{Document as WebDoc, HtmlNode as WebNode};

type MessageOfR<R: Renderer<S>, S> = <<R as Renderer<S>>::Rendered as DOMNode>::Message;

struct WebPlatformWriter<'a, 'd: 'a, 'n: 'a, U, R, S>(
    PhantomData<(&'a (), &'d (), &'n (), U, R, S)>
);
impl<'a, 'd: 'a, 'n: 'a, U, R, S> DOMNodeProcessor<'a, MessageOfR<R, S>> for WebPlatformWriter<'a, 'd, 'n, U, R, S>
    where
    U: Updater<S, MessageOfR<R, S>>,
    R: Renderer<S>
{
    type Acc = (*mut (U, R, S), &'a WebDoc<'d>, &'a WebNode<'n>);
    type Error = ();

    fn get_processor<T: DOMNode<Message=MessageOfR<R, S>>>() -> fn(&mut Self::Acc, &'a T) -> Result<(), Self::Error> {

        // Private to this function because it's actually unsafe to use, but there's
        // currently no way to make it unsafe to use a safe trait, and we need to use
        // the ListenerProcessor trait
        struct WebPlatformListenerWriter<
            'a, 'n: 'a,
            U: Updater<S, MessageOfR<R, S>>,
            R: Renderer<S>,
            S>
        (
            PhantomData<(&'a (), &'n (), U, R, S)>
        );
        impl<'a, 'n: 'a, U, R, S> ListenerProcessor<'a, MessageOfR<R, S>> for
            WebPlatformListenerWriter<'a, 'n, U, R, S>
            where
            U: Updater<S, MessageOfR<R, S>>,
            R: Renderer<S>
        {
            type Acc = (*mut (U, R, S), &'a WebNode<'n>);
            type Error = ();

            fn get_processor<L: Listener<Message=MessageOfR<R, S>>>() -> fn(&mut Self::Acc, &'a L) -> Result<(), Self::Error> {
                fn add_listener<'a, 'n, U, R, S, L> (
                    acc: &mut (*mut (U, R, S), &'a WebNode<'n>),
                    listener: &'a L) -> Result<(), ()> where L: Listener
                {
                    let (ref boxed_system_ptr_ref, ref node) = *acc;
                    let boxed_system_ptr: *mut (U, R, S) =
                        (*boxed_system_ptr_ref).clone();
                    let listener_ptr = listener as *const L;

                    node.on("click", move |_target| {
                        // TODO update
                        /*
                        let boxed_system_mut_ref: &mut (U, R, S) = unsafe {
                            boxed_system_ptr.as_mut().unwrap()
                        };
                        let listener_ref: &L = unsafe {
                            // The listener lives in the boxed_system, so is safe to Deref here
                            // so long as the listener lists in the boxed system aren't mutated
                            // (which they aren't between listener registration and callback)
                            listener_ptr.as_ref().unwrap()
                        };
                        let message = listener_ref.handle_event(domafic::events::Event {});
                        */
                    });

                    Ok(())
                }
                add_listener
            }
        }

        fn add_node<'a, 'd, 'n, T, U, R, S>(
                acc: &mut (*mut (U, R, S), &'a WebDoc<'d>, &'a WebNode<'n>),
                node: &T) -> Result<(), ()>
                where
                T: DOMNode<Message=MessageOfR<R, S>>,
                U: Updater<S, MessageOfR<R, S>>,
                R: Renderer<S>
        {
            let (ref boxed_system, ref document, ref parent_node) = *acc;

            match node.value() {
                DOMValue::Element { tag: tagname } => {
                    let html_node = document.element_create(tagname).unwrap();
                    for attr in node.attributes() {
                        html_node.prop_set_str(attr.0, attr.1);
                    }

                    // Reborrow of *document needed to match lifetimes for 'a
                    let new_acc = &mut (*boxed_system, &**document, &html_node);
                    node.children().process_all::<WebPlatformWriter<U, R, S>>(new_acc)?;
                    let (_, _, html_node) = *new_acc;
                    node.listeners().process_all::<WebPlatformListenerWriter<U, R, S>>(
                        &mut (*boxed_system, html_node)
                    )?;
                    parent_node.append(&html_node);
                }
                DOMValue::Text(text) => {
                    // TODO replace with createTextNode (need to add to webplatform API)
                    parent_node.html_append(text);
                }
            }
            Ok(())
        }
        add_node
    }
}
<commit_msg>Make it safer<commit_after>// TEMPORARY Test with asmjs
// TODO Replace with examples in /examples once Windows builds are fixed
// so that the manual `cargo rustc ... --linker="emcc.bat"` workaround is
// unnecessary

extern crate domafic;
use domafic::{DOMNode, DOMValue, IntoNode};
use domafic::tags::{button, div, h1};
use domafic::events::EventType::Click;
use domafic::listener::on;

#[macro_use] extern crate webplatform;
extern crate libc;

type State = usize;

enum Msg {
    Increment,
    Decrement,
}

fn main() {
    let update = |state: &mut State, msg: Msg| match msg {
        Msg::Increment => *state += 1,
        Msg::Decrement => *state -= 1,
    };

    let render = |state: &State| {
        div ((
            h1("Hello from rust!".into_node()),
            button ((
                on(Click, |_| Msg::Decrement),
                "-".into_node(),
            )),
            state.to_string().into_node(),
            button ((
                on(Click, |_| Msg::Increment),
                "+".into_node(),
            )),
        ))
    };

    run("body", update, render, 0);
}

trait Updater<State, Message> {
    fn update(&self, &mut State, Message) -> ();
}
impl<F, S, M> Updater<S, M> for F where F: Fn(&mut S, M) -> () {
    fn update(&self, state: &mut S, msg: M) -> () {
        (self)(state, msg)
    }
}

trait Renderer<State> {
    type Rendered: DOMNode;
    fn render(&self, &State) -> Self::Rendered;
}
impl<F, S, R> Renderer<S> for F where F: Fn(&S) -> R, R: DOMNode {
    type Rendered = R;
    fn render(&self, state: &S) -> Self::Rendered {
        (self)(state)
    }
}

fn run<U, R, S>(element_selector: &str, updater: U, renderer: R, initial_state: S) -> !
    where
    U: Updater<S, <<R as Renderer<S>>::Rendered as DOMNode>::Message>,
    R: Renderer<S>
{

    unsafe {
        // Lives forever on the stack, referenced and mutated in callbacks
        let mut app_system = (updater, renderer, initial_state);
        let app_system_mut_ref = &mut app_system;
        let app_system_mut_ptr = app_system_mut_ref as *mut (U, R, S);

        // Borrow only used to draw initial DOM to browser
        let new_app_system_mut_ref = &mut (*app_system_mut_ptr);

        // Get initial DOMNode
        let rendered = new_app_system_mut_ref.1.render(&(new_app_system_mut_ref).2);

        // Initialize the browser system
        let document = webplatform::init();
        let body = document.element_query(element_selector).unwrap();

        // Draw initial DOMNode to browser
        rendered.process_all::<WebPlatformWriter<U, R, S>>(
            &mut (app_system_mut_ptr, &document, &body)
        ).unwrap();

        webplatform::spin();
    }

    panic!("webplatform::spin() returned");
}

use std::marker::PhantomData;
use domafic::listener::Listener;
use domafic::processors::{DOMNodes, DOMNodeProcessor, Listeners, ListenerProcessor};
use webplatform::{Document as WebDoc, HtmlNode as WebNode};

type MessageOfR<R: Renderer<S>, S> = <<R as Renderer<S>>::Rendered as DOMNode>::Message;

struct WebPlatformWriter<'a, 'd, U:'d, R:'d, S:'d>(
    PhantomData<(&'a (), &'d (), U, R, S)>
);
impl<'a, 'd: 'a, U:'d, R:'d, S:'d> DOMNodeProcessor<'d, MessageOfR<R, S>> for WebPlatformWriter<'a, 'd, U, R, S>
    where
    U: Updater<S, MessageOfR<R, S>>,
    R: Renderer<S>
{
    type Acc = (*mut (U, R, S), &'a WebDoc<'d>, &'a WebNode<'d>);
    type Error = ();

    fn get_processor<T: DOMNode<Message=MessageOfR<R, S>>>() -> fn(&mut Self::Acc, &'d T) -> Result<(), Self::Error> {

        // Private to this function because it's actually unsafe to use, but there's
        // currently no way to make it unsafe to use a safe trait, and we need to use
        // the ListenerProcessor trait
        struct WebPlatformListenerWriter<
            'a, 'd: 'a,
            U: Updater<S, MessageOfR<R, S>> + 'd,
            R: Renderer<S> + 'd,
            S:'d>
        (
            PhantomData<(&'a (), &'d (), U, R, S)>
        );
        impl<'a, 'd: 'a, U:'d, R:'d, S:'d> ListenerProcessor<'d, MessageOfR<R, S>> for
            WebPlatformListenerWriter<'a, 'd, U, R, S>
            where
            U: Updater<S, MessageOfR<R, S>>,
            R: Renderer<S>
        {
            type Acc = (*mut (U, R, S), &'a WebNode<'d>);
            type Error = ();

            fn get_processor<L: Listener<Message=MessageOfR<R, S>>>() -> fn(&mut Self::Acc, &'d L) -> Result<(), Self::Error> {
                fn add_listener<'a, 'd, U:'d, R:'d, S:'d, L> (
                    acc: &mut (*mut (U, R, S), &'a WebNode<'d>),
                    listener: &'d L) -> Result<(), ()> where L: Listener
                {
                    let (ref boxed_system_ptr_ref, ref node) = *acc;
                    let boxed_system_ptr: *mut (U, R, S) =
                        (*boxed_system_ptr_ref).clone();
                    let listener_ptr = listener as *const L;

                    node.on("click", move |_target| {
                        let boxed_system_mut_ref: &mut (U, R, S) = unsafe {
                            boxed_system_ptr.as_mut().unwrap()
                        };
                        let listener_ref: &L = unsafe {
                            // The listener lives in the boxed_system, so is safe to Deref here
                            // so long as the listener lists in the boxed system aren't mutated
                            // (which they aren't between listener registration and callback)
                            listener_ptr.as_ref().unwrap()
                        };
                        let message = listener_ref.handle_event(domafic::events::Event {});
                        // TODO update
                    });

                    Ok(())
                }
                add_listener
            }
        }

        fn add_node<'a, 'd:'a, T, U:'d, R:'d, S:'d>(
                acc: &mut (*mut (U, R, S), &'a WebDoc<'d>, &'a WebNode<'d>),
                node: &'d T) -> Result<(), ()>
                where
                T: DOMNode<Message=MessageOfR<R, S>>,
                U: Updater<S, MessageOfR<R, S>>,
                R: Renderer<S>
        {
            let (ref boxed_system, ref document, ref parent_node) = *acc;

            match node.value() {
                DOMValue::Element { tag: tagname } => {
                    let html_node = document.element_create(tagname).unwrap();
                    for attr in node.attributes() {
                        html_node.prop_set_str(attr.0, attr.1);
                    }

                    // Reborrow of *document needed to match lifetimes for 'a
                    let new_acc = &mut (*boxed_system, &**document, &html_node);
                    node.children().process_all::<WebPlatformWriter<U, R, S>>(new_acc)?;
                    let (_, _, html_node) = *new_acc;
                    node.listeners().process_all::<WebPlatformListenerWriter<U, R, S>>(
                        &mut (*boxed_system, html_node)
                    )?;
                    parent_node.append(&html_node);
                }
                DOMValue::Text(text) => {
                    // TODO replace with createTextNode (need to add to webplatform API)
                    parent_node.html_append(text);
                }
            }
            Ok(())
        }
        add_node
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::io::{self, Write};
use std::fs::File;
use std::io::prelude::*;

//#[cfg(unix)]
//use std::os::unix::fs::MetadataExt;

#[cfg(linux)]
use std::os::linux::fs::MetadataExt;

#[cfg(target_os="macos")]
use std::os::macos::fs::MetadataExt;

fn main() {
    let args: Vec<String> = env::args().collect();

    for file in &args[1..] {
        read_file(file);
    }
}

fn read_file(file: &String) {
    let mut buffersize: usize = 1024;
    match File::open(file) {
        Ok(mut handle) => {
            if let Ok(meta) = handle.metadata() {
                let blk = meta.st_blksize();
                if blk < std::usize::MAX as u64 {
                    buffersize = blk as usize;
                }
            }

            println!("Using buffersize: {:?}", buffersize);
            let mut buffer = vec![0; buffersize];

            while let Ok(n) = handle.read(&mut buffer) {
                eprintln!("Data read: {}", n);
                if n == 0 {
                    break;
                };
                eprintln!("Read data!");
                if let Err(e) = io::stdout().write_all(&buffer) {
                    eprintln!("{}", e);
                }
            }
        }
        Err(error) => {
            eprintln!("{}", error);
        }
    }
}
<commit_msg>Removed unnecessary prints<commit_after>use std::env;
use std::io::{self, Write};
use std::fs::File;
use std::io::prelude::*;

//#[cfg(unix)]
//use std::os::unix::fs::MetadataExt;

#[cfg(linux)]
use std::os::linux::fs::MetadataExt;

#[cfg(target_os="macos")]
use std::os::macos::fs::MetadataExt;

fn main() {
    let args: Vec<String> = env::args().collect();

    for file in &args[1..] {
        read_file(file);
    }
}

fn read_file(file: &String) {
    let mut buffersize: usize = 1024;
    match File::open(file) {
        Ok(mut handle) => {
            if let Ok(meta) = handle.metadata() {
                let blk = meta.st_blksize();
                if blk < std::usize::MAX as u64 {
                    buffersize = blk as usize;
                }
            }

            let mut buffer = vec![0; buffersize];

            while let Ok(n) = handle.read(&mut buffer) {
                if n == 0 {
                    break;
                };
                if let Err(e) = io::stdout().write_all(&buffer) {
                    eprintln!("{}", e);
                }
            }
        }
        Err(error) => {
            eprintln!("{}", error);
        }
    }
}
<|endoftext|>