<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
#![macro_use]

use std::fmt;
use std::mem;
use std::num::NumCast;
use std::ops::{
    Index,
    Mul,
};
use std::raw::Slice;
use std::slice::AsSlice;
use blas::matrix::Matrix;
use blas::matrix::ops::{
    Gemm,
};
use blas::matrix_vector::ops::{
    Gemv,
};
use blas::vector::ops::Copy;
use default::Default;

pub struct Mat<T> {
    rows: usize,
    cols: usize,
    data: Vec<T>,
}

impl<T> Mat<T> {
    #[inline]
    pub fn new() -> Mat<T> {
        let _data: Vec<T> = Vec::new();
        Mat { rows: 0, cols: 0, data: _data }
    }

    #[inline]
    pub fn from_vec(rows: usize, cols: usize, vec: Vec<T>) -> Mat<T> {
        Mat { rows: rows, cols: cols, data: vec }
    }

    #[inline]
    pub fn zero(rows: usize, cols: usize) -> Mat<T> {
        let mut _data: Vec<T> = Vec::with_capacity(rows * cols);
        unsafe { _data.set_len(rows * cols); }
        Mat { rows: rows, cols: cols, data: _data}
    }

    #[inline]
    pub fn push(&mut self, value: T) {
        self.data.push(value);
    }

    #[inline]
    pub fn rows(&self) -> usize {
        self.rows
    }

    #[inline]
    pub fn cols(&self) -> usize {
        self.cols
    }

    #[inline]
    pub unsafe fn set_rows(&mut self, rows: usize) {
        self.rows = rows;
    }

    #[inline]
    pub unsafe fn set_cols(&mut self, cols: usize) {
        self.cols = cols;
    }

    #[inline]
    pub unsafe fn as_slice<'a>(&'a self) -> &'a [T] {
        self.data.as_slice()
    }

    #[inline]
    pub unsafe fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        self.data.as_mut_slice()
    }
}

impl<T> Matrix<T> for Mat<T> {
    #[inline]
    fn rows(&self) -> i32 {
        let l: Option<i32> = NumCast::from(self.rows());
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn cols(&self) -> i32 {
        let l: Option<i32> = NumCast::from(self.cols());
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn as_ptr(&self) -> *const T {
        unsafe { self.as_slice().as_ptr() }
    }

    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T {
        unsafe { self.as_mut_slice().as_mut_ptr() }
    }
}

impl<T: Copy> Clone for Mat<T> {
    fn clone(&self) -> Mat<T> {
        let n = self.rows * self.cols;

        let mut x = Vec::with_capacity(n);
        unsafe {
            Copy::copy(&self.data, &mut x);
            x.set_len(n);
        }

        Mat::from_vec(self.rows, self.cols, x)
    }
}

impl<T: PartialEq> PartialEq for Mat<T> {
    fn eq(&self, other: &Mat<T>) -> bool {
        self.rows == other.rows &&
        self.cols == other.cols &&
        self.data == other.data
    }
}

impl<T> Index<usize> for Mat<T> {
    type Output = [T];

    fn index<'a>(&'a self, index: &usize) -> &'a [T] {
        unsafe {
            let ptr = self.data.as_slice().as_ptr().offset((*index * self.cols) as isize);
            mem::transmute(Slice { data: ptr, len: self.cols })
        }
    }
}

impl<T: fmt::Show> fmt::Show for Mat<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for i in 0usize..self.rows {
            match writeln!(f, "{}", &self[i]) {
                Ok(_) => (),
                x => return x,
            }
        }

        Ok(())
    }
}

impl<'a, 'b, T> Mul<&'a Vec<T>> for &'b Mat<T>
where T: Default + Gemv {
    type Output = Vec<T>;

    fn mul(self, x: &'a Vec<T>) -> Vec<T> {
        let mut result = Vec::with_capacity(self.rows);

        Gemv::gemv(&Default::one(), self, x, &Default::zero(), &mut result);
        unsafe { result.set_len(self.rows); }

        result
    }
}

impl<'a, 'b, T> Mul<&'a Mat<T>> for &'b Mat<T>
where T: Default + Gemm {
    type Output = Mat<T>;

    fn mul(self, b: &'a Mat<T>) -> Mat<T> {
        let mut result = Mat::zero(self.cols, b.rows);
        Gemm::gemm(&Default::one(), self, b, &Default::zero(), &mut result);

        result
    }
}

#[macro_export]
macro_rules! mat(
    ($($($e: expr),+);*) => ({
        // leading _ to allow empty construction without a warning.
        let mut _temp = Mat::new();
        let mut rows = 0u;
        let mut _cols;
        $(
            rows += 1;
            _cols = 0u;
            $(
                _cols += 1;
                _temp.push($e);
            )+
        )*

        unsafe {
            _temp.set_rows(rows);
            _temp.set_cols(_cols);
        }

        _temp
    });
);

#[cfg(test)]
mod tests {
    extern crate test;

    use mat::Mat;

    #[test]
    fn index() {
        let a = mat![1f32, 2f32];
        assert_eq!(1.0, a[0][0]);
        assert_eq!(2.0, a[0][1]);

        let b = mat![1f32; 2f32];
        assert_eq!(1.0, b[0][0]);
        assert_eq!(2.0, b[1][0]);

        let m = mat![1f32, 2f32; 3f32, 4f32];
        assert_eq!(1.0, m[0][0]);
        assert_eq!(2.0, m[0][1]);
        assert_eq!(3.0, m[1][0]);
        assert_eq!(4.0, m[1][1]);
    }

    #[test]
    fn mul_vec() {
        let a = mat![1f32, -2f32; 2f32, -4f32];
        let x = vec![2f32, 1f32];

        assert_eq!(&a * &x, vec![0f32, 0f32]);
    }

    #[test]
    fn mul_mat() {
        let a = mat![1f32, -2f32; 2f32, -4f32];
        let b = mat![1f32, -2f32; 2f32, -4f32];

        let result = mat![-3f32, 6f32; -6f32, 12f32];
        assert_eq!(&a * &b, result);
    }
}
<commit_msg>Chang Show trait to Debug<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
#![macro_use]

use std::fmt;
use std::mem;
use std::num::NumCast;
use std::ops::{
    Index,
    Mul,
};
use std::raw::Slice;
use std::slice::AsSlice;
use blas::matrix::Matrix;
use blas::matrix::ops::{
    Gemm,
};
use blas::matrix_vector::ops::{
    Gemv,
};
use blas::vector::ops::Copy;
use default::Default;

pub struct Mat<T> {
    rows: usize,
    cols: usize,
    data: Vec<T>,
}

impl<T> Mat<T> {
    #[inline]
    pub fn new() -> Mat<T> {
        let _data: Vec<T> = Vec::new();
        Mat { rows: 0, cols: 0, data: _data }
    }

    #[inline]
    pub fn from_vec(rows: usize, cols: usize, vec: Vec<T>) -> Mat<T> {
        Mat { rows: rows, cols: cols, data: vec }
    }

    #[inline]
    pub fn zero(rows: usize, cols: usize) -> Mat<T> {
        let mut _data: Vec<T> = Vec::with_capacity(rows * cols);
        unsafe { _data.set_len(rows * cols); }
        Mat { rows: rows, cols: cols, data: _data}
    }

    #[inline]
    pub fn push(&mut self, value: T) {
        self.data.push(value);
    }

    #[inline]
    pub fn rows(&self) -> usize {
        self.rows
    }

    #[inline]
    pub fn cols(&self) -> usize {
        self.cols
    }

    #[inline]
    pub unsafe fn set_rows(&mut self, rows: usize) {
        self.rows = rows;
    }

    #[inline]
    pub unsafe fn set_cols(&mut self, cols: usize) {
        self.cols = cols;
    }

    #[inline]
    pub unsafe fn as_slice<'a>(&'a self) -> &'a [T] {
        self.data.as_slice()
    }

    #[inline]
    pub unsafe fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        self.data.as_mut_slice()
    }
}

impl<T> Matrix<T> for Mat<T> {
    #[inline]
    fn rows(&self) -> i32 {
        let l: Option<i32> = NumCast::from(self.rows());
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn cols(&self) -> i32 {
        let l: Option<i32> = NumCast::from(self.cols());
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn as_ptr(&self) -> *const T {
        unsafe { self.as_slice().as_ptr() }
    }

    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T {
        unsafe { self.as_mut_slice().as_mut_ptr() }
    }
}

impl<T: Copy> Clone for Mat<T> {
    fn clone(&self) -> Mat<T> {
        let n = self.rows * self.cols;

        let mut x = Vec::with_capacity(n);
        unsafe {
            Copy::copy(&self.data, &mut x);
            x.set_len(n);
        }

        Mat::from_vec(self.rows, self.cols, x)
    }
}

impl<T: PartialEq> PartialEq for Mat<T> {
    fn eq(&self, other: &Mat<T>) -> bool {
        self.rows == other.rows &&
        self.cols == other.cols &&
        self.data == other.data
    }
}

impl<T> Index<usize> for Mat<T> {
    type Output = [T];

    fn index<'a>(&'a self, index: usize) -> &'a [T] {
        unsafe {
            let ptr = self.data.as_slice().as_ptr().offset((index * self.cols) as isize);
            mem::transmute(Slice { data: ptr, len: self.cols })
        }
    }
}

impl<T: fmt::Debug> fmt::Debug for Mat<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for i in 0usize..self.rows {
            for j in 0usize..self.cols {
                match write!(f, "{:?}", self[i][j]) {
                    Ok(_) => (),
                    x => return x,
                }
            }

            match writeln!(f, "") {
                Ok(_) => (),
                x => return x,
            }
        }

        Ok(())
    }
}

impl<'a, 'b, T> Mul<&'a Vec<T>> for &'b Mat<T>
where T: Default + Gemv {
    type Output = Vec<T>;

    fn mul(self, x: &'a Vec<T>) -> Vec<T> {
        let mut result = Vec::with_capacity(self.rows);

        Gemv::gemv(&Default::one(), self, x, &Default::zero(), &mut result);
        unsafe { result.set_len(self.rows); }

        result
    }
}

impl<'a, 'b, T> Mul<&'a Mat<T>> for &'b Mat<T>
where T: Default + Gemm {
    type Output = Mat<T>;

    fn mul(self, b: &'a Mat<T>) -> Mat<T> {
        let mut result = Mat::zero(self.cols, b.rows);
        Gemm::gemm(&Default::one(), self, b, &Default::zero(), &mut result);

        result
    }
}

#[macro_export]
macro_rules! mat(
    ($($($e: expr),+);*) => ({
        // leading _ to allow empty construction without a warning.
        let mut _temp = Mat::new();
        let mut rows = 0u;
        let mut _cols;
        $(
            rows += 1;
            _cols = 0u;
            $(
                _cols += 1;
                _temp.push($e);
            )+
        )*

        unsafe {
            _temp.set_rows(rows);
            _temp.set_cols(_cols);
        }

        _temp
    });
);

#[cfg(test)]
mod tests {
    extern crate test;

    use mat::Mat;

    #[test]
    fn index() {
        let a = mat![1f32, 2f32];
        assert_eq!(1.0, a[0][0]);
        assert_eq!(2.0, a[0][1]);

        let b = mat![1f32; 2f32];
        assert_eq!(1.0, b[0][0]);
        assert_eq!(2.0, b[1][0]);

        let m = mat![1f32, 2f32; 3f32, 4f32];
        assert_eq!(1.0, m[0][0]);
        assert_eq!(2.0, m[0][1]);
        assert_eq!(3.0, m[1][0]);
        assert_eq!(4.0, m[1][1]);
    }

    #[test]
    fn mul_vec() {
        let a = mat![1f32, -2f32; 2f32, -4f32];
        let x = vec![2f32, 1f32];

        assert_eq!(&a * &x, vec![0f32, 0f32]);
    }

    #[test]
    fn mul_mat() {
        let a = mat![1f32, -2f32; 2f32, -4f32];
        let b = mat![1f32, -2f32; 2f32, -4f32];

        let result = mat![-3f32, 6f32; -6f32, 12f32];
        assert_eq!(&a * &b, result);
    }
}
<|endoftext|>


<commit_before>use cairo;
use cairo::MatrixTrait;
use cairo_sys;
use glib::translate::*;
use glib_sys;
use libc;
use pango;
use pango_sys;
use std::ptr;

use bbox::RsvgBbox;
use length::LengthUnit;
use node::NodeType;
use node::RsvgNode;
use state::{self, BaselineShift, FontSize, RsvgState};

pub enum RsvgDrawingCtx {}

#[allow(improper_ctypes)]
extern "C" {
    fn rsvg_drawing_ctx_get_current_state(draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState;
    fn rsvg_drawing_ctx_set_current_state(draw_ctx: *mut RsvgDrawingCtx, state: *mut RsvgState);

    fn rsvg_drawing_ctx_get_dpi(
        draw_ctx: *const RsvgDrawingCtx,
        out_dpi_x: *mut f64,
        out_dpi_y: *mut f64,
    );

    fn rsvg_drawing_ctx_get_view_box_size(
        draw_ctx: *const RsvgDrawingCtx,
        out_x: *mut f64,
        out_y: *mut f64,
    );

    fn rsvg_drawing_ctx_push_view_box(draw_ctx: *const RsvgDrawingCtx, width: f64, height: f64);

    fn rsvg_drawing_ctx_pop_view_box(draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_drawing_ctx_acquire_node(
        draw_ctx: *const RsvgDrawingCtx,
        url: *const libc::c_char,
    ) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_acquire_node_of_type(
        draw_ctx: *const RsvgDrawingCtx,
        url: *const libc::c_char,
        node_type: NodeType,
    ) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_release_node(draw_ctx: *const RsvgDrawingCtx, node: *mut RsvgNode);

    fn rsvg_drawing_ctx_set_affine_on_cr(
        draw_ctx: *const RsvgDrawingCtx,
        cr: *mut cairo_sys::cairo_t,
        affine: *const cairo::Matrix,
    );

    fn rsvg_drawing_ctx_get_pango_context(
        draw_ctx: *const RsvgDrawingCtx,
    ) -> *mut pango_sys::PangoContext;

    fn rsvg_drawing_ctx_insert_bbox(draw_ctx: *const RsvgDrawingCtx, bbox: *const RsvgBbox);

    fn rsvg_drawing_ctx_draw_node_from_stack(
        draw_ctx: *const RsvgDrawingCtx,
        node: *const RsvgNode,
        dominate: i32,
        clipping: glib_sys::gboolean,
    );

    fn rsvg_push_discrete_layer(draw_ctx: *const RsvgDrawingCtx, clipping: glib_sys::gboolean);
    fn rsvg_pop_discrete_layer(draw_ctx: *const RsvgDrawingCtx, clipping: glib_sys::gboolean);

    fn rsvg_cairo_get_cairo_context(draw_ctx: *const RsvgDrawingCtx) -> *mut cairo_sys::cairo_t;
    fn rsvg_cairo_set_cairo_context(draw_ctx: *const RsvgDrawingCtx, cr: *const cairo_sys::cairo_t);
}

pub fn get_dpi(draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut dpi_x: f64 = 0.0;
    let mut dpi_y: f64 = 0.0;

    unsafe {
        rsvg_drawing_ctx_get_dpi(draw_ctx, &mut dpi_x, &mut dpi_y);
    }

    (dpi_x, dpi_y)
}

pub fn get_normalized_font_size(draw_ctx: *const RsvgDrawingCtx) -> f64 {
    normalize_font_size(draw_ctx, get_current_state(draw_ctx))
}

pub fn get_accumulated_baseline_shift(draw_ctx: *const RsvgDrawingCtx) -> f64 {
    let mut shift = 0f64;

    let mut state = get_current_state(draw_ctx);
    while let Some(parent) = state::parent(state) {
        if let Some(BaselineShift(ref s)) = state::get_state_rust(state).baseline_shift {
            let parent_font_size = normalize_font_size(draw_ctx, parent);
            shift += s * parent_font_size;
        }
        state = parent;
    }

    shift
}

// Recursive evaluation of all parent elements regarding absolute font size
fn normalize_font_size(draw_ctx: *const RsvgDrawingCtx, state: *const RsvgState) -> f64 {
    let font_size = state::get_state_rust(state)
        .font_size
        .as_ref()
        .map_or_else(|| FontSize::default().0, |fs| fs.0);

    match font_size.unit {
        LengthUnit::Percent | LengthUnit::FontEm | LengthUnit::FontEx => {
            parent_font_size(draw_ctx, state) * font_size.length
        }
        LengthUnit::RelativeLarger => parent_font_size(draw_ctx, state) * 1.2f64,
        LengthUnit::RelativeSmaller => parent_font_size(draw_ctx, state) / 1.2f64,

        _ => font_size.normalize(draw_ctx),
    }
}

fn parent_font_size(draw_ctx: *const RsvgDrawingCtx, state: *const RsvgState) -> f64 {
    state::parent(state).map_or(12f64, |p| normalize_font_size(draw_ctx, p))
}

pub fn get_view_box_size(draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut w: f64 = 0.0;
    let mut h: f64 = 0.0;

    unsafe {
        rsvg_drawing_ctx_get_view_box_size(draw_ctx, &mut w, &mut h);
    }

    (w, h)
}

pub fn push_view_box(draw_ctx: *const RsvgDrawingCtx, width: f64, height: f64) {
    unsafe {
        rsvg_drawing_ctx_push_view_box(draw_ctx, width, height);
    }
}

pub fn pop_view_box(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_drawing_ctx_pop_view_box(draw_ctx);
    }
}

pub fn get_acquired_node(draw_ctx: *const RsvgDrawingCtx, url: &str) -> Option<AcquiredNode> {
    let raw_node = unsafe { rsvg_drawing_ctx_acquire_node(draw_ctx, str::to_glib_none(url).0) };

    if raw_node.is_null() {
        None
    } else {
        Some(AcquiredNode(draw_ctx, raw_node))
    }
}

pub fn get_acquired_node_of_type(
    draw_ctx: *const RsvgDrawingCtx,
    url: &str,
    node_type: NodeType,
) -> Option<AcquiredNode> {
    let raw_node = unsafe {
        rsvg_drawing_ctx_acquire_node_of_type(draw_ctx, str::to_glib_none(url).0, node_type)
    };

    if raw_node.is_null() {
        None
    } else {
        Some(AcquiredNode(draw_ctx, raw_node))
    }
}

// A function for modifying the top of the state stack depending on a
// flag given. If that flag is 0, style and transform will inherit
// normally. If that flag is 1, style will inherit normally with the
// exception that any value explicity set on the second last level
// will have a higher precedence than values set on the last level.
// If the flag equals two then the style will be overridden totally
// however the transform will be left as is. This is because of
// patterns which are not based on the context of their use and are
// rather based wholly on their own loading context. Other things
// may want to have this totally disabled, and a value of three will
// achieve this.
pub fn state_reinherit_top(draw_ctx: *const RsvgDrawingCtx, state: *mut RsvgState, dominate: i32) {
    let current = get_current_state(draw_ctx);

    match dominate {
        3 => unreachable!(),

        // This is a special domination mode for patterns, the transform
        // is simply left as is, wheras the style is totally overridden
        2 => state::force(current, state),

        dominate => {
            state::clone_from(current, state);

            if let Some(parent) = state::parent(current) {
                if dominate == 0 {
                    state::reinherit(current, parent);
                } else {
                    state::dominate(current, parent);
                }

                let mut rcurrent = state::get_state_rust(current);
                let rparent = state::get_state_rust(parent);
                rcurrent.affine = cairo::Matrix::multiply(&rcurrent.affine, &rparent.affine);
            }
        }
    }
}

pub fn push_discrete_layer(draw_ctx: *const RsvgDrawingCtx, clipping: bool) {
    unsafe {
        rsvg_push_discrete_layer(draw_ctx, clipping.to_glib());
    }
}

pub fn pop_discrete_layer(draw_ctx: *const RsvgDrawingCtx, clipping: bool) {
    unsafe {
        rsvg_pop_discrete_layer(draw_ctx, clipping.to_glib());
    }
}

pub fn get_cairo_context(draw_ctx: *const RsvgDrawingCtx) -> cairo::Context {
    unsafe {
        let raw_cr = rsvg_cairo_get_cairo_context(draw_ctx);

        cairo::Context::from_glib_none(raw_cr)
    }
}

pub fn set_cairo_context(draw_ctx: *const RsvgDrawingCtx, cr: &cairo::Context) {
    unsafe {
        let raw_cr = cr.to_glib_none().0;

        rsvg_cairo_set_cairo_context(draw_ctx, raw_cr);
    }
}

pub fn set_affine_on_cr(
    draw_ctx: *const RsvgDrawingCtx,
    cr: &cairo::Context,
    affine: &cairo::Matrix,
) {
    unsafe {
        rsvg_drawing_ctx_set_affine_on_cr(
            draw_ctx,
            cr.to_glib_none().0,
            affine as *const cairo::Matrix,
        );
    }
}

pub fn get_pango_context(draw_ctx: *const RsvgDrawingCtx) -> pango::Context {
    unsafe { from_glib_full(rsvg_drawing_ctx_get_pango_context(draw_ctx)) }
}

pub fn insert_bbox(draw_ctx: *const RsvgDrawingCtx, bbox: &RsvgBbox) {
    unsafe {
        rsvg_drawing_ctx_insert_bbox(draw_ctx, bbox as *const _);
    }
}

pub fn draw_node_from_stack(
    draw_ctx: *const RsvgDrawingCtx,
    node: *const RsvgNode,
    dominate: i32,
    clipping: bool,
) {
    unsafe {
        rsvg_drawing_ctx_draw_node_from_stack(draw_ctx, node, dominate, clipping.to_glib());
    }
}

pub fn get_current_state(draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState {
    unsafe { rsvg_drawing_ctx_get_current_state(draw_ctx) }
}

pub fn state_push(draw_ctx: *mut RsvgDrawingCtx) {
    let state = state::new_with_parent(get_current_state(draw_ctx));

    unsafe {
        rsvg_drawing_ctx_set_current_state(draw_ctx, state);
    }
}

pub fn state_pop(draw_ctx: *mut RsvgDrawingCtx) {
    let state = get_current_state(draw_ctx);

    unsafe {
        let parent = state::parent(state).unwrap_or(ptr::null_mut());
        rsvg_drawing_ctx_set_current_state(draw_ctx, parent);
        state::free(state);
    }
}

pub struct AcquiredNode(*const RsvgDrawingCtx, *mut RsvgNode);

impl Drop for AcquiredNode {
    fn drop(&mut self) {
        unsafe {
            rsvg_drawing_ctx_release_node(self.0, self.1);
        }
    }
}

impl AcquiredNode {
    pub fn get(&self) -> RsvgNode {
        unsafe { (*self.1).clone() }
    }
}

#[no_mangle]
pub extern "C" fn rsvg_drawing_ctx_state_push(draw_ctx: *mut RsvgDrawingCtx) {
    state_push(draw_ctx);
}

#[no_mangle]
pub extern "C" fn rsvg_drawing_ctx_state_pop(draw_ctx: *mut RsvgDrawingCtx) {
    state_pop(draw_ctx);
}
<commit_msg>drawing_ctx::insert_ink_bbox() - Bind to Rust<commit_after>use cairo;
use cairo::MatrixTrait;
use cairo_sys;
use glib::translate::*;
use glib_sys;
use libc;
use pango;
use pango_sys;
use std::ptr;

use bbox::RsvgBbox;
use length::LengthUnit;
use node::NodeType;
use node::RsvgNode;
use state::{self, BaselineShift, FontSize, RsvgState};

pub enum RsvgDrawingCtx {}

#[allow(improper_ctypes)]
extern "C" {
    fn rsvg_drawing_ctx_get_current_state(draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState;
    fn rsvg_drawing_ctx_set_current_state(draw_ctx: *mut RsvgDrawingCtx, state: *mut RsvgState);

    fn rsvg_drawing_ctx_get_dpi(
        draw_ctx: *const RsvgDrawingCtx,
        out_dpi_x: *mut f64,
        out_dpi_y: *mut f64,
    );

    fn rsvg_drawing_ctx_get_view_box_size(
        draw_ctx: *const RsvgDrawingCtx,
        out_x: *mut f64,
        out_y: *mut f64,
    );

    fn rsvg_drawing_ctx_push_view_box(draw_ctx: *const RsvgDrawingCtx, width: f64, height: f64);

    fn rsvg_drawing_ctx_pop_view_box(draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_drawing_ctx_acquire_node(
        draw_ctx: *const RsvgDrawingCtx,
        url: *const libc::c_char,
    ) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_acquire_node_of_type(
        draw_ctx: *const RsvgDrawingCtx,
        url: *const libc::c_char,
        node_type: NodeType,
    ) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_release_node(draw_ctx: *const RsvgDrawingCtx, node: *mut RsvgNode);

    fn rsvg_drawing_ctx_set_affine_on_cr(
        draw_ctx: *const RsvgDrawingCtx,
        cr: *mut cairo_sys::cairo_t,
        affine: *const cairo::Matrix,
    );

    fn rsvg_drawing_ctx_get_pango_context(
        draw_ctx: *const RsvgDrawingCtx,
    ) -> *mut pango_sys::PangoContext;

    fn rsvg_drawing_ctx_insert_bbox(draw_ctx: *const RsvgDrawingCtx, bbox: *const RsvgBbox);
    fn rsvg_drawing_ctx_insert_ink_bbox(draw_ctx: *const RsvgDrawingCtx, ink_bbox: *const RsvgBbox);

    fn rsvg_drawing_ctx_draw_node_from_stack(
        draw_ctx: *const RsvgDrawingCtx,
        node: *const RsvgNode,
        dominate: i32,
        clipping: glib_sys::gboolean,
    );

    fn rsvg_push_discrete_layer(draw_ctx: *const RsvgDrawingCtx, clipping: glib_sys::gboolean);
    fn rsvg_pop_discrete_layer(draw_ctx: *const RsvgDrawingCtx, clipping: glib_sys::gboolean);

    fn rsvg_cairo_get_cairo_context(draw_ctx: *const RsvgDrawingCtx) -> *mut cairo_sys::cairo_t;
    fn rsvg_cairo_set_cairo_context(draw_ctx: *const RsvgDrawingCtx, cr: *const cairo_sys::cairo_t);
}

pub fn get_dpi(draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut dpi_x: f64 = 0.0;
    let mut dpi_y: f64 = 0.0;

    unsafe {
        rsvg_drawing_ctx_get_dpi(draw_ctx, &mut dpi_x, &mut dpi_y);
    }

    (dpi_x, dpi_y)
}

pub fn get_normalized_font_size(draw_ctx: *const RsvgDrawingCtx) -> f64 {
    normalize_font_size(draw_ctx, get_current_state(draw_ctx))
}

pub fn get_accumulated_baseline_shift(draw_ctx: *const RsvgDrawingCtx) -> f64 {
    let mut shift = 0f64;

    let mut state = get_current_state(draw_ctx);
    while let Some(parent) = state::parent(state) {
        if let Some(BaselineShift(ref s)) = state::get_state_rust(state).baseline_shift {
            let parent_font_size = normalize_font_size(draw_ctx, parent);
            shift += s * parent_font_size;
        }
        state = parent;
    }

    shift
}

// Recursive evaluation of all parent elements regarding absolute font size
fn normalize_font_size(draw_ctx: *const RsvgDrawingCtx, state: *const RsvgState) -> f64 {
    let font_size = state::get_state_rust(state)
        .font_size
        .as_ref()
        .map_or_else(|| FontSize::default().0, |fs| fs.0);

    match font_size.unit {
        LengthUnit::Percent | LengthUnit::FontEm | LengthUnit::FontEx => {
            parent_font_size(draw_ctx, state) * font_size.length
        }
        LengthUnit::RelativeLarger => parent_font_size(draw_ctx, state) * 1.2f64,
        LengthUnit::RelativeSmaller => parent_font_size(draw_ctx, state) / 1.2f64,

        _ => font_size.normalize(draw_ctx),
    }
}

fn parent_font_size(draw_ctx: *const RsvgDrawingCtx, state: *const RsvgState) -> f64 {
    state::parent(state).map_or(12f64, |p| normalize_font_size(draw_ctx, p))
}

pub fn get_view_box_size(draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut w: f64 = 0.0;
    let mut h: f64 = 0.0;

    unsafe {
        rsvg_drawing_ctx_get_view_box_size(draw_ctx, &mut w, &mut h);
    }

    (w, h)
}

pub fn push_view_box(draw_ctx: *const RsvgDrawingCtx, width: f64, height: f64) {
    unsafe {
        rsvg_drawing_ctx_push_view_box(draw_ctx, width, height);
    }
}

pub fn pop_view_box(draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_drawing_ctx_pop_view_box(draw_ctx);
    }
}

pub fn get_acquired_node(draw_ctx: *const RsvgDrawingCtx, url: &str) -> Option<AcquiredNode> {
    let raw_node = unsafe { rsvg_drawing_ctx_acquire_node(draw_ctx, str::to_glib_none(url).0) };

    if raw_node.is_null() {
        None
    } else {
        Some(AcquiredNode(draw_ctx, raw_node))
    }
}

pub fn get_acquired_node_of_type(
    draw_ctx: *const RsvgDrawingCtx,
    url: &str,
    node_type: NodeType,
) -> Option<AcquiredNode> {
    let raw_node = unsafe {
        rsvg_drawing_ctx_acquire_node_of_type(draw_ctx, str::to_glib_none(url).0, node_type)
    };

    if raw_node.is_null() {
        None
    } else {
        Some(AcquiredNode(draw_ctx, raw_node))
    }
}

// A function for modifying the top of the state stack depending on a
// flag given. If that flag is 0, style and transform will inherit
// normally. If that flag is 1, style will inherit normally with the
// exception that any value explicity set on the second last level
// will have a higher precedence than values set on the last level.
// If the flag equals two then the style will be overridden totally
// however the transform will be left as is. This is because of
// patterns which are not based on the context of their use and are
// rather based wholly on their own loading context. Other things
// may want to have this totally disabled, and a value of three will
// achieve this.
pub fn state_reinherit_top(draw_ctx: *const RsvgDrawingCtx, state: *mut RsvgState, dominate: i32) {
    let current = get_current_state(draw_ctx);

    match dominate {
        3 => unreachable!(),

        // This is a special domination mode for patterns, the transform
        // is simply left as is, wheras the style is totally overridden
        2 => state::force(current, state),

        dominate => {
            state::clone_from(current, state);

            if let Some(parent) = state::parent(current) {
                if dominate == 0 {
                    state::reinherit(current, parent);
                } else {
                    state::dominate(current, parent);
                }

                let mut rcurrent = state::get_state_rust(current);
                let rparent = state::get_state_rust(parent);
                rcurrent.affine = cairo::Matrix::multiply(&rcurrent.affine, &rparent.affine);
            }
        }
    }
}

pub fn push_discrete_layer(draw_ctx: *const RsvgDrawingCtx, clipping: bool) {
    unsafe {
        rsvg_push_discrete_layer(draw_ctx, clipping.to_glib());
    }
}

pub fn pop_discrete_layer(draw_ctx: *const RsvgDrawingCtx, clipping: bool) {
    unsafe {
        rsvg_pop_discrete_layer(draw_ctx, clipping.to_glib());
    }
}

pub fn get_cairo_context(draw_ctx: *const RsvgDrawingCtx) -> cairo::Context {
    unsafe {
        let raw_cr = rsvg_cairo_get_cairo_context(draw_ctx);

        cairo::Context::from_glib_none(raw_cr)
    }
}

pub fn set_cairo_context(draw_ctx: *const RsvgDrawingCtx, cr: &cairo::Context) {
    unsafe {
        let raw_cr = cr.to_glib_none().0;

        rsvg_cairo_set_cairo_context(draw_ctx, raw_cr);
    }
}

pub fn set_affine_on_cr(
    draw_ctx: *const RsvgDrawingCtx,
    cr: &cairo::Context,
    affine: &cairo::Matrix,
) {
    unsafe {
        rsvg_drawing_ctx_set_affine_on_cr(
            draw_ctx,
            cr.to_glib_none().0,
            affine as *const cairo::Matrix,
        );
    }
}

pub fn get_pango_context(draw_ctx: *const RsvgDrawingCtx) -> pango::Context {
    unsafe { from_glib_full(rsvg_drawing_ctx_get_pango_context(draw_ctx)) }
}

pub fn insert_bbox(draw_ctx: *const RsvgDrawingCtx, bbox: &RsvgBbox) {
    unsafe {
        rsvg_drawing_ctx_insert_bbox(draw_ctx, bbox as *const _);
    }
}

pub fn insert_ink_bbox(draw_ctx: *const RsvgDrawingCtx, ink_bbox: &RsvgBbox) {
    unsafe {
        rsvg_drawing_ctx_insert_ink_bbox(draw_ctx, ink_bbox as *const _);
    }
}

pub fn draw_node_from_stack(
    draw_ctx: *const RsvgDrawingCtx,
    node: *const RsvgNode,
    dominate: i32,
    clipping: bool,
) {
    unsafe {
        rsvg_drawing_ctx_draw_node_from_stack(draw_ctx, node, dominate, clipping.to_glib());
    }
}

pub fn get_current_state(draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState {
    unsafe { rsvg_drawing_ctx_get_current_state(draw_ctx) }
}

pub fn state_push(draw_ctx: *mut RsvgDrawingCtx) {
    let state = state::new_with_parent(get_current_state(draw_ctx));

    unsafe {
        rsvg_drawing_ctx_set_current_state(draw_ctx, state);
    }
}

pub fn state_pop(draw_ctx: *mut RsvgDrawingCtx) {
    let state = get_current_state(draw_ctx);

    unsafe {
        let parent = state::parent(state).unwrap_or(ptr::null_mut());
        rsvg_drawing_ctx_set_current_state(draw_ctx, parent);
        state::free(state);
    }
}

pub struct AcquiredNode(*const RsvgDrawingCtx, *mut RsvgNode);

impl Drop for AcquiredNode {
    fn drop(&mut self) {
        unsafe {
            rsvg_drawing_ctx_release_node(self.0, self.1);
        }
    }
}

impl AcquiredNode {
    pub fn get(&self) -> RsvgNode {
        unsafe { (*self.1).clone() }
    }
}

#[no_mangle]
pub extern "C" fn rsvg_drawing_ctx_state_push(draw_ctx: *mut RsvgDrawingCtx) {
    state_push(draw_ctx);
}

#[no_mangle]
pub extern "C" fn rsvg_drawing_ctx_state_pop(draw_ctx: *mut RsvgDrawingCtx) {
    state_pop(draw_ctx);
}
<|endoftext|>


<commit_before>//! A single pod in a project.

use compose_yml::v2 as dc;
use compose_yml::v2::MergeOverride;
use serde_yaml;
use std::collections::BTreeMap;
use std::collections::btree_map;
use std::ffi::OsString;
use std::fs;
use std::path::{Path, PathBuf};
use std::str::FromStr;

use ovr::Override;
use project::Project;
use util::Error;

// Include some source code containing data structures we need to run
// through serde.
#[cfg(feature = "serde_macros")]
include!(concat!("pod_config.in.rs"));
#[cfg(feature = "serde_codegen")]
include!(concat!(env!("OUT_DIR"), "/pod_config.rs"));

/// Information about a `docker-compose.yml` file, including its path
/// relative to `base_dir` (`base_dir` is normally `$PROJECT/pods`), and
/// the normalized version of its contents:
///
/// 1. Any missing services will be explicitly added to an override file.
/// 2. The `env_file` list will be updated to contain the appropriate
///    `common.yml` file.
///
/// If this file doesn't actually exist on disk, we'll still fill in the
/// default contents as above.
///
/// If you need to process this further, clone the `File` and work on the
/// clone.  This is the master copy.
#[derive(Debug)]
struct FileInfo {
    /// The path to this file relative to `pods/`.
    rel_path: PathBuf,
    /// Either the data we loaded from file, or default data if the file
    /// didn't exist.
    file: dc::File,
}

impl FileInfo {
    /// Create a `FileInfo` by either loading `base_dir.join(rel_path)` or
    /// by creating an empty `dc::File` in its place.  Do not perform
    /// normalization.
    fn unnormalized(base_dir: &Path, rel_path: &Path) -> Result<FileInfo, Error> {
        let path = base_dir.join(rel_path);
        Ok(FileInfo {
            rel_path: rel_path.to_owned(),
            file: if path.exists() {
                debug!("Parsing {}", path.display());
                try!(dc::File::read_from_path(&path).map_err(|e| {
                    // Make sure we tie parse errors to a specific file, for
                    // the sake of sanity.
                    err!("Error parsing {}: {}", path.display(), e)
                }))
            } else {
                Default::default()
            },
        })
    }

    /// Make sure that all services from `base` are also present in this
    /// file.  If you're going tp call this, it must be called after
    /// `finish_normalization`
    fn ensure_all_services_from(&mut self, base: &dc::File) {
        for name in base.services.keys() {
            self.file
                .services
                .entry(name.to_owned())
                .or_insert_with(Default::default);
        }
    }

    /// Finish normalizing this file by inserting things like `env_file`
    /// entries.
    fn finish_normalization(&mut self) {
        // It's safe to call `unwrap` here because we know `rel_path` should
        // have a parent directory.
        let env_path = self.rel_path.parent().unwrap().join("common.env");
        for service in self.file.services.values_mut() {
            service.env_files.insert(0, dc::value(env_path.clone()));
        }
    }
}

impl FromStr for PodType {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "service" => Ok(PodType::Service),
            "task" => Ok(PodType::Task),
            _ => Err(err!("Unknown pod type: <{}>", s)),
        }
    }
}

/// A pod, specified by `pods/$NAME.yml` and zero or more
/// `pods/overrides/*/*.yml` overrides that we can apply to it.
#[derive(Debug)]
pub struct Pod {
    /// All paths in any associated `dc::File` should be intepreted
    /// relative to this base, including paths in override files.
    base_dir: PathBuf,

    /// The name of this pod, based on the file `pods/$NAME.yml`.
    name: String,

    /// The top-level file defining this pod.
    file_info: FileInfo,

    /// The individual override files for this pod.  There will always be a
    /// sensible value here for each pod, even if the file doesn't exist on
    /// disk.
    override_file_infos: BTreeMap<Override, FileInfo>,

    /// Per-pod configuration.
    config: Config,
}

impl Pod {
    /// Create a new pod, specifying the base directory from which we'll load
    /// pod definitions and the name of the pod.
    #[doc(hidden)]
    pub fn new<P, S>(base_dir: P,
                     name: S,
                     overrides: &[Override])
                     -> Result<Pod, Error>
        where P: Into<PathBuf>,
              S: Into<String>
    {
        let base_dir = base_dir.into();
        let name = name.into();

        // Load our `*.metadata.yml` file, if any.
        let config_path = base_dir.join(&format!("{}.metadata.yml", &name));
        let config: Config = if config_path.exists() {
            let f = try!(fs::File::open(&config_path)
                .map_err(|e| err!("Error opening {}: {}", &config_path.display(), e)));
            try!(serde_yaml::from_reader(f)
                .map_err(|e| err!("Error reading {}: {}", &config_path.display(), e)))
        } else {
            Config::default()
        };

        // Load our main `*.yml` file.
        let rel_path = Path::new(&format!("{}.yml", &name)).to_owned();
        let mut file_info = try!(FileInfo::unnormalized(&base_dir, &rel_path));
        file_info.finish_normalization();

        // Load our override `*.yml` files.
        let mut ovr_infos = BTreeMap::new();
        for ovr in overrides {
            let ovr_rel_path =
                Path::new(&format!("overrides/{}/{}.yml", ovr.name(), &name))
                    .to_owned();
            let mut ovr_info = try!(FileInfo::unnormalized(&base_dir, &ovr_rel_path));
            ovr_info.ensure_all_services_from(&file_info.file);
            ovr_info.finish_normalization();
            ovr_infos.insert(ovr.to_owned(), ovr_info);
        }

        Ok(Pod {
            base_dir: base_dir,
            name: name,
            file_info: file_info,
            override_file_infos: ovr_infos,
            config: config,
        })
    }

    /// Get the name of this pod.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Get the type of this pod.
    pub fn pod_type(&self) -> PodType {
        self.config.pod_type.unwrap_or(PodType::Service)
    }

    /// Is this pod enabled in the specified override?
    pub fn enabled_in(&self, ovr: &Override) -> bool {
        ovr.included_by(&self.config.enable_in_overrides)
    }

    /// The base directory for our relative paths.
    pub fn base_dir(&self) -> &Path {
        &self.base_dir
    }

    /// The path to the top-level file defining this pod, relative to the
    /// `base_dir` specified at creation time.
    pub fn rel_path(&self) -> &Path {
        &self.file_info.rel_path
    }

    /// The top-level file defining this pod.  This is normalized to
    /// include the appropriate `env_file` entries, but if you want to do
    /// more complicated transformations, you'll need to clone it with
    /// `to_owned()` first.
    pub fn file(&self) -> &dc::File {
        &self.file_info.file
    }

    /// Look up the file info associated with an override, or return an
    /// error if this override was not specified for this `Pod` at creation
    /// time.
    fn override_file_info(&self, ovr: &Override) -> Result<&FileInfo, Error> {
        self.override_file_infos
            .get(ovr)
            .ok_or_else(|| err!("The override {} is not defined", ovr.name()))
    }

    /// The path to the specificied override file for this pod.
    pub fn override_rel_path(&self, ovr: &Override) -> Result<&Path, Error> {
        Ok(&(try!(self.override_file_info(ovr)).rel_path))
    }

    /// The `dc::File` for this override.
    pub fn override_file(&self, ovr: &Override) -> Result<&dc::File, Error> {
        Ok(&(try!(self.override_file_info(ovr)).file))
    }

    /// Return the base file and the override file merged into a single
    /// `docker-compose.yml` file.
    pub fn merged_file(&self, ovr: &Override) -> Result<dc::File, Error> {
        // This is expensive so log it.
        debug!("Merging pod {} with override {}", self.name(), ovr.name());
        Ok(self.file().merge_override(try!(self.override_file(ovr))))
    }

    /// All the overrides associated with this pod.
    pub fn override_files(&self) -> OverrideFiles {
        OverrideFiles { iter: self.override_file_infos.iter() }
    }

    /// Iterate over all `dc::File` objects associated with this pod, including
    /// both the main `file()` and all the files in `override_files()`.
    pub fn all_files(&self) -> AllFiles {
        // Defer all the hard work to our iterator type.
        AllFiles {
            pod: self,
            state: AllFilesState::TopLevelFile,
        }
    }

    /// Command-line `-p` and `-f` arguments that we'll pass to
    /// `docker-compose` to describe this file.
    pub fn compose_args(&self,
                        proj: &Project,
                        ovr: &Override)
                        -> Result<Vec<OsString>, Error> {
        let compose_project_name = ovr.compose_project_name(proj);
        Ok(vec!["-p".into(),
                compose_project_name.into(),
                "-f".into(),
                proj.output_pods_dir().join(self.rel_path()).into()])
    }
}

/// An iterator over this pods overrides and their associated files.
#[allow(missing_debug_implementations)]
pub struct OverrideFiles<'a> {
    /// Our wrapped iterator.
    iter: btree_map::Iter<'a, Override, FileInfo>,
}

impl<'a> Iterator for OverrideFiles<'a> {
    type Item = (&'a Override, &'a dc::File);

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(ovr, file_info)| (ovr, &file_info.file))
    }
}

/// What should we yield next from our `AllFiles` iterator?
#[allow(missing_debug_implementations)]
enum AllFilesState<'a> {
    /// Yield the top-level `file()` next.
    TopLevelFile,
    /// Yield an item from this iterator next.
    OverrideFiles(OverrideFiles<'a>),
}

/// An iterator over all the `dc::File` objects associated with a pod, in
/// all overrides.
#[allow(missing_debug_implementations)]
pub struct AllFiles<'a> {
    /// The pod whose files we're iterating over.
    pod: &'a Pod,
    /// Our current iteration state.
    state: AllFilesState<'a>,
}

impl<'a> Iterator for AllFiles<'a> {
    type Item = &'a dc::File;

    fn next(&mut self) -> Option<Self::Item> {
        // We could try to implement this by calling:
        //
        // ```
        // iter::once(pod.file())
        //     .chain(pod.override_files().map(|(_, file)| file))
        // ```
        //
        // ...and storing the result in our object, but the type of that
        // expression is exquisitely hideous and we'd go mad.
        match self.state {
            AllFilesState::TopLevelFile => {
                self.state = AllFilesState::OverrideFiles(self.pod.override_files());
                Some(self.pod.file())
            }
            AllFilesState::OverrideFiles(ref mut iter) => {
                iter.next().map(|(_, file)| file)
            }
        }
    }
}

#[test]
fn pods_are_normalized_on_load() {
    use env_logger;
    use project::Project;
    let _ = env_logger::init();

    let proj = Project::from_example("hello").unwrap();
    let frontend = proj.pod("frontend").unwrap();

    let web = frontend.file().services.get("web").unwrap();
    assert_eq!(web.env_files.len(), 1);
    assert_eq!(web.env_files[0].value().unwrap(), Path::new("common.env"));

    // This test assumes that there's no `web` entry in the `production`
    // override, so we have to create everything from scratch.
    let production = proj.ovr("production").unwrap();
    let web_ovr = frontend.override_file(production)
        .unwrap()
        .services
        .get("web")
        .unwrap();
    assert_eq!(web_ovr.env_files.len(), 1);
    assert_eq!(web_ovr.env_files[0].value().unwrap(),
               Path::new("overrides/production/common.env"));
}

#[test]
fn can_merge_base_file_and_override() {
    use env_logger;
    let _ = env_logger::init();
    let proj: Project = Project::from_example("hello").unwrap();
    let ovr = proj.ovr("development").unwrap();
    let frontend = proj.pod("frontend").unwrap();
    let merged = frontend.merged_file(ovr).unwrap();
    let proxy = merged.services.get("proxy").unwrap();
    assert_eq!(proxy.env_files.len(), 2);
}

#[test]
fn pod_type_returns_type_of_pod() {
    use env_logger;
    let _ = env_logger::init();
    let proj: Project = Project::from_example("rails_hello").unwrap();
    let frontend = proj.pod("frontend").unwrap();
    assert_eq!(frontend.pod_type(), PodType::Service);
    let migrate = proj.pod("migrate").unwrap();
    assert_eq!(migrate.pod_type(), PodType::Task);
}
<commit_msg>Remove obsolete `FromStr` impl from PodType<commit_after>//! A single pod in a project.

use compose_yml::v2 as dc;
use compose_yml::v2::MergeOverride;
use serde_yaml;
use std::collections::BTreeMap;
use std::collections::btree_map;
use std::ffi::OsString;
use std::fs;
use std::path::{Path, PathBuf};

use ovr::Override;
use project::Project;
use util::Error;

// Include some source code containing data structures we need to run
// through serde.
#[cfg(feature = "serde_macros")]
include!(concat!("pod_config.in.rs"));
#[cfg(feature = "serde_codegen")]
include!(concat!(env!("OUT_DIR"), "/pod_config.rs"));

/// Information about a `docker-compose.yml` file, including its path
/// relative to `base_dir` (`base_dir` is normally `$PROJECT/pods`), and
/// the normalized version of its contents:
///
/// 1. Any missing services will be explicitly added to an override file.
/// 2. The `env_file` list will be updated to contain the appropriate
///    `common.yml` file.
///
/// If this file doesn't actually exist on disk, we'll still fill in the
/// default contents as above.
///
/// If you need to process this further, clone the `File` and work on the
/// clone.  This is the master copy.
#[derive(Debug)]
struct FileInfo {
    /// The path to this file relative to `pods/`.
    rel_path: PathBuf,
    /// Either the data we loaded from file, or default data if the file
    /// didn't exist.
    file: dc::File,
}

impl FileInfo {
    /// Create a `FileInfo` by either loading `base_dir.join(rel_path)` or
    /// by creating an empty `dc::File` in its place.  Do not perform
    /// normalization.
    fn unnormalized(base_dir: &Path, rel_path: &Path) -> Result<FileInfo, Error> {
        let path = base_dir.join(rel_path);
        Ok(FileInfo {
            rel_path: rel_path.to_owned(),
            file: if path.exists() {
                debug!("Parsing {}", path.display());
                try!(dc::File::read_from_path(&path).map_err(|e| {
                    // Make sure we tie parse errors to a specific file, for
                    // the sake of sanity.
                    err!("Error parsing {}: {}", path.display(), e)
                }))
            } else {
                Default::default()
            },
        })
    }

    /// Make sure that all services from `base` are also present in this
    /// file.  If you're going tp call this, it must be called after
    /// `finish_normalization`
    fn ensure_all_services_from(&mut self, base: &dc::File) {
        for name in base.services.keys() {
            self.file
                .services
                .entry(name.to_owned())
                .or_insert_with(Default::default);
        }
    }

    /// Finish normalizing this file by inserting things like `env_file`
    /// entries.
    fn finish_normalization(&mut self) {
        // It's safe to call `unwrap` here because we know `rel_path` should
        // have a parent directory.
        let env_path = self.rel_path.parent().unwrap().join("common.env");
        for service in self.file.services.values_mut() {
            service.env_files.insert(0, dc::value(env_path.clone()));
        }
    }
}

/// A pod, specified by `pods/$NAME.yml` and zero or more
/// `pods/overrides/*/*.yml` overrides that we can apply to it.
#[derive(Debug)]
pub struct Pod {
    /// All paths in any associated `dc::File` should be intepreted
    /// relative to this base, including paths in override files.
    base_dir: PathBuf,

    /// The name of this pod, based on the file `pods/$NAME.yml`.
    name: String,

    /// The top-level file defining this pod.
    file_info: FileInfo,

    /// The individual override files for this pod.  There will always be a
    /// sensible value here for each pod, even if the file doesn't exist on
    /// disk.
    override_file_infos: BTreeMap<Override, FileInfo>,

    /// Per-pod configuration.
    config: Config,
}

impl Pod {
    /// Create a new pod, specifying the base directory from which we'll load
    /// pod definitions and the name of the pod.
    #[doc(hidden)]
    pub fn new<P, S>(base_dir: P,
                     name: S,
                     overrides: &[Override])
                     -> Result<Pod, Error>
        where P: Into<PathBuf>,
              S: Into<String>
    {
        let base_dir = base_dir.into();
        let name = name.into();

        // Load our `*.metadata.yml` file, if any.
        let config_path = base_dir.join(&format!("{}.metadata.yml", &name));
        let config: Config = if config_path.exists() {
            let f = try!(fs::File::open(&config_path)
                .map_err(|e| err!("Error opening {}: {}", &config_path.display(), e)));
            try!(serde_yaml::from_reader(f)
                .map_err(|e| err!("Error reading {}: {}", &config_path.display(), e)))
        } else {
            Config::default()
        };

        // Load our main `*.yml` file.
        let rel_path = Path::new(&format!("{}.yml", &name)).to_owned();
        let mut file_info = try!(FileInfo::unnormalized(&base_dir, &rel_path));
        file_info.finish_normalization();

        // Load our override `*.yml` files.
        let mut ovr_infos = BTreeMap::new();
        for ovr in overrides {
            let ovr_rel_path =
                Path::new(&format!("overrides/{}/{}.yml", ovr.name(), &name))
                    .to_owned();
            let mut ovr_info = try!(FileInfo::unnormalized(&base_dir, &ovr_rel_path));
            ovr_info.ensure_all_services_from(&file_info.file);
            ovr_info.finish_normalization();
            ovr_infos.insert(ovr.to_owned(), ovr_info);
        }

        Ok(Pod {
            base_dir: base_dir,
            name: name,
            file_info: file_info,
            override_file_infos: ovr_infos,
            config: config,
        })
    }

    /// Get the name of this pod.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Get the type of this pod.
    pub fn pod_type(&self) -> PodType {
        self.config.pod_type.unwrap_or(PodType::Service)
    }

    /// Is this pod enabled in the specified override?
    pub fn enabled_in(&self, ovr: &Override) -> bool {
        ovr.included_by(&self.config.enable_in_overrides)
    }

    /// The base directory for our relative paths.
    pub fn base_dir(&self) -> &Path {
        &self.base_dir
    }

    /// The path to the top-level file defining this pod, relative to the
    /// `base_dir` specified at creation time.
    pub fn rel_path(&self) -> &Path {
        &self.file_info.rel_path
    }

    /// The top-level file defining this pod.  This is normalized to
    /// include the appropriate `env_file` entries, but if you want to do
    /// more complicated transformations, you'll need to clone it with
    /// `to_owned()` first.
    pub fn file(&self) -> &dc::File {
        &self.file_info.file
    }

    /// Look up the file info associated with an override, or return an
    /// error if this override was not specified for this `Pod` at creation
    /// time.
    fn override_file_info(&self, ovr: &Override) -> Result<&FileInfo, Error> {
        self.override_file_infos
            .get(ovr)
            .ok_or_else(|| err!("The override {} is not defined", ovr.name()))
    }

    /// The path to the specificied override file for this pod.
    pub fn override_rel_path(&self, ovr: &Override) -> Result<&Path, Error> {
        Ok(&(try!(self.override_file_info(ovr)).rel_path))
    }

    /// The `dc::File` for this override.
    pub fn override_file(&self, ovr: &Override) -> Result<&dc::File, Error> {
        Ok(&(try!(self.override_file_info(ovr)).file))
    }

    /// Return the base file and the override file merged into a single
    /// `docker-compose.yml` file.
    pub fn merged_file(&self, ovr: &Override) -> Result<dc::File, Error> {
        // This is expensive so log it.
        debug!("Merging pod {} with override {}", self.name(), ovr.name());
        Ok(self.file().merge_override(try!(self.override_file(ovr))))
    }

    /// All the overrides associated with this pod.
    pub fn override_files(&self) -> OverrideFiles {
        OverrideFiles { iter: self.override_file_infos.iter() }
    }

    /// Iterate over all `dc::File` objects associated with this pod, including
    /// both the main `file()` and all the files in `override_files()`.
    pub fn all_files(&self) -> AllFiles {
        // Defer all the hard work to our iterator type.
        AllFiles {
            pod: self,
            state: AllFilesState::TopLevelFile,
        }
    }

    /// Command-line `-p` and `-f` arguments that we'll pass to
    /// `docker-compose` to describe this file.
    pub fn compose_args(&self,
                        proj: &Project,
                        ovr: &Override)
                        -> Result<Vec<OsString>, Error> {
        let compose_project_name = ovr.compose_project_name(proj);
        Ok(vec!["-p".into(),
                compose_project_name.into(),
                "-f".into(),
                proj.output_pods_dir().join(self.rel_path()).into()])
    }
}

/// An iterator over this pods overrides and their associated files.
#[allow(missing_debug_implementations)]
pub struct OverrideFiles<'a> {
    /// Our wrapped iterator.
    iter: btree_map::Iter<'a, Override, FileInfo>,
}

impl<'a> Iterator for OverrideFiles<'a> {
    type Item = (&'a Override, &'a dc::File);

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(ovr, file_info)| (ovr, &file_info.file))
    }
}

/// What should we yield next from our `AllFiles` iterator?
#[allow(missing_debug_implementations)]
enum AllFilesState<'a> {
    /// Yield the top-level `file()` next.
    TopLevelFile,
    /// Yield an item from this iterator next.
    OverrideFiles(OverrideFiles<'a>),
}

/// An iterator over all the `dc::File` objects associated with a pod, in
/// all overrides.
#[allow(missing_debug_implementations)]
pub struct AllFiles<'a> {
    /// The pod whose files we're iterating over.
    pod: &'a Pod,
    /// Our current iteration state.
    state: AllFilesState<'a>,
}

impl<'a> Iterator for AllFiles<'a> {
    type Item = &'a dc::File;

    fn next(&mut self) -> Option<Self::Item> {
        // We could try to implement this by calling:
        //
        // ```
        // iter::once(pod.file())
        //     .chain(pod.override_files().map(|(_, file)| file))
        // ```
        //
        // ...and storing the result in our object, but the type of that
        // expression is exquisitely hideous and we'd go mad.
        match self.state {
            AllFilesState::TopLevelFile => {
                self.state = AllFilesState::OverrideFiles(self.pod.override_files());
                Some(self.pod.file())
            }
            AllFilesState::OverrideFiles(ref mut iter) => {
                iter.next().map(|(_, file)| file)
            }
        }
    }
}

#[test]
fn pods_are_normalized_on_load() {
    use env_logger;
    use project::Project;
    let _ = env_logger::init();

    let proj = Project::from_example("hello").unwrap();
    let frontend = proj.pod("frontend").unwrap();

    let web = frontend.file().services.get("web").unwrap();
    assert_eq!(web.env_files.len(), 1);
    assert_eq!(web.env_files[0].value().unwrap(), Path::new("common.env"));

    // This test assumes that there's no `web` entry in the `production`
    // override, so we have to create everything from scratch.
    let production = proj.ovr("production").unwrap();
    let web_ovr = frontend.override_file(production)
        .unwrap()
        .services
        .get("web")
        .unwrap();
    assert_eq!(web_ovr.env_files.len(), 1);
    assert_eq!(web_ovr.env_files[0].value().unwrap(),
               Path::new("overrides/production/common.env"));
}

#[test]
fn can_merge_base_file_and_override() {
    use env_logger;
    let _ = env_logger::init();
    let proj: Project = Project::from_example("hello").unwrap();
    let ovr = proj.ovr("development").unwrap();
    let frontend = proj.pod("frontend").unwrap();
    let merged = frontend.merged_file(ovr).unwrap();
    let proxy = merged.services.get("proxy").unwrap();
    assert_eq!(proxy.env_files.len(), 2);
}

#[test]
fn pod_type_returns_type_of_pod() {
    use env_logger;
    let _ = env_logger::init();
    let proj: Project = Project::from_example("rails_hello").unwrap();
    let frontend = proj.pod("frontend").unwrap();
    assert_eq!(frontend.pod_type(), PodType::Service);
    let migrate = proj.pod("migrate").unwrap();
    assert_eq!(migrate.pod_type(), PodType::Task);
}
<|endoftext|>


<commit_before>//! Raw mode.

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

/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(target_os = "redox")]
pub struct RawTerminal<W: Write> {
    output: W,
}

#[cfg(target_os = "redox")]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        write!(self, csi!("?82h")).unwrap();
    }
}

#[cfg(not(target_os = "redox"))]
use termios::Termios;
/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(not(target_os = "redox"))]
pub struct RawTerminal<W: Write> {
    prev_ios: Termios,
    output: W,
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        use termios::set_terminal_attr;
        set_terminal_attr(&mut self.prev_ios as *mut _);
    }
}

impl<W: Write> ops::Deref for RawTerminal<W> {
    type Target = W;

    fn deref(&self) -> &W {
        &self.output
    }
}

impl<W: Write> ops::DerefMut for RawTerminal<W> {
    fn deref_mut(&mut self) -> &mut W {
        &mut self.output
    }
}

impl<W: Write> Write for RawTerminal<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.output.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.output.flush()
    }
}

/// Types which can be converted into "raw mode".
pub trait IntoRawMode: Write + Sized {
    /// Switch to raw mode.
    ///
    /// Raw mode means that stdin won't be printed (it will instead have to be written manually by
    /// the program). Furthermore, the input isn't canonicalised or buffered (that is, you can
    /// read from stdin one byte of a time). The output is neither modified in any way.
    fn into_raw_mode(self) -> io::Result<RawTerminal<Self>>;
}

impl<W: Write> IntoRawMode for W {
    #[cfg(not(target_os = "redox"))]
    fn into_raw_mode(self) -> io::Result<RawTerminal<W>> {
        use termios::{cfmakeraw, get_terminal_attr, set_terminal_attr};

        let (mut ios, exit) = get_terminal_attr();
        let prev_ios = ios.clone();
        if exit != 0 {
            return Err(io::Error::new(io::ErrorKind::Other, "Unable to get Termios attribute."));
        }

        unsafe {
            cfmakeraw(&mut ios);
        }

        if set_terminal_attr(&mut ios as *mut _) != 0 {
            Err(io::Error::new(io::ErrorKind::Other, "Unable to set Termios attribute."))
        } else {
            let res = RawTerminal {
                prev_ios: prev_ios,
                output: self,
            };
            Ok(res)
        }
    }

    #[cfg(target_os = "redox")]
    fn into_raw_mode(mut self) -> io::Result<RawTerminal<W>> {
        write!(self, csi!("?82h")).map(|_| {
            RawTerminal { output: self }
        })
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Write, stdout};

    #[test]
    fn test_into_raw_mode() {
        let mut out = stdout().into_raw_mode().unwrap();

        out.write(b"this is a test, muahhahahah").unwrap();
    }
}
<commit_msg>Fix RawTerminal drop<commit_after>//! Raw mode.

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

/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(target_os = "redox")]
pub struct RawTerminal<W: Write> {
    output: W,
}

#[cfg(target_os = "redox")]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        write!(self, csi!("?82l")).unwrap();
    }
}

#[cfg(not(target_os = "redox"))]
use termios::Termios;
/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(not(target_os = "redox"))]
pub struct RawTerminal<W: Write> {
    prev_ios: Termios,
    output: W,
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        use termios::set_terminal_attr;
        set_terminal_attr(&mut self.prev_ios as *mut _);
    }
}

impl<W: Write> ops::Deref for RawTerminal<W> {
    type Target = W;

    fn deref(&self) -> &W {
        &self.output
    }
}

impl<W: Write> ops::DerefMut for RawTerminal<W> {
    fn deref_mut(&mut self) -> &mut W {
        &mut self.output
    }
}

impl<W: Write> Write for RawTerminal<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.output.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.output.flush()
    }
}

/// Types which can be converted into "raw mode".
pub trait IntoRawMode: Write + Sized {
    /// Switch to raw mode.
    ///
    /// Raw mode means that stdin won't be printed (it will instead have to be written manually by
    /// the program). Furthermore, the input isn't canonicalised or buffered (that is, you can
    /// read from stdin one byte of a time). The output is neither modified in any way.
    fn into_raw_mode(self) -> io::Result<RawTerminal<Self>>;
}

impl<W: Write> IntoRawMode for W {
    #[cfg(not(target_os = "redox"))]
    fn into_raw_mode(self) -> io::Result<RawTerminal<W>> {
        use termios::{cfmakeraw, get_terminal_attr, set_terminal_attr};

        let (mut ios, exit) = get_terminal_attr();
        let prev_ios = ios.clone();
        if exit != 0 {
            return Err(io::Error::new(io::ErrorKind::Other, "Unable to get Termios attribute."));
        }

        unsafe {
            cfmakeraw(&mut ios);
        }

        if set_terminal_attr(&mut ios as *mut _) != 0 {
            Err(io::Error::new(io::ErrorKind::Other, "Unable to set Termios attribute."))
        } else {
            let res = RawTerminal {
                prev_ios: prev_ios,
                output: self,
            };
            Ok(res)
        }
    }

    #[cfg(target_os = "redox")]
    fn into_raw_mode(mut self) -> io::Result<RawTerminal<W>> {
        write!(self, csi!("?82h")).map(|_| {
            RawTerminal { output: self }
        })
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Write, stdout};

    #[test]
    fn test_into_raw_mode() {
        let mut out = stdout().into_raw_mode().unwrap();

        out.write(b"this is a test, muahhahahah").unwrap();
    }
}
<|endoftext|>


<commit_before>use rm::linalg::matrix::Matrix;
use rm::linalg::vector::Vector;
use libnum::abs;

#[test]
fn create_mat_zeros() {
    let a = Matrix::<f32>::zeros(10, 10);

    assert_eq!(a.rows(), 10);
    assert_eq!(a.cols(), 10);

    for i in 0..10 {
        for j in 0..10 {
            assert_eq!(a[[i, j]], 0.0);
        }
    }
}

#[test]
fn create_mat_identity() {
    let a = Matrix::<f32>::identity(4);

    assert_eq!(a.rows(), 4);
    assert_eq!(a.cols(), 4);

    assert_eq!(a[[0, 0]], 1.0);
    assert_eq!(a[[1, 1]], 1.0);
    assert_eq!(a[[2, 2]], 1.0);
    assert_eq!(a[[3, 3]], 1.0);

    assert_eq!(a[[0, 1]], 0.0);
    assert_eq!(a[[2, 1]], 0.0);
    assert_eq!(a[[3, 0]], 0.0);
}

#[test]
fn create_mat_diag() {
    let a = Matrix::from_diag(&[1.0, 2.0, 3.0, 4.0]);

    assert_eq!(a.rows(), 4);
    assert_eq!(a.cols(), 4);

    assert_eq!(a[[0, 0]], 1.0);
    assert_eq!(a[[1, 1]], 2.0);
    assert_eq!(a[[2, 2]], 3.0);
    assert_eq!(a[[3, 3]], 4.0);

    assert_eq!(a[[0, 1]], 0.0);
    assert_eq!(a[[2, 1]], 0.0);
    assert_eq!(a[[3, 0]], 0.0);
}

#[test]
fn transpose_mat() {
    let a = Matrix::new(5, 2, vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10.]);

    let c = a.transpose();

    assert_eq!(c.cols(), a.rows());
    assert_eq!(c.rows(), a.cols());

    assert_eq!(a[[0, 0]], c[[0, 0]]);
    assert_eq!(a[[1, 0]], c[[0, 1]]);
    assert_eq!(a[[2, 0]], c[[0, 2]]);
    assert_eq!(a[[3, 0]], c[[0, 3]]);
    assert_eq!(a[[4, 0]], c[[0, 4]]);
    assert_eq!(a[[0, 1]], c[[1, 0]]);
    assert_eq!(a[[1, 1]], c[[1, 1]]);
    assert_eq!(a[[2, 1]], c[[1, 2]]);
    assert_eq!(a[[3, 1]], c[[1, 3]]);
    assert_eq!(a[[4, 1]], c[[1, 4]]);

}

#[test]
fn indexing_mat() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);

    assert_eq!(a[[0, 0]], 1.0);
    assert_eq!(a[[0, 1]], 2.0);
    assert_eq!(a[[1, 0]], 3.0);
    assert_eq!(a[[1, 1]], 4.0);
    assert_eq!(a[[2, 0]], 5.0);
    assert_eq!(a[[2, 1]], 6.0);
}

#[test]
fn matrix_mul() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = Matrix::new(2, 3, vec![1., 2., 3., 4., 5., 6.]);

    let c = a * b;

    assert_eq!(c.rows(), 3);
    assert_eq!(c.cols(), 3);

    assert_eq!(c[[0, 0]], 9.0);
    assert_eq!(c[[0, 1]], 12.0);
    assert_eq!(c[[0, 2]], 15.0);
    assert_eq!(c[[1, 0]], 19.0);
    assert_eq!(c[[1, 1]], 26.0);
    assert_eq!(c[[1, 2]], 33.0);
    assert_eq!(c[[2, 0]], 29.0);
    assert_eq!(c[[2, 1]], 40.0);
    assert_eq!(c[[2, 2]], 51.0);
}

#[test]
fn matrix_vec_mul() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = Vector::new(vec![4., 7.]);

    let c = a * b;

    assert_eq!(c.size(), 3);

    assert_eq!(c[0], 18.0);
    assert_eq!(c[1], 40.0);
    assert_eq!(c[2], 62.0);
}

#[test]
fn matrix_f32_mul() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);

    let c = a * 2.0;

    assert_eq!(c[[0, 0]], 2.0);
    assert_eq!(c[[0, 1]], 4.0);
    assert_eq!(c[[1, 0]], 6.0);
    assert_eq!(c[[1, 1]], 8.0);
    assert_eq!(c[[2, 0]], 10.0);
    assert_eq!(c[[2, 1]], 12.0);
}

#[test]
fn matrix_add() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = Matrix::new(3, 2, vec![2., 3., 4., 5., 6., 7.]);

    let c = a + b;

    assert_eq!(c[[0, 0]], 3.0);
    assert_eq!(c[[0, 1]], 5.0);
    assert_eq!(c[[1, 0]], 7.0);
    assert_eq!(c[[1, 1]], 9.0);
    assert_eq!(c[[2, 0]], 11.0);
    assert_eq!(c[[2, 1]], 13.0);
}

#[test]
fn matrix_f32_add() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = 3.0;

    let c = a + b;

    assert_eq!(c[[0, 0]], 4.0);
    assert_eq!(c[[0, 1]], 5.0);
    assert_eq!(c[[1, 0]], 6.0);
    assert_eq!(c[[1, 1]], 7.0);
    assert_eq!(c[[2, 0]], 8.0);
    assert_eq!(c[[2, 1]], 9.0);
}

#[test]
fn matrix_sub() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = Matrix::new(3, 2, vec![2., 3., 4., 5., 6., 7.]);

    let c = a - b;

    assert_eq!(c[[0, 0]], -1.0);
    assert_eq!(c[[0, 1]], -1.0);
    assert_eq!(c[[1, 0]], -1.0);
    assert_eq!(c[[1, 1]], -1.0);
    assert_eq!(c[[2, 0]], -1.0);
    assert_eq!(c[[2, 1]], -1.0);
}

#[test]
fn matrix_f32_sub() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = 3.0;

    let c = a - b;

    assert_eq!(c[[0, 0]], -2.0);
    assert_eq!(c[[0, 1]], -1.0);
    assert_eq!(c[[1, 0]], 0.0);
    assert_eq!(c[[1, 1]], 1.0);
    assert_eq!(c[[2, 0]], 2.0);
    assert_eq!(c[[2, 1]], 3.0);
}

#[test]
fn matrix_f32_div() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = 3.0;

    let c = a / b;

    assert_eq!(c[[0, 0]], 1.0 / 3.0);
    assert_eq!(c[[0, 1]], 2.0 / 3.0);
    assert_eq!(c[[1, 0]], 1.0);
    assert_eq!(c[[1, 1]], 4.0 / 3.0);
    assert_eq!(c[[2, 0]], 5.0 / 3.0);
    assert_eq!(c[[2, 1]], 2.0);
}

#[test]
fn matrix_lup_decomp() {
    let a = Matrix::new(3, 3, vec![1., 3., 5., 2., 4., 7., 1., 1., 0.]);

    let (l, u, p) = a.lup_decomp();

    let l_true = vec![1., 0., 0., 0.5, 1., 0., 0.5, -1., 1.];
    let u_true = vec![2., 4., 7., 0., 1., 1.5, 0., 0., -2.];
    let p_true = vec![0., 1., 0., 1., 0., 0., 0., 0., 1.];

    assert_eq!(*p.data(), p_true);
    assert_eq!(*l.data(), l_true);
    assert_eq!(*u.data(), u_true);

    let e = Matrix::<f64>::new(5,
                               5,
                               vec![1., 2., 3., 4., 5., 3., 0., 4., 5., 6., 2., 1., 2., 3., 4.,
                                    0., 0., 0., 6., 5., 0., 0., 0., 5., 6.]);

    let (l, u, p) = e.lup_decomp();
    let k = p.transpose() * l * u;

    for i in 0..25 {
        println!("{0},{1}", e.data()[i], k.data()[i]);
        assert_eq!(e.data()[i], k.data()[i]);
    }
}

#[test]
fn matrix_diag() {
    let a = Matrix::new(3, 3, vec![1., 3., 5., 2., 4., 7., 1., 1., 0.]);

    let b = a.is_diag();

    assert!(!b);

    let c = Matrix::new(3, 3, vec![1., 0., 0., 0., 2., 0., 0., 0., 3.]);
    let d = c.is_diag();

    assert!(d);
}

#[test]
fn matrix_det() {
    let a = Matrix::new(2, 2, vec![2., 3., 1., 2.]);
    let b = a.det();

    assert_eq!(b, 1.);

    let c = Matrix::new(3, 3, vec![1., 2., 3., 4., 5., 6., 7., 8., 9.]);
    let d = c.det();

    assert_eq!(d, 0.);

    let e = Matrix::<f64>::new(5,
                               5,
                               vec![1., 2., 3., 4., 5., 3., 0., 4., 5., 6., 2., 1., 2., 3., 4.,
                                    0., 0., 0., 6., 5., 0., 0., 0., 5., 6.]);

    let f = e.det();

    println!("det is {0}", f);
    let error = abs(f - 99.);
    assert!(error < 1e-10);
}

#[test]
fn matrix_solve() {
    let a = Matrix::new(2, 2, vec![2., 3., 1., 2.]);

    let y = Vector::new(vec![8., 5.]);

    let x = a.solve(y);

    assert_eq!(x.size(), 2);

    assert_eq!(x[0], 1.);
    assert_eq!(x[1], 2.);
}

#[test]
fn cholesky() {
    let a = Matrix::new(3,3, vec![25.,15.,-5.,15.,18.,0.,-5.,0.,11.]);

    let l = a.cholesky();

    assert_eq!(*l.data(), vec![5.,0.,0.,3.,3.,0.,-1.,1.,3.]);
}
<commit_msg>Removing unneeded comment<commit_after>use rm::linalg::matrix::Matrix;
use rm::linalg::vector::Vector;
use libnum::abs;

#[test]
fn create_mat_zeros() {
    let a = Matrix::<f32>::zeros(10, 10);

    assert_eq!(a.rows(), 10);
    assert_eq!(a.cols(), 10);

    for i in 0..10 {
        for j in 0..10 {
            assert_eq!(a[[i, j]], 0.0);
        }
    }
}

#[test]
fn create_mat_identity() {
    let a = Matrix::<f32>::identity(4);

    assert_eq!(a.rows(), 4);
    assert_eq!(a.cols(), 4);

    assert_eq!(a[[0, 0]], 1.0);
    assert_eq!(a[[1, 1]], 1.0);
    assert_eq!(a[[2, 2]], 1.0);
    assert_eq!(a[[3, 3]], 1.0);

    assert_eq!(a[[0, 1]], 0.0);
    assert_eq!(a[[2, 1]], 0.0);
    assert_eq!(a[[3, 0]], 0.0);
}

#[test]
fn create_mat_diag() {
    let a = Matrix::from_diag(&[1.0, 2.0, 3.0, 4.0]);

    assert_eq!(a.rows(), 4);
    assert_eq!(a.cols(), 4);

    assert_eq!(a[[0, 0]], 1.0);
    assert_eq!(a[[1, 1]], 2.0);
    assert_eq!(a[[2, 2]], 3.0);
    assert_eq!(a[[3, 3]], 4.0);

    assert_eq!(a[[0, 1]], 0.0);
    assert_eq!(a[[2, 1]], 0.0);
    assert_eq!(a[[3, 0]], 0.0);
}

#[test]
fn transpose_mat() {
    let a = Matrix::new(5, 2, vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10.]);

    let c = a.transpose();

    assert_eq!(c.cols(), a.rows());
    assert_eq!(c.rows(), a.cols());

    assert_eq!(a[[0, 0]], c[[0, 0]]);
    assert_eq!(a[[1, 0]], c[[0, 1]]);
    assert_eq!(a[[2, 0]], c[[0, 2]]);
    assert_eq!(a[[3, 0]], c[[0, 3]]);
    assert_eq!(a[[4, 0]], c[[0, 4]]);
    assert_eq!(a[[0, 1]], c[[1, 0]]);
    assert_eq!(a[[1, 1]], c[[1, 1]]);
    assert_eq!(a[[2, 1]], c[[1, 2]]);
    assert_eq!(a[[3, 1]], c[[1, 3]]);
    assert_eq!(a[[4, 1]], c[[1, 4]]);

}

#[test]
fn indexing_mat() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);

    assert_eq!(a[[0, 0]], 1.0);
    assert_eq!(a[[0, 1]], 2.0);
    assert_eq!(a[[1, 0]], 3.0);
    assert_eq!(a[[1, 1]], 4.0);
    assert_eq!(a[[2, 0]], 5.0);
    assert_eq!(a[[2, 1]], 6.0);
}

#[test]
fn matrix_mul() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = Matrix::new(2, 3, vec![1., 2., 3., 4., 5., 6.]);

    let c = a * b;

    assert_eq!(c.rows(), 3);
    assert_eq!(c.cols(), 3);

    assert_eq!(c[[0, 0]], 9.0);
    assert_eq!(c[[0, 1]], 12.0);
    assert_eq!(c[[0, 2]], 15.0);
    assert_eq!(c[[1, 0]], 19.0);
    assert_eq!(c[[1, 1]], 26.0);
    assert_eq!(c[[1, 2]], 33.0);
    assert_eq!(c[[2, 0]], 29.0);
    assert_eq!(c[[2, 1]], 40.0);
    assert_eq!(c[[2, 2]], 51.0);
}

#[test]
fn matrix_vec_mul() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = Vector::new(vec![4., 7.]);

    let c = a * b;

    assert_eq!(c.size(), 3);

    assert_eq!(c[0], 18.0);
    assert_eq!(c[1], 40.0);
    assert_eq!(c[2], 62.0);
}

#[test]
fn matrix_f32_mul() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);

    let c = a * 2.0;

    assert_eq!(c[[0, 0]], 2.0);
    assert_eq!(c[[0, 1]], 4.0);
    assert_eq!(c[[1, 0]], 6.0);
    assert_eq!(c[[1, 1]], 8.0);
    assert_eq!(c[[2, 0]], 10.0);
    assert_eq!(c[[2, 1]], 12.0);
}

#[test]
fn matrix_add() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = Matrix::new(3, 2, vec![2., 3., 4., 5., 6., 7.]);

    let c = a + b;

    assert_eq!(c[[0, 0]], 3.0);
    assert_eq!(c[[0, 1]], 5.0);
    assert_eq!(c[[1, 0]], 7.0);
    assert_eq!(c[[1, 1]], 9.0);
    assert_eq!(c[[2, 0]], 11.0);
    assert_eq!(c[[2, 1]], 13.0);
}

#[test]
fn matrix_f32_add() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = 3.0;

    let c = a + b;

    assert_eq!(c[[0, 0]], 4.0);
    assert_eq!(c[[0, 1]], 5.0);
    assert_eq!(c[[1, 0]], 6.0);
    assert_eq!(c[[1, 1]], 7.0);
    assert_eq!(c[[2, 0]], 8.0);
    assert_eq!(c[[2, 1]], 9.0);
}

#[test]
fn matrix_sub() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = Matrix::new(3, 2, vec![2., 3., 4., 5., 6., 7.]);

    let c = a - b;

    assert_eq!(c[[0, 0]], -1.0);
    assert_eq!(c[[0, 1]], -1.0);
    assert_eq!(c[[1, 0]], -1.0);
    assert_eq!(c[[1, 1]], -1.0);
    assert_eq!(c[[2, 0]], -1.0);
    assert_eq!(c[[2, 1]], -1.0);
}

#[test]
fn matrix_f32_sub() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = 3.0;

    let c = a - b;

    assert_eq!(c[[0, 0]], -2.0);
    assert_eq!(c[[0, 1]], -1.0);
    assert_eq!(c[[1, 0]], 0.0);
    assert_eq!(c[[1, 1]], 1.0);
    assert_eq!(c[[2, 0]], 2.0);
    assert_eq!(c[[2, 1]], 3.0);
}

#[test]
fn matrix_f32_div() {
    let a = Matrix::new(3, 2, vec![1., 2., 3., 4., 5., 6.]);
    let b = 3.0;

    let c = a / b;

    assert_eq!(c[[0, 0]], 1.0 / 3.0);
    assert_eq!(c[[0, 1]], 2.0 / 3.0);
    assert_eq!(c[[1, 0]], 1.0);
    assert_eq!(c[[1, 1]], 4.0 / 3.0);
    assert_eq!(c[[2, 0]], 5.0 / 3.0);
    assert_eq!(c[[2, 1]], 2.0);
}

#[test]
fn matrix_lup_decomp() {
    let a = Matrix::new(3, 3, vec![1., 3., 5., 2., 4., 7., 1., 1., 0.]);

    let (l, u, p) = a.lup_decomp();

    let l_true = vec![1., 0., 0., 0.5, 1., 0., 0.5, -1., 1.];
    let u_true = vec![2., 4., 7., 0., 1., 1.5, 0., 0., -2.];
    let p_true = vec![0., 1., 0., 1., 0., 0., 0., 0., 1.];

    assert_eq!(*p.data(), p_true);
    assert_eq!(*l.data(), l_true);
    assert_eq!(*u.data(), u_true);

    let e = Matrix::<f64>::new(5,
                               5,
                               vec![1., 2., 3., 4., 5., 3., 0., 4., 5., 6., 2., 1., 2., 3., 4.,
                                    0., 0., 0., 6., 5., 0., 0., 0., 5., 6.]);

    let (l, u, p) = e.lup_decomp();
    let k = p.transpose() * l * u;

    for i in 0..25 {
        assert_eq!(e.data()[i], k.data()[i]);
    }
}

#[test]
fn matrix_diag() {
    let a = Matrix::new(3, 3, vec![1., 3., 5., 2., 4., 7., 1., 1., 0.]);

    let b = a.is_diag();

    assert!(!b);

    let c = Matrix::new(3, 3, vec![1., 0., 0., 0., 2., 0., 0., 0., 3.]);
    let d = c.is_diag();

    assert!(d);
}

#[test]
fn matrix_det() {
    let a = Matrix::new(2, 2, vec![2., 3., 1., 2.]);
    let b = a.det();

    assert_eq!(b, 1.);

    let c = Matrix::new(3, 3, vec![1., 2., 3., 4., 5., 6., 7., 8., 9.]);
    let d = c.det();

    assert_eq!(d, 0.);

    let e = Matrix::<f64>::new(5,
                               5,
                               vec![1., 2., 3., 4., 5., 3., 0., 4., 5., 6., 2., 1., 2., 3., 4.,
                                    0., 0., 0., 6., 5., 0., 0., 0., 5., 6.]);

    let f = e.det();

    println!("det is {0}", f);
    let error = abs(f - 99.);
    assert!(error < 1e-10);
}

#[test]
fn matrix_solve() {
    let a = Matrix::new(2, 2, vec![2., 3., 1., 2.]);

    let y = Vector::new(vec![8., 5.]);

    let x = a.solve(y);

    assert_eq!(x.size(), 2);

    assert_eq!(x[0], 1.);
    assert_eq!(x[1], 2.);
}

#[test]
fn cholesky() {
    let a = Matrix::new(3,3, vec![25.,15.,-5.,15.,18.,0.,-5.,0.,11.]);

    let l = a.cholesky();

    assert_eq!(*l.data(), vec![5.,0.,0.,3.,3.,0.,-1.,1.,3.]);
}
<|endoftext|>


<commit_before>// (c) 2016 Productize SPRL <joost@productize.be>

use std::io;

use formatter::*;

use Sexp;
use Result;
use encode_string;

struct Serializer<W, F=CompactFormatter> {
    writer: W,
    formatter: F,
}

// dispatches only based on Formatter
impl<W> Serializer<W>
    where W: io::Write,
{
    fn new(writer: W) -> Self {
        Serializer::with_formatter(writer, CompactFormatter)
    }
}

impl<W> Serializer<W, RulesFormatter>
    where W: io::Write,
{
    fn new_rules(writer: W, rules:Rules) -> Self {
        Serializer::with_formatter(writer, RulesFormatter::new(rules))
    }
}

impl<W, F> Serializer<W, F>
    where W: io::Write,
          F: Formatter,
{
    fn with_formatter(writer: W, formatter: F) -> Self {
        Serializer {
            writer: writer,
            formatter: formatter,
        }
    }

    fn serialize_str(&mut self, value:&str) -> Result<()> {
        write!(&mut self.writer, "{}", encode_string(value)).map_err(From::from)
    }

    fn serialize(&mut self, value:&Sexp) -> Result<()> {
        match *value {
            Sexp::String(ref s) => {
                self.serialize_str(s)
            },
            Sexp::List(ref list) => {
                let mut first = true;
                if list.is_empty() {
                    try!(self.formatter.open(&mut self.writer, None));
                } else {
                    for v in list {
                        if first {
                            try!(self.formatter.open(&mut self.writer, Some(v)));
                            try!(self.serialize(v));
                            first = false;
                        } else {
                            try!(self.formatter.element(&mut self.writer, v));
                            try!(self.serialize(v));
                        }
                    }
                }
                self.formatter.close(&mut self.writer)
            },
            Sexp::Empty => Ok(()),
        }

    }
}

pub fn to_writer<W>(writer: &mut W, value: &Sexp) -> Result<()>
    where W: io::Write
{
    let mut ser = Serializer::new(writer);
    ser.serialize(value)
}

pub fn to_writer_with_rules<W>(writer: &mut W, rules:Rules, value:&Sexp) -> Result<()>
    where W: io::Write
{
    let mut ser = Serializer::new_rules(writer, rules);
    ser.serialize(value)
}

pub fn to_vec(value:&Sexp) -> Result<Vec<u8>> {
    let mut writer = Vec::with_capacity(128);
    try!(to_writer(&mut writer, value));
    Ok(writer)
}

pub fn to_vec_with_rules(value:&Sexp, rules:Rules) -> Result<Vec<u8>> {
    let mut writer = Vec::with_capacity(128);
    try!(to_writer_with_rules(&mut writer, rules, value));
    Ok(writer)
}

pub fn to_string(value:&Sexp) -> Result<String> {
    let vec = try!(to_vec(value));
    let string = try!(String::from_utf8(vec));
    Ok(string)
}

pub fn to_string_with_rules(value:&Sexp, rules:Rules) -> Result<String> {
    let vec = try!(to_vec_with_rules(value, rules));
    let string = try!(String::from_utf8(vec));
    Ok(string)
}
<commit_msg>with_formatter variants<commit_after>// (c) 2016 Productize SPRL <joost@productize.be>

use std::io;

use formatter::*;

use Sexp;
use Result;
use encode_string;

struct Serializer<W, F=CompactFormatter> {
    writer: W,
    formatter: F,
}

// dispatches only based on Formatter
impl<W> Serializer<W>
    where W: io::Write,
{
    fn new(writer: W) -> Self {
        Serializer::with_formatter(writer, CompactFormatter)
    }
}

impl<W> Serializer<W, RulesFormatter>
    where W: io::Write,
{
    fn new_rules(writer: W, rules:Rules) -> Self {
        Serializer::with_formatter(writer, RulesFormatter::new(rules))
    }
}

impl<W, F> Serializer<W, F>
    where W: io::Write,
          F: Formatter,
{
    fn with_formatter(writer: W, formatter: F) -> Self {
        Serializer {
            writer: writer,
            formatter: formatter,
        }
    }

    fn serialize_str(&mut self, value:&str) -> Result<()> {
        write!(&mut self.writer, "{}", encode_string(value)).map_err(From::from)
    }

    fn serialize(&mut self, value:&Sexp) -> Result<()> {
        match *value {
            Sexp::String(ref s) => {
                self.serialize_str(s)
            },
            Sexp::List(ref list) => {
                let mut first = true;
                if list.is_empty() {
                    try!(self.formatter.open(&mut self.writer, None));
                } else {
                    for v in list {
                        if first {
                            try!(self.formatter.open(&mut self.writer, Some(v)));
                            try!(self.serialize(v));
                            first = false;
                        } else {
                            try!(self.formatter.element(&mut self.writer, v));
                            try!(self.serialize(v));
                        }
                    }
                }
                self.formatter.close(&mut self.writer)
            },
            Sexp::Empty => Ok(()),
        }

    }
}

pub fn to_writer<W>(writer: &mut W, value: &Sexp) -> Result<()>
    where W: io::Write
{
    let mut ser = Serializer::new(writer);
    ser.serialize(value)
}

pub fn to_writer_with_formatter<W,F>(writer: &mut W, formatter:F, value: &Sexp) -> Result<()>
    where W: io::Write, F:Formatter
{
    let mut ser = Serializer::with_formatter(writer, formatter);
    ser.serialize(value)
}

pub fn to_writer_with_rules<W>(writer: &mut W, rules:Rules, value:&Sexp) -> Result<()>
    where W: io::Write
{
    let mut ser = Serializer::new_rules(writer, rules);
    ser.serialize(value)
}

pub fn to_vec(value:&Sexp) -> Result<Vec<u8>> {
    let mut writer = Vec::with_capacity(128);
    try!(to_writer(&mut writer, value));
    Ok(writer)
}

pub fn to_vec_with_rules(value:&Sexp, rules:Rules) -> Result<Vec<u8>> {
    let mut writer = Vec::with_capacity(128);
    try!(to_writer_with_rules(&mut writer, rules, value));
    Ok(writer)
}

pub fn to_vec_with_formatter<F>(value:&Sexp, formatter:F) -> Result<Vec<u8>>
    where F:Formatter
{
    let mut writer = Vec::with_capacity(128);
    try!(to_writer_with_formatter(&mut writer, formatter, value));
    Ok(writer)
}

pub fn to_string(value:&Sexp) -> Result<String> {
    let vec = try!(to_vec(value));
    let string = try!(String::from_utf8(vec));
    Ok(string)
}

pub fn to_string_with_rules(value:&Sexp, rules:Rules) -> Result<String> {
    let vec = try!(to_vec_with_rules(value, rules));
    let string = try!(String::from_utf8(vec));
    Ok(string)
}

pub fn to_string_with_formatter<F>(value:&Sexp, formatter:F) -> Result<String>
    where F:Formatter
{
    let vec = try!(to_vec_with_formatter(value, formatter));
    let string = try!(String::from_utf8(vec));
    Ok(string)
}
<|endoftext|>