<commit_before>use raii::Raii;
use {ffi, Handle, Return};
use std::ptr::null_mut;
use std;

/// Implemented for fixed size type those representation is directly compatible with ODBC
pub unsafe trait FixedSizeType: Sized + Default {
    fn c_data_type() -> ffi::SqlCDataType;
}

/// Indicates that a type can be retrieved using `Cursor::get_data`
pub unsafe trait Output: Sized {
    fn get_data(stmt: &mut Raii<ffi::Stmt>,
                col_or_param_num: u16,
                buffer: &mut [u8])
                -> Return<Option<Self>>;
}

unsafe impl FixedSizeType for i16 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_SSHORT
    }
}

unsafe impl FixedSizeType for u16 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_USHORT
    }
}

unsafe impl FixedSizeType for i32 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_SLONG
    }
}

unsafe impl FixedSizeType for u32 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_ULONG
    }
}

unsafe impl FixedSizeType for f32 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_FLOAT
    }
}

unsafe impl FixedSizeType for f64 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_DOUBLE
    }
}

unsafe impl<T> Output for T
    where T: FixedSizeType
{
    fn get_data(stmt: &mut Raii<ffi::Stmt>,
                col_or_param_num: u16,
                _: &mut [u8])
                -> Return<Option<Self>> {
        stmt.get_data_fixed_size(col_or_param_num)
    }
}

unsafe impl Output for String {
    fn get_data(stmt: &mut Raii<ffi::Stmt>,
                col_or_param_num: u16,
                buffer: &mut [u8])
                -> Return<Option<Self>> {
        stmt.get_data_string(col_or_param_num, buffer)
    }
}

impl Raii<ffi::Stmt> {
    fn get_data_fixed_size<T>(&mut self, col_or_param_num: u16) -> Return<Option<T>>
        where T: FixedSizeType
    {
        let mut out = T::default();
        let mut indicator: ffi::SQLLEN = 0;
        unsafe {
            // Get buffer length...
            let result = ffi::SQLGetData(self.handle(),
                                         col_or_param_num,
                                         T::c_data_type(),
                                         &mut out as *mut T as ffi::SQLPOINTER,
                                         std::mem::size_of::<Self>() as ffi::SQLLEN,
                                         &mut indicator as *mut ffi::SQLLEN);
            match result {
                ffi::SQL_SUCCESS => {
                    if indicator == ffi::SQL_NULL_DATA {
                        Return::Success(None)
                    } else {
                        Return::Success(Some(out))
                    }
                }
                ffi::SQL_SUCCESS_WITH_INFO => {
                    if indicator == ffi::SQL_NULL_DATA {
                        Return::Success(None)
                    } else {
                        Return::Success(Some(out))
                    }
                }
                ffi::SQL_ERROR => Return::Error,
                ffi::SQL_NO_DATA => panic!("SQLGetData has already returned the colmun data"),
                r => panic!("unexpected return value from SQLGetData: {:?}", r),
            }
        }
    }

    fn get_data_string(&mut self,
                       col_or_param_num: u16,
                       buffer: &mut [u8])
                       -> Return<Option<String>> {
        if buffer.len() == 0 {
            panic!("buffer length may not be null");
        }
        if buffer.len() > ffi::SQLLEN::max_value() as usize {
            panic!("buffer is larger than {} bytes", ffi::SQLLEN::max_value());
        }

        let mut indicator: ffi::SQLLEN = 0;
        unsafe {
            // Get buffer length...
            let result = ffi::SQLGetData(self.handle(),
                                         col_or_param_num,
                                         ffi::SQL_C_CHAR,
                                         buffer.as_mut_ptr() as ffi::SQLPOINTER,
                                         buffer.len() as ffi::SQLLEN,
                                         &mut indicator as *mut ffi::SQLLEN);
            match result {
                ffi::SQL_SUCCESS => {
                    if indicator == ffi::SQL_NULL_DATA {
                        Return::Success(None)
                    } else {
                        Return::Success(Some(std::str::from_utf8(&buffer[..(indicator as usize)])
                                                 .unwrap()
                                                 .to_owned()))
                    }
                }
                ffi::SQL_SUCCESS_WITH_INFO => {
                    if indicator == ffi::SQL_NO_TOTAL {
                        Return::SuccessWithInfo(None)
                    } else {
                        // Check if string has been truncated. String is also truncated if
                        // indicator is equal to BUF_LENGTH because of terminating nul
                        if indicator >= buffer.len() as ffi::SQLLEN {
                            let extra_space = (indicator as usize + 1) - (buffer.len() - 1);
                            let mut heap_buf = Vec::with_capacity((indicator as usize) + 1);
                            // Copy everything but the terminating zero into the new buffer
                            heap_buf.extend_from_slice(&buffer[..(buffer.len() - 1)]);
                            // increase length
                            heap_buf.extend(std::iter::repeat(0).take(extra_space));
                            // Get remainder of string
                            let ret = ffi::SQLGetData(self.handle(),
                                                      col_or_param_num,
                                                      ffi::SQL_C_CHAR,
                                                      heap_buf.as_mut_slice()[buffer.len() - 1..]
                                                          .as_mut_ptr() as
                                                      ffi::SQLPOINTER,
                                                      extra_space as ffi::SQLLEN,
                                                      null_mut());
                            heap_buf.pop();
                            let value = String::from_utf8(heap_buf).unwrap();
                            match ret {
                                ffi::SQL_SUCCESS => Return::Success(Some(value)),
                                ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(Some(value)),
                                ffi::SQL_ERROR => Return::Error,
                                r => panic!("SQLGetData returned {:?}", r),
                            }
                        } else {
                            // No truncation. Warning may be due to some other issue.
                            Return::SuccessWithInfo(Some(std::str::from_utf8(&buffer[..(indicator as
                                                                                usize)])
                                                                 .unwrap()
                                                                 .to_owned()))
                        }
                    }
                }
                ffi::SQL_ERROR => Return::Error,
                ffi::SQL_NO_DATA => panic!("SQLGetData has already returned the colmun data"),
                r => panic!("unexpected return value from SQLGetData: {:?}", r),
            }
        }
    }
}

<commit_msg>first attempt at get_data for str<commit_after>use raii::Raii;
use {ffi, Handle, Return};
use std::ptr::null_mut;
use std::str::from_utf8;
use std;

/// Implemented for fixed size type those representation is directly compatible with ODBC
pub unsafe trait FixedSizeType: Sized + Default {
    fn c_data_type() -> ffi::SqlCDataType;
}

/// Indicates that a type can be retrieved using `Cursor::get_data`
pub unsafe trait Output: Sized {
    fn get_data<'a>(stmt: &mut Raii<ffi::Stmt>,
                    col_or_param_num: u16,
                    buffer: &'a mut [u8])
                    -> Return<Option<Self>>;
}

unsafe impl FixedSizeType for u8 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_UTINYINT
    }
}

unsafe impl FixedSizeType for i8 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_STINYINT
    }
}

unsafe impl FixedSizeType for i16 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_SSHORT
    }
}

unsafe impl FixedSizeType for u16 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_USHORT
    }
}

unsafe impl FixedSizeType for i32 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_SLONG
    }
}

unsafe impl FixedSizeType for u32 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_ULONG
    }
}

unsafe impl FixedSizeType for f32 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_FLOAT
    }
}

unsafe impl FixedSizeType for f64 {
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_DOUBLE
    }
}

unsafe impl<T> Output for T
    where T: FixedSizeType
{
    fn get_data(stmt: &mut Raii<ffi::Stmt>,
                col_or_param_num: u16,
                _: &mut [u8])
                -> Return<Option<Self>> {
        stmt.get_data_fixed_size(col_or_param_num)
    }
}

unsafe impl Output for String {
    fn get_data(stmt: &mut Raii<ffi::Stmt>,
                col_or_param_num: u16,
                buffer: &mut [u8])
                -> Return<Option<Self>> {
        stmt.get_data_string(col_or_param_num, buffer)
    }
}

impl Raii<ffi::Stmt> {
    fn get_data_fixed_size<T>(&mut self, col_or_param_num: u16) -> Return<Option<T>>
        where T: FixedSizeType
    {
        let mut out = T::default();
        let mut indicator: ffi::SQLLEN = 0;
        unsafe {
            // Get buffer length...
            let result = ffi::SQLGetData(self.handle(),
                                         col_or_param_num,
                                         T::c_data_type(),
                                         &mut out as *mut T as ffi::SQLPOINTER,
                                         std::mem::size_of::<Self>() as ffi::SQLLEN,
                                         &mut indicator as *mut ffi::SQLLEN);
            match result {
                ffi::SQL_SUCCESS => {
                    if indicator == ffi::SQL_NULL_DATA {
                        Return::Success(None)
                    } else {
                        Return::Success(Some(out))
                    }
                }
                ffi::SQL_SUCCESS_WITH_INFO => {
                    if indicator == ffi::SQL_NULL_DATA {
                        Return::Success(None)
                    } else {
                        Return::Success(Some(out))
                    }
                }
                ffi::SQL_ERROR => Return::Error,
                ffi::SQL_NO_DATA => panic!("SQLGetData has already returned the colmun data"),
                r => panic!("unexpected return value from SQLGetData: {:?}", r),
            }
        }
    }

    fn get_data_str<'a>(&mut self,
                        col_or_param: u16,
                        buffer: &'a mut [u8])
                        -> Return<Option<&'a str>> {
        if buffer.len() == 0 {
            panic!("buffer length may not be null");
        }
        if buffer.len() > ffi::SQLLEN::max_value() as usize {
            panic!("buffer is larger than {} bytes", ffi::SQLLEN::max_value());
        }
        let mut indicator: ffi::SQLLEN = 0;
        unsafe {
            // Get buffer length...
            let result = ffi::SQLGetData(self.handle(),
                                         col_or_param,
                                         ffi::SQL_C_CHAR,
                                         buffer.as_mut_ptr() as ffi::SQLPOINTER,
                                         buffer.len() as ffi::SQLLEN,
                                         &mut indicator as *mut ffi::SQLLEN);
            match result {
                ffi::SQL_SUCCESS => {
                    if indicator == ffi::SQL_NULL_DATA {
                        Return::Success(None)
                    } else {
                        Return::Success(Some(from_utf8(&buffer[..(indicator as usize)]).unwrap()))
                    }
                }
                ffi::SQL_SUCCESS_WITH_INFO => {
                    if indicator == ffi::SQL_NULL_DATA {
                        Return::SuccessWithInfo(None)
                    } else {
                        if indicator >= buffer.len() as ffi::SQLLEN {
                            panic!("Buffer is not large enough to hold string")
                        } else {
                            Return::SuccessWithInfo(Some(from_utf8(&buffer[..(indicator as
                                                                       usize)])
                                                                 .unwrap()))
                        }
                    }
                }
                ffi::SQL_ERROR => Return::Error,
                ffi::SQL_NO_DATA => panic!("SQLGetData has already returned the colmun data"),
                r => panic!("unexpected return value from SQLGetData: {:?}", r),
            }
        }
    }

    fn get_data_string(&mut self,
                       col_or_param_num: u16,
                       buffer: &mut [u8])
                       -> Return<Option<String>> {
        if buffer.len() == 0 {
            panic!("buffer length may not be null");
        }
        if buffer.len() > ffi::SQLLEN::max_value() as usize {
            panic!("buffer is larger than {} bytes", ffi::SQLLEN::max_value());
        }

        let mut indicator: ffi::SQLLEN = 0;
        unsafe {
            // Get buffer length...
            let result = ffi::SQLGetData(self.handle(),
                                         col_or_param_num,
                                         ffi::SQL_C_CHAR,
                                         buffer.as_mut_ptr() as ffi::SQLPOINTER,
                                         buffer.len() as ffi::SQLLEN,
                                         &mut indicator as *mut ffi::SQLLEN);
            match result {
                ffi::SQL_SUCCESS => {
                    if indicator == ffi::SQL_NULL_DATA {
                        Return::Success(None)
                    } else {
                        Return::Success(Some(from_utf8(&buffer[..(indicator as usize)])
                                                 .unwrap()
                                                 .to_owned()))
                    }
                }
                ffi::SQL_SUCCESS_WITH_INFO => {
                    if indicator == ffi::SQL_NO_TOTAL {
                        Return::SuccessWithInfo(None)
                    } else {
                        // Check if string has been truncated. String is also truncated if
                        // indicator is equal to BUF_LENGTH because of terminating nul
                        if indicator >= buffer.len() as ffi::SQLLEN {
                            let extra_space = (indicator as usize + 1) - (buffer.len() - 1);
                            let mut heap_buf = Vec::with_capacity((indicator as usize) + 1);
                            // Copy everything but the terminating zero into the new buffer
                            heap_buf.extend_from_slice(&buffer[..(buffer.len() - 1)]);
                            // increase length
                            heap_buf.extend(std::iter::repeat(0).take(extra_space));
                            // Get remainder of string
                            let ret = ffi::SQLGetData(self.handle(),
                                                      col_or_param_num,
                                                      ffi::SQL_C_CHAR,
                                                      heap_buf.as_mut_slice()[buffer.len() - 1..]
                                                          .as_mut_ptr() as
                                                      ffi::SQLPOINTER,
                                                      extra_space as ffi::SQLLEN,
                                                      null_mut());
                            heap_buf.pop();
                            let value = String::from_utf8(heap_buf).unwrap();
                            match ret {
                                ffi::SQL_SUCCESS => Return::Success(Some(value)),
                                ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(Some(value)),
                                ffi::SQL_ERROR => Return::Error,
                                r => panic!("SQLGetData returned {:?}", r),
                            }
                        } else {
                            // No truncation. Warning may be due to some other issue.
                            Return::SuccessWithInfo(Some(from_utf8(&buffer[..(indicator as
                                                                       usize)])
                                                                 .unwrap()
                                                                 .to_owned()))
                        }
                    }
                }
                ffi::SQL_ERROR => Return::Error,
                ffi::SQL_NO_DATA => panic!("SQLGetData has already returned the colmun data"),
                r => panic!("unexpected return value from SQLGetData: {:?}", r),
            }
        }
    }
}

<|endoftext|>


<commit_before><commit_msg>refactoring loop<commit_after><|endoftext|>


<commit_before><commit_msg>add test for better ptr handling in enum niches<commit_after>// A niche-optimized enum where the discriminant is a pointer value -- relies on ptr-to-int casts in
// the niche handling code.
// compile-flags: -Zmiri-disable-stacked-borrows -Zmiri-disable-validation

fn main() {
    let x = 42;
    let val: Option<&i32> = unsafe { std::mem::transmute((&x as *const i32).wrapping_offset(2)) };
    assert!(val.is_some());
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.

enum E = u32;
struct S { a: u8, b: E }
const C: S = S { a: 0xA5, b: E(0xDEADBEEF) };

fn main() {
    assert C.b == 0xDEADBEEF;
}
<commit_msg>pub fn main<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.

enum E = u32;
struct S { a: u8, b: E }
const C: S = S { a: 0xA5, b: E(0xDEADBEEF) };

pub fn main() {
    assert C.b == 0xDEADBEEF;
}
<|endoftext|>


<commit_before><commit_msg>Added `ascii` module to core<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.

//! Operations on ASCII strings and characters.
//!
//! Most string operations in Rust act on UTF-8 strings. However, at times it
//! makes more sense to only consider the ASCII character set for a specific
//! operation.
//!
//! The [`escape_default`] function provides an iterator over the bytes of an
//! escaped version of the character given.
//!
//! [`escape_default`]: fn.escape_default.html

#![stable(feature = "rust1", since = "1.0.0")]

use fmt;
use ops::Range;
use iter::FusedIterator;

/// An iterator over the escaped version of a byte.
///
/// This `struct` is created by the [`escape_default`] function. See its
/// documentation for more.
///
/// [`escape_default`]: fn.escape_default.html
#[unstable(feature = "core_ascii", issue = "46409")]
pub struct EscapeDefault {
    range: Range<usize>,
    data: [u8; 4],
}

/// Returns an iterator that produces an escaped version of a `u8`.
///
/// The default is chosen with a bias toward producing literals that are
/// legal in a variety of languages, including C++11 and similar C-family
/// languages. The exact rules are:
///
/// * Tab is escaped as `\t`.
/// * Carriage return is escaped as `\r`.
/// * Line feed is escaped as `\n`.
/// * Single quote is escaped as `\'`.
/// * Double quote is escaped as `\"`.
/// * Backslash is escaped as `\\`.
/// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
///   inclusive is not escaped.
/// * Any other chars are given hex escapes of the form '\xNN'.
/// * Unicode escapes are never generated by this function.
///
/// # Examples
///
/// ```
/// let escaped = ascii::escape_default(b'0').next().unwrap();
/// assert_eq!(b'0', escaped);
///
/// let mut escaped = ascii::escape_default(b'\t');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b't', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\r');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'r', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\n');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'n', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\'');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'\'', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'"');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'"', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\\');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'\\', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\x9d');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'x', escaped.next().unwrap());
/// assert_eq!(b'9', escaped.next().unwrap());
/// assert_eq!(b'd', escaped.next().unwrap());
/// ```
#[unstable(feature = "core_ascii", issue = "46409")]
pub fn escape_ascii(c: u8) -> EscapeDefault {
    let (data, len) = match c {
        b'\t' => ([b'\\', b't', 0, 0], 2),
        b'\r' => ([b'\\', b'r', 0, 0], 2),
        b'\n' => ([b'\\', b'n', 0, 0], 2),
        b'\\' => ([b'\\', b'\\', 0, 0], 2),
        b'\'' => ([b'\\', b'\'', 0, 0], 2),
        b'"' => ([b'\\', b'"', 0, 0], 2),
        b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1),
        _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
    };

    return EscapeDefault { range: 0..len, data };

    fn hexify(b: u8) -> u8 {
        match b {
            0 ... 9 => b'0' + b,
            _ => b'a' + b - 10,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for EscapeDefault {
    type Item = u8;
    fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
    fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl DoubleEndedIterator for EscapeDefault {
    fn next_back(&mut self) -> Option<u8> {
        self.range.next_back().map(|i| self.data[i])
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ExactSizeIterator for EscapeDefault {}
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EscapeDefault {}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for EscapeDefault {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("EscapeDefault { .. }")
    }
}

#[cfg(test)]
mod tests {
    use char::from_u32;

    #[test]
    fn test_is_ascii() {
        assert!(b"".is_ascii());
        assert!(b"banana\0\x7F".is_ascii());
        assert!(b"banana\0\x7F".iter().all(|b| b.is_ascii()));
        assert!(!b"Vi\xe1\xbb\x87t Nam".is_ascii());
        assert!(!b"Vi\xe1\xbb\x87t Nam".iter().all(|b| b.is_ascii()));
        assert!(!b"\xe1\xbb\x87".iter().any(|b| b.is_ascii()));

        assert!("".is_ascii());
        assert!("banana\0\u{7F}".is_ascii());
        assert!("banana\0\u{7F}".chars().all(|c| c.is_ascii()));
        assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
        assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii()));
    }

    #[test]
    fn test_to_ascii_uppercase() {
        assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL");
        assert_eq!("hıKß".to_ascii_uppercase(), "HıKß");

        for i in 0..501 {
            let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
                        else { i };
            assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(),
                       (from_u32(upper).unwrap()).to_string());
        }
    }

    #[test]
    fn test_to_ascii_lowercase() {
        assert_eq!("url()URL()uRl()Ürl".to_ascii_lowercase(), "url()url()url()Ürl");
        // Dotted capital I, Kelvin sign, Sharp S.
        assert_eq!("HİKß".to_ascii_lowercase(), "hİKß");

        for i in 0..501 {
            let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
                        else { i };
            assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(),
                       (from_u32(lower).unwrap()).to_string());
        }
    }

    #[test]
    fn test_make_ascii_lower_case() {
        macro_rules! test {
            ($from: expr, $to: expr) => {
                {
                    let mut x = $from;
                    x.make_ascii_lowercase();
                    assert_eq!(x, $to);
                }
            }
        }
        test!(b'A', b'a');
        test!(b'a', b'a');
        test!(b'!', b'!');
        test!('A', 'a');
        test!('À', 'À');
        test!('a', 'a');
        test!('!', '!');
        test!(b"H\xc3\x89".to_vec(), b"h\xc3\x89");
        test!("HİKß".to_string(), "hİKß");
    }

    #[test]
    fn test_make_ascii_upper_case() {
        macro_rules! test {
            ($from: expr, $to: expr) => {
                {
                    let mut x = $from;
                    x.make_ascii_uppercase();
                    assert_eq!(x, $to);
                }
            }
        }
        test!(b'a', b'A');
        test!(b'A', b'A');
        test!(b'!', b'!');
        test!('a', 'A');
        test!('à', 'à');
        test!('A', 'A');
        test!('!', '!');
        test!(b"h\xc3\xa9".to_vec(), b"H\xc3\xa9");
        test!("hıKß".to_string(), "HıKß");

        let mut x = "Hello".to_string();
        x[..3].make_ascii_uppercase();  // Test IndexMut on String.
        assert_eq!(x, "HELlo")
    }

    #[test]
    fn test_eq_ignore_ascii_case() {
        assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));
        assert!(!"Ürl".eq_ignore_ascii_case("ürl"));
        // Dotted capital I, Kelvin sign, Sharp S.
        assert!("HİKß".eq_ignore_ascii_case("hİKß"));
        assert!(!"İ".eq_ignore_ascii_case("i"));
        assert!(!"K".eq_ignore_ascii_case("k"));
        assert!(!"ß".eq_ignore_ascii_case("s"));

        for i in 0..501 {
            let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
                        else { i };
            assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case(
                    &from_u32(lower).unwrap().to_string()));
        }
    }

    #[test]
    fn inference_works() {
        let x = "a".to_string();
        x.eq_ignore_ascii_case("A");
    }

    // Shorthands used by the is_ascii_* tests.
    macro_rules! assert_all {
        ($what:ident, $($str:tt),+) => {{
            $(
                for b in $str.chars() {
                    if !b.$what() {
                        panic!("expected {}({}) but it isn't",
                               stringify!($what), b);
                    }
                }
                for b in $str.as_bytes().iter() {
                    if !b.$what() {
                        panic!("expected {}(0x{:02x})) but it isn't",
                               stringify!($what), b);
                    }
                }
                assert!($str.$what());
                assert!($str.as_bytes().$what());
            )+
        }};
        ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+))
    }
    macro_rules! assert_none {
        ($what:ident, $($str:tt),+) => {{
            $(
                for b in $str.chars() {
                    if b.$what() {
                        panic!("expected not-{}({}) but it is",
                               stringify!($what), b);
                    }
                }
                for b in $str.as_bytes().iter() {
                    if b.$what() {
                        panic!("expected not-{}(0x{:02x})) but it is",
                               stringify!($what), b);
                    }
                }
            )*
        }};
        ($what:ident, $($str:tt),+,) => (assert_none!($what,$($str),+))
    }

    #[test]
    fn test_is_ascii_alphabetic() {
        assert_all!(is_ascii_alphabetic,
            "",
            "abcdefghijklmnopqrstuvwxyz",
            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
        );
        assert_none!(is_ascii_alphabetic,
            "0123456789",
            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
            " \t\n\x0c\r",
            "\x00\x01\x02\x03\x04\x05\x06\x07",
            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
            "\x10\x11\x12\x13\x14\x15\x16\x17",
            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
            "\x7f",
        );
    }

    #[test]
    fn test_is_ascii_uppercase() {
        assert_all!(is_ascii_uppercase,
            "",
            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
        );
        assert_none!(is_ascii_uppercase,
            "abcdefghijklmnopqrstuvwxyz",
            "0123456789",
            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
            " \t\n\x0c\r",
            "\x00\x01\x02\x03\x04\x05\x06\x07",
            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
            "\x10\x11\x12\x13\x14\x15\x16\x17",
            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
            "\x7f",
        );
    }

    #[test]
    fn test_is_ascii_lowercase() {
        assert_all!(is_ascii_lowercase,
            "abcdefghijklmnopqrstuvwxyz",
        );
        assert_none!(is_ascii_lowercase,
            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
            "0123456789",
            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
            " \t\n\x0c\r",
            "\x00\x01\x02\x03\x04\x05\x06\x07",
            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
            "\x10\x11\x12\x13\x14\x15\x16\x17",
            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
            "\x7f",
        );
    }

    #[test]
    fn test_is_ascii_alphanumeric() {
        assert_all!(is_ascii_alphanumeric,
            "",
            "abcdefghijklmnopqrstuvwxyz",
            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
            "0123456789",
        );
        assert_none!(is_ascii_alphanumeric,
            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
            " \t\n\x0c\r",
            "\x00\x01\x02\x03\x04\x05\x06\x07",
            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
            "\x10\x11\x12\x13\x14\x15\x16\x17",
            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
            "\x7f",
        );
    }

    #[test]
    fn test_is_ascii_digit() {
        assert_all!(is_ascii_digit,
            "",
            "0123456789",
        );
        assert_none!(is_ascii_digit,
            "abcdefghijklmnopqrstuvwxyz",
            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
            " \t\n\x0c\r",
            "\x00\x01\x02\x03\x04\x05\x06\x07",
            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
            "\x10\x11\x12\x13\x14\x15\x16\x17",
            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
            "\x7f",
        );
    }

    #[test]
    fn test_is_ascii_hexdigit() {
        assert_all!(is_ascii_hexdigit,
            "",
            "0123456789",
            "abcdefABCDEF",
        );
        assert_none!(is_ascii_hexdigit,
            "ghijklmnopqrstuvwxyz",
            "GHIJKLMNOQPRSTUVWXYZ",
            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
            " \t\n\x0c\r",
            "\x00\x01\x02\x03\x04\x05\x06\x07",
            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
            "\x10\x11\x12\x13\x14\x15\x16\x17",
            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
            "\x7f",
        );
    }

    #[test]
    fn test_is_ascii_punctuation() {
        assert_all!(is_ascii_punctuation,
            "",
            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
        );
        assert_none!(is_ascii_punctuation,
            "abcdefghijklmnopqrstuvwxyz",
            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
            "0123456789",
            " \t\n\x0c\r",
            "\x00\x01\x02\x03\x04\x05\x06\x07",
            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
            "\x10\x11\x12\x13\x14\x15\x16\x17",
            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
            "\x7f",
        );
    }

    #[test]
    fn test_is_ascii_graphic() {
        assert_all!(is_ascii_graphic,
            "",
            "abcdefghijklmnopqrstuvwxyz",
            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
            "0123456789",
            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
        );
        assert_none!(is_ascii_graphic,
            " \t\n\x0c\r",
            "\x00\x01\x02\x03\x04\x05\x06\x07",
            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
            "\x10\x11\x12\x13\x14\x15\x16\x17",
            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
            "\x7f",
        );
    }

    #[test]
    fn test_is_ascii_whitespace() {
        assert_all!(is_ascii_whitespace,
            "",
            " \t\n\x0c\r",
        );
        assert_none!(is_ascii_whitespace,
            "abcdefghijklmnopqrstuvwxyz",
            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
            "0123456789",
            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
            "\x00\x01\x02\x03\x04\x05\x06\x07",
            "\x08\x0b\x0e\x0f",
            "\x10\x11\x12\x13\x14\x15\x16\x17",
            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
            "\x7f",
        );
    }

    #[test]
    fn test_is_ascii_control() {
        assert_all!(is_ascii_control,
            "",
            "\x00\x01\x02\x03\x04\x05\x06\x07",
            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
            "\x10\x11\x12\x13\x14\x15\x16\x17",
            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
            "\x7f",
        );
        assert_none!(is_ascii_control,
            "abcdefghijklmnopqrstuvwxyz",
            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
            "0123456789",
            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
            " ",
        );
    }
}
<|endoftext|>


<commit_before><commit_msg>add paramfile module to commit<commit_after>use std::error::Error;
use std::fs::File;
use std::io::Read;

use yaml::{Yaml, YamlLoader};
use parameter::{ParameterValue, ParameterValues};

#[derive(Debug)]
/// ParameterFile struct
pub struct ParameterFile {
  /// filename
  pub filename: String,
  /// document string
  pub doc_str: String,
  /// parameters allocated from this file
  pub parameters: ParameterValues,
}

fn parse_document(doc_str: &String, parameter_values: &mut ParameterValues) {
    let docs = YamlLoader::load_from_str(doc_str).unwrap();
    for doc in &docs {
        let primary_key = "";
        let param_values = parse_yaml(doc, primary_key);
        parameter_values.extend(param_values);
      }
}

fn parse_yaml(doc: &Yaml, primary_key: &str) -> ParameterValues {
    let mut param_values = ParameterValues::new();
    match doc {
        &Yaml::Hash(ref h) => {
            for (key,value) in h {
                let combined_key = primary_key.to_string() + key.as_str().unwrap();
                match value {
                    &Yaml::String(ref s) => {
                        let pv = ParameterValue::Plain(s.to_string());
                        param_values.insert(combined_key,pv);
                    },
                    &Yaml::Integer(ref i) => {
                        let pv = ParameterValue::Plain(i.to_string());
                        param_values.insert(combined_key,pv);
                    },
                    &Yaml::Real(ref r) => {
                        let pv = ParameterValue::Plain(r.to_string());
                        param_values.insert(combined_key,pv);
                    },
                    _ => {
                        // Value type not supported
                        // Array, Alias and None
                    }
                }
            }
        },
        &Yaml::String(ref s) => {
            let pv = ParameterValue::Plain(s.to_string());
            param_values.insert(primary_key.to_string(),pv);
        },
        _ => {
            // Key type not supported
        }
    }
    param_values
}

impl ParameterFile {
    /// Create a new parameterfile object, composed of a filename
    /// and the parsed parameters
    pub fn from_file(filename: &str) -> Result<Self, String> {
        let mut parameter_values = ParameterValues::new();
        let mut fh = File::open(filename).map_err(|err| err.description().to_owned()).unwrap();
        let mut contents = String::new();
        fh.read_to_string(&mut contents).map_err(|err| err.description().to_owned())?;
        parse_document(&contents, &mut parameter_values);

        Ok(ParameterFile {
            filename: String::from(filename),
            doc_str: String::from(contents),
            parameters: parameter_values,
        })
    }

    /// Create a new parameterfile object from a String representing a yaml document
    pub fn from_str(doc_str: String) -> Result<Self, String> {
        let mut parameter_values = ParameterValues::new();
        parse_document(&doc_str, &mut parameter_values);

        Ok(ParameterFile {
            filename: String::from(""),
            doc_str: String::from(doc_str),
            parameters: parameter_values,
        })
    }
}
<|endoftext|>


<commit_before><commit_msg>Introduce mocks<commit_after>extern crate indy_crypto;
extern crate rmp_serde;
extern crate serde;
extern crate serde_json;
extern crate time;

use std::cmp::Eq;
use std::collections::{HashMap, HashSet};
use std::hash::{Hash, Hasher};
use super::zmq;
use errors::common::CommonError;
use utils::crypto::verkey_builder::build_full_verkey;

use self::indy_crypto::bls;

use services::ledger::merkletree::merkletree::MerkleTree;
use self::indy_crypto::utils::json::{JsonDecodable, JsonEncodable};

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct NodeData {
    pub alias: String,
    pub client_ip: Option<String>,
    #[serde(deserialize_with = "string_or_number")]
    #[serde(default)]
    pub client_port: Option<u64>,
    pub node_ip: Option<String>,
    #[serde(deserialize_with = "string_or_number")]
    #[serde(default)]
    pub node_port: Option<u64>,
    pub services: Option<Vec<String>>,
    pub blskey: Option<String>
}

fn string_or_number<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
    where D: serde::Deserializer<'de>
{
    let deser_res: Result<serde_json::Value, _> = serde::Deserialize::deserialize(deserializer);
    match deser_res {
        Ok(serde_json::Value::String(s)) => match s.parse::<u64>() {
            Ok(num) => Ok(Some(num)),
            Err(err) => Err(serde::de::Error::custom(format!("Invalid Node transaction: {:?}", err)))
        },
        Ok(serde_json::Value::Number(n)) => match n.as_u64() {
            Some(num) => Ok(Some(num)),
            None => Err(serde::de::Error::custom(format!("Invalid Node transaction")))
        },
        Ok(serde_json::Value::Null) => Ok(None),
        _ => Err(serde::de::Error::custom(format!("Invalid Node transaction"))),
    }
}

#[derive(Serialize, Deserialize)]
#[serde(untagged)]
pub enum NodeTransaction {
    NodeTransactionV0(NodeTransactionV0),
    NodeTransactionV1(NodeTransactionV1)
}

impl JsonEncodable for NodeTransaction {}

impl<'a> JsonDecodable<'a> for NodeTransaction {}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct NodeTransactionV0 {
    pub data: NodeData,
    pub dest: String,
    pub identifier: String,
    #[serde(rename = "txnId")]
    pub txn_id: Option<String>,
    pub verkey: Option<String>,
    #[serde(rename = "type")]
    pub txn_type: String
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct NodeTransactionV1 {
    pub txn: Txn,
    pub txn_metadata: Metadata,
    pub req_signature: ReqSignature,
    pub ver: String
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct Txn {
    #[serde(rename = "type")]
    pub txn_type: String,
    #[serde(rename = "protocolVersion")]
    pub protocol_version: Option<i32>,
    pub data: TxnData,
    pub metadata: TxnMetadata
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Metadata {
    pub creation_time: Option<u64>,
    pub seq_no: Option<i32>,
    pub txn_id: Option<String>
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ReqSignature {
    #[serde(rename = "type")]
    pub type_: Option<String>,
    pub values: Option<Vec<ReqSignatureValue>>
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct ReqSignatureValue {
    pub from: Option<String>,
    pub value: Option<String>
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct TxnData {
    pub data: NodeData,
    pub dest: String,
    pub verkey: Option<String>
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct TxnMetadata {
    pub req_id: Option<i64>,
    pub from: String
}

impl From<NodeTransaction> for NodeTransactionV1 {
    fn from(node_txn: NodeTransaction) -> Self {
        match node_txn {
            NodeTransaction::NodeTransactionV1(n_txn) => n_txn,
            NodeTransaction::NodeTransactionV0(n_txn) => {
                let txn = Txn {
                    txn_type: n_txn.txn_type,
                    protocol_version: None,
                    data: TxnData {
                        data: n_txn.data,
                        dest: n_txn.dest,
                        verkey: n_txn.verkey
                    },
                    metadata: TxnMetadata {
                        req_id: None,
                        from: n_txn.identifier
                    },
                };
                NodeTransactionV1 {
                    txn,
                    txn_metadata: Metadata {
                        seq_no: None,
                        txn_id: n_txn.txn_id,
                        creation_time: None
                    },
                    req_signature: ReqSignature {
                        type_: None,
                        values: None
                    },
                    ver: "1".to_string(),
                }
            }
        }
    }
}

impl NodeTransactionV1 {
    pub fn update(&mut self, other: &mut NodeTransactionV1) -> Result<(), CommonError> {
        assert_eq!(self.txn.data.dest, other.txn.data.dest);
        assert_eq!(self.txn.data.data.alias, other.txn.data.data.alias);

        if let Some(ref mut client_ip) = other.txn.data.data.client_ip {
            self.txn.data.data.client_ip = Some(client_ip.to_owned());
        }
        if let Some(ref mut client_port) = other.txn.data.data.client_port {
            self.txn.data.data.client_port = Some(client_port.to_owned());
        }
        if let Some(ref mut node_ip) = other.txn.data.data.node_ip {
            self.txn.data.data.node_ip = Some(node_ip.to_owned());
        }
        if let Some(ref mut node_port) = other.txn.data.data.node_port {
            self.txn.data.data.node_port = Some(node_port.to_owned());
        }
        if let Some(ref mut blskey) = other.txn.data.data.blskey {
            self.txn.data.data.blskey = Some(blskey.to_owned());
        }
        if let Some(ref mut services) = other.txn.data.data.services {
            self.txn.data.data.services = Some(services.to_owned());
        }
        if other.txn.data.verkey.is_some() {
            self.txn.data.verkey = Some(build_full_verkey(&self.txn.data.dest, other.txn.data.verkey.as_ref().map(String::as_str))?);
        }
        Ok(())
    }
}

#[allow(non_snake_case)]
#[derive(Serialize, Deserialize, Debug)]
pub struct LedgerStatus {
    pub txnSeqNo: usize,
    pub merkleRoot: String,
    pub ledgerId: u8,
    pub ppSeqNo: Option<String>,
    pub viewNo: Option<String>,
}

#[allow(non_snake_case)]
#[derive(Serialize, Deserialize, Debug)]
pub struct ConsistencyProof {
    //TODO almost all fields Option<> or find better approach
    pub seqNoEnd: usize,
    pub seqNoStart: usize,
    pub ledgerId: usize,
    pub hashes: Vec<String>,
    pub oldMerkleRoot: String,
    pub newMerkleRoot: String,
}

#[allow(non_snake_case)]
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
pub struct CatchupReq {
    pub ledgerId: usize,
    pub seqNoStart: usize,
    pub seqNoEnd: usize,
    pub catchupTill: usize,
}

impl<'a> JsonDecodable<'a> for CatchupReq {}

#[allow(non_snake_case)]
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct CatchupRep {
    pub ledgerId: usize,
    pub consProof: Vec<String>,
    pub txns: HashMap<String, serde_json::Value>,
}

impl CatchupRep {
    pub fn min_tx(&self) -> Result<usize, CommonError> {
        let mut min = None;
        for (k, _) in self.txns.iter() {
            let val = k.parse::<usize>()
                .map_err(|err| CommonError::InvalidStructure(format!("{:?}", err)))?;
            match min {
                None => min = Some(val),
                Some(m) => if val < m { min = Some(val) }
            }
        }
        min.ok_or(CommonError::InvalidStructure(format!("Empty Map")))
    }
}

#[derive(Serialize, Debug, Deserialize)]
#[serde(untagged)]
pub enum Reply {
    ReplyV0(ReplyV0),
    ReplyV1(ReplyV1)
}

impl Reply {
    pub fn req_id(self) -> u64 {
        match self {
            Reply::ReplyV0(reply) => reply.result.req_id,
            Reply::ReplyV1(reply) => reply.result.txn.metadata.req_id
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ReplyV0 {
    pub result: ResponseMetadata
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ReplyV1 {
    pub result: ReplyResultV1
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ReplyResultV1 {
    pub txn: ReplyTxnV1
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ReplyTxnV1 {
    pub metadata: ResponseMetadata
}

#[derive(Serialize, Debug, Deserialize)]
#[serde(untagged)]
pub enum Response {
    ResponseV0(ResponseV0),
    ResponseV1(ResponseV1)
}

impl Response {
    pub fn req_id(&self) -> u64 {
        match self {
            &Response::ResponseV0(ref res) => res.req_id,
            &Response::ResponseV1(ref res) => res.metadata.req_id
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ResponseV0 {
    pub req_id: u64
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ResponseV1 {
    pub metadata: ResponseMetadata
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ResponseMetadata {
    pub req_id: u64
}

#[derive(Serialize, Debug, Deserialize)]
#[serde(untagged)]
pub enum PoolLedgerTxn {
    PoolLedgerTxnV0(PoolLedgerTxnV0),
    PoolLedgerTxnV1(PoolLedgerTxnV1)
}

#[derive(Serialize, Deserialize, Debug)]
pub struct PoolLedgerTxnV0 {
    pub txn: Response,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct PoolLedgerTxnV1 {
    pub txn: PoolLedgerTxnDataV1,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct PoolLedgerTxnDataV1 {
    pub txn: Response,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct SimpleRequest {
    pub req_id: u64,
}

impl JsonEncodable for SimpleRequest {}

impl<'a> JsonDecodable<'a> for SimpleRequest {}

#[serde(tag = "op")]
#[derive(Serialize, Deserialize, Debug)]
pub enum Message {
    #[serde(rename = "CONSISTENCY_PROOF")]
    ConsistencyProof(ConsistencyProof),
    #[serde(rename = "LEDGER_STATUS")]
    LedgerStatus(LedgerStatus),
    #[serde(rename = "CATCHUP_REQ")]
    CatchupReq(CatchupReq),
    #[serde(rename = "CATCHUP_REP")]
    CatchupRep(CatchupRep),
    #[serde(rename = "REQACK")]
    ReqACK(Response),
    #[serde(rename = "REQNACK")]
    ReqNACK(Response),
    #[serde(rename = "REPLY")]
    Reply(Reply),
    #[serde(rename = "REJECT")]
    Reject(Response),
    #[serde(rename = "POOL_LEDGER_TXNS")]
    PoolLedgerTxns(PoolLedgerTxn),
    Ping,
    Pong,
}

impl Message {
    pub fn from_raw_str(str: &str) -> Result<Message, CommonError> {
        match str {
            "po" => Ok(Message::Pong),
            "pi" => Ok(Message::Ping),
            _ => Message::from_json(str).map_err(CommonError::from),
        }
    }
}

impl JsonEncodable for Message {}

impl<'a> JsonDecodable<'a> for Message {}

#[derive(Serialize, Deserialize)]
pub struct PoolConfig {
    pub genesis_txn: String
}

impl JsonEncodable for PoolConfig {}

impl<'a> JsonDecodable<'a> for PoolConfig {}

impl PoolConfig {
    pub fn default_for_name(name: &str) -> PoolConfig {
        let mut txn = name.to_string();
        txn += ".txn";
        PoolConfig { genesis_txn: txn }
    }
}

pub struct RemoteNode {
    pub name: String,
    pub public_key: Vec<u8>,
    pub zaddr: String,
    pub zsock: Option<zmq::Socket>,
    pub is_blacklisted: bool,
    pub blskey: Option<bls::VerKey>
}

pub struct CatchUpProcess {
    pub merkle_tree: MerkleTree,
    pub pending_reps: Vec<(CatchupRep, usize)>,
    pub resp_not_received_node_idx: HashSet<usize>,
}

pub trait MinValue {
    fn get_min_index(&self) -> Result<usize, CommonError>;
}

impl MinValue for Vec<(CatchupRep, usize)> {
    fn get_min_index(&self) -> Result<usize, CommonError> {
        let mut res = None;
        for (index, &(ref catchup_rep, _)) in self.iter().enumerate() {
            match res {
                None => { res = Some((catchup_rep, index)); }
                Some((min_rep, _)) => if catchup_rep.min_tx()? < min_rep.min_tx()? {
                    res = Some((catchup_rep, index));
                }
            }
        }
        Ok(res.ok_or(CommonError::InvalidStructure("Element not Found".to_string()))?.1)
    }
}

#[derive(Debug)]
pub struct HashableValue {
    pub inner: serde_json::Value
}

impl Eq for HashableValue {}

impl Hash for HashableValue {
    fn hash<H: Hasher>(&self, state: &mut H) {
        serde_json::to_string(&self.inner).unwrap().hash(state); //TODO
    }
}

impl PartialEq for HashableValue {
    fn eq(&self, other: &HashableValue) -> bool {
        self.inner.eq(&other.inner)
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct ResendableRequest {
    pub request: String,
    pub start_node: usize,
    pub next_node: usize,
    pub next_try_send_time: Option<time::Tm>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CommandProcess {
    pub nack_cnt: usize,
    pub replies: HashMap<HashableValue, usize>,
    pub accum_replies : Option<HashableValue>,
    pub parent_cmd_ids: Vec<i32>,
    pub resendable_request: Option<ResendableRequest>,
    pub full_cmd_timeout: Option<time::Tm>,
}

#[derive(Debug, PartialEq, Eq)]
pub enum ZMQLoopAction {
    RequestToSend(RequestToSend),
    MessageToProcess(MessageToProcess),
    Terminate(i32),
    Refresh(i32),
    Timeout,
}

#[derive(Debug, PartialEq, Eq)]
pub struct RequestToSend {
    pub request: String,
    pub id: i32,
}

#[derive(Debug, PartialEq, Eq)]
pub struct MessageToProcess {
    pub message: String,
    pub node_idx: usize,
}<|endoftext|>


<commit_before>use std::cell::{Cell, RefCell};
use std::io::{self, ErrorKind};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::sync::mpsc;

use mio;
use slab::Slab;
use futures::{Future, Tokens, Wake};

pub type Waiter = Arc<Wake>;
pub type Source = Arc<mio::Evented + Send + Sync>;

static NEXT_LOOP_ID: AtomicUsize = ATOMIC_USIZE_INIT;
scoped_thread_local!(static CURRENT_LOOP: Loop);

const SLAB_CAPACITY: usize = 1024 * 64;

pub struct Loop {
    id: usize,
    active: Cell<bool>,
    io: RefCell<mio::Poll>,
    tx: mio::channel::Sender<Message>,
    rx: mio::channel::Receiver<Message>,
    dispatch: RefCell<Slab<Scheduled, usize>>,
}

/// Handle to an event loop, used to construct I/O objects, send messages, and
/// otherwise interact indirectly with the event loop itself.
///
/// Handles can be cloned, and when cloned they will still refer to the
/// same underlying event loop.
#[derive(Clone)]
pub struct LoopHandle {
    id: usize,
    tx: mio::channel::Sender<Message>,
}

#[derive(Copy, Clone)]
pub enum Direction {
    Read,
    Write,
}

struct Scheduled {
    source: Source,
    reader: Option<Waiter>,
    writer: Option<Waiter>,
}

impl Scheduled {
    fn waiter_for(&mut self, dir: Direction) -> &mut Option<Waiter> {
        match dir {
            Direction::Read => &mut self.reader,
            Direction::Write => &mut self.writer,
        }
    }

    fn event_set(&self) -> mio::EventSet {
        let mut set = mio::EventSet::none();
        if self.reader.is_some() {
            set = set | mio::EventSet::readable()
        }
        if self.writer.is_some() {
            set = set | mio::EventSet::writable()
        }
        set
    }
}

enum Message {
    AddSource(Source, Arc<AtomicUsize>, Waiter),
    DropSource(usize),
    Schedule(usize, Direction, Waiter),
    Deschedule(usize, Direction),
    Shutdown,
}

fn register(poll: &mut mio::Poll, token: usize, sched: &Scheduled) {
    // TODO: handle error
    poll.register(&*sched.source,
                  mio::Token(token),
                  mio::EventSet::none(),
                  mio::PollOpt::level())
        .unwrap();
}

fn reregister(poll: &mut mio::Poll, token: usize, sched: &Scheduled) {
    // TODO: handle error
    poll.reregister(&*sched.source,
                    mio::Token(token),
                    sched.event_set(),
                    mio::PollOpt::edge() | mio::PollOpt::oneshot())
        .unwrap();
}

fn deregister(poll: &mut mio::Poll, sched: &Scheduled) {
    // TODO: handle error
    poll.deregister(&*sched.source).unwrap();
}

impl Loop {
    pub fn new() -> io::Result<Loop> {
        let (tx, rx) = mio::channel::from_std_channel(mpsc::channel());
        let io = try!(mio::Poll::new());
        try!(io.register(&rx,
                         mio::Token(0),
                         mio::EventSet::readable(),
                         mio::PollOpt::edge()));
        Ok(Loop {
            id: NEXT_LOOP_ID.fetch_add(1, Ordering::Relaxed),
            active: Cell::new(true),
            io: RefCell::new(io),
            tx: tx,
            rx: rx,
            dispatch: RefCell::new(Slab::new_starting_at(1, SLAB_CAPACITY)),
        })
    }

    pub fn handle(&self) -> LoopHandle {
        LoopHandle {
            id: self.id,
            tx: self.tx.clone(),
        }
    }

    pub fn run<F: Future>(self, f: F) -> Result<F::Item, F::Error> {
        let (tx_res, rx_res) = mpsc::channel();
        let handle = self.handle();
        f.then(move |res| {
            handle.shutdown();
            tx_res.send(res)
        }).forget();

        while self.active.get() {
            let amt;
            // On Linux, Poll::poll is epoll_wait, which may return EINTR if a
            // ptracer attaches. This retry loop prevents crashing when
            // attaching strace, or similar.
            loop {
                match self.io.borrow_mut().poll(None) {
                    Ok(a) => {
                        amt = a;
                        break;
                    }
                    Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
                    err @ Err(_) => {
                        err.unwrap();
                    }
                }
            }

            // TODO: coalesce token sets for a given Wake?
            for i in 0..amt {
                let event = self.io.borrow_mut().events().get(i).unwrap();
                let token = event.token().as_usize();
                if token == 0 {
                    self.consume_queue();
                } else {
                    let mut reader = None;
                    let mut writer = None;

                    if let Some(sched) = self.dispatch.borrow_mut().get_mut(token) {
                        if event.kind().is_readable() {
                            reader = sched.reader.take();
                        }

                        if event.kind().is_writable() {
                            writer = sched.writer.take();
                        }
                    }

                    CURRENT_LOOP.set(&self, || {
                        if let Some(reader_wake) = reader.take() {
                            reader_wake.wake(&Tokens::from_usize(token));
                        }
                        if let Some(writer_wake) = writer.take() {
                            writer_wake.wake(&Tokens::from_usize(token));
                        }
                    });

                    // For now, always reregister, to deal with the fact that
                    // combined oneshot + read|write requires rearming even if
                    // only one side fired.
                    //
                    // TODO: optimize this
                    if let Some(sched) = self.dispatch.borrow().get(token) {
                        reregister(&mut self.io.borrow_mut(), token, &sched);
                    }
                }
            }
        }

        rx_res.recv().unwrap()
    }

    fn add_source(&self, source: Source) -> usize {
        let sched = Scheduled {
            source: source,
            reader: None,
            writer: None,
        };
        let mut dispatch = self.dispatch.borrow_mut();
        // TODO: handle out of space
        let entry = dispatch.vacant_entry().unwrap();
        register(&mut self.io.borrow_mut(), entry.index(), &sched);
        entry.insert(sched).index()
    }

    fn drop_source(&self, token: usize) {
        let sched = self.dispatch.borrow_mut().remove(token).unwrap();
        deregister(&mut self.io.borrow_mut(), &sched);
    }

    fn schedule(&self, token: usize, dir: Direction, wake: Waiter) {
        let mut dispatch = self.dispatch.borrow_mut();
        let sched = dispatch.get_mut(token).unwrap();
        *sched.waiter_for(dir) = Some(wake);
        reregister(&mut self.io.borrow_mut(), token, sched);
    }

    fn deschedule(&self, token: usize, dir: Direction) {
        let mut dispatch = self.dispatch.borrow_mut();
        let sched = dispatch.get_mut(token).unwrap();
        *sched.waiter_for(dir) = None;
        reregister(&mut self.io.borrow_mut(), token, sched);
    }

    fn consume_queue(&self) {
        while let Ok(msg) = self.rx.try_recv() {
            self.notify(msg);
        }
    }

    fn notify(&self, msg: Message) {
        match msg {
            Message::AddSource(source, id, wake) => {
                let tok = self.add_source(source);
                id.store(tok, Ordering::Relaxed);
                wake.wake(&Tokens::from_usize(ADD_SOURCE_TOKEN));
            }
            Message::DropSource(tok) => self.drop_source(tok),
            Message::Schedule(tok, dir, wake) => self.schedule(tok, dir, wake),
            Message::Deschedule(tok, dir) => self.deschedule(tok, dir),
            Message::Shutdown => self.active.set(false),
        }
    }
}

impl LoopHandle {
    fn send(&self, msg: Message) {
        let mut msg_dance = Some(msg);

        if CURRENT_LOOP.is_set() {
            CURRENT_LOOP.with(|lp| {
                if lp.id == self.id {
                    // Need to execute all existing requests first, to ensure
                    // that our message is processed "in order"
                    lp.consume_queue();
                    lp.notify(msg_dance.take().unwrap());
                }
            })
        }

        if let Some(msg) = msg_dance.take() {
            self.tx
                .send(msg)
                .map_err(|_| ())
                .expect("failed to send register message") // todo: handle failure
        }
    }

    /// Add a new source to an event loop, returning a future which will resolve
    /// to the token that can be used to identify this source.
    ///
    /// When a new I/O object is created it needs to be communicated to the
    /// event loop to ensure that it's registered and ready to receive
    /// notifications. The event loop with then respond with a unique token that
    /// this handle can be identified with (the resolved value of the returned
    /// future).
    ///
    /// This token is then passed in turn to each of the methods below to
    /// interact with notifications on the I/O object itself.
    pub fn add_source(&self, source: Source) -> AddSource {
        AddSource {
            loop_handle: self.clone(),
            source: Some(source),
            id: Arc::new(AtomicUsize::new(0)),
            scheduled: false,
        }
    }

    fn add_source_(&self, source: Source, id: Arc<AtomicUsize>, wake: Waiter) {
        self.send(Message::AddSource(source, id, wake));
    }

    /// Begin listening for events on an event loop.
    ///
    /// Once an I/O object has been registered with the event loop through the
    /// `add_source` method, this method can be used with the assigned token to
    /// begin awaiting notifications.
    ///
    /// The `dir` argument indicates how the I/O object is expected to be
    /// awaited on (either readable or writable) and the `wake` callback will be
    /// invoked. Note that one the `wake` callback is invoked once it will not
    /// be invoked again, it must be re-`schedule`d to continue receiving
    /// notifications.
    pub fn schedule(&self, tok: usize, dir: Direction, wake: Arc<Wake>) {
        self.send(Message::Schedule(tok, dir, wake));
    }

    /// Stop listening for events on an event loop.
    ///
    /// Once a callback has been scheduled with the `schedule` method, it can be
    /// unregistered from the event loop with this method. This method does not
    /// guarantee that the callback will not be invoked if it hasn't already,
    /// but a best effort will be made to ensure it is not called.
    pub fn deschedule(&self, tok: usize, dir: Direction) {
        self.send(Message::Deschedule(tok, dir));
    }

    /// Unregister all information associated with a token on an event loop,
    /// deallocating all internal resources assigned to the given token.
    ///
    /// This method should be called whenever a source of events is being
    /// destroyed. This will ensure that the event loop can reuse `tok` for
    /// another I/O object if necessary and also remove it from any poll
    /// notifications and callbacks.
    ///
    /// Note that wake callbacks may still be invoked after this method is
    /// called as it may take some time for the message to drop a source to
    /// reach the event loop. Despite this fact, this method will attempt to
    /// ensure that the callbacks are **not** invoked, so pending scheduled
    /// callbacks cannot be relied upon to get called.
    pub fn drop_source(&self, tok: usize) {
        self.send(Message::DropSource(tok));
    }

    pub fn shutdown(&self) {
        self.send(Message::Shutdown);
    }
}

const ADD_SOURCE_TOKEN: usize = 0;

/// A future which will resolve a unique `tok` token for an I/O object.
///
/// Created through the `LoopHandle::add_source` method, this future can also
/// resolve to an error if there's an issue communicating with the event loop.
pub struct AddSource {
    loop_handle: LoopHandle,
    source: Option<Source>,
    id: Arc<AtomicUsize>,
    scheduled: bool,
}

impl Future for AddSource {
    type Item = usize;
    type Error = io::Error; // TODO: integrate channel error?

    fn poll(&mut self, tokens: &Tokens) -> Option<Result<usize, io::Error>> {
        if self.scheduled {
            if tokens.may_contain(&Tokens::from_usize(ADD_SOURCE_TOKEN)) {
                let id = self.id.load(Ordering::Relaxed);
                if id != 0 {
                    return Some(Ok(id))
                }
            }
        } else {
            if CURRENT_LOOP.is_set() {
                let res = CURRENT_LOOP.with(|lp| {
                    if lp.id == self.loop_handle.id {
                        Some(lp.add_source(self.source.take().unwrap()))
                    } else {
                        None
                    }
                });
                if let Some(id) = res {
                    return Some(Ok(id));
                }
            }
        }

        None
    }

    fn schedule(&mut self, wake: Arc<Wake>) {
        if self.scheduled { return; }
        self.scheduled = true;
        self.loop_handle.add_source_(self.source.take().unwrap(), self.id.clone(), wake);
    }
}
<commit_msg>s/Waiter/Arc<Wake>/<commit_after>use std::cell::{Cell, RefCell};
use std::io::{self, ErrorKind};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::sync::mpsc;

use mio;
use slab::Slab;
use futures::{Future, Tokens, Wake};

pub type Source = Arc<mio::Evented + Send + Sync>;

static NEXT_LOOP_ID: AtomicUsize = ATOMIC_USIZE_INIT;
scoped_thread_local!(static CURRENT_LOOP: Loop);

const SLAB_CAPACITY: usize = 1024 * 64;

pub struct Loop {
    id: usize,
    active: Cell<bool>,
    io: RefCell<mio::Poll>,
    tx: mio::channel::Sender<Message>,
    rx: mio::channel::Receiver<Message>,
    dispatch: RefCell<Slab<Scheduled, usize>>,
}

/// Handle to an event loop, used to construct I/O objects, send messages, and
/// otherwise interact indirectly with the event loop itself.
///
/// Handles can be cloned, and when cloned they will still refer to the
/// same underlying event loop.
#[derive(Clone)]
pub struct LoopHandle {
    id: usize,
    tx: mio::channel::Sender<Message>,
}

#[derive(Copy, Clone)]
pub enum Direction {
    Read,
    Write,
}

struct Scheduled {
    source: Source,
    reader: Option<Arc<Wake>>,
    writer: Option<Arc<Wake>>,
}

impl Scheduled {
    fn waiter_for(&mut self, dir: Direction) -> &mut Option<Arc<Wake>> {
        match dir {
            Direction::Read => &mut self.reader,
            Direction::Write => &mut self.writer,
        }
    }

    fn event_set(&self) -> mio::EventSet {
        let mut set = mio::EventSet::none();
        if self.reader.is_some() {
            set = set | mio::EventSet::readable()
        }
        if self.writer.is_some() {
            set = set | mio::EventSet::writable()
        }
        set
    }
}

enum Message {
    AddSource(Source, Arc<AtomicUsize>, Arc<Wake>),
    DropSource(usize),
    Schedule(usize, Direction, Arc<Wake>),
    Deschedule(usize, Direction),
    Shutdown,
}

fn register(poll: &mut mio::Poll, token: usize, sched: &Scheduled) {
    // TODO: handle error
    poll.register(&*sched.source,
                  mio::Token(token),
                  mio::EventSet::none(),
                  mio::PollOpt::level())
        .unwrap();
}

fn reregister(poll: &mut mio::Poll, token: usize, sched: &Scheduled) {
    // TODO: handle error
    poll.reregister(&*sched.source,
                    mio::Token(token),
                    sched.event_set(),
                    mio::PollOpt::edge() | mio::PollOpt::oneshot())
        .unwrap();
}

fn deregister(poll: &mut mio::Poll, sched: &Scheduled) {
    // TODO: handle error
    poll.deregister(&*sched.source).unwrap();
}

impl Loop {
    pub fn new() -> io::Result<Loop> {
        let (tx, rx) = mio::channel::from_std_channel(mpsc::channel());
        let io = try!(mio::Poll::new());
        try!(io.register(&rx,
                         mio::Token(0),
                         mio::EventSet::readable(),
                         mio::PollOpt::edge()));
        Ok(Loop {
            id: NEXT_LOOP_ID.fetch_add(1, Ordering::Relaxed),
            active: Cell::new(true),
            io: RefCell::new(io),
            tx: tx,
            rx: rx,
            dispatch: RefCell::new(Slab::new_starting_at(1, SLAB_CAPACITY)),
        })
    }

    pub fn handle(&self) -> LoopHandle {
        LoopHandle {
            id: self.id,
            tx: self.tx.clone(),
        }
    }

    pub fn run<F: Future>(self, f: F) -> Result<F::Item, F::Error> {
        let (tx_res, rx_res) = mpsc::channel();
        let handle = self.handle();
        f.then(move |res| {
            handle.shutdown();
            tx_res.send(res)
        }).forget();

        while self.active.get() {
            let amt;
            // On Linux, Poll::poll is epoll_wait, which may return EINTR if a
            // ptracer attaches. This retry loop prevents crashing when
            // attaching strace, or similar.
            loop {
                match self.io.borrow_mut().poll(None) {
                    Ok(a) => {
                        amt = a;
                        break;
                    }
                    Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
                    err @ Err(_) => {
                        err.unwrap();
                    }
                }
            }

            // TODO: coalesce token sets for a given Wake?
            for i in 0..amt {
                let event = self.io.borrow_mut().events().get(i).unwrap();
                let token = event.token().as_usize();
                if token == 0 {
                    self.consume_queue();
                } else {
                    let mut reader = None;
                    let mut writer = None;

                    if let Some(sched) = self.dispatch.borrow_mut().get_mut(token) {
                        if event.kind().is_readable() {
                            reader = sched.reader.take();
                        }

                        if event.kind().is_writable() {
                            writer = sched.writer.take();
                        }
                    }

                    CURRENT_LOOP.set(&self, || {
                        if let Some(reader_wake) = reader.take() {
                            reader_wake.wake(&Tokens::from_usize(token));
                        }
                        if let Some(writer_wake) = writer.take() {
                            writer_wake.wake(&Tokens::from_usize(token));
                        }
                    });

                    // For now, always reregister, to deal with the fact that
                    // combined oneshot + read|write requires rearming even if
                    // only one side fired.
                    //
                    // TODO: optimize this
                    if let Some(sched) = self.dispatch.borrow().get(token) {
                        reregister(&mut self.io.borrow_mut(), token, &sched);
                    }
                }
            }
        }

        rx_res.recv().unwrap()
    }

    fn add_source(&self, source: Source) -> usize {
        let sched = Scheduled {
            source: source,
            reader: None,
            writer: None,
        };
        let mut dispatch = self.dispatch.borrow_mut();
        // TODO: handle out of space
        let entry = dispatch.vacant_entry().unwrap();
        register(&mut self.io.borrow_mut(), entry.index(), &sched);
        entry.insert(sched).index()
    }

    fn drop_source(&self, token: usize) {
        let sched = self.dispatch.borrow_mut().remove(token).unwrap();
        deregister(&mut self.io.borrow_mut(), &sched);
    }

    fn schedule(&self, token: usize, dir: Direction, wake: Arc<Wake>) {
        let mut dispatch = self.dispatch.borrow_mut();
        let sched = dispatch.get_mut(token).unwrap();
        *sched.waiter_for(dir) = Some(wake);
        reregister(&mut self.io.borrow_mut(), token, sched);
    }

    fn deschedule(&self, token: usize, dir: Direction) {
        let mut dispatch = self.dispatch.borrow_mut();
        let sched = dispatch.get_mut(token).unwrap();
        *sched.waiter_for(dir) = None;
        reregister(&mut self.io.borrow_mut(), token, sched);
    }

    fn consume_queue(&self) {
        while let Ok(msg) = self.rx.try_recv() {
            self.notify(msg);
        }
    }

    fn notify(&self, msg: Message) {
        match msg {
            Message::AddSource(source, id, wake) => {
                let tok = self.add_source(source);
                id.store(tok, Ordering::Relaxed);
                wake.wake(&Tokens::from_usize(ADD_SOURCE_TOKEN));
            }
            Message::DropSource(tok) => self.drop_source(tok),
            Message::Schedule(tok, dir, wake) => self.schedule(tok, dir, wake),
            Message::Deschedule(tok, dir) => self.deschedule(tok, dir),
            Message::Shutdown => self.active.set(false),
        }
    }
}

impl LoopHandle {
    fn send(&self, msg: Message) {
        let mut msg_dance = Some(msg);

        if CURRENT_LOOP.is_set() {
            CURRENT_LOOP.with(|lp| {
                if lp.id == self.id {
                    // Need to execute all existing requests first, to ensure
                    // that our message is processed "in order"
                    lp.consume_queue();
                    lp.notify(msg_dance.take().unwrap());
                }
            })
        }

        if let Some(msg) = msg_dance.take() {
            self.tx
                .send(msg)
                .map_err(|_| ())
                .expect("failed to send register message") // todo: handle failure
        }
    }

    /// Add a new source to an event loop, returning a future which will resolve
    /// to the token that can be used to identify this source.
    ///
    /// When a new I/O object is created it needs to be communicated to the
    /// event loop to ensure that it's registered and ready to receive
    /// notifications. The event loop with then respond with a unique token that
    /// this handle can be identified with (the resolved value of the returned
    /// future).
    ///
    /// This token is then passed in turn to each of the methods below to
    /// interact with notifications on the I/O object itself.
    pub fn add_source(&self, source: Source) -> AddSource {
        AddSource {
            loop_handle: self.clone(),
            source: Some(source),
            id: Arc::new(AtomicUsize::new(0)),
            scheduled: false,
        }
    }

    fn add_source_(&self, source: Source, id: Arc<AtomicUsize>, wake: Arc<Wake>) {
        self.send(Message::AddSource(source, id, wake));
    }

    /// Begin listening for events on an event loop.
    ///
    /// Once an I/O object has been registered with the event loop through the
    /// `add_source` method, this method can be used with the assigned token to
    /// begin awaiting notifications.
    ///
    /// The `dir` argument indicates how the I/O object is expected to be
    /// awaited on (either readable or writable) and the `wake` callback will be
    /// invoked. Note that one the `wake` callback is invoked once it will not
    /// be invoked again, it must be re-`schedule`d to continue receiving
    /// notifications.
    pub fn schedule(&self, tok: usize, dir: Direction, wake: Arc<Wake>) {
        self.send(Message::Schedule(tok, dir, wake));
    }

    /// Stop listening for events on an event loop.
    ///
    /// Once a callback has been scheduled with the `schedule` method, it can be
    /// unregistered from the event loop with this method. This method does not
    /// guarantee that the callback will not be invoked if it hasn't already,
    /// but a best effort will be made to ensure it is not called.
    pub fn deschedule(&self, tok: usize, dir: Direction) {
        self.send(Message::Deschedule(tok, dir));
    }

    /// Unregister all information associated with a token on an event loop,
    /// deallocating all internal resources assigned to the given token.
    ///
    /// This method should be called whenever a source of events is being
    /// destroyed. This will ensure that the event loop can reuse `tok` for
    /// another I/O object if necessary and also remove it from any poll
    /// notifications and callbacks.
    ///
    /// Note that wake callbacks may still be invoked after this method is
    /// called as it may take some time for the message to drop a source to
    /// reach the event loop. Despite this fact, this method will attempt to
    /// ensure that the callbacks are **not** invoked, so pending scheduled
    /// callbacks cannot be relied upon to get called.
    pub fn drop_source(&self, tok: usize) {
        self.send(Message::DropSource(tok));
    }

    pub fn shutdown(&self) {
        self.send(Message::Shutdown);
    }
}

const ADD_SOURCE_TOKEN: usize = 0;

/// A future which will resolve a unique `tok` token for an I/O object.
///
/// Created through the `LoopHandle::add_source` method, this future can also
/// resolve to an error if there's an issue communicating with the event loop.
pub struct AddSource {
    loop_handle: LoopHandle,
    source: Option<Source>,
    id: Arc<AtomicUsize>,
    scheduled: bool,
}

impl Future for AddSource {
    type Item = usize;
    type Error = io::Error; // TODO: integrate channel error?

    fn poll(&mut self, tokens: &Tokens) -> Option<Result<usize, io::Error>> {
        if self.scheduled {
            if tokens.may_contain(&Tokens::from_usize(ADD_SOURCE_TOKEN)) {
                let id = self.id.load(Ordering::Relaxed);
                if id != 0 {
                    return Some(Ok(id))
                }
            }
        } else {
            if CURRENT_LOOP.is_set() {
                let res = CURRENT_LOOP.with(|lp| {
                    if lp.id == self.loop_handle.id {
                        Some(lp.add_source(self.source.take().unwrap()))
                    } else {
                        None
                    }
                });
                if let Some(id) = res {
                    return Some(Ok(id));
                }
            }
        }

        None
    }

    fn schedule(&mut self, wake: Arc<Wake>) {
        if self.scheduled { return; }
        self.scheduled = true;
        self.loop_handle.add_source_(self.source.take().unwrap(), self.id.clone(), wake);
    }
}
<|endoftext|>


<commit_before><commit_msg>Add rust code for prime-factors<commit_after>#[inline]
fn is_prime(n: u64) -> bool {
    if n <= 1 {
        return false;
    }

    if n <= 3 {
        return true;
    }

    if n % 2 == 0 || n % 3 == 0 {
        return false;
    }

    let mut i = 5;
    while i * i <= n {
        if n % i == 0 || n % (i + 2) == 0 {
            return false;
        }

        i += 6;
    }

    true
}

pub fn factors(number: u64) -> Vec<u64> {
    let mut p = 2;
    let mut v = number;
    let mut result = Vec::new();

    while p <= v {
        if !is_prime(p) || v % p != 0 {
            p += 1;
            continue;
        }

        v /= p;

        result.push(p);
    }

    result
}
<|endoftext|>


<commit_before><commit_msg>add rust folder and helloWorld file<commit_after><|endoftext|>


<commit_before>extern crate orbital;

use orbital::{BmpFile, Color, EventOption, Window};

use std::fs::File;
use std::io::Read;
use std::process::Command;
use std::thread;

use package::Package;

pub mod package;

fn draw(window: &mut Window, packages: &Vec<Box<Package>>, shutdown: &BmpFile, mouse_x: i32, mouse_y: i32){
    window.set(Color::rgba(0, 0, 0, 128));

    let mut x = 0;
    for package in packages.iter() {
        if package.icon.has_data() {
            let y = window.height() as isize - package.icon.height() as isize;

            if mouse_y >= y as i32 && mouse_x >= x && mouse_x < x + package.icon.width() as i32 {
                window.rect(x as i32, y as i32,
                                  package.icon.width() as u32, package.icon.height() as u32,
                                  Color::rgba(128, 128, 128, 128));

                /*
                window.rect(x as i32, y as i32 - 16,
                    package.name.len() as u32 * 8, 16,
                    Color::rgba(0, 0, 0, 128));

                let mut c_x = x;
                for c in package.name.chars() {
                    window.char(c_x as i32, y as i32 - 16,
                              c,
                              Color::rgb(255, 255, 255),
                              self.font.as_ptr() as usize);
                    c_x += 8;
                }
                */
            }

            window.image(x as i32, y as i32,
                        package.icon.width() as u32,
                        package.icon.height() as u32,
                        &package.icon);
            x = x + package.icon.width() as i32;
        }
    }

    if shutdown.has_data() {
        x = window.width() as i32 - shutdown.width() as i32;
        let y = window.height() as isize - shutdown.height() as isize;

        if mouse_y >= y as i32 && mouse_x >= x &&
           mouse_x < x + shutdown.width() as i32 {
            window.rect(x as i32, y as i32,
                              shutdown.width() as u32, shutdown.height() as u32,
                              Color::rgba(128, 128, 128, 128));
        }

        window.image(x as i32, y as i32,
                        shutdown.width() as u32, shutdown.height() as u32,
                        &shutdown);
        x = x + shutdown.width() as i32;
    }

    window.sync();
}

fn main() {
    let mut packages: Vec<Box<Package>> = Vec::new();

    //TODO: Use a directory walk
    match File::open("file:/apps/") {
        Ok(mut file) => {
            let mut string = String::new();
            if let Ok(_) = file.read_to_string(&mut string) {
                for folder in string.lines() {
                    if folder.ends_with('/') {
                        packages.push(Package::from_path(&("file:/apps/".to_string() + &folder)));
                    }
                }
            }
        }
        Err(err) => println!("Failed to open apps: {}", err),
    }
    /*
        for package in packages.iter() {
            let mut accepted = false;
            for accept in package.accepts.iter() {
                if (accept.starts_with('*') &&
                    path.ends_with(&accept.get_slice(Some(1), None))) ||
                   (accept.ends_with('*') &&
                    path.starts_with(&accept.get_slice(None, Some(accept.len() - 1)))) {
                    accepted = true;
                    break;
                }
            }
            if accepted {
                if Command::new(&package.binary).arg(&path).spawn_scheme().is_none() {
                    println!("{}: Failed to launch", package.binary);
                }
                break;
            }
        }
    */

    let shutdown = BmpFile::from_path("file:/ui/actions/system-shutdown.bmp");
    if ! shutdown.has_data() {
        println!("Failed to read shutdown icon");
    }

    let mut window = Window::new(0, 568, 800, 32, "Launcher").unwrap();

    draw(&mut window, &packages, &shutdown, -1, -1);
    'running: loop {
        for event in window.events() {
            println!("{:?}", event.to_option());
            match event.to_option() {
                EventOption::Mouse(mouse_event) => {
                    draw(&mut window, &packages, &shutdown, mouse_event.x, mouse_event.y);

                    if mouse_event.left_button {
                        let mut x = 0;
                        for package in packages.iter() {
                            if package.icon.has_data() {
                                if mouse_event.x >= x && mouse_event.x < x + package.icon.width() as i32 {
                                    if let Err(err) = Command::new(&package.binary).spawn() {
                                        println!("{}: Failed to launch: {}", package.binary, err);
                                    }
                                }
                                x = x + package.icon.width() as i32;
                            }
                        }

                        if shutdown.has_data() {
                            x = window.width() as i32 - shutdown.width() as i32;
                            let y = window.height() as i32 - shutdown.height() as i32;
                            if mouse_event.y >= y && mouse_event.x >= x &&
                               mouse_event.x < x + shutdown.width() as i32 {
                                   File::create("acpi:off");
                            }
                        }
                    }
                },
                EventOption::Quit(_) => break 'running,
                _ => ()
            }
        }

        thread::yield_now();
    }
}
<commit_msg>Do not log events in launcher<commit_after>extern crate orbital;

use orbital::{BmpFile, Color, EventOption, Window};

use std::fs::File;
use std::io::Read;
use std::process::Command;
use std::thread;

use package::Package;

pub mod package;

fn draw(window: &mut Window, packages: &Vec<Box<Package>>, shutdown: &BmpFile, mouse_x: i32, mouse_y: i32){
    window.set(Color::rgba(0, 0, 0, 128));

    let mut x = 0;
    for package in packages.iter() {
        if package.icon.has_data() {
            let y = window.height() as isize - package.icon.height() as isize;

            if mouse_y >= y as i32 && mouse_x >= x && mouse_x < x + package.icon.width() as i32 {
                window.rect(x as i32, y as i32,
                                  package.icon.width() as u32, package.icon.height() as u32,
                                  Color::rgba(128, 128, 128, 128));

                /*
                window.rect(x as i32, y as i32 - 16,
                    package.name.len() as u32 * 8, 16,
                    Color::rgba(0, 0, 0, 128));

                let mut c_x = x;
                for c in package.name.chars() {
                    window.char(c_x as i32, y as i32 - 16,
                              c,
                              Color::rgb(255, 255, 255),
                              self.font.as_ptr() as usize);
                    c_x += 8;
                }
                */
            }

            window.image(x as i32, y as i32,
                        package.icon.width() as u32,
                        package.icon.height() as u32,
                        &package.icon);
            x = x + package.icon.width() as i32;
        }
    }

    if shutdown.has_data() {
        x = window.width() as i32 - shutdown.width() as i32;
        let y = window.height() as isize - shutdown.height() as isize;

        if mouse_y >= y as i32 && mouse_x >= x &&
           mouse_x < x + shutdown.width() as i32 {
            window.rect(x as i32, y as i32,
                              shutdown.width() as u32, shutdown.height() as u32,
                              Color::rgba(128, 128, 128, 128));
        }

        window.image(x as i32, y as i32,
                        shutdown.width() as u32, shutdown.height() as u32,
                        &shutdown);
        x = x + shutdown.width() as i32;
    }

    window.sync();
}

fn main() {
    let mut packages: Vec<Box<Package>> = Vec::new();

    //TODO: Use a directory walk
    match File::open("file:/apps/") {
        Ok(mut file) => {
            let mut string = String::new();
            if let Ok(_) = file.read_to_string(&mut string) {
                for folder in string.lines() {
                    if folder.ends_with('/') {
                        packages.push(Package::from_path(&("file:/apps/".to_string() + &folder)));
                    }
                }
            }
        }
        Err(err) => println!("Failed to open apps: {}", err),
    }
    /*
        for package in packages.iter() {
            let mut accepted = false;
            for accept in package.accepts.iter() {
                if (accept.starts_with('*') &&
                    path.ends_with(&accept.get_slice(Some(1), None))) ||
                   (accept.ends_with('*') &&
                    path.starts_with(&accept.get_slice(None, Some(accept.len() - 1)))) {
                    accepted = true;
                    break;
                }
            }
            if accepted {
                if Command::new(&package.binary).arg(&path).spawn_scheme().is_none() {
                    println!("{}: Failed to launch", package.binary);
                }
                break;
            }
        }
    */

    let shutdown = BmpFile::from_path("file:/ui/actions/system-shutdown.bmp");
    if ! shutdown.has_data() {
        println!("Failed to read shutdown icon");
    }

    let mut window = Window::new(0, 568, 800, 32, "Launcher").unwrap();

    draw(&mut window, &packages, &shutdown, -1, -1);
    'running: loop {
        for event in window.events() {
            match event.to_option() {
                EventOption::Mouse(mouse_event) => {
                    draw(&mut window, &packages, &shutdown, mouse_event.x, mouse_event.y);

                    if mouse_event.left_button {
                        let mut x = 0;
                        for package in packages.iter() {
                            if package.icon.has_data() {
                                if mouse_event.x >= x && mouse_event.x < x + package.icon.width() as i32 {
                                    if let Err(err) = Command::new(&package.binary).spawn() {
                                        println!("{}: Failed to launch: {}", package.binary, err);
                                    }
                                }
                                x = x + package.icon.width() as i32;
                            }
                        }

                        if shutdown.has_data() {
                            x = window.width() as i32 - shutdown.width() as i32;
                            let y = window.height() as i32 - shutdown.height() as i32;
                            if mouse_event.y >= y && mouse_event.x >= x &&
                               mouse_event.x < x + shutdown.width() as i32 {
                                   File::create("acpi:off");
                            }
                        }
                    }
                },
                EventOption::Quit(_) => break 'running,
                _ => ()
            }
        }

        thread::yield_now();
    }
}
<|endoftext|>