<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use ffi;
use types::{gchar,gsize};
use types::{gpointer};

use alloc::libc_heap::malloc_raw;
use libc;
use libc::c_char;
use std::c_str::{CString,ToCStr};
use std::mem::transmute;
use std::ptr::copy_nonoverlapping_memory;
use std::slice;
use std::str;
use std::string;

pub struct UTF8Buf {
    data: *mut gchar,
}

impl UTF8Buf {

    pub unsafe fn wrap(data: *mut gchar) -> UTF8Buf {
        UTF8Buf { data: data }
    }

    pub fn into_collection(self) -> UTF8Str {
        unsafe {
            let len = libc::strlen(self.data as *const c_char);
            UTF8Str { buf: transmute(self), len: len as uint }
        }
    }

    pub fn to_string(&self) -> String {
        unsafe {
            string::raw::from_buf(self.data as *const gchar as *const u8)
        }
    }

    #[inline]
    pub fn to_owned(&self) -> String { self.to_string() }

    #[inline]
    pub fn into_string(self) -> String { self.to_string() }

    #[inline]
    pub fn into_owned(self) -> String { self.to_string() }

    #[inline]
    pub fn is_empty(&self) -> bool { unsafe { *self.data == 0 } }
}

impl Drop for UTF8Buf {
    fn drop(&mut self) {
        unsafe { ffi::g_free(self.data as gpointer) }
    }
}

impl Clone for UTF8Buf {
    fn clone(&self) -> UTF8Buf {
        unsafe {
            UTF8Buf::wrap(ffi::g_strdup(self.data as *const gchar))
        }
    }
}

unsafe fn dup_to_c_str(source: *const c_char, len: uint) -> CString {
    let copy = malloc_raw(len + 1) as *mut c_char;
    copy_nonoverlapping_memory(copy, source, len + 1);
    CString::new(copy as *const c_char, true)
}

impl ToCStr for UTF8Buf {

    fn to_c_str(&self) -> CString {
        unsafe { self.to_c_str_unchecked() }
    }

    unsafe fn to_c_str_unchecked(&self) -> CString {
        let src = self.data as *const c_char;
        let len = libc::strlen(src) as uint;
        dup_to_c_str(src, len)
    }

    fn with_c_str<T>(&self, f: |*const i8| -> T) -> T {
        f(self.data as *const i8)
    }

    unsafe fn with_c_str_unchecked<T>(&self, f: |*const i8| -> T) -> T {
        f(self.data as *const i8)
    }
}

pub struct UTF8Str {
    buf: UTF8Buf,
    len: uint
}

static NUL: gchar = 0;

impl UTF8Str {

    pub unsafe fn wrap(data: *mut gchar, len: uint) -> UTF8Str {
        UTF8Str { buf: UTF8Buf::wrap(data), len: len }
    }

    unsafe fn dup_raw(buf: *const gchar, len: uint) -> UTF8Str {
        let copy = ffi::g_malloc((len + 1) as gsize) as *mut gchar;
        copy_nonoverlapping_memory(copy, buf, len);
        *copy.offset(len as int) = NUL;
        UTF8Str::wrap(copy, len)
    }

    pub unsafe fn dup(cstr: *const gchar) -> UTF8Str {
        UTF8Str::dup_raw(cstr, libc::strlen(cstr) as uint)
    }

    pub unsafe fn ndup(cstr: *const gchar, len: uint) -> UTF8Str {
        let len = slice::raw::buf_as_slice(cstr, len, |s| {
            match s.position_elem(&NUL) {
                Some(pos) => pos,
                None      => len
            }
        });
        UTF8Str::dup_raw(cstr, len)
    }

    pub fn to_string(&self) -> String {
        unsafe {
            string::raw::from_buf_len(self.buf.data as *const u8, self.len)
        }
    }
}

impl Clone for UTF8Str {
    fn clone(&self) -> UTF8Str {
        unsafe {
            UTF8Str::dup_raw(self.buf.data as *const gchar, self.len)
        }
    }
}

impl Str for UTF8Str {
    fn as_slice<'a>(&'a self) -> &'a str {
        unsafe {
            slice::raw::buf_as_slice(
                self.buf.data as *const u8,
                self.len,
                |bytes| {
                    let s = str::raw::from_utf8(bytes);
                    transmute(s)
                })
        }
    }
}

impl StrAllocating for UTF8Str {
    fn into_string(self) -> String { self.to_string() }
}

impl Collection for UTF8Str {

    // Common sense says we should return the UTF-8 length,
    // but &str returns length in bytes, so...
    fn len(&self) -> uint { return self.len }

    fn is_empty(&self) -> bool { return self.len == 0 }
}

impl ToCStr for UTF8Str {

    fn to_c_str(&self) -> CString { self.buf.to_c_str() }

    unsafe fn to_c_str_unchecked(&self) -> CString {
        dup_to_c_str(self.buf.data as *const c_char, self.len)
    }

    fn with_c_str<T>(&self, f: |*const i8| -> T) -> T {
        self.buf.with_c_str(f)
    }

    unsafe fn with_c_str_unchecked<T>(&self, f: |*const i8| -> T) -> T {
        self.buf.with_c_str_unchecked(f)
    }
}

impl PartialEq for UTF8Str {
    fn eq(&self, other: &UTF8Str) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for UTF8Str { }

impl<S: Str> Equiv<S> for UTF8Str {
    fn equiv(&self, other: &S) -> bool {
        self.as_slice() == other.as_slice()
    }
}

pub trait WithUTF8 {
    fn with_utf8_c_str<T>(&self, f: |*const gchar| -> T) -> T;
}

impl WithUTF8 for UTF8Buf {

    fn with_utf8_c_str<T>(&self, f: |*const gchar| -> T) -> T {
        f(self.data as *const gchar)
    }
}

impl WithUTF8 for UTF8Str {

    fn with_utf8_c_str<T>(&self, f: |*const gchar| -> T) -> T {
        self.buf.with_utf8_c_str(f)
    }
}

impl<'a> WithUTF8 for &'a str {

    fn with_utf8_c_str<T>(&self, f: |*const gchar| -> T) -> T {
        self.with_c_str(f)
    }
}

impl WithUTF8 for String {

    fn with_utf8_c_str<T>(&self, f: |*const gchar| -> T) -> T {
        self.with_c_str(f)
    }
}
<commit_msg>Erased methods dup and ndup from UTF8Str<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use ffi;
use types::{gchar,gsize};
use types::{gpointer};

use alloc::libc_heap::malloc_raw;
use libc;
use libc::c_char;
use std::c_str::{CString,ToCStr};
use std::mem::transmute;
use std::ptr::copy_nonoverlapping_memory;
use std::slice;
use std::str;
use std::string;

pub struct UTF8Buf {
    data: *mut gchar,
}

impl UTF8Buf {

    pub unsafe fn wrap(data: *mut gchar) -> UTF8Buf {
        UTF8Buf { data: data }
    }

    pub fn into_collection(self) -> UTF8Str {
        unsafe {
            let len = libc::strlen(self.data as *const c_char);
            UTF8Str { buf: transmute(self), len: len as uint }
        }
    }

    pub fn to_string(&self) -> String {
        unsafe {
            string::raw::from_buf(self.data as *const gchar as *const u8)
        }
    }

    #[inline]
    pub fn to_owned(&self) -> String { self.to_string() }

    #[inline]
    pub fn into_string(self) -> String { self.to_string() }

    #[inline]
    pub fn into_owned(self) -> String { self.to_string() }

    #[inline]
    pub fn is_empty(&self) -> bool { unsafe { *self.data == 0 } }
}

impl Drop for UTF8Buf {
    fn drop(&mut self) {
        unsafe { ffi::g_free(self.data as gpointer) }
    }
}

impl Clone for UTF8Buf {
    fn clone(&self) -> UTF8Buf {
        unsafe {
            UTF8Buf::wrap(ffi::g_strdup(self.data as *const gchar))
        }
    }
}

unsafe fn dup_to_c_str(source: *const c_char, len: uint) -> CString {
    let copy = malloc_raw(len + 1) as *mut c_char;
    copy_nonoverlapping_memory(copy, source, len + 1);
    CString::new(copy as *const c_char, true)
}

impl ToCStr for UTF8Buf {

    fn to_c_str(&self) -> CString {
        unsafe { self.to_c_str_unchecked() }
    }

    unsafe fn to_c_str_unchecked(&self) -> CString {
        let src = self.data as *const c_char;
        let len = libc::strlen(src) as uint;
        dup_to_c_str(src, len)
    }

    fn with_c_str<T>(&self, f: |*const i8| -> T) -> T {
        f(self.data as *const i8)
    }

    unsafe fn with_c_str_unchecked<T>(&self, f: |*const i8| -> T) -> T {
        f(self.data as *const i8)
    }
}

pub struct UTF8Str {
    buf: UTF8Buf,
    len: uint
}

static NUL: gchar = 0;

impl UTF8Str {

    pub unsafe fn wrap(data: *mut gchar, len: uint) -> UTF8Str {
        UTF8Str { buf: UTF8Buf::wrap(data), len: len }
    }

    pub fn to_string(&self) -> String {
        unsafe {
            string::raw::from_buf_len(self.buf.data as *const u8, self.len)
        }
    }
}

impl Clone for UTF8Str {
    fn clone(&self) -> UTF8Str {
        unsafe {
            let copy = ffi::g_malloc((self.len + 1) as gsize) as *mut gchar;
            copy_nonoverlapping_memory(copy,
                    self.buf.data as *const gchar, self.len);
            *copy.offset(self.len as int) = NUL;
            UTF8Str::wrap(copy, self.len)
        }
    }
}

impl Str for UTF8Str {
    fn as_slice<'a>(&'a self) -> &'a str {
        unsafe {
            slice::raw::buf_as_slice(
                self.buf.data as *const u8,
                self.len,
                |bytes| {
                    let s = str::raw::from_utf8(bytes);
                    transmute(s)
                })
        }
    }
}

impl StrAllocating for UTF8Str {
    fn into_string(self) -> String { self.to_string() }
}

impl Collection for UTF8Str {

    // Common sense says we should return the UTF-8 length,
    // but &str returns length in bytes, so...
    fn len(&self) -> uint { return self.len }

    fn is_empty(&self) -> bool { return self.len == 0 }
}

impl ToCStr for UTF8Str {

    fn to_c_str(&self) -> CString { self.buf.to_c_str() }

    unsafe fn to_c_str_unchecked(&self) -> CString {
        dup_to_c_str(self.buf.data as *const c_char, self.len)
    }

    fn with_c_str<T>(&self, f: |*const i8| -> T) -> T {
        self.buf.with_c_str(f)
    }

    unsafe fn with_c_str_unchecked<T>(&self, f: |*const i8| -> T) -> T {
        self.buf.with_c_str_unchecked(f)
    }
}

impl PartialEq for UTF8Str {
    fn eq(&self, other: &UTF8Str) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for UTF8Str { }

impl<S: Str> Equiv<S> for UTF8Str {
    fn equiv(&self, other: &S) -> bool {
        self.as_slice() == other.as_slice()
    }
}

pub trait WithUTF8 {
    fn with_utf8_c_str<T>(&self, f: |*const gchar| -> T) -> T;
}

impl WithUTF8 for UTF8Buf {

    fn with_utf8_c_str<T>(&self, f: |*const gchar| -> T) -> T {
        f(self.data as *const gchar)
    }
}

impl WithUTF8 for UTF8Str {

    fn with_utf8_c_str<T>(&self, f: |*const gchar| -> T) -> T {
        self.buf.with_utf8_c_str(f)
    }
}

impl<'a> WithUTF8 for &'a str {

    fn with_utf8_c_str<T>(&self, f: |*const gchar| -> T) -> T {
        self.with_c_str(f)
    }
}

impl WithUTF8 for String {

    fn with_utf8_c_str<T>(&self, f: |*const gchar| -> T) -> T {
        self.with_c_str(f)
    }
}
<|endoftext|>


<commit_before>//Copyright 2016 secret-service-rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

// Contains helpers for:
//   exec_prompt
//   interfaces
//   formatting secrets
//
//   Consider: What else should be in here? Should
//   formatting secrets be in crypto? Should interfaces
//   have their own module?

use error::SsError;
use proxy::prompt::PromptProxy;
use proxy::service::ServiceProxy;
use session::Session;
use ss::SS_DBUS_NAME;
use ss_crypto::encrypt;
use proxy::SecretStruct;
use proxy::item::SecretStructInput;

use rand::{Rng, rngs::OsRng};
use std::sync::mpsc::channel;
use zvariant::ObjectPath;

// Helper enum for locking
pub(crate) enum LockAction {
    Lock,
    Unlock,
}

pub(crate) fn lock_or_unlock(
    conn: zbus::Connection,
    service_interface: &ServiceProxy,
    object_path: &ObjectPath,
    lock_action: LockAction
    ) -> ::Result<()>
{
    let objects = vec![object_path];

    let lock_action_res = match lock_action {
        LockAction::Lock => service_interface.lock(objects)?,
        LockAction::Unlock => service_interface.unlock(objects)?,
    };

    if lock_action_res.object_paths.is_empty() {
        exec_prompt(conn.clone(), &lock_action_res.prompt)?;
    }
    Ok(())
}

pub(crate) fn format_secret(
    session: &Session,
    secret: &[u8],
    content_type: &str
    ) -> ::Result<SecretStructInput>
{
    let content_type = content_type.to_owned();

    if session.is_encrypted() {
        let mut rng = OsRng {};
        let mut aes_iv = [0;16];
        rng.fill(&mut aes_iv);

        let encrypted_secret = encrypt(secret, &session.get_aes_key()[..], &aes_iv)?;

        // Construct secret struct
        let parameters = aes_iv.to_vec();
        let value = encrypted_secret;

        Ok(SecretStructInput {
            inner: SecretStruct {
                session: session.object_path.clone(),
                parameters,
                value,
                content_type,
            }
        })
    } else {
        // just Plain for now
        let parameters = Vec::new();
        let value = secret.to_vec();

        Ok(SecretStructInput {
            inner: SecretStruct {
                session: session.object_path.clone(),
                parameters,
                value,
                content_type,
            }
        })
    }
}

pub fn exec_prompt(conn: zbus::Connection, prompt: &ObjectPath) -> ::Result<zvariant::OwnedValue> {
    let prompt_interface = PromptProxy::new_for(
        &conn,
        SS_DBUS_NAME,
        prompt,
        )?;

    let (tx, rx) = channel();

    // create a handler for `completed` signal
    prompt_interface
        .connect_completed(move |dismissed, result| {
            let res = if dismissed {
                Err(SsError::Prompt)
            } else {
                Ok(result.into())
            };

            // FIXME remove unwrap
            tx.send(res).expect("remove this unwrap");

            Ok(())
        })?;

    // FIXME figure out window_id
    let window_id = "";
    prompt_interface.prompt(window_id)?;

    // waits for next signal and calls the handler.
    // If message handled by above handler, `next_signal` returns `Ok(None)`, ending loop.
    while prompt_interface.next_signal()?.is_some() {};

    // FIXME remove unwrap
    rx.recv().expect("remove this unwrap")
}
<commit_msg>make exec_prompt pub(crate)<commit_after>//Copyright 2016 secret-service-rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

// Contains helpers for:
//   exec_prompt
//   interfaces
//   formatting secrets
//
//   Consider: What else should be in here? Should
//   formatting secrets be in crypto? Should interfaces
//   have their own module?

use error::SsError;
use proxy::prompt::PromptProxy;
use proxy::service::ServiceProxy;
use session::Session;
use ss::SS_DBUS_NAME;
use ss_crypto::encrypt;
use proxy::SecretStruct;
use proxy::item::SecretStructInput;

use rand::{Rng, rngs::OsRng};
use std::sync::mpsc::channel;
use zvariant::ObjectPath;

// Helper enum for locking
pub(crate) enum LockAction {
    Lock,
    Unlock,
}

pub(crate) fn lock_or_unlock(
    conn: zbus::Connection,
    service_interface: &ServiceProxy,
    object_path: &ObjectPath,
    lock_action: LockAction
    ) -> ::Result<()>
{
    let objects = vec![object_path];

    let lock_action_res = match lock_action {
        LockAction::Lock => service_interface.lock(objects)?,
        LockAction::Unlock => service_interface.unlock(objects)?,
    };

    if lock_action_res.object_paths.is_empty() {
        exec_prompt(conn.clone(), &lock_action_res.prompt)?;
    }
    Ok(())
}

pub(crate) fn format_secret(
    session: &Session,
    secret: &[u8],
    content_type: &str
    ) -> ::Result<SecretStructInput>
{
    let content_type = content_type.to_owned();

    if session.is_encrypted() {
        let mut rng = OsRng {};
        let mut aes_iv = [0;16];
        rng.fill(&mut aes_iv);

        let encrypted_secret = encrypt(secret, &session.get_aes_key()[..], &aes_iv)?;

        // Construct secret struct
        let parameters = aes_iv.to_vec();
        let value = encrypted_secret;

        Ok(SecretStructInput {
            inner: SecretStruct {
                session: session.object_path.clone(),
                parameters,
                value,
                content_type,
            }
        })
    } else {
        // just Plain for now
        let parameters = Vec::new();
        let value = secret.to_vec();

        Ok(SecretStructInput {
            inner: SecretStruct {
                session: session.object_path.clone(),
                parameters,
                value,
                content_type,
            }
        })
    }
}

pub(crate) fn exec_prompt(conn: zbus::Connection, prompt: &ObjectPath) -> ::Result<zvariant::OwnedValue> {
    let prompt_interface = PromptProxy::new_for(
        &conn,
        SS_DBUS_NAME,
        prompt,
        )?;

    let (tx, rx) = channel();

    // create a handler for `completed` signal
    prompt_interface
        .connect_completed(move |dismissed, result| {
            let res = if dismissed {
                Err(SsError::Prompt)
            } else {
                Ok(result.into())
            };

            // FIXME remove unwrap
            tx.send(res).expect("remove this unwrap");

            Ok(())
        })?;

    // FIXME figure out window_id
    let window_id = "";
    prompt_interface.prompt(window_id)?;

    // waits for next signal and calls the handler.
    // If message handled by above handler, `next_signal` returns `Ok(None)`, ending loop.
    while prompt_interface.next_signal()?.is_some() {};

    // FIXME remove unwrap
    rx.recv().expect("remove this unwrap")
}
<|endoftext|>


<commit_before>use extra::treemap::TreeMap;
use std::vec;
use std::num::abs;

use common::*;
use monomial::*;

#[deriving(Eq, Clone)]
pub struct PolyOwning<Mon> {
  coefs: ~[R],
  mons:  ~[Mon]
}

#[deriving(Eq, Clone)]
pub struct PolyBorrowing<'self,Mon> {
  coefs: &'self [R],
  mons: &'self [Mon]
}

#[deriving(Eq, Clone)]
pub struct PolyBorrowingMons<'self,Mon> {
  coefs: ~[R],
  mons: &'self [Mon]
}

impl<Mon:Monomial> PolyOwning<Mon> {

  pub fn new(coefs: ~[R], mons: ~[Mon]) -> PolyOwning<Mon> {
    match (coefs.len(), mons.len()) {
      (0,0) => fail!("Empty arrays passed to polynomial constructor."),
      (x,y) if x != y => fail!("Arrays of different lengths passed to polynomial constructor."),
      _ => PolyOwning { coefs: coefs, mons: mons }
    }
  }

  pub fn zero() -> PolyOwning<Mon> {
    let one_mon: Mon = Monomial::one();
    PolyOwning { coefs: ~[0 as R], mons: ~[one_mon] }
  }

  pub fn zero_with_capacity(n: uint) -> PolyOwning<Mon> {
    let one_mon: Mon = Monomial::one();
    let mut coefs = vec::with_capacity(n);
    let mut mons = vec::with_capacity(n);
    coefs.push(0 as R);
    mons.push(one_mon);
    PolyOwning { coefs: coefs, mons: mons }
  }

  pub fn from_polys_lcomb<P:Polynomial<Mon>>(terms: &[(R,&P)]) -> PolyOwning<Mon> {
    let mut coefs_by_mon: TreeMap<Mon,R> = TreeMap::new();
    for &(c_p, p) in terms.iter() {
      p.each_term(|(c_m, m)| {
        if c_m != 0 as R {
          let did_update = match coefs_by_mon.find_mut(&m) {
            Some(c) => { *c += c_p * c_m; true }, None => false
          };
          if !did_update {
            coefs_by_mon.insert(m, c_p * c_m);
          }
        }
      });
    }
    let mut mons:  ~[Mon] = vec::with_capacity(coefs_by_mon.len());
    let mut coefs: ~[R] = vec::with_capacity(coefs_by_mon.len());
    for (mon, coef) in coefs_by_mon.iter() {
      if *coef != 0 as R {
        mons.push(mon.clone());
        coefs.push(*coef);
      }
    }
    PolyOwning { coefs: coefs, mons: mons }
  }

}

impl<'self,Mon:Monomial> PolyBorrowing<'self,Mon> {

  pub fn new(coefs: &'self [R], mons: &'self [Mon]) -> PolyBorrowing<'self,Mon> {
    match (coefs.len(), mons.len()) {
      (0,0) => fail!("Empty arrays passed to polynomial constructor."),
      (x,y) if x != y => fail!("Arrays of different lengths passed to polynomial constructor."),
      _ => PolyBorrowing { coefs: coefs, mons: mons }
    }
  }
}

impl<'self,Mon:Monomial> PolyBorrowingMons<'self,Mon> {

  pub fn new(coefs: ~[R], mons: &'self [Mon]) -> PolyBorrowingMons<'self,Mon> {
    match (coefs.len(), mons.len()) {
      (0,0) => fail!("Empty arrays passed to polynomial constructor."),
      (x,y) if x != y => fail!("Arrays of different lengths passed to polynomial constructor."),
      _ => PolyBorrowingMons { coefs: coefs, mons: mons }
    }
  }
}

pub trait Polynomial<Mon>: ToStr {

  fn domain_space_dims(_: Option<Self>) -> uint;

  fn num_terms(&self) -> uint;

  fn term(&self, n: uint) -> (R,Mon);

  fn foldl_terms<A>(&self, z: A, f: &fn(a: A, term: (R,Mon)) -> A) -> A;

  fn each_term(&self, f: &fn(term: (R,Mon)) -> ()) ->  ();

  fn canonical_form(&self) -> PolyOwning<Mon>;

  fn equiv<P: Polynomial<Mon>>(&self, other: &P) -> bool;

}

fn canonical_form_impl<Mon: Monomial>(coefs: &[R], mons: &[Mon]) -> (~[R],~[Mon]) {
  let mut coefs_by_mon: TreeMap<Mon,R> = TreeMap::new();
  for i in range(0, mons.len()) {
    let (mon, mon_coef) = (mons[i].clone(), coefs[i]);
    if mon_coef != 0 as R {
      let did_update = match coefs_by_mon.find_mut(&mon) {
        Some(coef) => { *coef += mon_coef; true }, None => false
      };
      if !did_update {
        coefs_by_mon.insert(mon, mon_coef);
      }
    }
  }
  let mut mons:  ~[Mon] = vec::with_capacity(coefs_by_mon.len());
  let mut coefs: ~[R] = vec::with_capacity(coefs_by_mon.len());
  for (mon, coef) in coefs_by_mon.iter() {
    if *coef != 0 as R {
      mons.push(mon.clone());
      coefs.push(*coef);
    }
  }
  (coefs, mons)
}

impl<Mon:Monomial> Polynomial<Mon>
               for PolyOwning<Mon> {

  #[inline]
  fn domain_space_dims(_: Option<PolyOwning<Mon>>) -> uint {
    Monomial::domain_space_dims(None::<Mon>)
  }

  #[inline]
  fn num_terms(&self) -> uint {
    self.mons.len()
  }

  #[inline]
  fn term(&self, n: uint) -> (R,Mon) {
    let coef = self.coefs[n];
    let mon = unsafe { self.mons.unsafe_get(n) }; // bounds-checked already in coef access
    (coef,mon)
  }

  fn foldl_terms<A>(&self, z: A, f: &fn(a: A, term: (R,Mon)) -> A) -> A {
    let mut acc_val = z;
    for n in range(0, self.mons.len()) {
      // let term = (self.coefs[n], self.mons[n].clone());
      let term = unsafe { (self.coefs.unsafe_get(n), self.mons.unsafe_get(n)) };
      acc_val = f(acc_val, term);
    }
    acc_val
  }

  #[inline]
  fn each_term(&self, f: &fn(term: (R,Mon)) -> ()) ->  () {
    for n in range(0, self.mons.len()) {
      unsafe { f((self.coefs.unsafe_get(n), self.mons.unsafe_get(n))) };
    }
  }

  fn canonical_form(&self) -> PolyOwning<Mon> {
    let (can_coefs, can_mons) = canonical_form_impl(self.coefs, self.mons);
    match can_mons.len() {
      0 => { let m: PolyOwning<Mon> = PolyOwning::zero(); m}
      _ => PolyOwning::new(can_coefs, can_mons)
    }
  }

  fn equiv<P: Polynomial<Mon>>(&self, other: &P) -> bool {
    let (self_can_coefs, self_can_mons) = canonical_form_impl(self.coefs, self.mons);
    let other_can = other.canonical_form();
    self_can_coefs == other_can.coefs && self_can_mons == other_can.mons
  }

}

impl<'self,Mon:Monomial> Polynomial<Mon>
                     for PolyBorrowing<'self,Mon> {

  #[inline]
  fn domain_space_dims(_: Option<PolyBorrowing<Mon>>) -> uint {
    Monomial::domain_space_dims(None::<Mon>)
  }

  #[inline]
  fn num_terms(&self) -> uint {
    self.mons.len()
  }

  #[inline]
  fn term(&self, n: uint) -> (R,Mon) {
    let coef = self.coefs[n];
    let mon = unsafe { self.mons.unsafe_get(n) }; // bounds-checked already in coef access
    (coef,mon)
  }

  fn foldl_terms<A>(&self, z: A, f: &fn(a: A, term: (R,Mon)) -> A) -> A {
    let mut acc_val = z;
    for n in range(0, self.mons.len()) {
      let term = unsafe { (self.coefs.unsafe_get(n), self.mons.unsafe_get(n)) };
      acc_val = f(acc_val, term);
    }
    acc_val
  }

  #[inline]
  fn each_term(&self, f: &fn(term: (R,Mon)) -> ()) ->  () {
    for n in range(0, self.mons.len()) {
      unsafe { f((self.coefs.unsafe_get(n), self.mons.unsafe_get(n))) };
    }
  }

  fn canonical_form(&self) -> PolyOwning<Mon> {
    let (can_coefs, can_mons) = canonical_form_impl(self.coefs, self.mons);
    match can_mons.len() {
      0 => { let zero: PolyOwning<Mon> = PolyOwning::zero(); zero}
      _ => PolyOwning::new(can_coefs, can_mons)
    }
  }

  fn equiv<P: Polynomial<Mon>>(&self, other: &P) -> bool {
    let (self_can_coefs, self_can_mons) = canonical_form_impl(self.coefs, self.mons);
    let other_can = other.canonical_form();
    self_can_coefs == other_can.coefs && self_can_mons == other_can.mons
  }

}

impl<'self,Mon:Monomial> Polynomial<Mon>
                     for PolyBorrowingMons<'self,Mon> {

  #[inline]
  fn domain_space_dims(_: Option<PolyBorrowingMons<Mon>>) -> uint {
    Monomial::domain_space_dims(None::<Mon>)
  }

  #[inline]
  fn num_terms(&self) -> uint {
    self.mons.len()
  }

  #[inline]
  fn term(&self, n: uint) -> (R,Mon) {
    let coef = self.coefs[n];
    let mon = unsafe { self.mons.unsafe_get(n) }; // bounds-checked already in coef access
    (coef,mon)
  }

  fn foldl_terms<A>(&self, z: A, f: &fn(a: A, term: (R,Mon)) -> A) -> A {
    let mut acc_val = z;
    for n in range(0, self.mons.len()) {
      let term = unsafe { (self.coefs.unsafe_get(n), self.mons.unsafe_get(n)) };
      acc_val = f(acc_val, term);
    }
    acc_val
  }

  #[inline]
  fn each_term(&self, f: &fn(term: (R,Mon)) -> ()) ->  () {
    for n in range(0, self.mons.len()) {
      unsafe { f((self.coefs.unsafe_get(n), self.mons.unsafe_get(n))) };
    }
  }

  fn canonical_form(&self) -> PolyOwning<Mon> {
    let (can_coefs, can_mons) = canonical_form_impl(self.coefs, self.mons);
    match can_mons.len() {
      0 => { let zero: PolyOwning<Mon> = PolyOwning::zero(); zero}
      _ => PolyOwning::new(can_coefs, can_mons)
    }
  }

  fn equiv<P: Polynomial<Mon>>(&self, other: &P) -> bool {
    let (self_can_coefs, self_can_mons) = canonical_form_impl(self.coefs, self.mons);
    let other_can = other.canonical_form();
    self_can_coefs == other_can.coefs && self_can_mons == other_can.mons
  }

}

// Implement ToStr trait.

fn to_str_impl<Mon: Monomial>(coefs: &[R], mons: &[Mon]) -> ~str {
  let term_strs = vec::from_fn(mons.len(), |i| {
    coefs[i].to_str() + " " + mons[i].to_str()
  });
  term_strs.connect(" + ")
}

impl<Mon:Monomial> ToStr
             for PolyOwning<Mon> {
  fn to_str(&self) -> ~str {
    to_str_impl(self.coefs, self.mons)
  }
}

impl<'self,Mon:Monomial> ToStr
                   for PolyBorrowing<'self,Mon> {
  fn to_str(&self) -> ~str {
    to_str_impl(self.coefs, self.mons)
  }
}

impl<'self,Mon:Monomial> ToStr
                   for PolyBorrowingMons<'self,Mon> {
  fn to_str(&self) -> ~str {
    to_str_impl(self.coefs, self.mons)
  }
}

pub trait Scalable {

  fn scaled(&self, r: R) -> Self;

  fn scale(&mut self, r: R) -> ();

}

impl<'self,Mon:Monomial> Scalable
                   for PolyBorrowingMons<'self,Mon> {
  #[inline]
  fn scaled(&self, r: R) -> PolyBorrowingMons<'self, Mon> {
    let scaled_coefs = vec::from_fn(self.coefs.len(), |i| r * self.coefs[i]);
    PolyBorrowingMons { coefs: scaled_coefs, mons: self.mons }
  }

  #[inline]
  fn scale(&mut self, r: R) -> () {
    for i in range(0, self.coefs.len()) {
      self.coefs[i] *= r;
    }
  }
}

impl<Mon:Monomial> Scalable
             for PolyOwning<Mon> {
  #[inline]
  fn scaled(&self, r: R) -> PolyOwning<Mon> {
    let scaled_coefs = vec::from_fn(self.coefs.len(), |i| r * self.coefs[i]);
    PolyOwning { coefs: scaled_coefs, mons: self.mons.clone() }
  }

  #[inline]
  fn scale(&mut self, r: R) -> () {
    for i in range(0, self.coefs.len()) {
      self.coefs[i] *= r;
    }
  }
}

pub fn mul<Mon:Monomial,P1:Polynomial<Mon>,P2:Polynomial<Mon>>(p1: &P1, p2: &P2) -> PolyOwning<Mon> {
  let n = p1.num_terms() * p2.num_terms();
  let mut mons = vec::with_capacity(n);
  let mut coefs = vec::with_capacity(n);
  p1.each_term(|(c1,m1)|
    p2.each_term(|(c2,m2)| {
      mons.push(m1 * m2);
      coefs.push(c1 * c2);
    })
  );
  PolyOwning { coefs: coefs, mons: mons }
}

// Convenience function to create polynomials in testing code. Performance critical code
// should use the ::new function implementations instead which will be more efficient.
pub fn poly<Mon:Monomial>(terms: &[(R,Mon)]) -> PolyOwning<Mon> {
  let mut coefs = vec::with_capacity(terms.len());
  let mut mons = vec::with_capacity(terms.len());
  for &(c, ref mon) in terms.iter() {
    coefs.push(c);
    mons.push(mon.clone());
  }
  PolyOwning { coefs: coefs, mons: mons }
}

pub fn approx_equiv<Mon:Monomial,P:Polynomial<Mon>>(p1: &P, p2: &P, tol: R) -> bool {
  let diff = PolyOwning::from_polys_lcomb([(1.,p1),(-1.,p2)]);
  diff.coefs.iter().all(|&c| abs(c) <= tol)
}

<commit_msg>Remove unnecessary domain_space_dims fun.<commit_after>use extra::treemap::TreeMap;
use std::vec;
use std::num::abs;

use common::*;
use monomial::*;

#[deriving(Eq, Clone)]
pub struct PolyOwning<Mon> {
  coefs: ~[R],
  mons:  ~[Mon]
}

#[deriving(Eq, Clone)]
pub struct PolyBorrowing<'self,Mon> {
  coefs: &'self [R],
  mons: &'self [Mon]
}

#[deriving(Eq, Clone)]
pub struct PolyBorrowingMons<'self,Mon> {
  coefs: ~[R],
  mons: &'self [Mon]
}

impl<Mon:Monomial> PolyOwning<Mon> {

  pub fn new(coefs: ~[R], mons: ~[Mon]) -> PolyOwning<Mon> {
    match (coefs.len(), mons.len()) {
      (0,0) => fail!("Empty arrays passed to polynomial constructor."),
      (x,y) if x != y => fail!("Arrays of different lengths passed to polynomial constructor."),
      _ => PolyOwning { coefs: coefs, mons: mons }
    }
  }

  pub fn zero() -> PolyOwning<Mon> {
    let one_mon: Mon = Monomial::one();
    PolyOwning { coefs: ~[0 as R], mons: ~[one_mon] }
  }

  pub fn zero_with_capacity(n: uint) -> PolyOwning<Mon> {
    let one_mon: Mon = Monomial::one();
    let mut coefs = vec::with_capacity(n);
    let mut mons = vec::with_capacity(n);
    coefs.push(0 as R);
    mons.push(one_mon);
    PolyOwning { coefs: coefs, mons: mons }
  }

  pub fn from_polys_lcomb<P:Polynomial<Mon>>(terms: &[(R,&P)]) -> PolyOwning<Mon> {
    let mut coefs_by_mon: TreeMap<Mon,R> = TreeMap::new();
    for &(c_p, p) in terms.iter() {
      p.each_term(|(c_m, m)| {
        if c_m != 0 as R {
          let did_update = match coefs_by_mon.find_mut(&m) {
            Some(c) => { *c += c_p * c_m; true }, None => false
          };
          if !did_update {
            coefs_by_mon.insert(m, c_p * c_m);
          }
        }
      });
    }
    let mut mons:  ~[Mon] = vec::with_capacity(coefs_by_mon.len());
    let mut coefs: ~[R] = vec::with_capacity(coefs_by_mon.len());
    for (mon, coef) in coefs_by_mon.iter() {
      if *coef != 0 as R {
        mons.push(mon.clone());
        coefs.push(*coef);
      }
    }
    PolyOwning { coefs: coefs, mons: mons }
  }

}

impl<'self,Mon:Monomial> PolyBorrowing<'self,Mon> {

  pub fn new(coefs: &'self [R], mons: &'self [Mon]) -> PolyBorrowing<'self,Mon> {
    match (coefs.len(), mons.len()) {
      (0,0) => fail!("Empty arrays passed to polynomial constructor."),
      (x,y) if x != y => fail!("Arrays of different lengths passed to polynomial constructor."),
      _ => PolyBorrowing { coefs: coefs, mons: mons }
    }
  }
}

impl<'self,Mon:Monomial> PolyBorrowingMons<'self,Mon> {

  pub fn new(coefs: ~[R], mons: &'self [Mon]) -> PolyBorrowingMons<'self,Mon> {
    match (coefs.len(), mons.len()) {
      (0,0) => fail!("Empty arrays passed to polynomial constructor."),
      (x,y) if x != y => fail!("Arrays of different lengths passed to polynomial constructor."),
      _ => PolyBorrowingMons { coefs: coefs, mons: mons }
    }
  }
}

pub trait Polynomial<Mon>: ToStr {

  fn num_terms(&self) -> uint;

  fn term(&self, n: uint) -> (R,Mon);

  fn foldl_terms<A>(&self, z: A, f: &fn(a: A, term: (R,Mon)) -> A) -> A;

  fn each_term(&self, f: &fn(term: (R,Mon)) -> ()) ->  ();

  fn canonical_form(&self) -> PolyOwning<Mon>;

  fn equiv<P: Polynomial<Mon>>(&self, other: &P) -> bool;

}

fn canonical_form_impl<Mon: Monomial>(coefs: &[R], mons: &[Mon]) -> (~[R],~[Mon]) {
  let mut coefs_by_mon: TreeMap<Mon,R> = TreeMap::new();
  for i in range(0, mons.len()) {
    let (mon, mon_coef) = (mons[i].clone(), coefs[i]);
    if mon_coef != 0 as R {
      let did_update = match coefs_by_mon.find_mut(&mon) {
        Some(coef) => { *coef += mon_coef; true }, None => false
      };
      if !did_update {
        coefs_by_mon.insert(mon, mon_coef);
      }
    }
  }
  let mut mons:  ~[Mon] = vec::with_capacity(coefs_by_mon.len());
  let mut coefs: ~[R] = vec::with_capacity(coefs_by_mon.len());
  for (mon, coef) in coefs_by_mon.iter() {
    if *coef != 0 as R {
      mons.push(mon.clone());
      coefs.push(*coef);
    }
  }
  (coefs, mons)
}

impl<Mon:Monomial> Polynomial<Mon>
               for PolyOwning<Mon> {

  #[inline]
  fn num_terms(&self) -> uint {
    self.mons.len()
  }

  #[inline]
  fn term(&self, n: uint) -> (R,Mon) {
    let coef = self.coefs[n];
    let mon = unsafe { self.mons.unsafe_get(n) }; // bounds-checked already in coef access
    (coef,mon)
  }

  fn foldl_terms<A>(&self, z: A, f: &fn(a: A, term: (R,Mon)) -> A) -> A {
    let mut acc_val = z;
    for n in range(0, self.mons.len()) {
      // let term = (self.coefs[n], self.mons[n].clone());
      let term = unsafe { (self.coefs.unsafe_get(n), self.mons.unsafe_get(n)) };
      acc_val = f(acc_val, term);
    }
    acc_val
  }

  #[inline]
  fn each_term(&self, f: &fn(term: (R,Mon)) -> ()) ->  () {
    for n in range(0, self.mons.len()) {
      unsafe { f((self.coefs.unsafe_get(n), self.mons.unsafe_get(n))) };
    }
  }

  fn canonical_form(&self) -> PolyOwning<Mon> {
    let (can_coefs, can_mons) = canonical_form_impl(self.coefs, self.mons);
    match can_mons.len() {
      0 => { let m: PolyOwning<Mon> = PolyOwning::zero(); m}
      _ => PolyOwning::new(can_coefs, can_mons)
    }
  }

  fn equiv<P: Polynomial<Mon>>(&self, other: &P) -> bool {
    let (self_can_coefs, self_can_mons) = canonical_form_impl(self.coefs, self.mons);
    let other_can = other.canonical_form();
    self_can_coefs == other_can.coefs && self_can_mons == other_can.mons
  }

}

impl<'self,Mon:Monomial> Polynomial<Mon>
                     for PolyBorrowing<'self,Mon> {

  #[inline]
  fn num_terms(&self) -> uint {
    self.mons.len()
  }

  #[inline]
  fn term(&self, n: uint) -> (R,Mon) {
    let coef = self.coefs[n];
    let mon = unsafe { self.mons.unsafe_get(n) }; // bounds-checked already in coef access
    (coef,mon)
  }

  fn foldl_terms<A>(&self, z: A, f: &fn(a: A, term: (R,Mon)) -> A) -> A {
    let mut acc_val = z;
    for n in range(0, self.mons.len()) {
      let term = unsafe { (self.coefs.unsafe_get(n), self.mons.unsafe_get(n)) };
      acc_val = f(acc_val, term);
    }
    acc_val
  }

  #[inline]
  fn each_term(&self, f: &fn(term: (R,Mon)) -> ()) ->  () {
    for n in range(0, self.mons.len()) {
      unsafe { f((self.coefs.unsafe_get(n), self.mons.unsafe_get(n))) };
    }
  }

  fn canonical_form(&self) -> PolyOwning<Mon> {
    let (can_coefs, can_mons) = canonical_form_impl(self.coefs, self.mons);
    match can_mons.len() {
      0 => { let zero: PolyOwning<Mon> = PolyOwning::zero(); zero}
      _ => PolyOwning::new(can_coefs, can_mons)
    }
  }

  fn equiv<P: Polynomial<Mon>>(&self, other: &P) -> bool {
    let (self_can_coefs, self_can_mons) = canonical_form_impl(self.coefs, self.mons);
    let other_can = other.canonical_form();
    self_can_coefs == other_can.coefs && self_can_mons == other_can.mons
  }

}

impl<'self,Mon:Monomial> Polynomial<Mon>
                     for PolyBorrowingMons<'self,Mon> {

  #[inline]
  fn num_terms(&self) -> uint {
    self.mons.len()
  }

  #[inline]
  fn term(&self, n: uint) -> (R,Mon) {
    let coef = self.coefs[n];
    let mon = unsafe { self.mons.unsafe_get(n) }; // bounds-checked already in coef access
    (coef,mon)
  }

  fn foldl_terms<A>(&self, z: A, f: &fn(a: A, term: (R,Mon)) -> A) -> A {
    let mut acc_val = z;
    for n in range(0, self.mons.len()) {
      let term = unsafe { (self.coefs.unsafe_get(n), self.mons.unsafe_get(n)) };
      acc_val = f(acc_val, term);
    }
    acc_val
  }

  #[inline]
  fn each_term(&self, f: &fn(term: (R,Mon)) -> ()) ->  () {
    for n in range(0, self.mons.len()) {
      unsafe { f((self.coefs.unsafe_get(n), self.mons.unsafe_get(n))) };
    }
  }

  fn canonical_form(&self) -> PolyOwning<Mon> {
    let (can_coefs, can_mons) = canonical_form_impl(self.coefs, self.mons);
    match can_mons.len() {
      0 => { let zero: PolyOwning<Mon> = PolyOwning::zero(); zero}
      _ => PolyOwning::new(can_coefs, can_mons)
    }
  }

  fn equiv<P: Polynomial<Mon>>(&self, other: &P) -> bool {
    let (self_can_coefs, self_can_mons) = canonical_form_impl(self.coefs, self.mons);
    let other_can = other.canonical_form();
    self_can_coefs == other_can.coefs && self_can_mons == other_can.mons
  }

}

// Implement ToStr trait.

fn to_str_impl<Mon: Monomial>(coefs: &[R], mons: &[Mon]) -> ~str {
  let term_strs = vec::from_fn(mons.len(), |i| {
    coefs[i].to_str() + " " + mons[i].to_str()
  });
  term_strs.connect(" + ")
}

impl<Mon:Monomial> ToStr
             for PolyOwning<Mon> {
  fn to_str(&self) -> ~str {
    to_str_impl(self.coefs, self.mons)
  }
}

impl<'self,Mon:Monomial> ToStr
                   for PolyBorrowing<'self,Mon> {
  fn to_str(&self) -> ~str {
    to_str_impl(self.coefs, self.mons)
  }
}

impl<'self,Mon:Monomial> ToStr
                   for PolyBorrowingMons<'self,Mon> {
  fn to_str(&self) -> ~str {
    to_str_impl(self.coefs, self.mons)
  }
}

pub trait Scalable {

  fn scaled(&self, r: R) -> Self;

  fn scale(&mut self, r: R) -> ();

}

impl<'self,Mon:Monomial> Scalable
                   for PolyBorrowingMons<'self,Mon> {
  #[inline]
  fn scaled(&self, r: R) -> PolyBorrowingMons<'self, Mon> {
    let scaled_coefs = vec::from_fn(self.coefs.len(), |i| r * self.coefs[i]);
    PolyBorrowingMons { coefs: scaled_coefs, mons: self.mons }
  }

  #[inline]
  fn scale(&mut self, r: R) -> () {
    for i in range(0, self.coefs.len()) {
      self.coefs[i] *= r;
    }
  }
}

impl<Mon:Monomial> Scalable
             for PolyOwning<Mon> {
  #[inline]
  fn scaled(&self, r: R) -> PolyOwning<Mon> {
    let scaled_coefs = vec::from_fn(self.coefs.len(), |i| r * self.coefs[i]);
    PolyOwning { coefs: scaled_coefs, mons: self.mons.clone() }
  }

  #[inline]
  fn scale(&mut self, r: R) -> () {
    for i in range(0, self.coefs.len()) {
      self.coefs[i] *= r;
    }
  }
}

pub fn mul<Mon:Monomial,P1:Polynomial<Mon>,P2:Polynomial<Mon>>(p1: &P1, p2: &P2) -> PolyOwning<Mon> {
  let n = p1.num_terms() * p2.num_terms();
  let mut mons = vec::with_capacity(n);
  let mut coefs = vec::with_capacity(n);
  p1.each_term(|(c1,m1)|
    p2.each_term(|(c2,m2)| {
      mons.push(m1 * m2);
      coefs.push(c1 * c2);
    })
  );
  PolyOwning { coefs: coefs, mons: mons }
}

// Convenience function to create polynomials in testing code. Performance critical code
// should use the ::new function implementations instead which will be more efficient.
pub fn poly<Mon:Monomial>(terms: &[(R,Mon)]) -> PolyOwning<Mon> {
  let mut coefs = vec::with_capacity(terms.len());
  let mut mons = vec::with_capacity(terms.len());
  for &(c, ref mon) in terms.iter() {
    coefs.push(c);
    mons.push(mon.clone());
  }
  PolyOwning { coefs: coefs, mons: mons }
}

pub fn approx_equiv<Mon:Monomial,P:Polynomial<Mon>>(p1: &P, p2: &P, tol: R) -> bool {
  let diff = PolyOwning::from_polys_lcomb([(1.,p1),(-1.,p2)]);
  diff.coefs.iter().all(|&c| abs(c) <= tol)
}

<|endoftext|>


<commit_before>//
// Copyright:: Copyright (c) 2015 Chef Software, Inc.
// License:: Apache License, Version 2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use utils::{self, walk_tree_for_path, mkdir_recursive};
use utils::path_ext::is_dir;
use errors::{DeliveryError, Kind};
use types::DeliveryResult;
use std::path::{Path, PathBuf};
use http::APIClient;
use git::{self, ReviewResult};
use std::process::{Output, Command};
use std::fs;
use std::fs::File;
use std::io::prelude::*;

// README with a brief description of delivery and how to use it. This is added
// to a new project by `delivery init` so we have something to submit as the
// first change.
//
// We load this up as bytes since that's what std::io::Write takes for
// arguments.
static DELIVERY_DOT_MD_CONTENT: &'static [u8] = include_bytes!("DELIVERY.md");

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Type {
    Bitbucket,
    Github
}

#[derive(Debug, Clone)]
pub struct SourceCodeProvider {
    pub repo_name: String,
    pub organization: String,
    pub branch: String,
    pub verify_ssl: bool,
    pub kind: Type,
}

impl SourceCodeProvider {
    // Create a new `SourceCodeProvider`. Returns an error result if
    // required configuration values are missing. Expects to find
    // `scp`, `repository`, `scp-organization`, `branch`, and `ssl`.
    pub fn new(scp: &str, repo: &str, org: &str, branch: &str,
               no_ssl: bool) -> DeliveryResult<SourceCodeProvider> {
        let scp_kind = match scp {
            "github" => Type::Github,
            "bitbucket" => Type::Bitbucket,
            _ => return Err(DeliveryError{ kind: Kind::UnknownProjectType, detail:None })
        };
        if repo.to_string().is_empty()
            || org.to_string().is_empty()
            || branch.to_string().is_empty() {
            match scp_kind {
                Type::Github => return Err(
                    DeliveryError{
                        kind: Kind::OptionConstraint,
                        detail: Some(format!("Missing Github Source Code Provider attributes, specify: \
                                              repo-name, org-name and pipeline(default: master)"))
                    }
                ),
                Type::Bitbucket => return Err(
                    DeliveryError{
                        kind: Kind::OptionConstraint,
                        detail: Some(format!("Missing Bitbucket Source Code Provider attributes, specify: \
                                              repo-name, project-key and pipeline(default: master)"))
                    }
                ),
            }
        }
        Ok(SourceCodeProvider {
            kind: scp_kind,
            repo_name: repo.to_string(),
            organization: org.to_string(),
            branch: branch.to_string(),
            verify_ssl: !no_ssl,
        })
    }

    // Verify if the SCP is configured on the Delivery Server
    pub fn verify_server_config(&self, client: &APIClient) -> DeliveryResult<()> {
        match self.kind {
            Type::Github => {
                let scp_config = try!(client.get_github_server_config());
                if scp_config.is_empty() {
                    return Err(DeliveryError{ kind: Kind::NoGithubSCPConfig, detail: None })
                }
            },
            Type::Bitbucket => {
                let scp_config = try!(client.get_bitbucket_server_config());
                if scp_config.is_empty() {
                    return Err(DeliveryError{ kind: Kind::NoBitbucketSCPConfig, detail: None })
                }
            }
        }
        Ok(())
    }
}

// Create a Delivery Pipeline.
// Returns true if created, returns false if already exists.
pub fn create_delivery_pipeline(client: &APIClient, org: &String,
                                proj: &String, pipe: &String) -> DeliveryResult<bool> {
    if client.pipeline_exists(org, proj, pipe) {
        return Ok(false)
    } else {
        try!(client.create_pipeline(org, proj, pipe, Some(pipe)));
        return Ok(true)
    }
}

// Create a Delivery Project with Delivery as SCP (default).
// If the project is created, return true.
// If the project already exists, return false
pub fn create_delivery_project(client: &APIClient,
                               org: &String,
                               proj: &String) -> DeliveryResult<bool> {
    if client.project_exists(org, proj) {
        return Ok(false)
    } else {
        try!(client.create_delivery_project(org, proj));
        return Ok(true)
    }
}

// Push local content to the Delivery Server if no upstream commits.
// Returns true if commits pushed, returns false if upstream commits found.
pub fn push_project_content_to_delivery(pipeline: &str) -> DeliveryResult<bool> {
    if try!(git::server_content(pipeline)) {
        Ok(false)
    } else {
        try!(git::git_push(pipeline));
        Ok(true)
    }
}

// Create delivery remote if it doesn't exist. Returns true if created.
pub fn create_delivery_remote_if_missing(
      delivery_git_ssh_url: &String) -> DeliveryResult<bool> {
    if try!(git::config_repo(delivery_git_ssh_url, &project_path())) {
        return Ok(true)
    } else {
        return Ok(false)
    }
}

// Check to see if the origin remote is set up.
pub fn missing_github_remote() -> DeliveryResult<bool> {
    let git_remote_result = git::git_command(&["remote"], &project_path());
    match git_remote_result {
        Ok(git_result) => Ok(!git_result.stdout.contains("origin")),
        Err(e) => return Err(e)
    }
}

/// Search for the project root directory
///
/// We will walk through the provided path tree until we find the
/// git config (`.git/config`) annd then we will extract the root
/// directory.
///
/// # Examples
///
/// Having this directory tree:
/// /delivery-cli
///  ├── .git
///  │   └── config
///  ├── src
///  │   └── delivery
///  └── features
///
/// ```
/// use std::env;
/// use delivery::project::root_dir;
///
/// let root = env::current_dir().unwrap();
///
/// //Stepping into `delivery-cli/src/delivery`
/// let mut delivery_src = env::current_dir().unwrap();
/// delivery_src.push("src/delivery");
///
/// assert_eq!(root, root_dir(&delivery_src.as_path()).unwrap());
/// ```
pub fn root_dir(dir: &Path) -> DeliveryResult<PathBuf> {
    match walk_tree_for_path(&PathBuf::from(&dir), ".git/config") {
        Some(p) => {
           let git_d = p.parent().unwrap();
           let root_d = git_d.parent().unwrap();
           Ok(PathBuf::from(root_d))
        },
        None => Err(DeliveryError{kind: Kind::NoGitConfig,
                                  detail: None})
    }
}

pub fn project_path() -> PathBuf {
    root_dir(&utils::cwd()).unwrap()
}

// Return the project name from the current path
pub fn project_from_cwd() -> DeliveryResult<String> {
    let cwd = try!(self::root_dir(&utils::cwd()));
    Ok(cwd.file_name().unwrap().to_str().unwrap().to_string())
}

// Return the project name or try to extract it from the current path
pub fn project_or_from_cwd(proj: &str) -> DeliveryResult<String> {
    if proj.is_empty() {
        project_from_cwd()
    } else {
        Ok(proj.to_string())
    }
}

// Create the feature branch `add-delivery-config`
//
// This branch is created to start modifying the project repository
// In the case of a failure, we could roll back fearly easy by checking
// out master and deleting this feature branch.
//
// If feature branch created, return true, else return false.
pub fn create_feature_branch_if_missing(project_path: &PathBuf, branch_name: &str) -> DeliveryResult<bool> {
    match git::git_command(&["checkout", "-b", branch_name], project_path) {
        Ok(_) => {
            return Ok(true);
        },
        Err(e) => {
            match e.detail.clone() {
                Some(msg) => {
                    if msg.contains(&format!("A branch named '{}' already exists", branch_name)) {
                       try!(git::git_command(&["checkout", branch_name], project_path));
                        return Ok(false)
                    } else {
                        return Err(e)
                    }
                },
                // Unexpected error, raise.
                None => Err(e)
            }
        }
    }
}

// Add and commit the generated build_cookbook
pub fn add_commit_build_cookbook(custom_config_passed: &bool) -> DeliveryResult<()> {
    // .delivery is probably not yet under version control, so we have to add
    // the whole folder instead of .delivery/build_cookbook.
    try!(git::git_command(&["add", ".delivery"], &project_path()));
    let mut commit_msg = "Adds Delivery build cookbook".to_string();
    if !(*custom_config_passed) {
        commit_msg = commit_msg + " and config";
    }
    try!(git::git_command(&["commit", "-m", &commit_msg], &project_path()));
    Ok(())
}

// Create the delivery readme if it doesn't exist already.
pub fn create_delivery_readme() -> DeliveryResult<bool> {
    // NOTE: this isn't guaranteed to be in the project root; however it is only invoked via
    // `delivery init` which makes some assumptions elsewhere that the CWD is the project root.
    if !PathBuf::from("DELIVERY.md").exists() {
        let mut f = try!(File::create("DELIVERY.md"));
        try!(f.write_all(&DELIVERY_DOT_MD_CONTENT));
        Ok(true)
    } else {
        Ok(false)
    }
}

pub fn commit_delivery_readme() -> DeliveryResult<()> {
    try!(git::git_command(&["add", "DELIVERY.md"], &project_path()));
    let commit_msg = "New pipeline verification commit".to_string();
    try!(git::git_command(&["commit", "-m", &commit_msg], &project_path()));
    Ok(())
}

pub fn create_dot_delivery() -> &'static Path {
    // TODO: should we be doing some relative pathing here?
    let dot_delivery = Path::new(".delivery");
    fs::create_dir_all(dot_delivery).unwrap();
    dot_delivery
}

pub fn create_default_build_cookbook() -> DeliveryResult<Command> {
    let mut command = utils::make_command("chef");
    command.arg("generate")
        .arg("build-cookbook")
        .arg(".delivery/build_cookbook")
        .current_dir(&project_path());
    let output = try!(command.output());
    try!(handle_chef_generate_cookbook_cmd(output));
    Ok(command)
}

#[derive(Debug)]
pub enum CustomCookbookSource {
    Cached,
    Disk,
    Git
}

// Custom build_cookbook generation
//
// This method handles a custom generator which could be:
// 1) A local path
// 2) Or a git repo URL
// TODO) From Supermarket
pub fn download_or_mv_custom_build_cookbook_generator(
        generator: &Path,
        cache_path: &Path) -> DeliveryResult<CustomCookbookSource> {
    try!(mkdir_recursive(cache_path));
    if generator.has_root() {
        try!(utils::copy_recursive(&generator, &cache_path));
        return Ok(CustomCookbookSource::Disk)
    } else {
        let cache_path_str = &cache_path.to_string_lossy();
        let generator_str = &generator.to_string_lossy();
        if is_dir(&cache_path) {
            return Ok(CustomCookbookSource::Cached)
        } else {
            try!(git::clone(&cache_path_str, &generator_str));
            return Ok(CustomCookbookSource::Git)
        }
    }
}

// Generate the build_cookbook using ChefDK generate
pub fn chef_generate_build_cookbook_from_generator(
      generator: &Path, project_path: &Path) -> DeliveryResult<Command> {
    let mut command = utils::make_command("chef");
    command.arg("generate")
        .arg("cookbook")
        .arg(".delivery/build_cookbook")
        .arg("-g")
        .arg(generator)
        .current_dir(&project_path);

    let output = try!(command.output());
    try!(handle_chef_generate_cookbook_cmd(output));
    Ok(command)
}

// Default cookbooks generator cache path
pub fn generator_cache_path() -> DeliveryResult<PathBuf> {
    utils::home_dir(&[".delivery/cache/generator-cookbooks"])
}

fn handle_chef_generate_cookbook_cmd(output: Output) -> DeliveryResult<()> {
    if !output.status.success() {
        return Err(
            DeliveryError {
                kind: Kind::FailedToExecute,
                detail: Some(format!(
                            "Failed to execute chef generate:\n\
                            STDOUT: {}\nSTDERR: {}",
                            String::from_utf8_lossy(&output.stdout),
                            String::from_utf8_lossy(&output.stderr)
                        ))
            }
        )
    }
    Ok(())
}

pub fn review(target: &String, head: &String) -> DeliveryResult<ReviewResult> {
    if target == head {
        Err(DeliveryError{ kind: Kind::CannotReviewSameBranch, detail: None })
    } else {
        Ok(try!(git::git_push_review(head, target)))
    }
}

pub fn handle_review_result(review: &ReviewResult,
                            no_open: &bool) -> DeliveryResult<Option<String>> {
    match review.url {
        Some(ref url) => {
            if !no_open {
                try!(utils::open::item(&url));
            }
            Ok(Some(url.clone()))
        },
        None => Ok(None)
    }
}

#[cfg(test)]
mod tests {
    use std::path::Path;
    use super::root_dir;

    #[test]
    fn detect_error_if_root_project_is_not_a_git_repo() {
        // This path doesn't even exist
        // So we will expect to throw an Err(_)
        let lib_path = Path::new("/project/src/libraries");
        match root_dir(&lib_path) {
            Ok(_) => assert!(false),
            Err(_) => assert!(true)
        }
    }
}
<commit_msg>Pull the generator from github<commit_after>//
// Copyright:: Copyright (c) 2015 Chef Software, Inc.
// License:: Apache License, Version 2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use utils::{self, walk_tree_for_path, mkdir_recursive};
use utils::path_ext::is_dir;
use errors::{DeliveryError, Kind};
use types::DeliveryResult;
use std::path::{Path, PathBuf};
use http::APIClient;
use git::{self, ReviewResult};
use std::process::{Output, Command};
use std::fs;
use std::fs::File;
use std::io::prelude::*;

// README with a brief description of delivery and how to use it. This is added
// to a new project by `delivery init` so we have something to submit as the
// first change.
//
// We load this up as bytes since that's what std::io::Write takes for
// arguments.
static DELIVERY_DOT_MD_CONTENT: &'static [u8] = include_bytes!("DELIVERY.md");

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Type {
    Bitbucket,
    Github
}

#[derive(Debug, Clone)]
pub struct SourceCodeProvider {
    pub repo_name: String,
    pub organization: String,
    pub branch: String,
    pub verify_ssl: bool,
    pub kind: Type,
}

impl SourceCodeProvider {
    // Create a new `SourceCodeProvider`. Returns an error result if
    // required configuration values are missing. Expects to find
    // `scp`, `repository`, `scp-organization`, `branch`, and `ssl`.
    pub fn new(scp: &str, repo: &str, org: &str, branch: &str,
               no_ssl: bool) -> DeliveryResult<SourceCodeProvider> {
        let scp_kind = match scp {
            "github" => Type::Github,
            "bitbucket" => Type::Bitbucket,
            _ => return Err(DeliveryError{ kind: Kind::UnknownProjectType, detail:None })
        };
        if repo.to_string().is_empty()
            || org.to_string().is_empty()
            || branch.to_string().is_empty() {
            match scp_kind {
                Type::Github => return Err(
                    DeliveryError{
                        kind: Kind::OptionConstraint,
                        detail: Some(format!("Missing Github Source Code Provider attributes, specify: \
                                              repo-name, org-name and pipeline(default: master)"))
                    }
                ),
                Type::Bitbucket => return Err(
                    DeliveryError{
                        kind: Kind::OptionConstraint,
                        detail: Some(format!("Missing Bitbucket Source Code Provider attributes, specify: \
                                              repo-name, project-key and pipeline(default: master)"))
                    }
                ),
            }
        }
        Ok(SourceCodeProvider {
            kind: scp_kind,
            repo_name: repo.to_string(),
            organization: org.to_string(),
            branch: branch.to_string(),
            verify_ssl: !no_ssl,
        })
    }

    // Verify if the SCP is configured on the Delivery Server
    pub fn verify_server_config(&self, client: &APIClient) -> DeliveryResult<()> {
        match self.kind {
            Type::Github => {
                let scp_config = try!(client.get_github_server_config());
                if scp_config.is_empty() {
                    return Err(DeliveryError{ kind: Kind::NoGithubSCPConfig, detail: None })
                }
            },
            Type::Bitbucket => {
                let scp_config = try!(client.get_bitbucket_server_config());
                if scp_config.is_empty() {
                    return Err(DeliveryError{ kind: Kind::NoBitbucketSCPConfig, detail: None })
                }
            }
        }
        Ok(())
    }
}

// Create a Delivery Pipeline.
// Returns true if created, returns false if already exists.
pub fn create_delivery_pipeline(client: &APIClient, org: &String,
                                proj: &String, pipe: &String) -> DeliveryResult<bool> {
    if client.pipeline_exists(org, proj, pipe) {
        return Ok(false)
    } else {
        try!(client.create_pipeline(org, proj, pipe, Some(pipe)));
        return Ok(true)
    }
}

// Create a Delivery Project with Delivery as SCP (default).
// If the project is created, return true.
// If the project already exists, return false
pub fn create_delivery_project(client: &APIClient,
                               org: &String,
                               proj: &String) -> DeliveryResult<bool> {
    if client.project_exists(org, proj) {
        return Ok(false)
    } else {
        try!(client.create_delivery_project(org, proj));
        return Ok(true)
    }
}

// Push local content to the Delivery Server if no upstream commits.
// Returns true if commits pushed, returns false if upstream commits found.
pub fn push_project_content_to_delivery(pipeline: &str) -> DeliveryResult<bool> {
    if try!(git::server_content(pipeline)) {
        Ok(false)
    } else {
        try!(git::git_push(pipeline));
        Ok(true)
    }
}

// Create delivery remote if it doesn't exist. Returns true if created.
pub fn create_delivery_remote_if_missing(
      delivery_git_ssh_url: &String) -> DeliveryResult<bool> {
    if try!(git::config_repo(delivery_git_ssh_url, &project_path())) {
        return Ok(true)
    } else {
        return Ok(false)
    }
}

// Check to see if the origin remote is set up.
pub fn missing_github_remote() -> DeliveryResult<bool> {
    let git_remote_result = git::git_command(&["remote"], &project_path());
    match git_remote_result {
        Ok(git_result) => Ok(!git_result.stdout.contains("origin")),
        Err(e) => return Err(e)
    }
}

/// Search for the project root directory
///
/// We will walk through the provided path tree until we find the
/// git config (`.git/config`) annd then we will extract the root
/// directory.
///
/// # Examples
///
/// Having this directory tree:
/// /delivery-cli
///  ├── .git
///  │   └── config
///  ├── src
///  │   └── delivery
///  └── features
///
/// ```
/// use std::env;
/// use delivery::project::root_dir;
///
/// let root = env::current_dir().unwrap();
///
/// //Stepping into `delivery-cli/src/delivery`
/// let mut delivery_src = env::current_dir().unwrap();
/// delivery_src.push("src/delivery");
///
/// assert_eq!(root, root_dir(&delivery_src.as_path()).unwrap());
/// ```
pub fn root_dir(dir: &Path) -> DeliveryResult<PathBuf> {
    match walk_tree_for_path(&PathBuf::from(&dir), ".git/config") {
        Some(p) => {
           let git_d = p.parent().unwrap();
           let root_d = git_d.parent().unwrap();
           Ok(PathBuf::from(root_d))
        },
        None => Err(DeliveryError{kind: Kind::NoGitConfig,
                                  detail: None})
    }
}

pub fn project_path() -> PathBuf {
    root_dir(&utils::cwd()).unwrap()
}

// Return the project name from the current path
pub fn project_from_cwd() -> DeliveryResult<String> {
    let cwd = try!(self::root_dir(&utils::cwd()));
    Ok(cwd.file_name().unwrap().to_str().unwrap().to_string())
}

// Return the project name or try to extract it from the current path
pub fn project_or_from_cwd(proj: &str) -> DeliveryResult<String> {
    if proj.is_empty() {
        project_from_cwd()
    } else {
        Ok(proj.to_string())
    }
}

// Create the feature branch `add-delivery-config`
//
// This branch is created to start modifying the project repository
// In the case of a failure, we could roll back fearly easy by checking
// out master and deleting this feature branch.
//
// If feature branch created, return true, else return false.
pub fn create_feature_branch_if_missing(project_path: &PathBuf, branch_name: &str) -> DeliveryResult<bool> {
    match git::git_command(&["checkout", "-b", branch_name], project_path) {
        Ok(_) => {
            return Ok(true);
        },
        Err(e) => {
            match e.detail.clone() {
                Some(msg) => {
                    if msg.contains(&format!("A branch named '{}' already exists", branch_name)) {
                       try!(git::git_command(&["checkout", branch_name], project_path));
                        return Ok(false)
                    } else {
                        return Err(e)
                    }
                },
                // Unexpected error, raise.
                None => Err(e)
            }
        }
    }
}

// Add and commit the generated build_cookbook
pub fn add_commit_build_cookbook(custom_config_passed: &bool) -> DeliveryResult<()> {
    // .delivery is probably not yet under version control, so we have to add
    // the whole folder instead of .delivery/build_cookbook.
    try!(git::git_command(&["add", ".delivery"], &project_path()));
    let mut commit_msg = "Adds Delivery build cookbook".to_string();
    if !(*custom_config_passed) {
        commit_msg = commit_msg + " and config";
    }
    try!(git::git_command(&["commit", "-m", &commit_msg], &project_path()));
    Ok(())
}

// Create the delivery readme if it doesn't exist already.
pub fn create_delivery_readme() -> DeliveryResult<bool> {
    // NOTE: this isn't guaranteed to be in the project root; however it is only invoked via
    // `delivery init` which makes some assumptions elsewhere that the CWD is the project root.
    if !PathBuf::from("DELIVERY.md").exists() {
        let mut f = try!(File::create("DELIVERY.md"));
        try!(f.write_all(&DELIVERY_DOT_MD_CONTENT));
        Ok(true)
    } else {
        Ok(false)
    }
}

pub fn commit_delivery_readme() -> DeliveryResult<()> {
    try!(git::git_command(&["add", "DELIVERY.md"], &project_path()));
    let commit_msg = "New pipeline verification commit".to_string();
    try!(git::git_command(&["commit", "-m", &commit_msg], &project_path()));
    Ok(())
}

pub fn create_dot_delivery() -> &'static Path {
    // TODO: should we be doing some relative pathing here?
    let dot_delivery = Path::new(".delivery");
    fs::create_dir_all(dot_delivery).unwrap();
    dot_delivery
}

pub fn create_default_build_cookbook() -> DeliveryResult<Command> {
    let mut command = utils::make_command("chef");
    command.arg("generate")
        .arg("build-cookbook")
        .arg(".delivery/build_cookbook")
        .current_dir(&project_path());
    let output = try!(command.output());
    try!(handle_chef_generate_cookbook_cmd(output));
    Ok(command)
}

#[derive(Debug)]
pub enum CustomCookbookSource {
    Cached,
    Disk,
    Git
}

// Custom build_cookbook generation
//
// This method handles a custom generator which could be:
// 1) A local path
// 2) Or a git repo URL
// TODO) From Supermarket
pub fn download_or_mv_custom_build_cookbook_generator(
        generator: &Path,
        cache_path: &Path) -> DeliveryResult<CustomCookbookSource> {
    try!(mkdir_recursive(cache_path));
    if generator.has_root() {
        try!(utils::copy_recursive(&generator, &cache_path));
        return Ok(CustomCookbookSource::Disk)
    } else {
        let mut cache_generator_path: PathBuf = cache_path.to_path_buf();
        cache_generator_path.push(generator.file_name().unwrap());
        if is_dir(&cache_generator_path) {
            return Ok(CustomCookbookSource::Cached)
        } else {
            let cache_path_str = &cache_generator_path.to_string_lossy();
            let generator_str  = &generator.to_string_lossy();
            try!(git::clone(&cache_path_str, &generator_str));
            return Ok(CustomCookbookSource::Git)
        }
    }
}

// Generate the build_cookbook using ChefDK generate
pub fn chef_generate_build_cookbook_from_generator(
      generator: &Path, project_path: &Path) -> DeliveryResult<Command> {
    let mut command = utils::make_command("chef");
    command.arg("generate")
        .arg("cookbook")
        .arg(".delivery/build_cookbook")
        .arg("-g")
        .arg(generator)
        .current_dir(&project_path);

    let output = try!(command.output());
    try!(handle_chef_generate_cookbook_cmd(output));
    Ok(command)
}

// Default cookbooks generator cache path
pub fn generator_cache_path() -> DeliveryResult<PathBuf> {
    utils::home_dir(&[".delivery/cache/generator-cookbooks"])
}

fn handle_chef_generate_cookbook_cmd(output: Output) -> DeliveryResult<()> {
    if !output.status.success() {
        return Err(
            DeliveryError {
                kind: Kind::FailedToExecute,
                detail: Some(format!(
                            "Failed to execute chef generate:\n\
                            STDOUT: {}\nSTDERR: {}",
                            String::from_utf8_lossy(&output.stdout),
                            String::from_utf8_lossy(&output.stderr)
                        ))
            }
        )
    }
    Ok(())
}

pub fn review(target: &String, head: &String) -> DeliveryResult<ReviewResult> {
    if target == head {
        Err(DeliveryError{ kind: Kind::CannotReviewSameBranch, detail: None })
    } else {
        Ok(try!(git::git_push_review(head, target)))
    }
}

pub fn handle_review_result(review: &ReviewResult,
                            no_open: &bool) -> DeliveryResult<Option<String>> {
    match review.url {
        Some(ref url) => {
            if !no_open {
                try!(utils::open::item(&url));
            }
            Ok(Some(url.clone()))
        },
        None => Ok(None)
    }
}

#[cfg(test)]
mod tests {
    use std::path::Path;
    use super::root_dir;

    #[test]
    fn detect_error_if_root_project_is_not_a_git_repo() {
        // This path doesn't even exist
        // So we will expect to throw an Err(_)
        let lib_path = Path::new("/project/src/libraries");
        match root_dir(&lib_path) {
            Ok(_) => assert!(false),
            Err(_) => assert!(true)
        }
    }
}
<|endoftext|>


<commit_before>extern crate parity_wasm;

use std::env::args;

use parity_wasm::{interpreter, ModuleInstanceInterface, RuntimeValue};
use parity_wasm::elements::{Internal, External, Type, FunctionType, ValueType};

fn main() {
    let args: Vec<_> = args().collect();
    if args.len() < 3 {
        println!("Usage: {} <wasm file> <exported func> [<arg>...]", args[0]);
        return;
    }
    let func_name = &args[2];
    let (_, program_args) = args.split_at(3);

    // Intrepreter initialization.
    // parity_wasm::ProgramInstance can be parameterized with a custom User error which could be returned from imported functions
    // parity_wasm::DefaultProgramInstance parametrize ProgramInstance with a pre-defined "DummyUserError"
    let program = parity_wasm::DefaultProgramInstance::with_env_params(
        interpreter::EnvParams {
            total_stack: 128*1024,
            total_memory: 2*1024*1024,
            allow_memory_growth: false,
        }
    ).expect("Program instance to load");

    let module = parity_wasm::deserialize_file(&args[1]).expect("File to be deserialized");

    // Extracts call arguments from command-line arguments
    let execution_params = {
        // Export section has an entry with a func_name with an index inside a module
        let export_section = module.export_section().expect("No export section found");
        // It's a section with function declarations (which are references to the type section entries)
        let function_section = module.function_section().expect("No function section found");
        // Type section stores function types which are referenced by function_section entries
        let type_section = module.type_section().expect("No type section found");

        // A given function name used to find export section entry which contains
        // an `internal` field which points to the index in the function index space
        let found_entry = export_section.entries().iter()
            .find(|entry| func_name == entry.field()).expect(&format!("No export with name {} found", func_name));

        // Function index in the function index space (internally-defined + imported)
        let function_index: usize = match found_entry.internal() {
            &Internal::Function(index) => index as usize,
            _ => panic!("Founded export is not a function"),
        };
        // We need to count import section entries to substract it from
        let import_section_len: usize = match module.import_section() {
            Some(import) =>
                import.entries().iter().filter(|entry| match entry.external() {
                    &External::Function(_) => true,
                    _ => false,
                    }).count(),
            None => 0,
        };

        // Calculates a function index within module's function section
        let function_index_in_section = function_index - import_section_len;

        // Getting a type reference from a function section entry
        let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;

        // Use the reference to get an actual function type
        let function_type: &FunctionType = match &type_section.types()[func_type_ref] {
            &Type::Function(ref func_type) => func_type,
        };

        // Parses arguments and constructs runtime values in correspondence of their types
        let args: Vec<RuntimeValue> = function_type.params().iter().enumerate().map(|(i, value)| match value {
            &ValueType::I32 => RuntimeValue::I32(program_args[i].parse::<i32>().expect(&format!("Can't parse arg #{} as i32", program_args[i]))),
            &ValueType::I64 => RuntimeValue::I64(program_args[i].parse::<i64>().expect(&format!("Can't parse arg #{} as i64", program_args[i]))),
            &ValueType::F32 => RuntimeValue::F32(program_args[i].parse::<f32>().expect(&format!("Can't parse arg #{} as f32", program_args[i]))),
            &ValueType::F64 => RuntimeValue::F64(program_args[i].parse::<f64>().expect(&format!("Can't parse arg #{} as f64", program_args[i]))),
        }).collect();

        interpreter::ExecutionParams::from(args)
    };

    // Intialize deserialized module.
    let module = program.add_module("main", module, None).expect("Failed to initialize module");

    println!("Result: {:?}", module.execute_export(func_name, execution_params).expect(""));
}
<commit_msg>update comments<commit_after>extern crate parity_wasm;

use std::env::args;

use parity_wasm::{interpreter, ModuleInstanceInterface, RuntimeValue};
use parity_wasm::elements::{Internal, External, Type, FunctionType, ValueType};

fn main() {
    let args: Vec<_> = args().collect();
    if args.len() < 3 {
        println!("Usage: {} <wasm file> <exported func> [<arg>...]", args[0]);
        return;
    }
    let func_name = &args[2];
    let (_, program_args) = args.split_at(3);

    // Intrepreter initialization.
    // parity_wasm::ProgramInstance can be parameterized with a custom User error which could be returned from imported functions
    // parity_wasm::DefaultProgramInstance parametrize ProgramInstance with a pre-defined "DummyUserError"
    let program = parity_wasm::DefaultProgramInstance::with_env_params(
        interpreter::EnvParams {
            total_stack: 128*1024,
            total_memory: 2*1024*1024,
            allow_memory_growth: false,
        }
    ).expect("Program instance to load");

    let module = parity_wasm::deserialize_file(&args[1]).expect("File to be deserialized");

    // Extracts call arguments from command-line arguments
    let execution_params = {
        // Export section has an entry with a func_name with an index inside a module
        let export_section = module.export_section().expect("No export section found");
        // It's a section with function declarations (which are references to the type section entries)
        let function_section = module.function_section().expect("No function section found");
        // Type section stores function types which are referenced by function_section entries
        let type_section = module.type_section().expect("No type section found");

        // A given function name used to find export section entry which contains
        // an `internal` field which points to the index in the function index space
        let found_entry = export_section.entries().iter()
            .find(|entry| func_name == entry.field()).expect(&format!("No export with name {} found", func_name));

        // Function index in the function index space (internally-defined + imported)
        let function_index: usize = match found_entry.internal() {
            &Internal::Function(index) => index as usize,
            _ => panic!("Founded export is not a function"),
        };

        // We need to count import section entries (functions only!) to subtract it from function_index
        // and obtain the index within the function section
        let import_section_len: usize = match module.import_section() {
            Some(import) =>
                import.entries().iter().filter(|entry| match entry.external() {
                    &External::Function(_) => true,
                    _ => false,
                    }).count(),
            None => 0,
        };

        // Calculates a function index within module's function section
        let function_index_in_section = function_index - import_section_len;

        // Getting a type reference from a function section entry
        let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;

        // Use the reference to get an actual function type
        let function_type: &FunctionType = match &type_section.types()[func_type_ref] {
            &Type::Function(ref func_type) => func_type,
        };

        // Parses arguments and constructs runtime values in correspondence of their types
        let args: Vec<RuntimeValue> = function_type.params().iter().enumerate().map(|(i, value)| match value {
            &ValueType::I32 => RuntimeValue::I32(program_args[i].parse::<i32>().expect(&format!("Can't parse arg #{} as i32", program_args[i]))),
            &ValueType::I64 => RuntimeValue::I64(program_args[i].parse::<i64>().expect(&format!("Can't parse arg #{} as i64", program_args[i]))),
            &ValueType::F32 => RuntimeValue::F32(program_args[i].parse::<f32>().expect(&format!("Can't parse arg #{} as f32", program_args[i]))),
            &ValueType::F64 => RuntimeValue::F64(program_args[i].parse::<f64>().expect(&format!("Can't parse arg #{} as f64", program_args[i]))),
        }).collect();

        interpreter::ExecutionParams::from(args)
    };

    // Intialize deserialized module.
    let module = program.add_module("main", module, None).expect("Failed to initialize module");

    println!("Result: {:?}", module.execute_export(func_name, execution_params).expect(""));
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate http;
extern crate router;

// To build, $ cargo test
// To use, go to http://127.0.0.1:3000/test

use std::io::net::ip::Ipv4Addr;
use iron::{Server, Iron, Request, Response, Chain, Status, Unwind, FromFn};
use http::status;
use router::{Router, Params};

fn main() {
    let mut server: Server = Iron::new();
    let mut router = Router::new();

    fn handler(req: &mut Request, res: &mut Response) -> Status {
        let ref query = req.alloy.find::<Params>().unwrap().find("query").unwrap();
        let _ = res.serve(status::Ok, query.as_slice());
        Unwind
    }

    // Setup our route.
    router.get("/:query", FromFn::new(handler));

    server.chain.link(router);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

<commit_msg>(fix) Update example for alloy renaming.<commit_after>extern crate iron;
extern crate http;
extern crate router;

// To build, $ cargo test
// To use, go to http://127.0.0.1:3000/test

use std::io::net::ip::Ipv4Addr;
use iron::{Server, Iron, Request, Response, Chain, Status, Unwind, FromFn};
use http::status;
use router::{Router, Params};

fn main() {
    let mut server: Server = Iron::new();
    let mut router = Router::new();

    fn handler(req: &mut Request, res: &mut Response) -> Status {
        let ref query = req.extensions.find::<Params>().unwrap().find("query").unwrap();
        let _ = res.serve(status::Ok, query.as_slice());
        Unwind
    }

    // Setup our route.
    router.get("/:query", FromFn::new(handler));

    server.chain.link(router);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

<|endoftext|>