<commit_before>use diesel::prelude::*;

use DB_POOL;
use domain::github::{GitHubUser, Issue, IssueComment};
use domain::rfcbot::{FcpProposal, FcpReviewRequest};
use error::DashResult;

#[derive(Serialize)]
pub struct FcpWithInfo {
    pub fcp: FcpProposal,
    pub reviews: Vec<(GitHubUser, bool)>,
    pub issue: Issue,
    pub status_comment: IssueComment,
}

pub fn all_fcps() -> DashResult<Vec<FcpWithInfo>> {
    use domain::schema::{fcp_proposal, fcp_review_request, githubuser, issue, issuecomment};

    let conn = &*DB_POOL.get()?;

    let proposals = fcp_proposal::table
        .filter(fcp_proposal::fcp_start.is_null())
        .load::<FcpProposal>(conn)?;

    let mut all_fcps = Vec::new();

    for fcp in proposals {
        let reviews = fcp_review_request::table
            .filter(fcp_review_request::fk_proposal.eq(fcp.id))
            .load::<FcpReviewRequest>(conn)?;

        let mut reviews_with_users = Vec::new();

        for review in reviews {
            let user = githubuser::table
                .filter(githubuser::id.eq(review.fk_reviewer))
                .first(conn)?;
            reviews_with_users.push((user, review.reviewed));
        }

        let status_comment = issuecomment::table
            .filter(issuecomment::id.eq(fcp.fk_bot_tracking_comment))
            .first::<IssueComment>(conn)?;

        let issue = issue::table
            .filter(issue::id.eq(fcp.fk_issue))
            .first::<Issue>(conn)?;

        let fcp_with_info = FcpWithInfo {
            fcp: fcp,
            reviews: reviews_with_users,
            issue: issue,
            status_comment: status_comment,
        };

        all_fcps.push(fcp_with_info);
    }

    Ok(all_fcps)
}

#[derive(Queryable, Serialize)]
pub struct IndividualFcp {
    issue: Issue,
    proposal: FcpProposal,
    review_request: FcpReviewRequest,
}

pub fn individual_nags(username: &str) -> DashResult<(GitHubUser, Vec<IndividualFcp>)> {
    use domain::schema::{fcp_proposal, fcp_review_request, githubuser, issue};
    let conn = &*DB_POOL.get()?;

    let user = githubuser::table
        .filter(githubuser::login.eq(username))
        .first::<GitHubUser>(conn)?;

    let review_requests = fcp_review_request::table
        .filter(fcp_review_request::fk_reviewer.eq(user.id))
        .filter(fcp_review_request::reviewed.eq(false))
        .load::<FcpReviewRequest>(conn)?;

    let mut fcps = Vec::new();

    for rr in review_requests {
        let proposal = fcp_proposal::table
            .filter(fcp_proposal::id.eq(rr.fk_proposal))
            .first::<FcpProposal>(conn)?;

        let issue = issue::table
            .filter(issue::id.eq(proposal.fk_issue))
            .first::<Issue>(conn)?;

        let fcp = IndividualFcp {
            issue: issue,
            proposal: proposal,
            review_request: rr,
        };

        fcps.push(fcp);
    }

    Ok((user, fcps))
}
<commit_msg>fix #212 by filtering in unstarted fcps. (#223)<commit_after>use diesel::prelude::*;

use DB_POOL;
use domain::github::{GitHubUser, Issue, IssueComment};
use domain::rfcbot::{FcpProposal, FcpReviewRequest};
use error::DashResult;

#[derive(Serialize)]
pub struct FcpWithInfo {
    pub fcp: FcpProposal,
    pub reviews: Vec<(GitHubUser, bool)>,
    pub issue: Issue,
    pub status_comment: IssueComment,
}

pub fn all_fcps() -> DashResult<Vec<FcpWithInfo>> {
    use domain::schema::{fcp_proposal, fcp_review_request, githubuser, issue, issuecomment};

    let conn = &*DB_POOL.get()?;

    let proposals = fcp_proposal::table
        .filter(fcp_proposal::fcp_start.is_null())
        .load::<FcpProposal>(conn)?;

    let mut all_fcps = Vec::new();

    for fcp in proposals {
        let reviews = fcp_review_request::table
            .filter(fcp_review_request::fk_proposal.eq(fcp.id))
            .load::<FcpReviewRequest>(conn)?;

        let mut reviews_with_users = Vec::new();

        for review in reviews {
            let user = githubuser::table
                .filter(githubuser::id.eq(review.fk_reviewer))
                .first(conn)?;
            reviews_with_users.push((user, review.reviewed));
        }

        let status_comment = issuecomment::table
            .filter(issuecomment::id.eq(fcp.fk_bot_tracking_comment))
            .first::<IssueComment>(conn)?;

        let issue = issue::table
            .filter(issue::id.eq(fcp.fk_issue))
            .first::<Issue>(conn)?;

        let fcp_with_info = FcpWithInfo {
            fcp: fcp,
            reviews: reviews_with_users,
            issue: issue,
            status_comment: status_comment,
        };

        all_fcps.push(fcp_with_info);
    }

    Ok(all_fcps)
}

#[derive(Queryable, Serialize)]
pub struct IndividualFcp {
    issue: Issue,
    proposal: FcpProposal,
    review_request: FcpReviewRequest,
}

pub fn individual_nags(username: &str) -> DashResult<(GitHubUser, Vec<IndividualFcp>)> {
    use domain::schema::{fcp_proposal, fcp_review_request, githubuser, issue};
    let conn = &*DB_POOL.get()?;

    let user = githubuser::table
        .filter(githubuser::login.eq(username))
        .first::<GitHubUser>(conn)?;

    let review_requests = fcp_review_request::table
        .inner_join(fcp_proposal::table)
            .filter(fcp_proposal::fcp_start.is_null())
        .filter(fcp_review_request::fk_reviewer.eq(user.id))
        .filter(fcp_review_request::reviewed.eq(false))
        .load::<(FcpReviewRequest, FcpProposal)>(conn)?;

    let mut fcps = Vec::new();
    for (rr, proposal) in review_requests {
        let issue = issue::table
            .filter(issue::id.eq(proposal.fk_issue))
            .first::<Issue>(conn)?;

        fcps.push(IndividualFcp {
            issue: issue,
            proposal: proposal,
            review_request: rr,
        });
    }

    Ok((user, fcps))
}
<|endoftext|>


<commit_before>//! Minimal wrapper around internal Perl API.

use perl_sys::funcs::*;

pub use perl_sys::types::*;
pub use perl_sys::consts::*;

pub type Stack = OuroborosStack;

#[derive(Copy, Clone)]
pub struct Interpreter (PerlThreadContext);

impl Interpreter {
    pub unsafe fn new(pthx: PerlThreadContext) -> Interpreter { Interpreter(pthx) }

    pub unsafe fn sv_iv(&self, sv: *mut SV) -> IV { ouroboros_sv_iv(self.0, sv) }
    pub unsafe fn sv_uv(&self, sv: *mut SV) -> UV { ouroboros_sv_uv(self.0, sv) }
    pub unsafe fn sv_nv(&self, sv: *mut SV) -> NV { ouroboros_sv_nv(self.0, sv) }

    pub unsafe fn sv_refcnt_inc(&self, sv: *mut SV) { ouroboros_sv_refcnt_inc_void_nn(self.0, sv) }
    pub unsafe fn sv_refcnt_dec(&self, sv: *mut SV) { ouroboros_sv_refcnt_dec_nn(self.0, sv) }

    pub unsafe fn av_fetch(&self, av: *mut AV, key: SSize_t) -> *mut *mut SV { Perl_av_fetch(self.0, av, key, 0) }
    pub unsafe fn av_fetch_lvalue(&self, av: *mut AV, key: SSize_t) -> *mut *mut SV { Perl_av_fetch(self.0, av, key, 1) }
    pub unsafe fn av_store(&self, av: *mut AV, key: SSize_t, sv: *mut SV) -> *mut *mut SV { Perl_av_store(self.0, av, key, sv) }

    pub unsafe fn st_init(&self, stack: &mut Stack) { ouroboros_stack_init(self.0, stack) }
    pub unsafe fn st_prepush(&self, stack: &mut Stack) { ouroboros_stack_prepush(self.0, stack) }
    pub unsafe fn st_putback(&self, stack: &mut Stack) { ouroboros_stack_putback(self.0, stack) }
    pub unsafe fn st_extend(&self, stack: &mut Stack, len: Size_t) { ouroboros_stack_extend(self.0, stack, len) }

    pub unsafe fn st_fetch(&self, stack: &mut Stack, idx: SSize_t) -> *mut SV { ouroboros_stack_fetch(self.0, stack, idx) }
    pub unsafe fn st_push(&self, stack: &mut Stack, val: *mut SV) { ouroboros_stack_push_sv(self.0, stack, val) }
    pub unsafe fn st_push_iv(&self, stack: &mut Stack, val: IV) { ouroboros_stack_push_iv(self.0, stack, val) }
    pub unsafe fn st_push_uv(&self, stack: &mut Stack, val: UV) { ouroboros_stack_push_uv(self.0, stack, val) }
    pub unsafe fn st_push_nv(&self, stack: &mut Stack, val: NV) { ouroboros_stack_push_nv(self.0, stack, val) }

    pub unsafe fn call_pv(&self, name: *const i8, flags: I32) -> I32 { Perl_call_pv(self.0, name, flags) }

    pub unsafe fn new_xs(&self, name: *const i8, func: XSUBADDR_t, file: *const i8) -> *mut CV {
        Perl_newXS(self.0, name, func, file)
    }
    pub unsafe fn new_sv(&self, len: STRLEN) -> *mut SV { Perl_newSV(self.0, len) }
    pub unsafe fn new_sv_iv(&self, val: IV) -> *mut SV { Perl_newSViv(self.0, val) }
    pub unsafe fn new_sv_uv(&self, val: UV) -> *mut SV { Perl_newSVuv(self.0, val) }
    pub unsafe fn new_sv_nv(&self, val: NV) -> *mut SV { Perl_newSVnv(self.0, val) }
    pub unsafe fn new_sv_pvn(&self, val: *const i8, len: STRLEN, flags: U32) -> *mut SV { Perl_newSVpvn_flags(self.0, val, len, flags) }

    pub unsafe fn get_av(&self, name: *const i8) -> *mut AV { Perl_get_av(self.0, name, 0) }
}
<commit_msg>Pass exceptions from Perl to Rust.<commit_after>//! Minimal wrapper around internal Perl API.

use std::mem;
use std::os::raw::{ c_int };
use perl_sys::funcs::*;

pub use perl_sys::types::*;
pub use perl_sys::consts::*;

pub type Stack = OuroborosStack;

#[derive(Copy, Clone)]
pub struct Interpreter (PerlThreadContext);

impl Interpreter {
    pub unsafe fn new(pthx: PerlThreadContext) -> Interpreter { Interpreter(pthx) }
}

// Contains result of failed JMPENV_PUSH() while propagating through Rust.
struct Xcpt(c_int);

// Wrapper to safely call potentially dying perl functions (which is pretty much all of them because
// magic and ties).
//
// Put actual call into Perl inside a closure. `ouroboros_xcpt_try()` will call the closure while
// capturing Perl exceptions, so they don't skip Rust code except the closure itself, which should
// be fine, since closure is FnMut and has no destructors.
//
// If it returns zero, we assume that closure did not die and `v` was assigned to, making it safe to
// return, otherwise we panic and possibly uninitialized `v` is not revealed.
//
// This only works with POD return types and non-panicing $body, which should always be the case for
// Perl API.
macro_rules! xcpt_try {
    ( $se:ident, $( $body:stmt )* ) => {{
        let mut v = mem::uninitialized();
        {
            let mut callback: &mut FnMut() = &mut || v = { $( $body )* };
            let rc = ouroboros_xcpt_try($se.0,
                                        mem::transmute(xcpt_bouncer as extern "C" fn(_)),
                                        mem::transmute(&mut callback));
            if rc != 0 {
                panic!(Xcpt(rc));
            }
        }
        v
    }}
}

// Helper function for calling Rust closure from C.
extern "C" fn xcpt_bouncer(closure: &mut &mut FnMut()) {
    (*closure)();
}

macro_rules! perl_api_inner {
    (
        pub unsafe fn $name:ident ( & $se:ident, $( $pname:ident : $ptype:ty ),* ) {
            $( $body:stmt )*
        }
        $( $rest:tt )*
    ) => (
        perl_api_inner! {
            pub unsafe fn $name ( & $se, $( $pname : $ptype ),* ) -> () { $( $body )* }
            $( $rest )*
        }
    );

    (
        pub unsafe fn $name:ident ( & $se:ident, $( $pname:ident : $ptype:ty ),* ) -> $rtype:ty {
            $( $body:stmt )*
        }
        $( $rest:tt )*
    ) => (
        pub unsafe fn $name ( & $se, $( $pname : $ptype ),* ) -> $rtype {
            xcpt_try! { $se, $( $body )* }
        }
        perl_api_inner! { $( $rest )* }
    );

    () => ();
}

macro_rules! perl_api {
    ( $( $tt:tt )* ) => ( impl Interpreter { perl_api_inner! { $( $tt )* } } )
}

perl_api! {
    pub unsafe fn sv_iv(&self, sv: *mut SV) -> IV { ouroboros_sv_iv(self.0, sv) }
    pub unsafe fn sv_uv(&self, sv: *mut SV) -> UV { ouroboros_sv_uv(self.0, sv) }
    pub unsafe fn sv_nv(&self, sv: *mut SV) -> NV { ouroboros_sv_nv(self.0, sv) }

    pub unsafe fn sv_refcnt_inc(&self, sv: *mut SV) { ouroboros_sv_refcnt_inc_void_nn(self.0, sv) }
    pub unsafe fn sv_refcnt_dec(&self, sv: *mut SV) { ouroboros_sv_refcnt_dec_nn(self.0, sv) }

    pub unsafe fn av_fetch(&self, av: *mut AV, key: SSize_t) -> *mut *mut SV { Perl_av_fetch(self.0, av, key, 0) }
    pub unsafe fn av_fetch_lvalue(&self, av: *mut AV, key: SSize_t) -> *mut *mut SV { Perl_av_fetch(self.0, av, key, 1) }
    pub unsafe fn av_store(&self, av: *mut AV, key: SSize_t, sv: *mut SV) -> *mut *mut SV { Perl_av_store(self.0, av, key, sv) }

    pub unsafe fn st_init(&self, stack: &mut Stack) { ouroboros_stack_init(self.0, stack) }
    pub unsafe fn st_prepush(&self, stack: &mut Stack) { ouroboros_stack_prepush(self.0, stack) }
    pub unsafe fn st_putback(&self, stack: &mut Stack) { ouroboros_stack_putback(self.0, stack) }
    pub unsafe fn st_extend(&self, stack: &mut Stack, len: Size_t) { ouroboros_stack_extend(self.0, stack, len) }

    pub unsafe fn st_fetch(&self, stack: &mut Stack, idx: SSize_t) -> *mut SV { ouroboros_stack_fetch(self.0, stack, idx) }
    pub unsafe fn st_push(&self, stack: &mut Stack, val: *mut SV) { ouroboros_stack_push_sv(self.0, stack, val) }
    pub unsafe fn st_push_iv(&self, stack: &mut Stack, val: IV) { ouroboros_stack_push_iv(self.0, stack, val) }
    pub unsafe fn st_push_uv(&self, stack: &mut Stack, val: UV) { ouroboros_stack_push_uv(self.0, stack, val) }
    pub unsafe fn st_push_nv(&self, stack: &mut Stack, val: NV) { ouroboros_stack_push_nv(self.0, stack, val) }

    pub unsafe fn call_pv(&self, name: *const i8, flags: I32) -> I32 { Perl_call_pv(self.0, name, flags) }

    pub unsafe fn new_xs(&self, name: *const i8, func: XSUBADDR_t, file: *const i8) -> *mut CV {
        Perl_newXS(self.0, name, func, file)
    }
    pub unsafe fn new_sv(&self, len: STRLEN) -> *mut SV { Perl_newSV(self.0, len) }
    pub unsafe fn new_sv_iv(&self, val: IV) -> *mut SV { Perl_newSViv(self.0, val) }
    pub unsafe fn new_sv_uv(&self, val: UV) -> *mut SV { Perl_newSVuv(self.0, val) }
    pub unsafe fn new_sv_nv(&self, val: NV) -> *mut SV { Perl_newSVnv(self.0, val) }
    pub unsafe fn new_sv_pvn(&self, val: *const i8, len: STRLEN, flags: U32) -> *mut SV { Perl_newSVpvn_flags(self.0, val, len, flags) }

    pub unsafe fn get_av(&self, name: *const i8) -> *mut AV { Perl_get_av(self.0, name, 0) }
}
<|endoftext|>


<commit_before>use std::uint::iterate;
use std::num::{One, Zero};
use std::vec::swap;
use std::cmp::ApproxEq;
use std::rand::{Rand, Rng, RngUtil};
use std::iterator::IteratorUtil;
use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
use traits::dim::Dim;
use traits::ring::Ring;
use traits::inv::Inv;
use traits::division_ring::DivisionRing;
use traits::transpose::Transpose;
use traits::rlmul::{RMul, LMul};
use traits::transformation::Transform;
use traits::homogeneous::{ToHomogeneous, FromHomogeneous};
use traits::indexable::Indexable;
use traits::column::Column;
use traits::iterable::{Iterable, IterableMut};

mod mat_impl;

#[deriving(ToStr)]
pub struct Mat1<N>
{ mij: [N, ..1 * 1] }

mat_impl!(Mat1, 1)
one_impl!(Mat1, [ _1 ])
zero_impl!(Mat1, [ _0 ])
dim_impl!(Mat1, 1)
mat_indexable_impl!(Mat1, 1)
mul_impl!(Mat1, 1)
rmul_impl!(Mat1, Vec1, 1)
lmul_impl!(Mat1, Vec1, 1)
transform_impl!(Mat1, Vec1)
// inv_impl!(Mat1, 1)
transpose_impl!(Mat1, 1)
approx_eq_impl!(Mat1)
rand_impl!(Mat1, rng, [ rng ])
to_homogeneous_impl!(Mat1, Mat2, 1)
from_homogeneous_impl!(Mat2, Mat1, 1)
column_impl!(Mat2, 2)

#[deriving(ToStr)]
pub struct Mat2<N>
{ mij: [N, ..2 * 2] }

mat_impl!(Mat2, 2)
one_impl!(Mat2, [ _1 | _0 |
                  _0 | _1 ])
zero_impl!(Mat2, [ _0 | _0 |
                   _0 | _0 ])
dim_impl!(Mat2, 2)
mat_indexable_impl!(Mat2, 2)
mul_impl!(Mat2, 2)
rmul_impl!(Mat2, Vec2, 2)
lmul_impl!(Mat2, Vec2, 2)
transform_impl!(Mat2, Vec2)
// inv_impl!(Mat2, 2)
transpose_impl!(Mat2, 2)
approx_eq_impl!(Mat2)
rand_impl!(Mat2, rng, [ rng | rng |
                        rng | rng ])
to_homogeneous_impl!(Mat2, Mat3, 2)
from_homogeneous_impl!(Mat3, Mat2, 2)

#[deriving(ToStr)]
pub struct Mat3<N>
{ mij: [N, ..3 * 3] }

mat_impl!(Mat3, 3)
one_impl!(Mat3, [ _1 | _0 | _0 |
                  _0 | _1 | _0 |
                  _0 | _0 | _1 ])
zero_impl!(Mat3, [ _0 | _0 | _0 |
                  _0 | _0 | _0 |
                  _0 | _0 | _0 ])
dim_impl!(Mat3, 3)
mat_indexable_impl!(Mat3, 3)
mul_impl!(Mat3, 3)
rmul_impl!(Mat3, Vec3, 3)
lmul_impl!(Mat3, Vec3, 3)
transform_impl!(Mat3, Vec3)
// inv_impl!(Mat3, 3)
transpose_impl!(Mat3, 3)
approx_eq_impl!(Mat3)
rand_impl!(Mat3, rng, [ rng | rng | rng |
                        rng | rng | rng |
                        rng | rng | rng])
to_homogeneous_impl!(Mat3, Mat4, 3)
from_homogeneous_impl!(Mat4, Mat3, 3)

#[deriving(ToStr)]
pub struct Mat4<N>
{ mij: [N, ..4 * 4] }

mat_impl!(Mat4, 4)
one_impl!(Mat4, [
          _1 | _0 | _0 | _0 |
          _0 | _1 | _0 | _0 |
          _0 | _0 | _1 | _0 |
          _0 | _0 | _0 | _1
          ])
zero_impl!(Mat4, [
          _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0
          ])
dim_impl!(Mat4, 4)
mat_indexable_impl!(Mat4, 4)
mul_impl!(Mat4, 4)
rmul_impl!(Mat4, Vec4, 4)
lmul_impl!(Mat4, Vec4, 4)
transform_impl!(Mat4, Vec4)
inv_impl!(Mat4, 4)
transpose_impl!(Mat4, 4)
approx_eq_impl!(Mat4)
rand_impl!(Mat4, rng, [
           rng | rng | rng | rng |
           rng | rng | rng | rng |
           rng | rng | rng | rng |
           rng | rng | rng | rng
           ])
to_homogeneous_impl!(Mat4, Mat5, 4)
from_homogeneous_impl!(Mat5, Mat4, 4)

#[deriving(ToStr)]
pub struct Mat5<N>
{ mij: [N, ..5 * 5] }

mat_impl!(Mat5, 5)
one_impl!(Mat5, [
          _1 | _0 | _0 | _0 | _0 |
          _0 | _1 | _0 | _0 | _0 |
          _0 | _0 | _1 | _0 | _0 |
          _0 | _0 | _0 | _1 | _0 |
          _0 | _0 | _0 | _0 | _1
          ])
zero_impl!(Mat5, [
          _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0
          ])
dim_impl!(Mat5, 5)
mat_indexable_impl!(Mat5, 5)
mul_impl!(Mat5, 5)
rmul_impl!(Mat5, Vec5, 5)
lmul_impl!(Mat5, Vec5, 5)
transform_impl!(Mat5, Vec5)
inv_impl!(Mat5, 5)
transpose_impl!(Mat5, 5)
approx_eq_impl!(Mat5)
rand_impl!(Mat5, rng, [
           rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng
           ])
to_homogeneous_impl!(Mat5, Mat6, 5)
from_homogeneous_impl!(Mat6, Mat5, 5)

#[deriving(ToStr)]
pub struct Mat6<N>
{ mij: [N, ..6 * 6] }

mat_impl!(Mat6, 6)
one_impl!(Mat6, [
          _1 | _0 | _0 | _0 | _0 | _0 |
          _0 | _1 | _0 | _0 | _0 | _0 |
          _0 | _0 | _1 | _0 | _0 | _0 |
          _0 | _0 | _0 | _1 | _0 | _0 |
          _0 | _0 | _0 | _0 | _1 | _0 |
          _0 | _0 | _0 | _0 | _0 | _1
          ])
zero_impl!(Mat6, [
          _0 | _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 | _0
          ])
dim_impl!(Mat6, 6)
mat_indexable_impl!(Mat6, 6)
mul_impl!(Mat6, 6)
rmul_impl!(Mat6, Vec6, 6)
lmul_impl!(Mat6, Vec6, 6)
transform_impl!(Mat6, Vec6)
inv_impl!(Mat6, 6)
transpose_impl!(Mat6, 6)
approx_eq_impl!(Mat6)
rand_impl!(Mat6, rng, [
           rng | rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng | rng
           ])
<commit_msg>Add Column implementations.<commit_after>use std::uint::iterate;
use std::num::{One, Zero};
use std::vec::swap;
use std::cmp::ApproxEq;
use std::rand::{Rand, Rng, RngUtil};
use std::iterator::IteratorUtil;
use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
use traits::dim::Dim;
use traits::ring::Ring;
use traits::inv::Inv;
use traits::division_ring::DivisionRing;
use traits::transpose::Transpose;
use traits::rlmul::{RMul, LMul};
use traits::transformation::Transform;
use traits::homogeneous::{ToHomogeneous, FromHomogeneous};
use traits::indexable::Indexable;
use traits::column::Column;
use traits::iterable::{Iterable, IterableMut};

mod mat_impl;

#[deriving(ToStr)]
pub struct Mat1<N>
{ mij: [N, ..1 * 1] }

mat_impl!(Mat1, 1)
one_impl!(Mat1, [ _1 ])
zero_impl!(Mat1, [ _0 ])
dim_impl!(Mat1, 1)
mat_indexable_impl!(Mat1, 1)
mul_impl!(Mat1, 1)
rmul_impl!(Mat1, Vec1, 1)
lmul_impl!(Mat1, Vec1, 1)
transform_impl!(Mat1, Vec1)
// inv_impl!(Mat1, 1)
transpose_impl!(Mat1, 1)
approx_eq_impl!(Mat1)
rand_impl!(Mat1, rng, [ rng ])
to_homogeneous_impl!(Mat1, Mat2, 1)
from_homogeneous_impl!(Mat2, Mat1, 1)
column_impl!(Mat1, 1)

#[deriving(ToStr)]
pub struct Mat2<N>
{ mij: [N, ..2 * 2] }

mat_impl!(Mat2, 2)
one_impl!(Mat2, [ _1 | _0 |
                  _0 | _1 ])
zero_impl!(Mat2, [ _0 | _0 |
                   _0 | _0 ])
dim_impl!(Mat2, 2)
mat_indexable_impl!(Mat2, 2)
mul_impl!(Mat2, 2)
rmul_impl!(Mat2, Vec2, 2)
lmul_impl!(Mat2, Vec2, 2)
transform_impl!(Mat2, Vec2)
// inv_impl!(Mat2, 2)
transpose_impl!(Mat2, 2)
approx_eq_impl!(Mat2)
rand_impl!(Mat2, rng, [ rng | rng |
                        rng | rng ])
to_homogeneous_impl!(Mat2, Mat3, 2)
from_homogeneous_impl!(Mat3, Mat2, 2)
column_impl!(Mat2, 2)

#[deriving(ToStr)]
pub struct Mat3<N>
{ mij: [N, ..3 * 3] }

mat_impl!(Mat3, 3)
one_impl!(Mat3, [ _1 | _0 | _0 |
                  _0 | _1 | _0 |
                  _0 | _0 | _1 ])
zero_impl!(Mat3, [ _0 | _0 | _0 |
                  _0 | _0 | _0 |
                  _0 | _0 | _0 ])
dim_impl!(Mat3, 3)
mat_indexable_impl!(Mat3, 3)
mul_impl!(Mat3, 3)
rmul_impl!(Mat3, Vec3, 3)
lmul_impl!(Mat3, Vec3, 3)
transform_impl!(Mat3, Vec3)
// inv_impl!(Mat3, 3)
transpose_impl!(Mat3, 3)
approx_eq_impl!(Mat3)
rand_impl!(Mat3, rng, [ rng | rng | rng |
                        rng | rng | rng |
                        rng | rng | rng])
to_homogeneous_impl!(Mat3, Mat4, 3)
from_homogeneous_impl!(Mat4, Mat3, 3)
column_impl!(Mat3, 3)

#[deriving(ToStr)]
pub struct Mat4<N>
{ mij: [N, ..4 * 4] }

mat_impl!(Mat4, 4)
one_impl!(Mat4, [
          _1 | _0 | _0 | _0 |
          _0 | _1 | _0 | _0 |
          _0 | _0 | _1 | _0 |
          _0 | _0 | _0 | _1
          ])
zero_impl!(Mat4, [
          _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0
          ])
dim_impl!(Mat4, 4)
mat_indexable_impl!(Mat4, 4)
mul_impl!(Mat4, 4)
rmul_impl!(Mat4, Vec4, 4)
lmul_impl!(Mat4, Vec4, 4)
transform_impl!(Mat4, Vec4)
inv_impl!(Mat4, 4)
transpose_impl!(Mat4, 4)
approx_eq_impl!(Mat4)
rand_impl!(Mat4, rng, [
           rng | rng | rng | rng |
           rng | rng | rng | rng |
           rng | rng | rng | rng |
           rng | rng | rng | rng
           ])
to_homogeneous_impl!(Mat4, Mat5, 4)
from_homogeneous_impl!(Mat5, Mat4, 4)
column_impl!(Mat4, 4)

#[deriving(ToStr)]
pub struct Mat5<N>
{ mij: [N, ..5 * 5] }

mat_impl!(Mat5, 5)
one_impl!(Mat5, [
          _1 | _0 | _0 | _0 | _0 |
          _0 | _1 | _0 | _0 | _0 |
          _0 | _0 | _1 | _0 | _0 |
          _0 | _0 | _0 | _1 | _0 |
          _0 | _0 | _0 | _0 | _1
          ])
zero_impl!(Mat5, [
          _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0
          ])
dim_impl!(Mat5, 5)
mat_indexable_impl!(Mat5, 5)
mul_impl!(Mat5, 5)
rmul_impl!(Mat5, Vec5, 5)
lmul_impl!(Mat5, Vec5, 5)
transform_impl!(Mat5, Vec5)
inv_impl!(Mat5, 5)
transpose_impl!(Mat5, 5)
approx_eq_impl!(Mat5)
rand_impl!(Mat5, rng, [
           rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng
           ])
to_homogeneous_impl!(Mat5, Mat6, 5)
from_homogeneous_impl!(Mat6, Mat5, 5)
column_impl!(Mat5, 5)

#[deriving(ToStr)]
pub struct Mat6<N>
{ mij: [N, ..6 * 6] }

mat_impl!(Mat6, 6)
one_impl!(Mat6, [
          _1 | _0 | _0 | _0 | _0 | _0 |
          _0 | _1 | _0 | _0 | _0 | _0 |
          _0 | _0 | _1 | _0 | _0 | _0 |
          _0 | _0 | _0 | _1 | _0 | _0 |
          _0 | _0 | _0 | _0 | _1 | _0 |
          _0 | _0 | _0 | _0 | _0 | _1
          ])
zero_impl!(Mat6, [
          _0 | _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 | _0 |
          _0 | _0 | _0 | _0 | _0 | _0
          ])
dim_impl!(Mat6, 6)
mat_indexable_impl!(Mat6, 6)
mul_impl!(Mat6, 6)
rmul_impl!(Mat6, Vec6, 6)
lmul_impl!(Mat6, Vec6, 6)
transform_impl!(Mat6, Vec6)
inv_impl!(Mat6, 6)
transpose_impl!(Mat6, 6)
approx_eq_impl!(Mat6)
rand_impl!(Mat6, rng, [
           rng | rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng | rng |
           rng | rng | rng | rng | rng | rng
           ])
column_impl!(Mat6, 6)
<|endoftext|>


<commit_before>extern crate time;

use std::ops::Deref;

use ::expr::{Expr, Type, Error as E, Result};
use ::eval::funcall;
use ::env::Env;
use ::util::*;

pub fn k_skk_calc(env: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args, (op, Sym));
    let skk_num_list = try!(env.find(&"skk-num-list".to_string())).clone();
    get_args!(&skk_num_list, (x, Int) (y, Int));
    let res = match &op[..] {
        "+" => x + y,
        "-" => x - y,
        "*" => x * y,
        "/" => x / y,
        op => return //Err(format!("unknown operator {}", op))
                       Err(E::User(format!("unknown operator {}", op)))
    };
    Ok(kint(res))
}

pub fn k_skk_current_date_1(_: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args);
    // TODO: don't allocate month/wday table every time
    let mvec = vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    let wvec = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
    let now = time::now();
    let year = (now.tm_year + 1900).to_string();
    let month = mvec[now.tm_mon as usize];
    let mday = now.tm_mday.to_string();
    let wday = wvec[now.tm_wday as usize];
    let hour = now.tm_hour.to_string();
    let min = now.tm_min.to_string();
    let sec = now.tm_sec.to_string();
    Ok(klist!(year, month, mday, wday, hour, min, sec))
}

pub fn k_skk_current_date(env: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args, (f, Proc));
    let date_information = klist!("2013", "Jan", "29", "Tue", "22", "59", "50");
    let format = knil();
    let gengo = knil(); //or t
    let and_time = knil();
    funcall(env, f, &klist!(date_information, format, gengo, and_time))
}

pub fn init(mut env: &mut Env) -> Result<()>{
    env.fregister("skk-calc", kprim("k_skk_calc", k_skk_calc));
    env.fregister("skk-current-date-1", kprim("k_skk_current_date_1", k_skk_current_date_1));
    env.fregister("skk-current-date", kprim("k_skk_current_date", k_skk_current_date));
    Ok(())
}
<commit_msg>use optional argument<commit_after>extern crate time;

use std::ops::Deref;

use ::expr::{Expr, Type, Error as E, Result};
use ::eval::funcall;
use ::env::Env;
use ::util::*;

pub fn k_skk_calc(env: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args, (op, Sym));
    let skk_num_list = try!(env.find(&"skk-num-list".to_string())).clone();
    get_args!(&skk_num_list, (x, Int) (y, Int));
    let res = match &op[..] {
        "+" => x + y,
        "-" => x - y,
        "*" => x * y,
        "/" => x / y,
        op => return //Err(format!("unknown operator {}", op))
                       Err(E::User(format!("unknown operator {}", op)))
    };
    Ok(kint(res))
}

pub fn k_skk_current_date_1(_: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args, (_, opt Any));
    // TODO: don't allocate month/wday table every time
    let mvec = vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    let wvec = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
    let now = time::now();
    let year = (now.tm_year + 1900).to_string();
    let month = mvec[now.tm_mon as usize];
    let mday = now.tm_mday.to_string();
    let wday = wvec[now.tm_wday as usize];
    let hour = now.tm_hour.to_string();
    let min = now.tm_min.to_string();
    let sec = now.tm_sec.to_string();
    Ok(klist!(year, month, mday, wday, hour, min, sec))
}

pub fn k_skk_current_date(mut env: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args, (f, opt Proc));
    let date_information = try!(k_skk_current_date_1(&mut env, &knil()));
    let format = knil();
    let gengo = knil(); //or t
    let and_time = knil();
    match f {
        Some(f) => funcall(env, f, &klist!(date_information, format, gengo, and_time)),
        None => Ok(knil())
    }

}

pub fn init(mut env: &mut Env) -> Result<()>{
    env.fregister("skk-calc", kprim("k_skk_calc", k_skk_calc));
    env.fregister("skk-current-date-1", kprim("k_skk_current_date_1", k_skk_current_date_1));
    env.fregister("skk-current-date", kprim("k_skk_current_date", k_skk_current_date));
    Ok(())
}
<|endoftext|>


<commit_before>//! The AWS STS API.

#![allow(unused_imports)]

include!(concat!(env!("OUT_DIR"), "/sts.rs"));

pub use self::credential::{StsSessionCredentialsProvider};

mod credential {
    use std::error::Error;
    use std::fmt;

    use hyper::Client;
    use chrono::*;

    use ::{AwsCredentials, ProfileProvider, CredentialsError,
        ProvideAwsCredentials, DispatchSignedRequest};
    use super::{AssumeRoleRequest, AssumeRoleResponse, AssumeRoleError,
        AssumeRoleWithSAMLRequest, AssumeRoleWithSAMLResponse, AssumeRoleWithSAMLError,
        AssumeRoleWithWebIdentityRequest, AssumeRoleWithWebIdentityResponse, AssumeRoleWithWebIdentityError,
        DecodeAuthorizationMessageRequest, DecodeAuthorizationMessageResponse, DecodeAuthorizationMessageError,
        GetCallerIdentityRequest, GetCallerIdentityResponse, GetCallerIdentityError,
        GetFederationTokenRequest, GetFederationTokenResponse, GetFederationTokenError,
        GetSessionTokenRequest, GetSessionTokenResponse, GetSessionTokenError,
        StsClient};

    pub const DEFAULT_DURATION_SECONDS: i32 = 3600;
    pub const DEFAULT_ROLE_DURATION_SECONDS: i32 = 900;

    pub trait NewAwsCredsForStsCreds {
        fn new_for_credentials(sts_creds: ::sts::Credentials) -> Result<AwsCredentials, CredentialsError>;
    }

    impl NewAwsCredsForStsCreds for AwsCredentials {
        fn new_for_credentials(sts_creds: ::sts::Credentials) -> Result<AwsCredentials, CredentialsError> {
            let expires_at = try!(sts_creds.expiration.parse::<DateTime<UTC>>().map_err(CredentialsError::from));

            Ok(AwsCredentials::new(
                sts_creds.access_key_id,
                sts_creds.secret_access_key,
                Some(sts_creds.session_token),
                expires_at))
        }
    }

    pub trait StsSessionCredentialsClient {
        fn assume_role(&self, input: &AssumeRoleRequest) -> Result<AssumeRoleResponse, AssumeRoleError>;

        fn assume_role_with_saml(&self, input: &AssumeRoleWithSAMLRequest) -> Result<AssumeRoleWithSAMLResponse, AssumeRoleWithSAMLError>;

        fn assume_role_with_web_identity(&self, input: &AssumeRoleWithWebIdentityRequest) -> Result<AssumeRoleWithWebIdentityResponse, AssumeRoleWithWebIdentityError>;

        fn decode_authorization_message(&self, input: &DecodeAuthorizationMessageRequest) -> Result<DecodeAuthorizationMessageResponse, DecodeAuthorizationMessageError>;

        fn get_caller_identity(&self, input: &GetCallerIdentityRequest) -> Result<GetCallerIdentityResponse, GetCallerIdentityError> ;

        fn get_federation_token(&self, input: &GetFederationTokenRequest) -> Result<GetFederationTokenResponse, GetFederationTokenError>;

        fn get_session_token(&self, input: &GetSessionTokenRequest) -> Result<GetSessionTokenResponse, GetSessionTokenError>;
    }

    impl <P,D> StsSessionCredentialsClient for StsClient<P,D> where P: ProvideAwsCredentials, D: DispatchSignedRequest {
        fn assume_role(&self, input: &AssumeRoleRequest) -> Result<AssumeRoleResponse, AssumeRoleError> {
            StsClient::assume_role(self, input)
        }

        fn assume_role_with_saml(&self, input: &AssumeRoleWithSAMLRequest) -> Result<AssumeRoleWithSAMLResponse, AssumeRoleWithSAMLError> {
            StsClient::assume_role_with_saml(self, input)
        }

        fn assume_role_with_web_identity(&self, input: &AssumeRoleWithWebIdentityRequest) -> Result<AssumeRoleWithWebIdentityResponse, AssumeRoleWithWebIdentityError> {
            StsClient::assume_role_with_web_identity(self, input)
        }

        fn decode_authorization_message(&self, input: &DecodeAuthorizationMessageRequest) -> Result<DecodeAuthorizationMessageResponse, DecodeAuthorizationMessageError> {
            StsClient::decode_authorization_message(self, input)
        }

        fn get_caller_identity(&self, input: &GetCallerIdentityRequest) -> Result<GetCallerIdentityResponse, GetCallerIdentityError> {
            StsClient::get_caller_identity(self, input)
        }

        fn get_federation_token(&self, input: &GetFederationTokenRequest) -> Result<GetFederationTokenResponse, GetFederationTokenError> {
            StsClient::get_federation_token(self, input)
        }

        fn get_session_token(&self, input: &GetSessionTokenRequest) -> Result<GetSessionTokenResponse, GetSessionTokenError> {
            StsClient::get_session_token(self, input)
        }
    }

    pub struct StsSessionCredentialsProvider {
        sts_client: Box<StsSessionCredentialsClient>,
        session_duration: Duration,
        mfa_serial: Option<String>,
        mfa_code: Option<String>,
    }

    impl StsSessionCredentialsProvider {
        pub fn new<P,D>(sts_client: StsClient<P,D>,
                duration: Option<Duration>,
                mfa_serial: Option<String>,
                ) -> StsSessionCredentialsProvider
                where P: ProvideAwsCredentials + 'static, D: DispatchSignedRequest + 'static {
            StsSessionCredentialsProvider {
                sts_client: Box::new(sts_client),
                session_duration: duration.unwrap_or(Duration::seconds(DEFAULT_DURATION_SECONDS as i64)),
                mfa_serial: mfa_serial,
                mfa_code: None,
            }
        }

        pub fn set_mfa_code<S>(&mut self, code: S) where S: Into<String> {
            self.mfa_code = Some(code.into());
        }

        pub fn clear_mfa_code(&mut self) {
            self.mfa_code = None;
        }

        pub fn get_session_token(&self) -> Result<AwsCredentials, CredentialsError> {
            match self.sts_client.get_session_token(
                &GetSessionTokenRequest {
                    serial_number: self.mfa_serial.clone(),
                    token_code: self.mfa_code.clone(),
                    duration_seconds: Some(self.session_duration.num_seconds() as i32),
                    ..Default::default()
                }) {
                Ok(resp) => {
                    let creds = try!(resp.credentials.ok_or(CredentialsError::new("no credentials in response")));

                    AwsCredentials::new_for_credentials(creds)
                },
                err =>
                    Err(CredentialsError::new(format!("StsProvider get_session_token error: {:?}", err)))
            }
        }
    }

    impl ProvideAwsCredentials for StsSessionCredentialsProvider {
        fn credentials(&self) -> Result<AwsCredentials, CredentialsError> {
            self.get_session_token()
        }
    }

    pub struct StsAssumeRoleSessionCredentialsProvider {
        sts_client: Box<StsSessionCredentialsClient>,
        role_arn: String,
        session_name: String,
        external_id: Option<String>,
        session_duration: Duration,
        scope_down_policy: Option<String>,
    }

    impl StsAssumeRoleSessionCredentialsProvider {
        pub fn new<P,D>(sts_client: StsClient<P,D>,
                role_arn: String,
                session_name: String,
                external_id: Option<String>,
                session_duration: Option<Duration>,
                scope_down_policy: Option<String>,
                )
                -> StsAssumeRoleSessionCredentialsProvider
                where P: ProvideAwsCredentials + 'static, D: DispatchSignedRequest + 'static {
            StsAssumeRoleSessionCredentialsProvider {
                sts_client: Box::new(sts_client),
                role_arn: role_arn,
                session_name: session_name,
                external_id: external_id,
                session_duration: session_duration.unwrap_or(Duration::seconds(DEFAULT_ROLE_DURATION_SECONDS as i64)),
                scope_down_policy: scope_down_policy,
            }
        }

        pub fn assume_role(&self) -> Result<AwsCredentials, CredentialsError> {
            match self.sts_client.assume_role(&AssumeRoleRequest {
                role_arn: self.role_arn.clone(),
                role_session_name: self.session_name.clone(),
                duration_seconds: Some(self.session_duration.num_seconds() as i32),
                external_id: self.external_id.clone(),
                policy: self.scope_down_policy.clone(),
                ..Default::default()
            }) {
                Err(err) =>
                    Err(CredentialsError::new(format!("Sts AssumeRoleError: {:?}", err))),
                Ok(resp) => {
                    let creds = try!(resp.credentials.ok_or(CredentialsError::new("no credentials in response")));

                    AwsCredentials::new_for_credentials(creds)
                }
            }
        }
    }

    impl ProvideAwsCredentials for StsAssumeRoleSessionCredentialsProvider {
        fn credentials(&self) -> Result<AwsCredentials, CredentialsError> {
            self.assume_role()
        }
    }

    pub struct StsWebIdentityFederationSessionCredentialsProvider {
        sts_client: Box<StsSessionCredentialsClient>,
        wif_token: String,
        wif_provider: Option<String>,
        role_arn: String,
        session_name: String,
        session_duration: Duration,
        scope_down_policy: Option<String>,
    }

    impl StsWebIdentityFederationSessionCredentialsProvider {
        pub fn new<P,D>(sts_client: StsClient<P,D>,
                wif_token: String,
                wif_provider: Option<String>,
                role_arn: String,
                session_name: String,
                session_duration: Option<Duration>,
                policy: Option<String>,
                ) -> StsWebIdentityFederationSessionCredentialsProvider
                where P: ProvideAwsCredentials + 'static, D: DispatchSignedRequest + 'static {
            StsWebIdentityFederationSessionCredentialsProvider {
                sts_client: Box::new(sts_client),
                wif_token: wif_token,
                wif_provider: wif_provider,
                role_arn: role_arn,
                session_name: session_name,
                session_duration: session_duration.unwrap_or(Duration::seconds(DEFAULT_DURATION_SECONDS as i64)),
                scope_down_policy: policy,
            }
        }

        pub fn assume_role_with_web_identity(&self) -> Result<AwsCredentials, CredentialsError> {
            match self.sts_client.assume_role_with_web_identity(&AssumeRoleWithWebIdentityRequest {
                web_identity_token: self.wif_token.clone(),
                provider_id: self.wif_provider.clone(),
                role_arn: self.role_arn.clone(),
                role_session_name: self.session_name.clone(),
                duration_seconds: Some(self.session_duration.num_seconds() as i32),
                policy: self.scope_down_policy.clone(),
                ..Default::default()
            }) {
                Err(err) =>
                    Err(CredentialsError::new(format!("Sts AssumeRoleWithWebIdentityError: {:?}", err))),
                Ok(resp) => {
                    let creds = try!(resp.credentials.ok_or(CredentialsError::new("no credentials in response")));

                    let mut aws_creds = try!(AwsCredentials::new_for_credentials(creds));

                    if let Some(subject_from_wif) = resp.subject_from_web_identity_token {
                        aws_creds.claims_mut().insert(::claims::SUBJECT.to_owned(), subject_from_wif);
                    }

                    Ok(aws_creds)
                }
            }
        }
    }

    impl ProvideAwsCredentials for StsWebIdentityFederationSessionCredentialsProvider {
        fn credentials(&self) -> Result<AwsCredentials, CredentialsError> {
            self.assume_role_with_web_identity()
        }
    }
}<commit_msg>fix imports<commit_after>//! The AWS STS API.

#![allow(unused_imports)]

include!(concat!(env!("OUT_DIR"), "/sts.rs"));

pub use self::credential::{
    StsSessionCredentialsProvider,
    StsAssumeRoleSessionCredentialsProvider,
    StsWebIdentityFederationSessionCredentialsProvider,
    NewAwsCredsForStsCreds,
    };

mod credential {
    use std::error::Error;
    use std::fmt;

    use hyper::Client;
    use chrono::*;

    use ::{AwsCredentials, ProfileProvider, CredentialsError,
        ProvideAwsCredentials, DispatchSignedRequest};
    use super::{AssumeRoleRequest, AssumeRoleResponse, AssumeRoleError,
        AssumeRoleWithSAMLRequest, AssumeRoleWithSAMLResponse, AssumeRoleWithSAMLError,
        AssumeRoleWithWebIdentityRequest, AssumeRoleWithWebIdentityResponse, AssumeRoleWithWebIdentityError,
        DecodeAuthorizationMessageRequest, DecodeAuthorizationMessageResponse, DecodeAuthorizationMessageError,
        GetCallerIdentityRequest, GetCallerIdentityResponse, GetCallerIdentityError,
        GetFederationTokenRequest, GetFederationTokenResponse, GetFederationTokenError,
        GetSessionTokenRequest, GetSessionTokenResponse, GetSessionTokenError,
        StsClient};

    pub const DEFAULT_DURATION_SECONDS: i32 = 3600;
    pub const DEFAULT_ROLE_DURATION_SECONDS: i32 = 900;

    pub trait NewAwsCredsForStsCreds {
        fn new_for_credentials(sts_creds: ::sts::Credentials) -> Result<AwsCredentials, CredentialsError>;
    }

    impl NewAwsCredsForStsCreds for AwsCredentials {
        fn new_for_credentials(sts_creds: ::sts::Credentials) -> Result<AwsCredentials, CredentialsError> {
            let expires_at = try!(sts_creds.expiration.parse::<DateTime<UTC>>().map_err(CredentialsError::from));

            Ok(AwsCredentials::new(
                sts_creds.access_key_id,
                sts_creds.secret_access_key,
                Some(sts_creds.session_token),
                expires_at))
        }
    }

    pub trait StsSessionCredentialsClient {
        fn assume_role(&self, input: &AssumeRoleRequest) -> Result<AssumeRoleResponse, AssumeRoleError>;

        fn assume_role_with_saml(&self, input: &AssumeRoleWithSAMLRequest) -> Result<AssumeRoleWithSAMLResponse, AssumeRoleWithSAMLError>;

        fn assume_role_with_web_identity(&self, input: &AssumeRoleWithWebIdentityRequest) -> Result<AssumeRoleWithWebIdentityResponse, AssumeRoleWithWebIdentityError>;

        fn decode_authorization_message(&self, input: &DecodeAuthorizationMessageRequest) -> Result<DecodeAuthorizationMessageResponse, DecodeAuthorizationMessageError>;

        fn get_caller_identity(&self, input: &GetCallerIdentityRequest) -> Result<GetCallerIdentityResponse, GetCallerIdentityError> ;

        fn get_federation_token(&self, input: &GetFederationTokenRequest) -> Result<GetFederationTokenResponse, GetFederationTokenError>;

        fn get_session_token(&self, input: &GetSessionTokenRequest) -> Result<GetSessionTokenResponse, GetSessionTokenError>;
    }

    impl <P,D> StsSessionCredentialsClient for StsClient<P,D> where P: ProvideAwsCredentials, D: DispatchSignedRequest {
        fn assume_role(&self, input: &AssumeRoleRequest) -> Result<AssumeRoleResponse, AssumeRoleError> {
            StsClient::assume_role(self, input)
        }

        fn assume_role_with_saml(&self, input: &AssumeRoleWithSAMLRequest) -> Result<AssumeRoleWithSAMLResponse, AssumeRoleWithSAMLError> {
            StsClient::assume_role_with_saml(self, input)
        }

        fn assume_role_with_web_identity(&self, input: &AssumeRoleWithWebIdentityRequest) -> Result<AssumeRoleWithWebIdentityResponse, AssumeRoleWithWebIdentityError> {
            StsClient::assume_role_with_web_identity(self, input)
        }

        fn decode_authorization_message(&self, input: &DecodeAuthorizationMessageRequest) -> Result<DecodeAuthorizationMessageResponse, DecodeAuthorizationMessageError> {
            StsClient::decode_authorization_message(self, input)
        }

        fn get_caller_identity(&self, input: &GetCallerIdentityRequest) -> Result<GetCallerIdentityResponse, GetCallerIdentityError> {
            StsClient::get_caller_identity(self, input)
        }

        fn get_federation_token(&self, input: &GetFederationTokenRequest) -> Result<GetFederationTokenResponse, GetFederationTokenError> {
            StsClient::get_federation_token(self, input)
        }

        fn get_session_token(&self, input: &GetSessionTokenRequest) -> Result<GetSessionTokenResponse, GetSessionTokenError> {
            StsClient::get_session_token(self, input)
        }
    }

    pub struct StsSessionCredentialsProvider {
        sts_client: Box<StsSessionCredentialsClient>,
        session_duration: Duration,
        mfa_serial: Option<String>,
        mfa_code: Option<String>,
    }

    impl StsSessionCredentialsProvider {
        pub fn new<P,D>(sts_client: StsClient<P,D>,
                duration: Option<Duration>,
                mfa_serial: Option<String>,
                ) -> StsSessionCredentialsProvider
                where P: ProvideAwsCredentials + 'static, D: DispatchSignedRequest + 'static {
            StsSessionCredentialsProvider {
                sts_client: Box::new(sts_client),
                session_duration: duration.unwrap_or(Duration::seconds(DEFAULT_DURATION_SECONDS as i64)),
                mfa_serial: mfa_serial,
                mfa_code: None,
            }
        }

        pub fn set_mfa_code<S>(&mut self, code: S) where S: Into<String> {
            self.mfa_code = Some(code.into());
        }

        pub fn clear_mfa_code(&mut self) {
            self.mfa_code = None;
        }

        pub fn get_session_token(&self) -> Result<AwsCredentials, CredentialsError> {
            match self.sts_client.get_session_token(
                &GetSessionTokenRequest {
                    serial_number: self.mfa_serial.clone(),
                    token_code: self.mfa_code.clone(),
                    duration_seconds: Some(self.session_duration.num_seconds() as i32),
                    ..Default::default()
                }) {
                Ok(resp) => {
                    let creds = try!(resp.credentials.ok_or(CredentialsError::new("no credentials in response")));

                    AwsCredentials::new_for_credentials(creds)
                },
                err =>
                    Err(CredentialsError::new(format!("StsProvider get_session_token error: {:?}", err)))
            }
        }
    }

    impl ProvideAwsCredentials for StsSessionCredentialsProvider {
        fn credentials(&self) -> Result<AwsCredentials, CredentialsError> {
            self.get_session_token()
        }
    }

    pub struct StsAssumeRoleSessionCredentialsProvider {
        sts_client: Box<StsSessionCredentialsClient>,
        role_arn: String,
        session_name: String,
        external_id: Option<String>,
        session_duration: Duration,
        scope_down_policy: Option<String>,
    }

    impl StsAssumeRoleSessionCredentialsProvider {
        pub fn new<P,D>(sts_client: StsClient<P,D>,
                role_arn: String,
                session_name: String,
                external_id: Option<String>,
                session_duration: Option<Duration>,
                scope_down_policy: Option<String>,
                )
                -> StsAssumeRoleSessionCredentialsProvider
                where P: ProvideAwsCredentials + 'static, D: DispatchSignedRequest + 'static {
            StsAssumeRoleSessionCredentialsProvider {
                sts_client: Box::new(sts_client),
                role_arn: role_arn,
                session_name: session_name,
                external_id: external_id,
                session_duration: session_duration.unwrap_or(Duration::seconds(DEFAULT_ROLE_DURATION_SECONDS as i64)),
                scope_down_policy: scope_down_policy,
            }
        }

        pub fn assume_role(&self) -> Result<AwsCredentials, CredentialsError> {
            match self.sts_client.assume_role(&AssumeRoleRequest {
                role_arn: self.role_arn.clone(),
                role_session_name: self.session_name.clone(),
                duration_seconds: Some(self.session_duration.num_seconds() as i32),
                external_id: self.external_id.clone(),
                policy: self.scope_down_policy.clone(),
                ..Default::default()
            }) {
                Err(err) =>
                    Err(CredentialsError::new(format!("Sts AssumeRoleError: {:?}", err))),
                Ok(resp) => {
                    let creds = try!(resp.credentials.ok_or(CredentialsError::new("no credentials in response")));

                    AwsCredentials::new_for_credentials(creds)
                }
            }
        }
    }

    impl ProvideAwsCredentials for StsAssumeRoleSessionCredentialsProvider {
        fn credentials(&self) -> Result<AwsCredentials, CredentialsError> {
            self.assume_role()
        }
    }

    pub struct StsWebIdentityFederationSessionCredentialsProvider {
        sts_client: Box<StsSessionCredentialsClient>,
        wif_token: String,
        wif_provider: Option<String>,
        role_arn: String,
        session_name: String,
        session_duration: Duration,
        scope_down_policy: Option<String>,
    }

    impl StsWebIdentityFederationSessionCredentialsProvider {
        pub fn new<P,D>(sts_client: StsClient<P,D>,
                wif_token: String,
                wif_provider: Option<String>,
                role_arn: String,
                session_name: String,
                session_duration: Option<Duration>,
                policy: Option<String>,
                ) -> StsWebIdentityFederationSessionCredentialsProvider
                where P: ProvideAwsCredentials + 'static, D: DispatchSignedRequest + 'static {
            StsWebIdentityFederationSessionCredentialsProvider {
                sts_client: Box::new(sts_client),
                wif_token: wif_token,
                wif_provider: wif_provider,
                role_arn: role_arn,
                session_name: session_name,
                session_duration: session_duration.unwrap_or(Duration::seconds(DEFAULT_DURATION_SECONDS as i64)),
                scope_down_policy: policy,
            }
        }

        pub fn assume_role_with_web_identity(&self) -> Result<AwsCredentials, CredentialsError> {
            match self.sts_client.assume_role_with_web_identity(&AssumeRoleWithWebIdentityRequest {
                web_identity_token: self.wif_token.clone(),
                provider_id: self.wif_provider.clone(),
                role_arn: self.role_arn.clone(),
                role_session_name: self.session_name.clone(),
                duration_seconds: Some(self.session_duration.num_seconds() as i32),
                policy: self.scope_down_policy.clone(),
                ..Default::default()
            }) {
                Err(err) =>
                    Err(CredentialsError::new(format!("Sts AssumeRoleWithWebIdentityError: {:?}", err))),
                Ok(resp) => {
                    let creds = try!(resp.credentials.ok_or(CredentialsError::new("no credentials in response")));

                    let mut aws_creds = try!(AwsCredentials::new_for_credentials(creds));

                    if let Some(subject_from_wif) = resp.subject_from_web_identity_token {
                        aws_creds.claims_mut().insert(::claims::SUBJECT.to_owned(), subject_from_wif);
                    }

                    Ok(aws_creds)
                }
            }
        }
    }

    impl ProvideAwsCredentials for StsWebIdentityFederationSessionCredentialsProvider {
        fn credentials(&self) -> Result<AwsCredentials, CredentialsError> {
            self.assume_role_with_web_identity()
        }
    }
}<|endoftext|>


<commit_before>extern crate libc;

use std;
use std::mem;
use libc::c_char;
use std::ffi::CStr;

use nom::*;

use rparser::*;

use tls_parser::tls::{TlsMessage,TlsMessageHandshake,TlsRecordType,TlsRawRecord,parse_tls_raw_record,parse_tls_record_with_header};
use tls_parser::tls_ciphers::*;
use tls_parser::tls_dh::*;
use tls_parser::tls_ec::*;
use tls_parser::tls_extensions::*;
use tls_parser::tls_sign_hash::*;
use tls_parser::tls_states::{TlsState,tls_state_transition};

// --------------------------------------------
// example implementation: TLS parser

#[repr(u32)]
pub enum TlsParserEvents {
    HeartbeatOverflow = 1,
    InvalidState = 2,

    RecordIncomplete = 3,
    RecordWithExtraBytes = 4,
    RecordOverflow = 5,
}

pub struct TlsParser<'a> {
    pub o: Option<&'a[u8]>,

    pub events: Vec<u32>,

    pub compression: Option<u8>,
    pub cipher: Option<&'a TlsCipherSuite>,
    pub state: TlsState,

    pub kx_bits: Option<u32>,

    /// TCP segments defragmentation buffer
    pub tcp_buffer: Vec<u8>,

    /// Handshake defragmentation buffer
    pub buffer: Vec<u8>,

    pub has_signature_algorithms: bool,
}

impl<'a> TlsParser<'a> {
    pub fn new(i: &'a[u8]) -> TlsParser<'a> {
        TlsParser{
            o:Some(i),
            events:Vec::new(),
            compression:None,
            cipher:None,
            state:TlsState::None,
            kx_bits: None,
            // capacity is the amount of space allocated, which means elements can be added
            // without reallocating the vector
            tcp_buffer:Vec::with_capacity(16384),
            buffer:Vec::with_capacity(16384),
            has_signature_algorithms:false,
        }
    }

    /// Message-level TLS parsing
    fn parse_message_level(&mut self, msg: &TlsMessage) -> u32 {
        debug!("parse_message_level {:?}",msg);
        let mut status = R_STATUS_OK;
        if self.state == TlsState::ClientChangeCipherSpec {
            // Ignore records from now on, they are encrypted
            return status;
        };
        // update state machine
        match tls_state_transition(self.state, msg) {
            Ok(s)  => self.state = s,
            Err(_) => {
                self.state = TlsState::Invalid;
                self.events.push(TlsParserEvents::InvalidState as u32);
                status |= R_STATUS_EVENTS;
            },
        };
        debug!("TLS new state: {:?}",self.state);
        // extract variables
        match *msg {
            TlsMessage::Handshake(ref m) => {
                match *m {
                    TlsMessageHandshake::ClientHello(ref content) => {
                        let ext = parse_tls_extensions(content.ext.unwrap_or(b""));
                        match &ext {
                            &IResult::Done(_,ref l) => {
                                for extension in l {
                                    match *extension {
                                        TlsExtension::SignatureAlgorithms(_) => self.has_signature_algorithms = true,
                                        _ => (),
                                    }
                                }
                            },
                            e @ _ => error!("Could not parse extentions: {:?}",e),
                        };
                        debug!("ext {:?}", ext);
                    },
                    TlsMessageHandshake::ServerHello(ref content) => {
                        self.compression = Some(content.compression);
                        self.cipher = TlsCipherSuite::from_id(content.cipher);
                        match self.cipher {
                            Some(c) => {
                                debug!("Selected cipher: {:?}", c)
                            },
                            _ => warn!("Unknown cipher 0x{:x}", content.cipher),
                        };
                        let ext = parse_tls_extensions(content.ext.unwrap_or(b""));
                        debug!("extensions: {:?}", ext);
                    },
                    TlsMessageHandshake::Certificate(ref content) => {
                        debug!("cert chain length: {}",content.cert_chain.len());
                        for cert in &content.cert_chain {
                            debug!("cert: {:?}",cert);
                        }
                    },
                    TlsMessageHandshake::ServerKeyExchange(ref content) => {
                        // The SKE contains the chosen algorithm for the ephemeral key
                        match self.cipher {
                            None => (),
                            Some (c) => { self.kx_bits = rusticata_tls_get_kx_bits(c,content.parameters,self.has_signature_algorithms) },
                        }
                    },
                    _ => (),
                }
            },
            TlsMessage::Heartbeat(ref d) => {
                if d.payload_len as usize > d.payload.len() {
                    warn!("Heartbeat message with incorrect length {}. Heartbleed attempt ?",d.payload.len());
                    self.events.push(TlsParserEvents::HeartbeatOverflow as u32);
                    status |= R_STATUS_EVENTS;
                }
            },
            _ => (),
        }

        status
    }

    fn parse_record_level<'b>(&mut self, r: &TlsRawRecord<'b>) -> u32 {
        let mut v : Vec<u8>;
        let mut status = R_STATUS_OK;

        debug!("parse_record_level {}",r.data.len());
        // debug!("{:?}",r.data);

        // only parse some message types
        match TlsRecordType::try_from_u8(r.hdr.record_type) {
            Ok(TlsRecordType::ChangeCipherSpec) => (),
            Ok(TlsRecordType::Handshake)        => (),
            _ => return status,
        }

        // Check if a record is being defragmented
        let record_buffer = match self.buffer.len() {
            0 => r.data,
            _ => {
                v = self.buffer.split_off(0);
                // sanity check vector length to avoid memory exhaustion
                // maximum length may be 2^24 (handshake message)
                if self.buffer.len() + r.data.len() > 16777216 {
                    self.events.push(TlsParserEvents::RecordOverflow as u32);
                    return R_STATUS_EVENTS;
                };
                v.extend_from_slice(r.data);
                v.as_slice()
            },
        };
        // do not parse if session is encrypted
        if self.state == TlsState::ClientChangeCipherSpec {
            return status;
        };
        // XXX record may be compressed
        //
        // Parse record contents as plaintext
        match parse_tls_record_with_header(record_buffer,r.hdr.clone()) {
            IResult::Done(rem2,ref msg_list) => {
                for msg in msg_list {
                    status |= self.parse_message_level(msg);
                };
                if rem2.len() > 0 {
                    warn!("extra bytes in TLS record: {:?}",rem2);
                    self.events.push(TlsParserEvents::RecordWithExtraBytes as u32);
                    status |= R_STATUS_EVENTS;
                };
            }
            IResult::Incomplete(_) => {
                debug!("Defragmentation required (TLS record)");
                // Record is fragmented
                self.buffer.extend_from_slice(r.data);
            },
            IResult::Error(e) => { warn!("parse_tls_record_with_header failed: {:?}",e); status |= R_STATUS_FAIL; },
        };

        status
    }

    pub fn parse_tcp_level<'b>(&mut self, i: &'b[u8]) -> u32 {
        let mut v : Vec<u8>;
        let mut status = R_STATUS_OK;
        debug!("parse_tcp_level ({})",i.len());
        // debug!("{:?}",i);
        // Check if TCP data is being defragmented
        let tcp_buffer = match self.tcp_buffer.len() {
            0 => i,
            _ => {
                v = self.tcp_buffer.split_off(0);
                // sanity check vector length to avoid memory exhaustion
                // maximum length may be 2^24 (handshake message)
                if self.tcp_buffer.len() + i.len() > 16777216 {
                    self.events.push(TlsParserEvents::RecordOverflow as u32);
                    return R_STATUS_EVENTS;
                };
                v.extend_from_slice(i);
                v.as_slice()
            },
        };
        // debug!("tcp_buffer ({})",tcp_buffer.len());
        let mut cur_i = tcp_buffer;
        while cur_i.len() > 0 {
            match parse_tls_raw_record(cur_i) {
                IResult::Done(rem, ref r) => {
                    // debug!("rem: {:?}",rem);
                    cur_i = rem;
                    status |= self.parse_record_level(r);
                },
                IResult::Incomplete(_) => {
                    debug!("Fragmentation required (TCP level)");
                    self.tcp_buffer.extend_from_slice(cur_i);
                    break;
                },
                IResult::Error(e) => { warn!("Parsing failed: {:?}",e); break },
            }
        };
        status
    }
}

r_declare_state_new!(r_tls_state_new,TlsParser,b"TLS parser");
r_declare_state_free!(r_tls_state_free,TlsParser,{ () });

impl<'a> RParser for TlsParser<'a> {
    fn parse(&mut self, i: &[u8], direction: u8) -> u32 {
        debug!("[TLS->parse: direction={}, len={}]",direction,i.len());

        if i.len() == 0 {
            // Connection closed ?
            return R_STATUS_OK;
        };

        self.parse_tcp_level(i)
    }
}

fn tls_probe(i: &[u8]) -> bool {
    if i.len() <= 2 { return false; }
    // first byte is record type (between 0x14 and 0x17, 0x16 is handhake)
    // second is TLS version major (0x3)
    // third is TLS version minor (0x0 for SSLv3, 0x1 for TLSv1.0, etc.)
    match (i[0],i[1],i[2]) {
        (0x14...0x17,0x03,0...3) => true,
        _ => false,
    }
}

r_implement_probe!(r_tls_probe,tls_probe);
r_implement_parse!(r_tls_parse,TlsParser);

// --------------------------------------------

#[no_mangle]
pub extern fn r_tls_get_next_event(ptr: *mut libc::c_char) -> u32
// pub extern fn r_tls_get_next_event<'a>(this: &mut TlsParser<'a>) -> u32
{
    assert!(!ptr.is_null());
    let this: &mut TlsParser = unsafe { mem::transmute(ptr) };
    match this.events.pop() {
        None     => 0xffffffff,
        Some(ev) => ev,
    }
}

#[no_mangle]
// pub extern fn rusticata_tls_get_cipher(ptr: *mut libc::c_char) -> u32
// or
pub extern fn rusticata_tls_get_cipher<'a>(this: &TlsParser<'a>) -> u32
// but this gives a warning:
// warning: generic functions must be mangled, #[warn(no_mangle_generic_items)] on by default
{
    // let this: &Box<TlsParser> = unsafe { mem::transmute(ptr) };
    match this.cipher {
        None    => 0,
        Some(c) => c.id.into(),
    }
}

#[no_mangle]
pub extern fn rusticata_tls_get_compression<'a>(this: &TlsParser<'a>) -> u32
{
    this.compression.unwrap_or(0) as u32
}

#[no_mangle]
pub extern fn rusticata_tls_get_dh_key_bits<'a>(this: &TlsParser<'a>) -> u32
{
    this.kx_bits.unwrap_or(0) as u32
}

#[no_mangle]
pub extern fn rusticata_tls_cipher_of_string(value: *const c_char) -> u32
{
    let c_str = unsafe { CStr::from_ptr(value) };
    let s = c_str.to_str().unwrap();
    match TlsCipherSuite::from_name(s) {
        Some(c) => c.id as u32,
        None    => 0,
    }
}

#[no_mangle]
pub extern fn rusticata_tls_kx_of_cipher(id: u16) -> u32
{
    match TlsCipherSuite::from_id(id) {
        Some(c) => c.kx.clone() as u32,
        None    => 0,
    }
}

#[no_mangle]
pub extern fn rusticata_tls_au_of_cipher(id: u16) -> u32
{
    match TlsCipherSuite::from_id(id) {
        Some(c) => c.au.clone() as u32,
        None    => 0,
    }
}

#[no_mangle]
pub extern fn rusticata_tls_enc_of_cipher(id: u16) -> u32
{
    match TlsCipherSuite::from_id(id) {
        Some(c) => c.enc.clone() as u32,
        None    => 0,
    }
}

#[no_mangle]
pub extern fn rusticata_tls_encmode_of_cipher(id: u16) -> u32
{
    match TlsCipherSuite::from_id(id) {
        Some(c) => c.enc_mode.clone() as u32,
        None    => 0,
    }
}

#[no_mangle]
pub extern fn rusticata_tls_mac_of_cipher(id: u16) -> u32
{
    match TlsCipherSuite::from_id(id) {
        Some(c) => c.mac.clone() as u32,
        None    => 0,
    }
}

fn rusticata_tls_get_kx_bits(cipher: &TlsCipherSuite, parameters: &[u8], extended: bool) -> Option<u32> {
    match cipher.kx {
        TlsCipherKx::Ecdhe |
        TlsCipherKx::Ecdh    => {
            // Signed ECDH params
            match parse_content_and_signature(parameters,parse_ecdh_params,extended) {
                IResult::Done(_,ref parsed) => {
                    debug!("ECDHE Parameters: {:?}",parsed);
                    info!("Temp key: using cipher {:?}",parsed.0.curve_params);
                    match &parsed.0.curve_params.params_content {
                        &ECParametersContent::NamedCurve(curve_id) => {
                            match named_curve_of_u16(curve_id) {
                                None => (),
                                Some(named_curve) => {
                                    let key_bits = named_curve.key_bits().unwrap_or(0);
                                    debug!("NamedCurve: {:?}, key={:?} bits",named_curve,key_bits);
                                    return Some(key_bits as u32);
                                },
                            }
                        },
                        c @ _ => info!("Request for key_bits of unknown curve {:?}",c),
                    }
                },
                e @ _ => error!("Could not parse ECDHE parameters {:?}",e),
            };
            ()
        },
        TlsCipherKx::Dhe => {
            // Signed DH params
            match parse_content_and_signature(parameters,parse_dh_params,extended) {
                IResult::Done(_,ref parsed) => {
                    debug!("DHE Parameters: {:?}",parsed);
                    info!("Temp key: using DHE size_p={:?} bits",parsed.0.dh_p.len() * 8);
                    return Some((parsed.0.dh_p.len() * 8) as u32);
                },
                e @ _ => error!("Could not parse DHE parameters {:?}",e),
            };
            ()
        },
        TlsCipherKx::Dh => {
            // Anonymous DH params
            match parse_dh_params(parameters) {
                IResult::Done(_,ref parsed) => {
                    debug!("ADH Parameters: {:?}",parsed);
                    info!("Temp key: using ADH size_p={:?} bits",parsed.dh_p.len() * 8);
                    return Some((parsed.dh_p.len() * 8) as u32);
                },
                e @ _ => error!("Could not parse ADH parameters {:?}",e),
            };
            ()
        },
        ref kx @ _ => debug!("unhandled KX algorithm: {:?}",kx),
    };
    None
}
<commit_msg>Use function from enum_primitive to get TlsRecordType<commit_after>extern crate libc;

use std;
use std::mem;
use libc::c_char;
use std::ffi::CStr;

use nom::*;

use num_traits::FromPrimitive;

use rparser::*;

use tls_parser::tls::{TlsMessage,TlsMessageHandshake,TlsRecordType,TlsRawRecord,parse_tls_raw_record,parse_tls_record_with_header};
use tls_parser::tls_ciphers::*;
use tls_parser::tls_dh::*;
use tls_parser::tls_ec::*;
use tls_parser::tls_extensions::*;
use tls_parser::tls_sign_hash::*;
use tls_parser::tls_states::{TlsState,tls_state_transition};

// --------------------------------------------
// example implementation: TLS parser

#[repr(u32)]
pub enum TlsParserEvents {
    HeartbeatOverflow = 1,
    InvalidState = 2,

    RecordIncomplete = 3,
    RecordWithExtraBytes = 4,
    RecordOverflow = 5,
}

pub struct TlsParser<'a> {
    pub o: Option<&'a[u8]>,

    pub events: Vec<u32>,

    pub compression: Option<u8>,
    pub cipher: Option<&'a TlsCipherSuite>,
    pub state: TlsState,

    pub kx_bits: Option<u32>,

    /// TCP segments defragmentation buffer
    pub tcp_buffer: Vec<u8>,

    /// Handshake defragmentation buffer
    pub buffer: Vec<u8>,

    pub has_signature_algorithms: bool,
}

impl<'a> TlsParser<'a> {
    pub fn new(i: &'a[u8]) -> TlsParser<'a> {
        TlsParser{
            o:Some(i),
            events:Vec::new(),
            compression:None,
            cipher:None,
            state:TlsState::None,
            kx_bits: None,
            // capacity is the amount of space allocated, which means elements can be added
            // without reallocating the vector
            tcp_buffer:Vec::with_capacity(16384),
            buffer:Vec::with_capacity(16384),
            has_signature_algorithms:false,
        }
    }

    /// Message-level TLS parsing
    fn parse_message_level(&mut self, msg: &TlsMessage) -> u32 {
        debug!("parse_message_level {:?}",msg);
        let mut status = R_STATUS_OK;
        if self.state == TlsState::ClientChangeCipherSpec {
            // Ignore records from now on, they are encrypted
            return status;
        };
        // update state machine
        match tls_state_transition(self.state, msg) {
            Ok(s)  => self.state = s,
            Err(_) => {
                self.state = TlsState::Invalid;
                self.events.push(TlsParserEvents::InvalidState as u32);
                status |= R_STATUS_EVENTS;
            },
        };
        debug!("TLS new state: {:?}",self.state);
        // extract variables
        match *msg {
            TlsMessage::Handshake(ref m) => {
                match *m {
                    TlsMessageHandshake::ClientHello(ref content) => {
                        let ext = parse_tls_extensions(content.ext.unwrap_or(b""));
                        match &ext {
                            &IResult::Done(_,ref l) => {
                                for extension in l {
                                    match *extension {
                                        TlsExtension::SignatureAlgorithms(_) => self.has_signature_algorithms = true,
                                        _ => (),
                                    }
                                }
                            },
                            e @ _ => error!("Could not parse extentions: {:?}",e),
                        };
                        debug!("ext {:?}", ext);
                    },
                    TlsMessageHandshake::ServerHello(ref content) => {
                        self.compression = Some(content.compression);
                        self.cipher = TlsCipherSuite::from_id(content.cipher);
                        match self.cipher {
                            Some(c) => {
                                debug!("Selected cipher: {:?}", c)
                            },
                            _ => warn!("Unknown cipher 0x{:x}", content.cipher),
                        };
                        let ext = parse_tls_extensions(content.ext.unwrap_or(b""));
                        debug!("extensions: {:?}", ext);
                    },
                    TlsMessageHandshake::Certificate(ref content) => {
                        debug!("cert chain length: {}",content.cert_chain.len());
                        for cert in &content.cert_chain {
                            debug!("cert: {:?}",cert);
                        }
                    },
                    TlsMessageHandshake::ServerKeyExchange(ref content) => {
                        // The SKE contains the chosen algorithm for the ephemeral key
                        match self.cipher {
                            None => (),
                            Some (c) => { self.kx_bits = rusticata_tls_get_kx_bits(c,content.parameters,self.has_signature_algorithms) },
                        }
                    },
                    _ => (),
                }
            },
            TlsMessage::Heartbeat(ref d) => {
                if d.payload_len as usize > d.payload.len() {
                    warn!("Heartbeat message with incorrect length {}. Heartbleed attempt ?",d.payload.len());
                    self.events.push(TlsParserEvents::HeartbeatOverflow as u32);
                    status |= R_STATUS_EVENTS;
                }
            },
            _ => (),
        }

        status
    }

    fn parse_record_level<'b>(&mut self, r: &TlsRawRecord<'b>) -> u32 {
        let mut v : Vec<u8>;
        let mut status = R_STATUS_OK;

        debug!("parse_record_level {}",r.data.len());
        // debug!("{:?}",r.data);

        // only parse some message types
        match TlsRecordType::from_u8(r.hdr.record_type) {
            Some(TlsRecordType::ChangeCipherSpec) => (),
            Some(TlsRecordType::Handshake)        => (),
            _ => return status,
        }

        // Check if a record is being defragmented
        let record_buffer = match self.buffer.len() {
            0 => r.data,
            _ => {
                v = self.buffer.split_off(0);
                // sanity check vector length to avoid memory exhaustion
                // maximum length may be 2^24 (handshake message)
                if self.buffer.len() + r.data.len() > 16777216 {
                    self.events.push(TlsParserEvents::RecordOverflow as u32);
                    return R_STATUS_EVENTS;
                };
                v.extend_from_slice(r.data);
                v.as_slice()
            },
        };
        // do not parse if session is encrypted
        if self.state == TlsState::ClientChangeCipherSpec {
            return status;
        };
        // XXX record may be compressed
        //
        // Parse record contents as plaintext
        match parse_tls_record_with_header(record_buffer,r.hdr.clone()) {
            IResult::Done(rem2,ref msg_list) => {
                for msg in msg_list {
                    status |= self.parse_message_level(msg);
                };
                if rem2.len() > 0 {
                    warn!("extra bytes in TLS record: {:?}",rem2);
                    self.events.push(TlsParserEvents::RecordWithExtraBytes as u32);
                    status |= R_STATUS_EVENTS;
                };
            }
            IResult::Incomplete(_) => {
                debug!("Defragmentation required (TLS record)");
                // Record is fragmented
                self.buffer.extend_from_slice(r.data);
            },
            IResult::Error(e) => { warn!("parse_tls_record_with_header failed: {:?}",e); status |= R_STATUS_FAIL; },
        };

        status
    }

    pub fn parse_tcp_level<'b>(&mut self, i: &'b[u8]) -> u32 {
        let mut v : Vec<u8>;
        let mut status = R_STATUS_OK;
        debug!("parse_tcp_level ({})",i.len());
        // debug!("{:?}",i);
        // Check if TCP data is being defragmented
        let tcp_buffer = match self.tcp_buffer.len() {
            0 => i,
            _ => {
                v = self.tcp_buffer.split_off(0);
                // sanity check vector length to avoid memory exhaustion
                // maximum length may be 2^24 (handshake message)
                if self.tcp_buffer.len() + i.len() > 16777216 {
                    self.events.push(TlsParserEvents::RecordOverflow as u32);
                    return R_STATUS_EVENTS;
                };
                v.extend_from_slice(i);
                v.as_slice()
            },
        };
        // debug!("tcp_buffer ({})",tcp_buffer.len());
        let mut cur_i = tcp_buffer;
        while cur_i.len() > 0 {
            match parse_tls_raw_record(cur_i) {
                IResult::Done(rem, ref r) => {
                    // debug!("rem: {:?}",rem);
                    cur_i = rem;
                    status |= self.parse_record_level(r);
                },
                IResult::Incomplete(_) => {
                    debug!("Fragmentation required (TCP level)");
                    self.tcp_buffer.extend_from_slice(cur_i);
                    break;
                },
                IResult::Error(e) => { warn!("Parsing failed: {:?}",e); break },
            }
        };
        status
    }
}

r_declare_state_new!(r_tls_state_new,TlsParser,b"TLS parser");
r_declare_state_free!(r_tls_state_free,TlsParser,{ () });

impl<'a> RParser for TlsParser<'a> {
    fn parse(&mut self, i: &[u8], direction: u8) -> u32 {
        debug!("[TLS->parse: direction={}, len={}]",direction,i.len());

        if i.len() == 0 {
            // Connection closed ?
            return R_STATUS_OK;
        };

        self.parse_tcp_level(i)
    }
}

fn tls_probe(i: &[u8]) -> bool {
    if i.len() <= 2 { return false; }
    // first byte is record type (between 0x14 and 0x17, 0x16 is handhake)
    // second is TLS version major (0x3)
    // third is TLS version minor (0x0 for SSLv3, 0x1 for TLSv1.0, etc.)
    match (i[0],i[1],i[2]) {
        (0x14...0x17,0x03,0...3) => true,
        _ => false,
    }
}

r_implement_probe!(r_tls_probe,tls_probe);
r_implement_parse!(r_tls_parse,TlsParser);

// --------------------------------------------

#[no_mangle]
pub extern fn r_tls_get_next_event(ptr: *mut libc::c_char) -> u32
// pub extern fn r_tls_get_next_event<'a>(this: &mut TlsParser<'a>) -> u32
{
    assert!(!ptr.is_null());
    let this: &mut TlsParser = unsafe { mem::transmute(ptr) };
    match this.events.pop() {
        None     => 0xffffffff,
        Some(ev) => ev,
    }
}

#[no_mangle]
// pub extern fn rusticata_tls_get_cipher(ptr: *mut libc::c_char) -> u32
// or
pub extern fn rusticata_tls_get_cipher<'a>(this: &TlsParser<'a>) -> u32
// but this gives a warning:
// warning: generic functions must be mangled, #[warn(no_mangle_generic_items)] on by default
{
    // let this: &Box<TlsParser> = unsafe { mem::transmute(ptr) };
    match this.cipher {
        None    => 0,
        Some(c) => c.id.into(),
    }
}

#[no_mangle]
pub extern fn rusticata_tls_get_compression<'a>(this: &TlsParser<'a>) -> u32
{
    this.compression.unwrap_or(0) as u32
}

#[no_mangle]
pub extern fn rusticata_tls_get_dh_key_bits<'a>(this: &TlsParser<'a>) -> u32
{
    this.kx_bits.unwrap_or(0) as u32
}

#[no_mangle]
pub extern fn rusticata_tls_cipher_of_string(value: *const c_char) -> u32
{
    let c_str = unsafe { CStr::from_ptr(value) };
    let s = c_str.to_str().unwrap();
    match TlsCipherSuite::from_name(s) {
        Some(c) => c.id as u32,
        None    => 0,
    }
}

#[no_mangle]
pub extern fn rusticata_tls_kx_of_cipher(id: u16) -> u32
{
    match TlsCipherSuite::from_id(id) {
        Some(c) => c.kx.clone() as u32,
        None    => 0,
    }
}

#[no_mangle]
pub extern fn rusticata_tls_au_of_cipher(id: u16) -> u32
{
    match TlsCipherSuite::from_id(id) {
        Some(c) => c.au.clone() as u32,
        None    => 0,
    }
}

#[no_mangle]
pub extern fn rusticata_tls_enc_of_cipher(id: u16) -> u32
{
    match TlsCipherSuite::from_id(id) {
        Some(c) => c.enc.clone() as u32,
        None    => 0,
    }
}

#[no_mangle]
pub extern fn rusticata_tls_encmode_of_cipher(id: u16) -> u32
{
    match TlsCipherSuite::from_id(id) {
        Some(c) => c.enc_mode.clone() as u32,
        None    => 0,
    }
}

#[no_mangle]
pub extern fn rusticata_tls_mac_of_cipher(id: u16) -> u32
{
    match TlsCipherSuite::from_id(id) {
        Some(c) => c.mac.clone() as u32,
        None    => 0,
    }
}

fn rusticata_tls_get_kx_bits(cipher: &TlsCipherSuite, parameters: &[u8], extended: bool) -> Option<u32> {
    match cipher.kx {
        TlsCipherKx::Ecdhe |
        TlsCipherKx::Ecdh    => {
            // Signed ECDH params
            match parse_content_and_signature(parameters,parse_ecdh_params,extended) {
                IResult::Done(_,ref parsed) => {
                    debug!("ECDHE Parameters: {:?}",parsed);
                    info!("Temp key: using cipher {:?}",parsed.0.curve_params);
                    match &parsed.0.curve_params.params_content {
                        &ECParametersContent::NamedCurve(curve_id) => {
                            match named_curve_of_u16(curve_id) {
                                None => (),
                                Some(named_curve) => {
                                    let key_bits = named_curve.key_bits().unwrap_or(0);
                                    debug!("NamedCurve: {:?}, key={:?} bits",named_curve,key_bits);
                                    return Some(key_bits as u32);
                                },
                            }
                        },
                        c @ _ => info!("Request for key_bits of unknown curve {:?}",c),
                    }
                },
                e @ _ => error!("Could not parse ECDHE parameters {:?}",e),
            };
            ()
        },
        TlsCipherKx::Dhe => {
            // Signed DH params
            match parse_content_and_signature(parameters,parse_dh_params,extended) {
                IResult::Done(_,ref parsed) => {
                    debug!("DHE Parameters: {:?}",parsed);
                    info!("Temp key: using DHE size_p={:?} bits",parsed.0.dh_p.len() * 8);
                    return Some((parsed.0.dh_p.len() * 8) as u32);
                },
                e @ _ => error!("Could not parse DHE parameters {:?}",e),
            };
            ()
        },
        TlsCipherKx::Dh => {
            // Anonymous DH params
            match parse_dh_params(parameters) {
                IResult::Done(_,ref parsed) => {
                    debug!("ADH Parameters: {:?}",parsed);
                    info!("Temp key: using ADH size_p={:?} bits",parsed.dh_p.len() * 8);
                    return Some((parsed.dh_p.len() * 8) as u32);
                },
                e @ _ => error!("Could not parse ADH parameters {:?}",e),
            };
            ()
        },
        ref kx @ _ => debug!("unhandled KX algorithm: {:?}",kx),
    };
    None
}
<|endoftext|>


<commit_before>extern crate winapi;
extern crate kernel32;

use self::super::Size;

/// Gets the current terminal size
pub fn get() -> Option<Size> {
    //http://rosettacode.org/wiki/Terminal_control/Dimensions#Windows
    use self::winapi::HANDLE;
    use self::kernel32::{GetStdHandle, GetConsoleScreenBufferInfo, GetLastError};
    use self::winapi::{
        CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT,
        STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE
    };
    let stdout: HANDLE = unsafe {
        GetStdHandle(STD_OUTPUT_HANDLE)
    };
    println!("stdout {:?}", stdout);
    if stdout == INVALID_HANDLE_VALUE {
        println!("handle was invalid");
        return None
    }
    let zc = COORD { X: 0, Y: 0 };
    // screen buffer info is a container of console display information
    // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx
    let mut info = CONSOLE_SCREEN_BUFFER_INFO {
        dwSize: zc.clone(),
        dwCursorPosition: zc.clone(),
        wAttributes: 0,
        srWindow: SMALL_RECT { Left:0, Top: 0, Right: 0, Bottom: 0 },
        dwMaximumWindowSize: zc
    };
    let success: bool = unsafe {
        // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
        let result = GetConsoleScreenBufferInfo(stdout, &mut info);
        println!("result was {}", result);
        if result == 0 {
            println!("last error was {:?}", GetLastError());
        }
        result != 0
    };
    println!("info {:?}", info);
    if success {
        Some(
            Size {
                rows: (info.srWindow.Bottom - info.srWindow.Top + 1) as u16,
                cols: (info.srWindow.Right - info.srWindow.Left + 1) as u16
            }
        )
    } else {
        None
    }
}
<commit_msg>testing windows<commit_after>extern crate winapi;
extern crate kernel32;

use self::super::Size;

/// Gets the current terminal size
pub fn get() -> Option<Size> {
    //http://rosettacode.org/wiki/Terminal_control/Dimensions#Windows
    use self::winapi::HANDLE;
    use self::kernel32::{self, GetStdHandle, GetConsoleScreenBufferInfo, GetLastError};
    use self::winapi::{
        self,
        CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT,
        STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE
    };
    let name = b"CONOUT$\0";
    let handle: HANDLE = unsafe {
        kernel32::CreateFileA(
            name.as_ptr() as *const i8,
            winapi::GENERIC_READ | winapi::GENERIC_WRITE,
            winapi::FILE_SHARE_WRITE,
            ptr::null_mut(),
            winapi::OPEN_EXISTING,
            0,
            ptr::null_mut(),
        )
    };
    println!("handle {:?}", handle);
    if handle == INVALID_HANDLE_VALUE {
        println!("handle was invalid");
        return None
    }
    let zc = COORD { X: 0, Y: 0 };
    // screen buffer info is a container of console display information
    // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx
    let mut info = ::std::mem::uninitialized();/*CONSOLE_SCREEN_BUFFER_INFO {
        dwSize: zc.clone(),
        dwCursorPosition: zc.clone(),
        wAttributes: 0,
        srWindow: SMALL_RECT { Left:0, Top: 0, Right: 0, Bottom: 0 },
        dwMaximumWindowSize: zc
    };*/
    let success: bool = unsafe {
        // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
        let result = GetConsoleScreenBufferInfo(handle, &mut info);
        println!("result was {}", result);
        if result == 0 {
            println!("last error was {:?}", GetLastError());
        }
        result != 0
    };
    println!("info {:?}", info);
    if success {
        Some(
            Size {
                rows: (info.srWindow.Bottom - info.srWindow.Top + 1) as u16,
                cols: (info.srWindow.Right - info.srWindow.Left + 1) as u16
            }
        )
    } else {
        None
    }
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::Result;

/// Header used by TGA image files
#[derive(Debug)]
struct Header {
    id_length: u8, // length of ID string
    map_type: u8, // color map type
    image_type: u8, // image type code
    map_origin: u16, // starting index of map
    map_length: u16, // length of map
    map_entry_size: u8, // size of map entries in bits
    x_origin: u16, // x-origin of image
    y_origin: u16, // y-origin of image
    image_width: u16, // width of image
    image_height: u16, // height of image
    pixel_depth: u8, // bits per pixel
    image_desc: u8, // image descriptor
}

#[derive(Clone,Copy)]
pub struct TgaColor {
    pub rgba: [u8; 4],
}

impl TgaColor {
    fn write<W: WriteBytesExt>(self: &Self, w: &mut W) -> Result<()> {
        try!(w.write_u8(self.rgba[2]));
        try!(w.write_u8(self.rgba[1]));
        try!(w.write_u8(self.rgba[0]));
        try!(w.write_u8(self.rgba[3]));
        Ok(())
    }
}

const RAW_TRUE_COLOR: u8 = 2;
const ARGB_DEPTH: u8 = 32;

impl Header {
    fn new(w: u16, h: u16) -> Header {
        Header {
            id_length: 0,
            map_type: 0,
            image_type: RAW_TRUE_COLOR,
            map_origin: 0,
            map_length: 0,
            map_entry_size: 0,
            x_origin: 0,
            y_origin: 0,
            image_width: w,
            image_height: h,
            pixel_depth: ARGB_DEPTH,
            image_desc: 0,
        }
    }

    fn write<W: WriteBytesExt>(self: &Self, w: &mut W) -> Result<()> {
        try!(w.write_u8(self.id_length));
        try!(w.write_u8(self.map_type));
        try!(w.write_u8(self.image_type));
        try!(w.write_u16::<LittleEndian>(self.map_origin));
        try!(w.write_u16::<LittleEndian>(self.map_length));
        try!(w.write_u8(self.map_entry_size));
        try!(w.write_u16::<LittleEndian>(self.x_origin));
        try!(w.write_u16::<LittleEndian>(self.y_origin));
        try!(w.write_u16::<LittleEndian>(self.image_width));
        try!(w.write_u16::<LittleEndian>(self.image_height));
        try!(w.write_u8(self.pixel_depth));
        try!(w.write_u8(self.image_desc));
        Ok(())
    }
}

pub struct TgaImage {
    width: usize,
    height: usize,
    data: Vec<TgaColor>,
}

impl TgaImage {
    pub fn new(w: usize, h: usize) -> TgaImage {
        let c = TgaColor { rgba: [0, 0, 0, 255] };
        TgaImage {
            width: w,
            height: h,
            data: vec![c; w * h],
        }
    }
    pub fn write<W: WriteBytesExt>(self: &Self, w: &mut W) -> Result<()> {
        try!(Header::new(self.width as u16, self.height as u16).write(w));
        for c in &self.data {
            try!(c.write(w));
        }
        Ok(())
    }
    pub fn set(self: &mut Self, i: usize, j: usize, t: TgaColor) -> () {
        self.data[j * self.height + i] = t
    }
    fn get(self: &Self, i: usize, j: usize) -> TgaColor {
        self.data[j * self.height + i]
    }
}
<commit_msg>comments<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::Result;

/// Header used by TGA image files
#[derive(Debug)]
struct Header {
    id_length: u8, // length of ID string
    map_type: u8, // color map type
    image_type: u8, // image type code
    map_origin: u16, // starting index of map
    map_length: u16, // length of map
    map_entry_size: u8, // size of map entries in bits
    x_origin: u16, // x-origin of image
    y_origin: u16, // y-origin of image
    image_width: u16, // width of image
    image_height: u16, // height of image
    pixel_depth: u8, // bits per pixel
    image_desc: u8, // image descriptor
}

#[derive(Clone,Copy)]
pub struct TgaColor {
    pub rgba: [u8; 4],
}

impl TgaColor {
    fn write<W: WriteBytesExt>(self: &Self, w: &mut W) -> Result<()> {
        try!(w.write_u8(self.rgba[2])); // r
        try!(w.write_u8(self.rgba[1])); // g
        try!(w.write_u8(self.rgba[0])); // b
        try!(w.write_u8(self.rgba[3])); // a
        Ok(())
    }
}

const RAW_TRUE_COLOR: u8 = 2;
const ARGB_DEPTH: u8 = 32;

impl Header {
    fn new(w: u16, h: u16) -> Header {
        Header {
            id_length: 0,
            map_type: 0,
            image_type: RAW_TRUE_COLOR,
            map_origin: 0,
            map_length: 0,
            map_entry_size: 0,
            x_origin: 0,
            y_origin: 0,
            image_width: w,
            image_height: h,
            pixel_depth: ARGB_DEPTH,
            image_desc: 0,
        }
    }
    fn write<W: WriteBytesExt>(self: &Self, w: &mut W) -> Result<()> {
        try!(w.write_u8(self.id_length));
        try!(w.write_u8(self.map_type));
        try!(w.write_u8(self.image_type));
        try!(w.write_u16::<LittleEndian>(self.map_origin));
        try!(w.write_u16::<LittleEndian>(self.map_length));
        try!(w.write_u8(self.map_entry_size));
        try!(w.write_u16::<LittleEndian>(self.x_origin));
        try!(w.write_u16::<LittleEndian>(self.y_origin));
        try!(w.write_u16::<LittleEndian>(self.image_width));
        try!(w.write_u16::<LittleEndian>(self.image_height));
        try!(w.write_u8(self.pixel_depth));
        try!(w.write_u8(self.image_desc));
        Ok(())
    }
}

pub struct TgaImage {
    width: usize,
    height: usize,
    data: Vec<TgaColor>,
}

impl TgaImage {
    pub fn new(w: usize, h: usize) -> TgaImage {
        let c = TgaColor { rgba: [0, 0, 0, 255] };
        TgaImage {
            width: w,
            height: h,
            data: vec![c; w * h],
        }
    }
    pub fn write<W: WriteBytesExt>(self: &Self, w: &mut W) -> Result<()> {
        try!(Header::new(self.width as u16, self.height as u16).write(w));
        for c in &self.data {
            try!(c.write(w));
        }
        Ok(())
    }
    pub fn set(self: &mut Self, i: usize, j: usize, t: TgaColor) -> () {
        self.data[j * self.height + i] = t
    }
    fn get(self: &Self, i: usize, j: usize) -> TgaColor {
        self.data[j * self.height + i]
    }
}
<|endoftext|>