<commit_before>// Copyright 2015 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.

//! Parsing of GCC-style Language-Specific Data Area (LSDA)
//! For details see:
//!   http://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html
//!   http://mentorembedded.github.io/cxx-abi/exceptions.pdf
//!   http://www.airs.com/blog/archives/460
//!   http://www.airs.com/blog/archives/464
//!
//! A reference implementation may be found in the GCC source tree
//! (<root>/libgcc/unwind-c.c as of this writing)

#![allow(non_upper_case_globals)]
#![allow(unused)]

use dwarf::DwarfReader;
use core::mem;

pub const DW_EH_PE_omit: u8 = 0xFF;
pub const DW_EH_PE_absptr: u8 = 0x00;

pub const DW_EH_PE_uleb128: u8 = 0x01;
pub const DW_EH_PE_udata2: u8 = 0x02;
pub const DW_EH_PE_udata4: u8 = 0x03;
pub const DW_EH_PE_udata8: u8 = 0x04;
pub const DW_EH_PE_sleb128: u8 = 0x09;
pub const DW_EH_PE_sdata2: u8 = 0x0A;
pub const DW_EH_PE_sdata4: u8 = 0x0B;
pub const DW_EH_PE_sdata8: u8 = 0x0C;

pub const DW_EH_PE_pcrel: u8 = 0x10;
pub const DW_EH_PE_textrel: u8 = 0x20;
pub const DW_EH_PE_datarel: u8 = 0x30;
pub const DW_EH_PE_funcrel: u8 = 0x40;
pub const DW_EH_PE_aligned: u8 = 0x50;

pub const DW_EH_PE_indirect: u8 = 0x80;

#[derive(Copy, Clone)]
pub struct EHContext<'a> {
    pub ip: usize, // Current instruction pointer
    pub func_start: usize, // Address of the current function
    pub get_text_start: &'a Fn() -> usize, // Get address of the code section
    pub get_data_start: &'a Fn() -> usize, // Get address of the data section
}

pub enum EHAction {
    None,
    Cleanup(usize),
    Catch(usize),
    Terminate,
}

pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm"));

pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction {
    if lsda.is_null() {
        return EHAction::None;
    }

    let func_start = context.func_start;
    let mut reader = DwarfReader::new(lsda);

    let start_encoding = reader.read::<u8>();
    // base address for landing pad offsets
    let lpad_base = if start_encoding != DW_EH_PE_omit {
        read_encoded_pointer(&mut reader, context, start_encoding)
    } else {
        func_start
    };

    let ttype_encoding = reader.read::<u8>();
    if ttype_encoding != DW_EH_PE_omit {
        // Rust doesn't analyze exception types, so we don't care about the type table
        reader.read_uleb128();
    }

    let call_site_encoding = reader.read::<u8>();
    let call_site_table_length = reader.read_uleb128();
    let action_table = reader.ptr.offset(call_site_table_length as isize);
    let ip = context.ip;

    if !USING_SJLJ_EXCEPTIONS {
        while reader.ptr < action_table {
            let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding);
            let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding);
            let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding);
            let cs_action = reader.read_uleb128();
            // Callsite table is sorted by cs_start, so if we've passed the ip, we
            // may stop searching.
            if ip < func_start + cs_start {
                break;
            }
            if ip < func_start + cs_start + cs_len {
                if cs_lpad == 0 {
                    return EHAction::None;
                } else {
                    let lpad = lpad_base + cs_lpad;
                    return interpret_cs_action(cs_action, lpad);
                }
            }
        }
        // Ip is not present in the table.  This should not hapen... but it does: issie #35011.
        // So rather than returning EHAction::Terminate, we do this.
        EHAction::None
    } else {
        // SjLj version:
        // The "IP" is an index into the call-site table, with two exceptions:
        // -1 means 'no-action', and 0 means 'terminate'.
        match ip as isize {
           -1 => return EHAction::None,
            0 => return EHAction::Terminate,
            _ => (),
        }
        let mut idx = ip;
        loop {
            let cs_lpad = reader.read_uleb128();
            let cs_action = reader.read_uleb128();
            idx -= 1;
            if idx == 0 {
                // Can never have null landing pad for sjlj -- that would have
                // been indicated by a -1 call site index.
                let lpad = (cs_lpad + 1) as usize;
                return interpret_cs_action(cs_action, lpad);
            }
        }
    }
}

fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction {
    if cs_action == 0 {
        EHAction::Cleanup(lpad)
    } else {
        EHAction::Catch(lpad)
    }
}

#[inline]
fn round_up(unrounded: usize, align: usize) -> usize {
    assert!(align.is_power_of_two());
    (unrounded + align - 1) & !(align - 1)
}

unsafe fn read_encoded_pointer(reader: &mut DwarfReader,
                               context: &EHContext,
                               encoding: u8)
                               -> usize {
    assert!(encoding != DW_EH_PE_omit);

    // DW_EH_PE_aligned implies it's an absolute pointer value
    if encoding == DW_EH_PE_aligned {
        reader.ptr = round_up(reader.ptr as usize, mem::size_of::<usize>()) as *const u8;
        return reader.read::<usize>();
    }

    let mut result = match encoding & 0x0F {
        DW_EH_PE_absptr => reader.read::<usize>(),
        DW_EH_PE_uleb128 => reader.read_uleb128() as usize,
        DW_EH_PE_udata2 => reader.read::<u16>() as usize,
        DW_EH_PE_udata4 => reader.read::<u32>() as usize,
        DW_EH_PE_udata8 => reader.read::<u64>() as usize,
        DW_EH_PE_sleb128 => reader.read_sleb128() as usize,
        DW_EH_PE_sdata2 => reader.read::<i16>() as usize,
        DW_EH_PE_sdata4 => reader.read::<i32>() as usize,
        DW_EH_PE_sdata8 => reader.read::<i64>() as usize,
        _ => panic!(),
    };

    result += match encoding & 0x70 {
        DW_EH_PE_absptr => 0,
        // relative to address of the encoded value, despite the name
        DW_EH_PE_pcrel => reader.ptr as usize,
        DW_EH_PE_funcrel => {
            assert!(context.func_start != 0);
            context.func_start
        }
        DW_EH_PE_textrel => {
            (*context.get_text_start)()
        }
        DW_EH_PE_datarel => {
            (*context.get_data_start)()
        }
        _ => panic!(),
    };

    if encoding & DW_EH_PE_indirect != 0 {
        result = *(result as *const usize);
    }

    result
}
<commit_msg>Rollup merge of #35066 - vadimcn:fix-typos, r=apasel422<commit_after>// Copyright 2015 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.

//! Parsing of GCC-style Language-Specific Data Area (LSDA)
//! For details see:
//!   http://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html
//!   http://mentorembedded.github.io/cxx-abi/exceptions.pdf
//!   http://www.airs.com/blog/archives/460
//!   http://www.airs.com/blog/archives/464
//!
//! A reference implementation may be found in the GCC source tree
//! (<root>/libgcc/unwind-c.c as of this writing)

#![allow(non_upper_case_globals)]
#![allow(unused)]

use dwarf::DwarfReader;
use core::mem;

pub const DW_EH_PE_omit: u8 = 0xFF;
pub const DW_EH_PE_absptr: u8 = 0x00;

pub const DW_EH_PE_uleb128: u8 = 0x01;
pub const DW_EH_PE_udata2: u8 = 0x02;
pub const DW_EH_PE_udata4: u8 = 0x03;
pub const DW_EH_PE_udata8: u8 = 0x04;
pub const DW_EH_PE_sleb128: u8 = 0x09;
pub const DW_EH_PE_sdata2: u8 = 0x0A;
pub const DW_EH_PE_sdata4: u8 = 0x0B;
pub const DW_EH_PE_sdata8: u8 = 0x0C;

pub const DW_EH_PE_pcrel: u8 = 0x10;
pub const DW_EH_PE_textrel: u8 = 0x20;
pub const DW_EH_PE_datarel: u8 = 0x30;
pub const DW_EH_PE_funcrel: u8 = 0x40;
pub const DW_EH_PE_aligned: u8 = 0x50;

pub const DW_EH_PE_indirect: u8 = 0x80;

#[derive(Copy, Clone)]
pub struct EHContext<'a> {
    pub ip: usize, // Current instruction pointer
    pub func_start: usize, // Address of the current function
    pub get_text_start: &'a Fn() -> usize, // Get address of the code section
    pub get_data_start: &'a Fn() -> usize, // Get address of the data section
}

pub enum EHAction {
    None,
    Cleanup(usize),
    Catch(usize),
    Terminate,
}

pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm"));

pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction {
    if lsda.is_null() {
        return EHAction::None;
    }

    let func_start = context.func_start;
    let mut reader = DwarfReader::new(lsda);

    let start_encoding = reader.read::<u8>();
    // base address for landing pad offsets
    let lpad_base = if start_encoding != DW_EH_PE_omit {
        read_encoded_pointer(&mut reader, context, start_encoding)
    } else {
        func_start
    };

    let ttype_encoding = reader.read::<u8>();
    if ttype_encoding != DW_EH_PE_omit {
        // Rust doesn't analyze exception types, so we don't care about the type table
        reader.read_uleb128();
    }

    let call_site_encoding = reader.read::<u8>();
    let call_site_table_length = reader.read_uleb128();
    let action_table = reader.ptr.offset(call_site_table_length as isize);
    let ip = context.ip;

    if !USING_SJLJ_EXCEPTIONS {
        while reader.ptr < action_table {
            let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding);
            let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding);
            let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding);
            let cs_action = reader.read_uleb128();
            // Callsite table is sorted by cs_start, so if we've passed the ip, we
            // may stop searching.
            if ip < func_start + cs_start {
                break;
            }
            if ip < func_start + cs_start + cs_len {
                if cs_lpad == 0 {
                    return EHAction::None;
                } else {
                    let lpad = lpad_base + cs_lpad;
                    return interpret_cs_action(cs_action, lpad);
                }
            }
        }
        // Ip is not present in the table.  This should not happen... but it does: issue #35011.
        // So rather than returning EHAction::Terminate, we do this.
        EHAction::None
    } else {
        // SjLj version:
        // The "IP" is an index into the call-site table, with two exceptions:
        // -1 means 'no-action', and 0 means 'terminate'.
        match ip as isize {
           -1 => return EHAction::None,
            0 => return EHAction::Terminate,
            _ => (),
        }
        let mut idx = ip;
        loop {
            let cs_lpad = reader.read_uleb128();
            let cs_action = reader.read_uleb128();
            idx -= 1;
            if idx == 0 {
                // Can never have null landing pad for sjlj -- that would have
                // been indicated by a -1 call site index.
                let lpad = (cs_lpad + 1) as usize;
                return interpret_cs_action(cs_action, lpad);
            }
        }
    }
}

fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction {
    if cs_action == 0 {
        EHAction::Cleanup(lpad)
    } else {
        EHAction::Catch(lpad)
    }
}

#[inline]
fn round_up(unrounded: usize, align: usize) -> usize {
    assert!(align.is_power_of_two());
    (unrounded + align - 1) & !(align - 1)
}

unsafe fn read_encoded_pointer(reader: &mut DwarfReader,
                               context: &EHContext,
                               encoding: u8)
                               -> usize {
    assert!(encoding != DW_EH_PE_omit);

    // DW_EH_PE_aligned implies it's an absolute pointer value
    if encoding == DW_EH_PE_aligned {
        reader.ptr = round_up(reader.ptr as usize, mem::size_of::<usize>()) as *const u8;
        return reader.read::<usize>();
    }

    let mut result = match encoding & 0x0F {
        DW_EH_PE_absptr => reader.read::<usize>(),
        DW_EH_PE_uleb128 => reader.read_uleb128() as usize,
        DW_EH_PE_udata2 => reader.read::<u16>() as usize,
        DW_EH_PE_udata4 => reader.read::<u32>() as usize,
        DW_EH_PE_udata8 => reader.read::<u64>() as usize,
        DW_EH_PE_sleb128 => reader.read_sleb128() as usize,
        DW_EH_PE_sdata2 => reader.read::<i16>() as usize,
        DW_EH_PE_sdata4 => reader.read::<i32>() as usize,
        DW_EH_PE_sdata8 => reader.read::<i64>() as usize,
        _ => panic!(),
    };

    result += match encoding & 0x70 {
        DW_EH_PE_absptr => 0,
        // relative to address of the encoded value, despite the name
        DW_EH_PE_pcrel => reader.ptr as usize,
        DW_EH_PE_funcrel => {
            assert!(context.func_start != 0);
            context.func_start
        }
        DW_EH_PE_textrel => {
            (*context.get_text_start)()
        }
        DW_EH_PE_datarel => {
            (*context.get_data_start)()
        }
        _ => panic!(),
    };

    if encoding & DW_EH_PE_indirect != 0 {
        result = *(result as *const usize);
    }

    result
}
<|endoftext|>


<commit_before>//! Buffers implements an in-memory `std::io::Read` for testing.

use std::str;
use std::cmp;
use std::io::{Read, Result};

/// Buffer to read from (similar to C++`s `std::stringistream`).
#[allow(dead_code)]
pub struct IBuffer {
    /// buffer to read from
    buf: Vec<u8>,
    /// current offset
    offset: usize,
}

#[allow(dead_code)]
impl IBuffer {
    /// Creates an `IBuffer` from a string.
    /// This works best, when the string just contains ASCII
    /// characters as the characters are convertes to bytes.
    pub fn from_str(s: &str) -> IBuffer {
        IBuffer {
            buf: s.as_bytes().to_vec(),
            offset: 0,
        }
    }
}

impl Read for IBuffer {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let len = cmp::min(buf.len(), self.buf.len() - self.offset);
        buf[0..len].copy_from_slice(&self.buf[self.offset..(self.offset + len)]);
        self.offset += len;
        Ok(len)
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn read_from_string() {
        let mut in_buf = IBuffer::from_str("Hello world");

        let mut buf = [0u8; 6];

        let res = in_buf.read(&mut buf);
        assert_eq!(6, res.expect("read must be ok"));
        assert_eq!([b'H', b'e', b'l', b'l', b'o', b' '], buf);
    }

    #[test]
    fn read_from_string_overflow() {
        let mut in_buf = IBuffer::from_str("Hello world");

        let mut buf = [0u8; 6];

        let _ = in_buf.read(&mut buf);
        let res = in_buf.read(&mut buf);
        assert_eq!(5, res.expect("read must be ok"));
        assert_eq!([b'w', b'o', b'r', b'l', b'd'], buf[0..5]);
    }

    #[test]
    fn read_from_string_eof() {
        let mut in_buf = IBuffer::from_str("Hello world");

        let mut buf = [0u8; 6];

        let _ = in_buf.read(&mut buf);
        let _ = in_buf.read(&mut buf);
        let res = in_buf.read(&mut buf);
        assert_eq!(0, res.expect("read must be ok"));
    }

}
<commit_msg>removed old IBuffer tests from buffer.rs (are now in buffer_tests.rs)<commit_after>//! Buffers implements an in-memory `std::io::Read` for testing.

use std::str;
use std::cmp;
use std::io::{Read, Result};

/// Buffer to read from (similar to C++`s `std::stringistream`).
#[allow(dead_code)]
pub struct IBuffer {
    /// buffer to read from
    buf: Vec<u8>,
    /// current offset
    offset: usize,
}

#[allow(dead_code)]
impl IBuffer {
    /// Creates an `IBuffer` from a string.
    /// This works best, when the string just contains ASCII
    /// characters as the characters are convertes to bytes.
    pub fn from_str(s: &str) -> IBuffer {
        IBuffer {
            buf: s.as_bytes().to_vec(),
            offset: 0,
        }
    }
}

impl Read for IBuffer {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let len = cmp::min(buf.len(), self.buf.len() - self.offset);
        buf[0..len].copy_from_slice(&self.buf[self.offset..(self.offset + len)]);
        self.offset += len;
        Ok(len)
    }
}
<|endoftext|>


<commit_before>use hb;
use std;

use font::Font;
use common::{HarfbuzzObject, Tag};

pub type GlyphPosition = hb::hb_glyph_position_t;
pub type GlyphInfo = hb::hb_glyph_info_t;
pub type Feature = hb::hb_feature_t;

fn language_to_string(tag: hb::hb_language_t) -> &'static str {
    let lang_string_ptr = unsafe { hb::hb_language_to_string(tag) };
    let cstring = unsafe { std::ffi::CStr::from_ptr(lang_string_ptr) };
    cstring.to_str().expect("harfbuzz error: language string is not valid utf-8!")
}

struct BufferRaw {
    hb_buffer: *mut hb::hb_buffer_t,
}
impl BufferRaw {
    fn new() -> BufferRaw {
        let buffer = unsafe { hb::hb_buffer_create() };

        BufferRaw { hb_buffer: buffer }
    }

    fn as_raw(&self) -> *mut hb::hb_buffer_t {
        self.hb_buffer
    }

    fn len(&self) -> usize {
        unsafe { hb::hb_buffer_get_length(self.hb_buffer) as usize }
    }

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

    fn add_str(&mut self, string: &str) {
        let utf8_ptr = string.as_ptr() as *const i8;
        unsafe {
            hb::hb_buffer_add_utf8(self.hb_buffer,
                                   utf8_ptr,
                                   string.len() as i32,
                                   0,
                                   string.len() as i32);
        }
    }

    fn set_direction(&mut self, direction: hb::hb_direction_t) {
        unsafe { hb::hb_buffer_set_direction(self.hb_buffer, direction) };
    }

    /// Returns the `Buffer`'s text direction.
    fn get_direction(&self) -> hb::hb_direction_t {
        unsafe { hb::hb_buffer_get_direction(self.hb_buffer) }
    }

    fn set_language(&mut self, lang: hb::hb_language_t) {
        unsafe { hb::hb_buffer_set_language(self.hb_buffer, lang) }
    }

    fn get_language(&self) -> &'static str {
        let lang = unsafe { hb::hb_buffer_get_language(self.hb_buffer) };
        language_to_string(lang)
    }

    fn set_script(&mut self, script: hb::hb_script_t) {
        unsafe { hb::hb_buffer_set_script(self.hb_buffer, script) }
    }

    fn get_script(&self) -> hb::hb_script_t {
        unsafe { hb::hb_buffer_get_script(self.hb_buffer) }
    }

    fn guess_segment_properties(&mut self) {
        unsafe { hb::hb_buffer_guess_segment_properties(self.hb_buffer) };
    }

    fn get_segment_properties(&self) -> hb::hb_segment_properties_t {
        unsafe {
            let mut segment_props: hb::hb_segment_properties_t = std::mem::uninitialized();
            hb::hb_buffer_get_segment_properties(self.hb_buffer, &mut segment_props as *mut _);
            segment_props
        }
    }

    fn shape(&mut self, font: &Font, features: &[Feature]) {
        unsafe {
            hb::hb_shape(font.as_raw(),
                         self.hb_buffer,
                         features.as_ptr(),
                         features.len() as u32)
        };
    }

    fn clear_contents(&mut self) {
        unsafe { hb::hb_buffer_clear_contents(self.hb_buffer) };
    }

    fn get_glyph_positions(&self) -> &mut [GlyphPosition] {
        unsafe {
            let mut length: u32 = 0;
            let glyph_pos = hb::hb_buffer_get_glyph_positions(self.hb_buffer,
                                                              &mut length as *mut u32);
            std::slice::from_raw_parts_mut(glyph_pos, length as usize)
        }
    }

    fn get_glyph_infos(&self) -> &mut [GlyphInfo] {
        unsafe {
            let mut length: u32 = 0;
            let glyph_infos = hb::hb_buffer_get_glyph_infos(self.hb_buffer,
                                                            &mut length as *mut u32);
            std::slice::from_raw_parts_mut(glyph_infos, length as usize)
        }
    }

    /// Reverse the `Buffer`'s contents.
    fn reverse(&mut self) {
        unsafe { hb::hb_buffer_reverse(self.hb_buffer) };
    }

    /// Reverse the `Buffer`'s contents in the range from `start` to `end`.
    fn reverse_range(&mut self, start: usize, end: usize) {
        assert!(start <= self.len(), end <= self.len());
        unsafe {
            hb::hb_buffer_reverse_range(self.hb_buffer, start as u32, end as u32)
        }
    }
}

impl Drop for BufferRaw {
    fn drop(&mut self) {
        unsafe {
            hb::hb_buffer_destroy(self.hb_buffer);
        }
    }
}

/// A `UnicodeBuffer` can be filled with unicode text and corresponding
pub struct UnicodeBuffer(BufferRaw);
#[allow(dead_code)]
impl UnicodeBuffer {
    /// Creates a new empty `Buffer`.
    pub fn new() -> UnicodeBuffer {
        UnicodeBuffer(BufferRaw::new())
    }

    /// Returns a pointer to the underlying raw harfbuzz buffer.
    pub fn as_raw(&self) -> *mut hb::hb_buffer_t {
        self.0.as_raw()
    }

    /// Returns the length of the data of the buffer.
    ///
    /// When called before shaping this is the number of unicode codepoints contained in the
    /// buffer. When called after shaping it returns the number of glyphs stored.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns `true` if the buffer contains no elements.
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// Adds the string slice to the `Buffer`'s array of codepoints.
    pub fn add_str(mut self, string: &str) -> UnicodeBuffer {
        self.0.add_str(string);
        self
    }

    fn get_string(&self) -> String {
        let mut result = String::with_capacity(self.len());
        for info in self.0.get_glyph_infos() {
            let chr = std::char::from_u32(info.codepoint).unwrap();
            result.push(chr)
        }
        result
    }

    /// Sets the text direction of the `Buffer`'s contents.
    pub fn set_direction(mut self, direction: hb::hb_direction_t) -> UnicodeBuffer {
        self.0.set_direction(direction);
        self
    }

    /// Returns the `Buffer`'s text direction.
    pub fn get_direction(&self) -> hb::hb_direction_t {
        self.0.get_direction()
    }

    pub fn set_script(mut self, script: Tag) -> UnicodeBuffer {
        self.0.set_script(script.0);
        self
    }

    pub fn get_script(&self) -> Tag {
        Tag(self.0.get_script())
    }

    pub fn get_language(&self) -> &'static str {
        self.0.get_language()
    }

    pub fn guess_segment_properties(mut self) -> UnicodeBuffer {
        self.0.guess_segment_properties();
        self
    }

    pub fn get_segment_properties(&self) -> hb::hb_segment_properties_t {
        self.0.get_segment_properties()
    }

    pub fn shape(mut self, font: &Font, features: &[Feature]) -> GlyphBuffer {
        self = self.guess_segment_properties();
        self.0.shape(font, features);
        GlyphBuffer(self.0)
    }

    pub fn clear_contents(mut self) -> UnicodeBuffer {
        self.0.clear_contents();
        self
    }
}

impl std::fmt::Debug for UnicodeBuffer {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        fmt.debug_struct("Buffer")
            .field("content", &self.get_string())
            .field("direction", &self.get_direction())
            .field("language", &self.get_language().to_owned())
            .finish()
    }
}

impl std::default::Default for UnicodeBuffer {
    fn default() -> UnicodeBuffer {
        UnicodeBuffer::new()
    }
}

/// A `GlyphBuffer` is obtained through the `shape` function of a `UnicodeBuffer`. It contains
/// the resulting output information of the shaping process.
pub struct GlyphBuffer(BufferRaw);

impl GlyphBuffer {
    /// Returns the length of the data of the buffer.
    ///
    /// When called before shaping this is the number of unicode codepoints contained in the
    /// buffer. When called after shaping it returns the number of glyphs stored.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns `true` if the buffer contains no elements.
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    pub fn get_glyph_positions(&self) -> &mut [GlyphPosition] {
        self.0.get_glyph_positions()
    }

    pub fn get_glyph_infos(&self) -> &mut [GlyphInfo] {
        self.0.get_glyph_infos()
    }

    /// Reverse the `Buffer`'s contents.
    pub fn reverse(&mut self) {
        self.0.reverse()
    }

    /// Reverse the `Buffer`'s contents in the range from `start` to `end`.
    pub fn reverse_range(&mut self, start: usize, end: usize) {
        self.0.reverse_range(start, end)
    }

    /// Clears the contents of the glyph buffer and returns an empty `UnicodeBuffer` reusing the
    /// existing allocation.
    pub fn clear(mut self) -> UnicodeBuffer {
        self.0.clear_contents();
        UnicodeBuffer(self.0)
    }
}

impl std::fmt::Debug for GlyphBuffer {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        fmt.debug_struct("Buffer")
            .field("glyph positions", &self.get_glyph_positions())
            .field("glyph infos", &self.get_glyph_infos())
            .finish()
    }
}

#[derive(Debug)]
pub enum Buffer {
    UnicodeBuffer(UnicodeBuffer),
    GlyphBuffer(GlyphBuffer),
}
<commit_msg>Add Clone implementations for Buffer*.<commit_after>use hb;
use std;

use font::Font;
use common::{HarfbuzzObject, Tag};

pub type GlyphPosition = hb::hb_glyph_position_t;
pub type GlyphInfo = hb::hb_glyph_info_t;
pub type Feature = hb::hb_feature_t;

fn language_to_string(tag: hb::hb_language_t) -> &'static str {
    let lang_string_ptr = unsafe { hb::hb_language_to_string(tag) };
    let cstring = unsafe { std::ffi::CStr::from_ptr(lang_string_ptr) };
    cstring.to_str().expect("harfbuzz error: language string is not valid utf-8!")
}

struct BufferRaw {
    hb_buffer: *mut hb::hb_buffer_t,
}
impl BufferRaw {
    fn new() -> BufferRaw {
        let buffer = unsafe { hb::hb_buffer_create() };

        BufferRaw { hb_buffer: buffer }
    }

    fn as_raw(&self) -> *mut hb::hb_buffer_t {
        self.hb_buffer
    }

    fn len(&self) -> usize {
        unsafe { hb::hb_buffer_get_length(self.hb_buffer) as usize }
    }

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

    fn add_str(&mut self, string: &str) {
        let utf8_ptr = string.as_ptr() as *const i8;
        unsafe {
            hb::hb_buffer_add_utf8(self.hb_buffer,
                                   utf8_ptr,
                                   string.len() as i32,
                                   0,
                                   string.len() as i32);
        }
    }

    fn set_direction(&mut self, direction: hb::hb_direction_t) {
        unsafe { hb::hb_buffer_set_direction(self.hb_buffer, direction) };
    }

    /// Returns the `Buffer`'s text direction.
    fn get_direction(&self) -> hb::hb_direction_t {
        unsafe { hb::hb_buffer_get_direction(self.hb_buffer) }
    }

    fn set_language(&mut self, lang: hb::hb_language_t) {
        unsafe { hb::hb_buffer_set_language(self.hb_buffer, lang) }
    }

    fn get_language(&self) -> &'static str {
        let lang = unsafe { hb::hb_buffer_get_language(self.hb_buffer) };
        language_to_string(lang)
    }

    fn set_script(&mut self, script: hb::hb_script_t) {
        unsafe { hb::hb_buffer_set_script(self.hb_buffer, script) }
    }

    fn get_script(&self) -> hb::hb_script_t {
        unsafe { hb::hb_buffer_get_script(self.hb_buffer) }
    }

    fn guess_segment_properties(&mut self) {
        unsafe { hb::hb_buffer_guess_segment_properties(self.hb_buffer) };
    }

    fn get_segment_properties(&self) -> hb::hb_segment_properties_t {
        unsafe {
            let mut segment_props: hb::hb_segment_properties_t = std::mem::uninitialized();
            hb::hb_buffer_get_segment_properties(self.hb_buffer, &mut segment_props as *mut _);
            segment_props
        }
    }

    fn shape(&mut self, font: &Font, features: &[Feature]) {
        unsafe {
            hb::hb_shape(font.as_raw(),
                         self.hb_buffer,
                         features.as_ptr(),
                         features.len() as u32)
        };
    }

    fn clear_contents(&mut self) {
        unsafe { hb::hb_buffer_clear_contents(self.hb_buffer) };
    }

    fn get_glyph_positions(&self) -> &mut [GlyphPosition] {
        unsafe {
            let mut length: u32 = 0;
            let glyph_pos = hb::hb_buffer_get_glyph_positions(self.hb_buffer,
                                                              &mut length as *mut u32);
            std::slice::from_raw_parts_mut(glyph_pos, length as usize)
        }
    }

    fn get_glyph_infos(&self) -> &mut [GlyphInfo] {
        unsafe {
            let mut length: u32 = 0;
            let glyph_infos = hb::hb_buffer_get_glyph_infos(self.hb_buffer,
                                                            &mut length as *mut u32);
            std::slice::from_raw_parts_mut(glyph_infos, length as usize)
        }
    }

    /// Reverse the `Buffer`'s contents.
    fn reverse(&mut self) {
        unsafe { hb::hb_buffer_reverse(self.hb_buffer) };
    }

    /// Reverse the `Buffer`'s contents in the range from `start` to `end`.
    fn reverse_range(&mut self, start: usize, end: usize) {
        assert!(start <= self.len(), end <= self.len());
        unsafe {
            hb::hb_buffer_reverse_range(self.hb_buffer, start as u32, end as u32)
        }
    }
}

impl Clone for BufferRaw {
    fn clone(&self) -> Self {
        unsafe {
            hb::hb_buffer_reference(self.hb_buffer);
        }
        BufferRaw { hb_buffer: self.hb_buffer }
    }
}

impl Drop for BufferRaw {
    fn drop(&mut self) {
        unsafe {
            hb::hb_buffer_destroy(self.hb_buffer);
        }
    }
}

/// A `UnicodeBuffer` can be filled with unicode text and corresponding
#[derive(Clone)]
pub struct UnicodeBuffer(BufferRaw);
#[allow(dead_code)]
impl UnicodeBuffer {
    /// Creates a new empty `Buffer`.
    pub fn new() -> UnicodeBuffer {
        UnicodeBuffer(BufferRaw::new())
    }

    /// Returns a pointer to the underlying raw harfbuzz buffer.
    pub fn as_raw(&self) -> *mut hb::hb_buffer_t {
        self.0.as_raw()
    }

    /// Returns the length of the data of the buffer.
    ///
    /// When called before shaping this is the number of unicode codepoints contained in the
    /// buffer. When called after shaping it returns the number of glyphs stored.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns `true` if the buffer contains no elements.
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// Adds the string slice to the `Buffer`'s array of codepoints.
    pub fn add_str(mut self, string: &str) -> UnicodeBuffer {
        self.0.add_str(string);
        self
    }

    fn get_string(&self) -> String {
        let mut result = String::with_capacity(self.len());
        for info in self.0.get_glyph_infos() {
            let chr = std::char::from_u32(info.codepoint).unwrap();
            result.push(chr)
        }
        result
    }

    /// Sets the text direction of the `Buffer`'s contents.
    pub fn set_direction(mut self, direction: hb::hb_direction_t) -> UnicodeBuffer {
        self.0.set_direction(direction);
        self
    }

    /// Returns the `Buffer`'s text direction.
    pub fn get_direction(&self) -> hb::hb_direction_t {
        self.0.get_direction()
    }

    pub fn set_script(mut self, script: Tag) -> UnicodeBuffer {
        self.0.set_script(script.0);
        self
    }

    pub fn get_script(&self) -> Tag {
        Tag(self.0.get_script())
    }

    pub fn get_language(&self) -> &'static str {
        self.0.get_language()
    }

    pub fn guess_segment_properties(mut self) -> UnicodeBuffer {
        self.0.guess_segment_properties();
        self
    }

    pub fn get_segment_properties(&self) -> hb::hb_segment_properties_t {
        self.0.get_segment_properties()
    }

    pub fn shape(mut self, font: &Font, features: &[Feature]) -> GlyphBuffer {
        self = self.guess_segment_properties();
        self.0.shape(font, features);
        GlyphBuffer(self.0)
    }

    pub fn clear_contents(mut self) -> UnicodeBuffer {
        self.0.clear_contents();
        self
    }
}

impl std::fmt::Debug for UnicodeBuffer {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        fmt.debug_struct("Buffer")
            .field("content", &self.get_string())
            .field("direction", &self.get_direction())
            .field("language", &self.get_language().to_owned())
            .finish()
    }
}

impl std::default::Default for UnicodeBuffer {
    fn default() -> UnicodeBuffer {
        UnicodeBuffer::new()
    }
}

/// A `GlyphBuffer` is obtained through the `shape` function of a `UnicodeBuffer`. It contains
/// the resulting output information of the shaping process.
#[derive(Clone)]
pub struct GlyphBuffer(BufferRaw);

impl GlyphBuffer {
    /// Returns the length of the data of the buffer.
    ///
    /// When called before shaping this is the number of unicode codepoints contained in the
    /// buffer. When called after shaping it returns the number of glyphs stored.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns `true` if the buffer contains no elements.
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    pub fn get_glyph_positions(&self) -> &mut [GlyphPosition] {
        self.0.get_glyph_positions()
    }

    pub fn get_glyph_infos(&self) -> &mut [GlyphInfo] {
        self.0.get_glyph_infos()
    }

    /// Reverse the `Buffer`'s contents.
    pub fn reverse(&mut self) {
        self.0.reverse()
    }

    /// Reverse the `Buffer`'s contents in the range from `start` to `end`.
    pub fn reverse_range(&mut self, start: usize, end: usize) {
        self.0.reverse_range(start, end)
    }

    /// Clears the contents of the glyph buffer and returns an empty `UnicodeBuffer` reusing the
    /// existing allocation.
    pub fn clear(mut self) -> UnicodeBuffer {
        self.0.clear_contents();
        UnicodeBuffer(self.0)
    }
}

impl std::fmt::Debug for GlyphBuffer {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        fmt.debug_struct("Buffer")
            .field("glyph positions", &self.get_glyph_positions())
            .field("glyph infos", &self.get_glyph_infos())
            .finish()
    }
}

#[derive(Debug, Clone)]
pub enum Buffer {
    UnicodeBuffer(UnicodeBuffer),
    GlyphBuffer(GlyphBuffer),
}
<|endoftext|>


<commit_before><commit_msg>Remove unnecessary public fields<commit_after><|endoftext|>


<commit_before>use std::f32::consts::PI;

use na::{self, Norm, Inverse, Matrix4, FromHomogeneous, ToHomogeneous, PerspectiveMatrix3};

use {Vector3f, Point3f, Point2f, Transform};
use bounds::Bounds2f;
use ray::Ray;

/// Projective pinhole camera.
/// TODO: abstract the Camera interface and handle multiple camera types.
#[derive(Debug)]
pub struct Camera {
    camera_to_world: Transform,
    camera_to_screen: Matrix4<f32>,
    raster_to_camera: Matrix4<f32>,
}

impl Camera {
    pub fn new(camera_to_world: Transform,
               film_size: Point2f,
               lens_radius: f32,
               focal_distance: f32,
               fov: f32)
               -> Camera {
        #[cfg_attr(rustfmt, rustfmt_skip)]
        fn scale(x: f32, y: f32, z: f32) -> Matrix4<f32> {
            Matrix4::<f32>::new(x, 0.0, 0.0, 0.0,
                                0.0, y, 0.0, 0.0,
                                0.0, 0.0, z, 0.0,
                                0.0, 0.0, 0.0, 1.0)
        }

        #[cfg_attr(rustfmt, rustfmt_skip)]
        fn translate(x: f32, y: f32, z: f32) -> Matrix4<f32> {
            Matrix4::<f32>::new(1.0, 0.0, 0.0, x,
                                0.0, 1.0, 0.0, y,
                                0.0, 0.0, 1.0, z,
                                0.0, 0.0, 0.0, 1.0)
        }

        #[cfg_attr(rustfmt, rustfmt_skip)]
        fn perspective(fov: f32, n: f32, f: f32) -> Matrix4<f32> {
            let persp = Matrix4::<f32>::new(1.0, 0.0, 0.0, 0.0,
                                            0.0, 1.0, 0.0, 0.0,
                                            0.0, 0.0, f / (f - n), -f * n / (f - n),
                                            0.0, 0.0, 1.0, 0.0);
            let inv_tan_ang = 1.0 / (fov.to_radians() / 2.0).tan();
            scale(inv_tan_ang, inv_tan_ang, 1.0) * persp
        }

        let aspect_ratio = film_size.x / film_size.y;
        let screen_window = if aspect_ratio > 1.0 {
            Bounds2f::from_points(&Point2f::new(-aspect_ratio, -1.0),
                                  &Point2f::new(aspect_ratio, 1.0))
        } else {
            Bounds2f::from_points(&Point2f::new(-1.0, -1.0 / aspect_ratio),
                                  &Point2f::new(1.0, 1.0 / aspect_ratio))
        };
        let camera_to_screen = perspective(fov, 1e-2, 1000.0);
        // PerspectiveMatrix3::<f32>::new(1.0, fov.to_radians(), 1e-2, 1000.0);
        // let camera_to_screen = camera_to_screen_perspective.as_matrix();
        let screen_to_raster = scale(film_size.x, film_size.y, 1.0) *
                               scale(1.0 / (screen_window.p_max.x - screen_window.p_min.x),
                                     1.0 / (screen_window.p_min.y - screen_window.p_max.y),
                                     1.0) *
                               translate(-screen_window.p_min.x, -screen_window.p_max.y, 0.0);
        let raster_to_screen = screen_to_raster.inverse().unwrap();
        let raster_to_camera = camera_to_screen.inverse().unwrap() * raster_to_screen;
        Camera {
            camera_to_world: camera_to_world,
            camera_to_screen: camera_to_screen,
            raster_to_camera: raster_to_camera,
        }
    }

    pub fn generate_ray(&self, sample: &Point2f) -> Ray {
        let p_film = Point3f::new(sample.x, sample.y, 0.0);
        let p_camera: Point3f = na::from_homogeneous(&(self.raster_to_camera *
                                                       p_film.to_homogeneous()));

        let ray = Ray::new(na::origin(), p_camera.to_vector().normalize());
        // TODO modify ray for depth of field
        ray.transform(&self.camera_to_world).0
    }
}

pub struct CameraSample {
    pub p_film: Point2f,
    pub p_lens: Point2f,
    pub time: f32,
}
<commit_msg>Implement Camera::generate_ray_differential()<commit_after>use std::f32::consts::PI;

use na::{self, Norm, Inverse, Matrix4, FromHomogeneous, ToHomogeneous, PerspectiveMatrix3};

use {Vector3f, Point3f, Point2f, Transform};
use bounds::Bounds2f;
use ray::{Ray, RayDifferential};

/// Projective pinhole camera.
/// TODO: abstract the Camera interface and handle multiple camera types.
#[derive(Debug)]
pub struct Camera {
    camera_to_world: Transform,
    camera_to_screen: Matrix4<f32>,
    raster_to_camera: Matrix4<f32>,
    dx_camera: Vector3f,
    dy_camera: Vector3f,
}

impl Camera {
    pub fn new(camera_to_world: Transform,
               film_size: Point2f,
               lens_radius: f32,
               focal_distance: f32,
               fov: f32)
               -> Camera {
        #[cfg_attr(rustfmt, rustfmt_skip)]
        fn scale(x: f32, y: f32, z: f32) -> Matrix4<f32> {
            Matrix4::<f32>::new(x, 0.0, 0.0, 0.0,
                                0.0, y, 0.0, 0.0,
                                0.0, 0.0, z, 0.0,
                                0.0, 0.0, 0.0, 1.0)
        }

        #[cfg_attr(rustfmt, rustfmt_skip)]
        fn translate(x: f32, y: f32, z: f32) -> Matrix4<f32> {
            Matrix4::<f32>::new(1.0, 0.0, 0.0, x,
                                0.0, 1.0, 0.0, y,
                                0.0, 0.0, 1.0, z,
                                0.0, 0.0, 0.0, 1.0)
        }

        #[cfg_attr(rustfmt, rustfmt_skip)]
        fn perspective(fov: f32, n: f32, f: f32) -> Matrix4<f32> {
            let persp = Matrix4::<f32>::new(1.0, 0.0, 0.0, 0.0,
                                            0.0, 1.0, 0.0, 0.0,
                                            0.0, 0.0, f / (f - n), -f * n / (f - n),
                                            0.0, 0.0, 1.0, 0.0);
            let inv_tan_ang = 1.0 / (fov.to_radians() / 2.0).tan();
            scale(inv_tan_ang, inv_tan_ang, 1.0) * persp
        }

        let aspect_ratio = film_size.x / film_size.y;
        let screen_window = if aspect_ratio > 1.0 {
            Bounds2f::from_points(&Point2f::new(-aspect_ratio, -1.0),
                                  &Point2f::new(aspect_ratio, 1.0))
        } else {
            Bounds2f::from_points(&Point2f::new(-1.0, -1.0 / aspect_ratio),
                                  &Point2f::new(1.0, 1.0 / aspect_ratio))
        };
        let camera_to_screen = perspective(fov, 1e-2, 1000.0);
        // PerspectiveMatrix3::<f32>::new(1.0, fov.to_radians(), 1e-2, 1000.0);
        // let camera_to_screen = camera_to_screen_perspective.as_matrix();
        let screen_to_raster = scale(film_size.x, film_size.y, 1.0) *
                               scale(1.0 / (screen_window.p_max.x - screen_window.p_min.x),
                                     1.0 / (screen_window.p_min.y - screen_window.p_max.y),
                                     1.0) *
                               translate(-screen_window.p_min.x, -screen_window.p_max.y, 0.0);
        let raster_to_screen = screen_to_raster.inverse().unwrap();
        let raster_to_camera = camera_to_screen.inverse().unwrap() * raster_to_screen;

        // compute differential changes in origin for perspective camera rays
        let dx_camera = na::from_homogeneous(&((raster_to_camera *
                                                Point3f::new(1.0, 0.0, 0.0).to_homogeneous()) -
                                               (raster_to_camera *
                                                Point3f::new(0.0, 0.0, 0.0).to_homogeneous())));
        let dy_camera = na::from_homogeneous(&((raster_to_camera *
                                                Point3f::new(0.0, 1.0, 0.0).to_homogeneous()) -
                                               (raster_to_camera *
                                                Point3f::new(0.0, 0.0, 0.0).to_homogeneous())));

        Camera {
            camera_to_world: camera_to_world,
            camera_to_screen: camera_to_screen,
            raster_to_camera: raster_to_camera,
            dx_camera: dx_camera,
            dy_camera: dy_camera,
        }
    }

    pub fn generate_ray(&self, sample: &Point2f) -> Ray {
        let p_film = Point3f::new(sample.x, sample.y, 0.0);
        let p_camera: Point3f = na::from_homogeneous(&(self.raster_to_camera *
                                                       p_film.to_homogeneous()));

        let ray = Ray::new(na::origin(), p_camera.to_vector().normalize());
        // TODO modify ray for depth of field
        ray.transform(&self.camera_to_world).0
    }

    pub fn generate_ray_differential(&self, sample: &Point2f) -> Ray {
        let p_film = Point3f::new(sample.x, sample.y, 0.0);
        let p_camera: Point3f = na::from_homogeneous(&(self.raster_to_camera *
                                                       p_film.to_homogeneous()));

        let mut ray = Ray::new(na::origin(), p_camera.to_vector().normalize())
            .transform(&self.camera_to_world)
            .0;
        // TODO modify ray for depth of field
        // compute offset rays for PerspectiveCamera ray differentials
        let diff = RayDifferential {
            rx_origin: ray.o,
            ry_origin: ray.o,
            rx_direction: (p_camera.to_vector() + self.dx_camera).normalize(),
            ry_direction: (p_camera.to_vector() + self.dy_camera).normalize(),
        };

        ray.differential = Some(diff);

        ray
    }
}

pub struct CameraSample {
    pub p_film: Point2f,
    pub p_lens: Point2f,
    pub time: f32,
}
<|endoftext|>


<commit_before>#![allow(unused_variables, dead_code)] // macros

/// Dbus macro for Layout code

use super::utils::{parse_edge, parse_uuid, parse_direction, parse_axis, lock_tree_dbus};

use dbus::tree::MethodErr;

use super::super::layout::{Layout, commands as layout_cmd};
use rustwlc::{ResizeEdge, Point};

dbus_interface! {
    path: "/org/way_cooler/Layout";
    name: "org.way_cooler.Layout";

    fn ActiveContainerId() -> container_id: DBusResult<String> {
        let tree = try!(lock_tree_dbus());
        match tree.active_id() {
            Some(id) => Ok(id.to_string()),
            None => Ok("".to_string())
        }
    }

    fn ToggleFloat(container_id: String) -> success: DBusResult<bool> {
        let maybe_uuid = try!(parse_uuid("container_id", &container_id));
        match maybe_uuid {
            Some(uuid) => {
                let mut tree = try!(lock_tree_dbus());
                tree.toggle_float()
                    .and(Ok(true))
                    .map_err(|err| {
                        MethodErr::failed(&format!("{:?}", err))
                    })
            },
            None => {
                layout_cmd::toggle_float();
                Ok(true)
            }
        }
    }

    fn MoveContainer(container_id: String, direction: String) -> success: DBusResult<bool> {
        let target_uuid = try!(parse_uuid("container_id", &container_id));
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_active(target_uuid, direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SplitContainer(container_id: String, split_axis: String) -> success: DBusResult<bool> {
        let uuid = try!(parse_uuid("container_id", &container_id));
        let axis = try!(parse_axis("split_direction", split_axis.as_str()));
        // TODO Tree commands need to have these defined on the Tree,
        // for now this is _ok_, but we are swallowing an potential Tree lock error here.
        match axis {
            Layout::Horizontal => layout_cmd::split_horizontal(),
            Layout::Vertical => layout_cmd::split_vertical(),
            Layout::Tabbed => layout_cmd::tile_tabbed(),
            Layout::Stacked => layout_cmd::tile_stacked()
        }
        Ok(true)
    }

    fn ToggleCardinalTiling(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.toggle_cardinal_tiling(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SwitchWorkspace(w_name: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        tree.switch_to_workspace(w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn CloseView(view_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("view_id", &view_id))
            .or_else(|| tree.active_id())
            .ok_or(MethodErr::failed(&"No active container")));
        tree.remove_view_by_id(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn Focus(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));

        tree.focus(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn FocusDir(direction: String) -> success: DBusResult<bool> {
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_focus(direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SendToWorkspace(container_id: String, w_name: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.send_to_workspace(uuid, w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn Debug() -> success: DBusResult<String> {
        Ok(format!("{}", layout_cmd::tree_as_json()))
    }

    fn ContainerInActiveWorkspace(container_id: String) -> success: DBusResult<bool> {
        let tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.container_in_active_workspace(uuid)
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn FullScreen(container_id: String, toggle: bool) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.set_fullscreen(uuid, toggle)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SetPointerPos(x: i32, y: i32) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let point = Point { x: x, y: y};
        tree.set_pointer_pos(point)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn GrabAtCorner(container_id: String, dir: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        let mut edge = ResizeEdge::empty();
        for word in dir.split(',') {
            edge |= try!(parse_edge(word))
        }
        tree.grab_at_corner(uuid, edge)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn ActiveWorkspace() -> name: DBusResult<String> {
        let tree = try!(lock_tree_dbus());
        tree.active_workspace()
            .map(|container| container.name())
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }
}
<commit_msg>Added D-Bus command to lock the screen<commit_after>#![allow(unused_variables, dead_code)] // macros

/// Dbus macro for Layout code

use super::utils::{parse_edge, parse_uuid, parse_direction, parse_axis, lock_tree_dbus};

use dbus::tree::MethodErr;

use super::super::layout::{Layout, commands as layout_cmd};
use rustwlc::{ResizeEdge, Point};

dbus_interface! {
    path: "/org/way_cooler/Layout";
    name: "org.way_cooler.Layout";

    fn ActiveContainerId() -> container_id: DBusResult<String> {
        let tree = try!(lock_tree_dbus());
        match tree.active_id() {
            Some(id) => Ok(id.to_string()),
            None => Ok("".to_string())
        }
    }

    fn ToggleFloat(container_id: String) -> success: DBusResult<bool> {
        let maybe_uuid = try!(parse_uuid("container_id", &container_id));
        match maybe_uuid {
            Some(uuid) => {
                let mut tree = try!(lock_tree_dbus());
                tree.toggle_float()
                    .and(Ok(true))
                    .map_err(|err| {
                        MethodErr::failed(&format!("{:?}", err))
                    })
            },
            None => {
                layout_cmd::toggle_float();
                Ok(true)
            }
        }
    }

    fn MoveContainer(container_id: String, direction: String) -> success: DBusResult<bool> {
        let target_uuid = try!(parse_uuid("container_id", &container_id));
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_active(target_uuid, direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SplitContainer(container_id: String, split_axis: String) -> success: DBusResult<bool> {
        let uuid = try!(parse_uuid("container_id", &container_id));
        let axis = try!(parse_axis("split_direction", split_axis.as_str()));
        // TODO Tree commands need to have these defined on the Tree,
        // for now this is _ok_, but we are swallowing an potential Tree lock error here.
        match axis {
            Layout::Horizontal => layout_cmd::split_horizontal(),
            Layout::Vertical => layout_cmd::split_vertical(),
            Layout::Tabbed => layout_cmd::tile_tabbed(),
            Layout::Stacked => layout_cmd::tile_stacked()
        }
        Ok(true)
    }

    fn ToggleCardinalTiling(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.toggle_cardinal_tiling(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SwitchWorkspace(w_name: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        tree.switch_to_workspace(w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn CloseView(view_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("view_id", &view_id))
            .or_else(|| tree.active_id())
            .ok_or(MethodErr::failed(&"No active container")));
        tree.remove_view_by_id(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn Focus(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));

        tree.focus(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn FocusDir(direction: String) -> success: DBusResult<bool> {
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_focus(direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SendToWorkspace(container_id: String, w_name: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.send_to_workspace(uuid, w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn Debug() -> success: DBusResult<String> {
        Ok(format!("{}", layout_cmd::tree_as_json()))
    }

    fn ContainerInActiveWorkspace(container_id: String) -> success: DBusResult<bool> {
        let tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.container_in_active_workspace(uuid)
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn FullScreen(container_id: String, toggle: bool) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.set_fullscreen(uuid, toggle)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SetPointerPos(x: i32, y: i32) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let point = Point { x: x, y: y};
        tree.set_pointer_pos(point)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn GrabAtCorner(container_id: String, dir: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        let mut edge = ResizeEdge::empty();
        for word in dir.split(',') {
            edge |= try!(parse_edge(word))
        }
        tree.grab_at_corner(uuid, edge)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn ActiveWorkspace() -> name: DBusResult<String> {
        let tree = try!(lock_tree_dbus());
        tree.active_workspace()
            .map(|container| container.name())
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn LockScreen() -> success: DBusResult<bool> {
        use ::lockscreen::spawn_lock_screen;
        spawn_lock_screen();
        Ok(true)
    }
}
<|endoftext|>


<commit_before>#![feature(box_syntax, box_patterns)]

#[macro_use]
extern crate log;
extern crate rustc_serialize;
//extern crate toml;
extern crate docopt;

pub mod process;
pub mod util;

use rustc_serialize::{
    Decodable,
    Encodable,
};

use process::{
    Process,
};

pub fn execute<A, V>(process: Process<A, V>)
    where A: Decodable,
          V: Encodable,
{
    let result = process.execute();
    result.handle(|r| {
        r.unwrap();
    });
}

// Cargo defines this environment variable at compile time from the crate's manifest.
fn version() -> String {
    format!("jarvis {}", env!("CARGO_PKG_VERSION"))
}
<commit_msg>error handler<commit_after>#![feature(box_syntax, box_patterns)]

#[macro_use]
extern crate log;
extern crate rustc_serialize;
//extern crate toml;
extern crate docopt;

pub mod process;
pub mod util;

use rustc_serialize::{
    Decodable,
    Encodable,
};

use process::{
    Process,
};

use util::{
    Error,
};

pub fn execute<A, V>(process: Process<A, V>)
    where A: Decodable,
          V: Encodable,
{
    let result = process.execute();
    result.handle(|r| {
        match r {
            Ok(_) => {},
            Err(e) => { handle_error(e) },
        }
    });
}

fn handle_error(e: Error) -> ! {
    println!("{}", e);
    ::std::process::exit(1);
}

// Cargo defines this environment variable at compile time from the crate's manifest.
fn version() -> String {
    format!("jarvis {}", env!("CARGO_PKG_VERSION"))
}
<|endoftext|>


<commit_before>
extern crate std;
extern crate core;
extern crate num;
extern crate uuid;

use std::str::SendStr;

use super::def::*;
use super::serialize::*;
use super::reader::*;
use std::collections::TreeMap;

pub static CQL_VERSION_STRINGS:  [&'static str, .. 3] = ["3.0.0", "3.0.0", "3.0.0"];
pub static CQL_MAX_SUPPORTED_VERSION:u8 = 0x03;

macro_rules! serialize_and_check_io_error(
    ($writer: expr, $obj: ident, $version: expr, $msg: expr) => {
        match $obj.serialize($writer, $version) {
            Err(e) => return Err(RCError { kind: SerializeError, desc: format!("{} -> {}", $msg, e.desc).into_maybe_owned()}),
            _ => ()
        }
    }
)

type PrepsStore = TreeMap<String, Box<CqlPreparedStat>>;

pub struct Client {
    socket: std::io::net::tcp::TcpStream,
    pub version: u8,
    prepared: PrepsStore
}

impl Client {

    fn new(socket: std::io::net::tcp::TcpStream, version: u8) -> Client {
        Client {socket: socket, version: version, prepared: TreeMap::new()}
    }

    fn build_auth<'a>(&self, creds: &'a Vec<SendStr>, stream: i8) -> CqlRequest<'a> {
        return CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: stream,
            opcode: OpcodeOptions,
            body: RequestCred(creds),
        };
    }

    fn build_options(&self) -> CqlRequest {
        return CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeOptions,
            body: RequestOptions,
        };
    }

    pub fn exec_query(&mut self, query_str: &str, con: Consistency::Consistency) -> RCResult<CqlResponse> {
        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeQuery,
            body: RequestQuery(query_str, con, 0)};

        let ref mut socket = self.socket;
        serialize_and_check_io_error!(socket, q, self.version, "Error serializing query");
        let res = read_and_check_io_error!(socket, read_cql_response, self.version, "Error reading query");
        Ok(res)
    }

    pub fn exec_prepared(&mut self, ps_id: &str, params: &[CqlValue], con: Consistency::Consistency) -> RCResult<CqlResponse> {
        let preps = match self.prepared.find(&String::from_str(ps_id)) {
            Some(ps) => &**ps,
            None => return Err(RCError::new(format!("Unknown prepared statement <{}>", ps_id), GenericError))
        };

        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeExecute,
            body: RequestExec(preps, params, con, 0x01),
        };

        serialize_and_check_io_error!(&mut self.socket, q, self.version, "Error serializing prepared statement execution");

        /* Code to debug prepared statements. Write to file the serialization of the request

        let path = Path::new("prepared_data.bin");
        let display = path.display();
        let mut file = match std::io::File::create(&path) {
            Err(why) => fail!("couldn't create {}: {}", display, why.desc),
            Ok(file) => file,
        };

        serialize_and_check_io_error!(&mut file, q, self.version, "Error serializing query");

        */

        Ok(read_and_check_io_error!(self.socket, read_cql_response, self.version, "Error reading prepared statement execution result"))
    }

    pub fn prepared_statement(&mut self, query_str: &str, query_id: &str) -> RCResult<()> {
        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodePrepare,
            body: RequestPrepare(query_str),
        };

        serialize_and_check_io_error!(&mut self.socket, q, self.version, "Error serializing prepared statement");

        let res = read_and_check_io_error!(&mut self.socket, read_cql_response, self.version, "Error reading query");
        match res.body {
            ResultPrepared(preps) => {
                self.prepared.insert(String::from_str(query_id), preps);
                Ok(())
            },
            _ => Err(RCError::new("Response does not contain prepared statement", ReadError))
        }
    }
}

fn send_startup(socket: &mut std::io::TcpStream, version: u8, creds: Option<&Vec<SendStr>>) -> RCResult<()> {
    let body = CqlStringMap {
        pairs:vec![CqlPair{key: "CQL_VERSION", value: CQL_VERSION_STRINGS[(version-1) as uint]}],
    };
    let msg_startup = CqlRequest {
        version: version,
        flags: 0x00,
        stream: 0x01,
        opcode: OpcodeStartup,
        body: RequestStartup(body),
    };
    serialize_and_check_error!(socket, msg_startup, version, "Error serializing startup message");

    let response = read_and_check_io_error!(socket, read_cql_response, version, "Error reding response");
    match response.body {
        ResponseReady =>  Ok(()),
        ResponseAuth(_) => {
            match creds {
                Some(cred) => {
                    let msg_auth = CqlRequest {
                        version: version,
                        flags: 0x00,
                        stream: 0x01,
                        opcode: OpcodeOptions,
                        body: RequestCred(cred),
                    };
                    serialize_and_check_error!(socket, msg_auth, version, "Error serializing request (auth)");

                    let response = read_and_check_io_error!(socket, read_cql_response, version, "Error reding authenticaton response");
                    match response.body {
                        ResponseReady => Ok(()),
                        ResponseError(_, ref msg) => Err(RCError::new(format!("Error in authentication: {}", msg), ReadError)),
                        _ => Err(RCError::new("Server returned unknown message", ReadError))
                    }
                },
                None => Err(RCError::new("Credential should be provided for authentication", ReadError))
            }
        },
        ResponseError(_, ref msg) => Err(RCError::new(format!("Error connecting: {}", msg), ReadError)),
        _ => Err(RCError::new("Wrong response to startup", ReadError))
    }
}

pub fn connect(ip: &'static str, port: u16, creds:Option<&Vec<SendStr>>) -> RCResult<Client> {

    let mut version = CQL_MAX_SUPPORTED_VERSION;

    while version >= 0x01 {
        let res = std::io::TcpStream::connect(ip.as_slice(), port);
        if res.is_err() {
            return Err(RCError::new(format!("Failed to connect to server at {}:{}", ip.as_slice(), port), ConnectionError));
        }

        let mut socket = res.unwrap();

        match send_startup(& mut socket, version, creds) {
            Ok(_) => return Ok(Client::new(socket, version)),
            Err(e) => println!("Error connecting with protocol version v{}: {}", version, e.desc)
        }
        version -= 1;
    }
    Err(RCError::new("Unable to find suitable protocol version (v1, v2, v3)", ReadError))
}
<commit_msg>Use specific import instead of wildcard<commit_after>
extern crate std;
extern crate core;
extern crate num;
extern crate uuid;

use std::str::SendStr;

use super::def::*;
use super::serialize::CqlSerializable;
use super::reader::*;
use std::collections::TreeMap;

pub static CQL_VERSION_STRINGS:  [&'static str, .. 3] = ["3.0.0", "3.0.0", "3.0.0"];
pub static CQL_MAX_SUPPORTED_VERSION:u8 = 0x03;

macro_rules! serialize_and_check_io_error(
    ($writer: expr, $obj: ident, $version: expr, $msg: expr) => {
        match $obj.serialize($writer, $version) {
            Err(e) => return Err(RCError { kind: SerializeError, desc: format!("{} -> {}", $msg, e.desc).into_maybe_owned()}),
            _ => ()
        }
    }
)

type PrepsStore = TreeMap<String, Box<CqlPreparedStat>>;

pub struct Client {
    socket: std::io::net::tcp::TcpStream,
    pub version: u8,
    prepared: PrepsStore
}

impl Client {

    fn new(socket: std::io::net::tcp::TcpStream, version: u8) -> Client {
        Client {socket: socket, version: version, prepared: TreeMap::new()}
    }

    fn build_auth<'a>(&self, creds: &'a Vec<SendStr>, stream: i8) -> CqlRequest<'a> {
        return CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: stream,
            opcode: OpcodeOptions,
            body: RequestCred(creds),
        };
    }

    fn build_options(&self) -> CqlRequest {
        return CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeOptions,
            body: RequestOptions,
        };
    }

    pub fn exec_query(&mut self, query_str: &str, con: Consistency::Consistency) -> RCResult<CqlResponse> {
        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeQuery,
            body: RequestQuery(query_str, con, 0)};

        let ref mut socket = self.socket;
        serialize_and_check_io_error!(socket, q, self.version, "Error serializing query");
        let res = read_and_check_io_error!(socket, read_cql_response, self.version, "Error reading query");
        Ok(res)
    }

    pub fn exec_prepared(&mut self, ps_id: &str, params: &[CqlValue], con: Consistency::Consistency) -> RCResult<CqlResponse> {
        let preps = match self.prepared.find(&String::from_str(ps_id)) {
            Some(ps) => &**ps,
            None => return Err(RCError::new(format!("Unknown prepared statement <{}>", ps_id), GenericError))
        };

        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeExecute,
            body: RequestExec(preps, params, con, 0x01),
        };

        serialize_and_check_io_error!(&mut self.socket, q, self.version, "Error serializing prepared statement execution");

        /* Code to debug prepared statements. Write to file the serialization of the request

        let path = Path::new("prepared_data.bin");
        let display = path.display();
        let mut file = match std::io::File::create(&path) {
            Err(why) => fail!("couldn't create {}: {}", display, why.desc),
            Ok(file) => file,
        };

        serialize_and_check_io_error!(&mut file, q, self.version, "Error serializing query");

        */

        Ok(read_and_check_io_error!(self.socket, read_cql_response, self.version, "Error reading prepared statement execution result"))
    }

    pub fn prepared_statement(&mut self, query_str: &str, query_id: &str) -> RCResult<()> {
        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodePrepare,
            body: RequestPrepare(query_str),
        };

        serialize_and_check_io_error!(&mut self.socket, q, self.version, "Error serializing prepared statement");

        let res = read_and_check_io_error!(&mut self.socket, read_cql_response, self.version, "Error reading query");
        match res.body {
            ResultPrepared(preps) => {
                self.prepared.insert(String::from_str(query_id), preps);
                Ok(())
            },
            _ => Err(RCError::new("Response does not contain prepared statement", ReadError))
        }
    }
}

fn send_startup(socket: &mut std::io::TcpStream, version: u8, creds: Option<&Vec<SendStr>>) -> RCResult<()> {
    let body = CqlStringMap {
        pairs:vec![CqlPair{key: "CQL_VERSION", value: CQL_VERSION_STRINGS[(version-1) as uint]}],
    };
    let msg_startup = CqlRequest {
        version: version,
        flags: 0x00,
        stream: 0x01,
        opcode: OpcodeStartup,
        body: RequestStartup(body),
    };
    serialize_and_check_error!(socket, msg_startup, version, "Error serializing startup message");

    let response = read_and_check_io_error!(socket, read_cql_response, version, "Error reding response");
    match response.body {
        ResponseReady =>  Ok(()),
        ResponseAuth(_) => {
            match creds {
                Some(cred) => {
                    let msg_auth = CqlRequest {
                        version: version,
                        flags: 0x00,
                        stream: 0x01,
                        opcode: OpcodeOptions,
                        body: RequestCred(cred),
                    };
                    serialize_and_check_error!(socket, msg_auth, version, "Error serializing request (auth)");

                    let response = read_and_check_io_error!(socket, read_cql_response, version, "Error reding authenticaton response");
                    match response.body {
                        ResponseReady => Ok(()),
                        ResponseError(_, ref msg) => Err(RCError::new(format!("Error in authentication: {}", msg), ReadError)),
                        _ => Err(RCError::new("Server returned unknown message", ReadError))
                    }
                },
                None => Err(RCError::new("Credential should be provided for authentication", ReadError))
            }
        },
        ResponseError(_, ref msg) => Err(RCError::new(format!("Error connecting: {}", msg), ReadError)),
        _ => Err(RCError::new("Wrong response to startup", ReadError))
    }
}

pub fn connect(ip: &'static str, port: u16, creds:Option<&Vec<SendStr>>) -> RCResult<Client> {

    let mut version = CQL_MAX_SUPPORTED_VERSION;

    while version >= 0x01 {
        let res = std::io::TcpStream::connect(ip.as_slice(), port);
        if res.is_err() {
            return Err(RCError::new(format!("Failed to connect to server at {}:{}", ip.as_slice(), port), ConnectionError));
        }

        let mut socket = res.unwrap();

        match send_startup(& mut socket, version, creds) {
            Ok(_) => return Ok(Client::new(socket, version)),
            Err(e) => println!("Error connecting with protocol version v{}: {}", version, e.desc)
        }
        version -= 1;
    }
    Err(RCError::new("Unable to find suitable protocol version (v1, v2, v3)", ReadError))
}
<|endoftext|>


<commit_before>
use ir::Value;

/// Keeps track of the users of a value.
#[derive(Clone,Debug)]
pub struct Users<'a>
{
    users: Vec<&'a Value>,
}

impl<'a> Users<'a>
{
    /// Creates a new user list.
    pub fn new<I>(users: I) -> Self
        where I: Iterator<Item=&'a Value> {

        Users {
            users: users.collect(),
        }
    }

    /// Gets the values that are users.
    pub fn users(&self) -> ::std::slice::Iter<&'a Value> {
        self.users.iter()
    }
}
<commit_msg>Removed lang::Users<commit_after><|endoftext|>


<commit_before>use std;

/// Struct that holds information about your app.
///
/// It's recommended to create a single `const` instance of `AppInfo`:
///
/// ```
/// use app_dirs::AppInfo;
/// const APP_INFO: AppInfo = AppInfo{name: "Awesome App", author: "Dedicated Dev"};
/// ```
///
/// # Caveats
/// Functions in this library sanitize any characters that could be
/// non-filename-safe from `name` and `author`. The resulting paths will be
/// more human-readable if you stick to **letters, numbers, spaces, hyphens,
/// underscores, and periods** for both properties.
///
/// The `author` property is currently only used by Windows, as macOS and *nix
/// specifications don't require it. Make sure your `name` string is unique!
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct AppInfo {
    /// Name of your app (e.g. "Hearthstone").
    pub name: &'static str,
    /// Author of your app (e.g. "Blizzard").
    pub author: &'static str,
}

/// Enum specifying the type of app data you want to store.
///
/// **Different platforms are NOT guaranteed to distinguish between each data
/// type.** Keep this in mind when choosing data file paths.
///
/// Example: Windows does not supported shared application data and does not
/// distinguish between config and data. Therefore, on Windows, all variants
/// except `UserCache` return the same path.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum AppDataType {
    /// User-specific app configuration data.
    UserConfig,
    /// User-specific arbitrary app data.
    UserData,
    /// User-specific app cache data.
    UserCache,
    /// System-wide arbitrary app data.
    SharedData,
    /// System-wide app configuration data.
    SharedConfig,
}

impl AppDataType {
    /// Returns `true` for non-user-specific data types.
    pub fn is_shared(&self) -> bool {
        use AppDataType::*;
        match *self {
            SharedData | SharedConfig => true,
            _ => false,
        }
    }
}

/// Error type for any `app_dirs` operation.
#[derive(Debug)]
pub enum AppDirsError {
    /// An I/O error occurred during the operation.
    Io(std::io::Error),
    /// App-specific directories are not properly supported by the system
    /// (e.g. required environment variables don't exist).
    NotSupported,
    /// App info given to this library was invalid (e.g. app name or author
    /// were empty).
    InvalidAppInfo,
}

impl From<std::io::Error> for AppDirsError {
    fn from(e: std::io::Error) -> Self {
        AppDirsError::Io(e)
    }
}
<commit_msg>impl std::error::Error for AppDirsError (closes #8)<commit_after>use std;

/// Struct that holds information about your app.
///
/// It's recommended to create a single `const` instance of `AppInfo`:
///
/// ```
/// use app_dirs::AppInfo;
/// const APP_INFO: AppInfo = AppInfo{name: "Awesome App", author: "Dedicated Dev"};
/// ```
///
/// # Caveats
/// Functions in this library sanitize any characters that could be
/// non-filename-safe from `name` and `author`. The resulting paths will be
/// more human-readable if you stick to **letters, numbers, spaces, hyphens,
/// underscores, and periods** for both properties.
///
/// The `author` property is currently only used by Windows, as macOS and *nix
/// specifications don't require it. Make sure your `name` string is unique!
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct AppInfo {
    /// Name of your app (e.g. "Hearthstone").
    pub name: &'static str,
    /// Author of your app (e.g. "Blizzard").
    pub author: &'static str,
}

/// Enum specifying the type of app data you want to store.
///
/// **Different platforms are NOT guaranteed to distinguish between each data
/// type.** Keep this in mind when choosing data file paths.
///
/// Example: Windows does not supported shared application data and does not
/// distinguish between config and data. Therefore, on Windows, all variants
/// except `UserCache` return the same path.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum AppDataType {
    /// User-specific app configuration data.
    UserConfig,
    /// User-specific arbitrary app data.
    UserData,
    /// User-specific app cache data.
    UserCache,
    /// System-wide arbitrary app data.
    SharedData,
    /// System-wide app configuration data.
    SharedConfig,
}

impl AppDataType {
    /// Returns `true` for non-user-specific data types.
    pub fn is_shared(&self) -> bool {
        use AppDataType::*;
        match *self {
            SharedData | SharedConfig => true,
            _ => false,
        }
    }
}

const ERR_NOT_SUPPORTED: &'static str = "App data directories not supported";
const ERR_INVALID_APP_INFO: &'static str = "Invalid app name or author";

/// Error type for any `app_dirs` operation.
#[derive(Debug)]
pub enum AppDirsError {
    /// An I/O error occurred during the operation.
    Io(std::io::Error),
    /// App-specific directories are not properly supported by the system
    /// (e.g. required environment variables don't exist).
    NotSupported,
    /// App info given to this library was invalid (e.g. app name or author
    /// were empty).
    InvalidAppInfo,
}

impl std::fmt::Display for AppDirsError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        use AppDirsError::*;
        match *self {
            Io(ref e) => e.fmt(f),
            NotSupported => f.write_str(ERR_NOT_SUPPORTED),
            InvalidAppInfo => f.write_str(ERR_INVALID_APP_INFO),
        }
    }
}

impl std::error::Error for AppDirsError {
    fn description(&self) -> &str {
        use AppDirsError::*;
        match *self {
            Io(ref e) => e.description(),
            NotSupported => "App data directories not supported",
            InvalidAppInfo => "Invalid app name or author",
        }
    }
    fn cause(&self) -> Option<&std::error::Error> {
        use AppDirsError::*;
        match *self {
            Io(ref e) => Some(e),
            NotSupported => None,
            InvalidAppInfo => None,
        }
    }
}

impl From<std::io::Error> for AppDirsError {
    fn from(e: std::io::Error) -> Self {
        AppDirsError::Io(e)
    }
}
<|endoftext|>


<commit_before>const VERSION: &'static str = env!("CARGO_PKG_VERSION");

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use clap::{App, AppSettings, Arg, ArgMatches};
use semver::{SemVerError, Version};

pub fn get_config() -> Config {
    let matches = build_cli_parser().get_matches();
    Config::from_matches(matches)
}

fn build_cli_parser<'a, 'b>() -> App<'a, 'b> {
    App::new("cargo-bump")
        .version(VERSION)
        .author("Wraithan McCarroll <xwraithanx@gmail.com>")
        .usage("cargo bump [FLAGS] [<version> | major | minor | patch]")
        .about("Increments the version number in Cargo.toml as specified.")
        .setting(AppSettings::ArgRequiredElseHelp)
        .version_short("v")
        .arg(
            Arg::with_name("bump")
                .possible_value("bump")
                .index(1)
                .required(true)
                .hidden(true),
        )
        .arg(Arg::with_name("version").index(2).help(
            "Version should be a semver (https://semver.org/) string or the \
             position of the current version to increment: major, minor or patch.",
        ))
}

fn search_up_for(root: &Path, target: &str) -> Option<PathBuf> {
    let mut current = root;

    loop {
        let potential = current.join(target);

        if fs::metadata(&potential).is_ok() {
            return Some(potential);
        }

        match current.parent() {
            Some(parent) => current = parent,
            None => return None,
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct Config {
    pub version: NewVersion,
    pub root: PathBuf,
    pub manifest: PathBuf,
}

impl Config {
    fn from_matches(matches: ArgMatches) -> Config {
        let cwd = env::current_dir().unwrap();
        let manifest =
            search_up_for(&cwd, "Cargo.toml").unwrap_or_else(|| panic!("couldn't find Cargo.toml"));
        let mut root = manifest.clone();
        root.pop();
        Config {
            version: NewVersion::from_str(matches.value_of("version").unwrap_or("patch")).expect(
                "Invalid semver version, expected version or major, minor, patch",
            ),
            root: root,
            manifest: manifest,
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum NewVersion {
    Replace(Version),
    Major,
    Minor,
    Patch,
}

impl FromStr for NewVersion {
    type Err = SemVerError;
    fn from_str(input: &str) -> Result<NewVersion, Self::Err> {
        Ok(match input {
            "major" => NewVersion::Major,
            "minor" => NewVersion::Minor,
            "patch" => NewVersion::Patch,
            _ => NewVersion::Replace(Version::parse(input)?),
        })
    }
}

#[cfg(test)]
mod tests {
    use super::{build_cli_parser, Config, NewVersion};
    use std::env;
    use semver::Version;

    fn test_config(input: Vec<&str>, version: NewVersion, git_tag: bool, message: &str) {
        let parser = build_cli_parser();
        let root = env::current_dir().unwrap();
        let mut manifest = root.clone();
        manifest.push("Cargo.toml");
        let matches = parser.get_matches_from_safe(input).unwrap();
        let config = Config::from_matches(matches);
        assert_eq!(config.version, version);
        assert_eq!(config.git_tag, git_tag);
        assert_eq!(&config.message, message);
        assert_eq!(config.root, root);
        assert_eq!(config.manifest, manifest);
    }

    #[test]
    fn bump_arg_only() {
        let input = vec!["cargo-bump", "bump"];
        test_config(input, NewVersion::Patch, true, "v%s")
    }

    #[test]
    fn version_arg_minor() {
        let input = vec!["cargo-bump", "bump", "minor"];
        test_config(input, NewVersion::Minor, true, "v%s")
    }

    #[test]
    fn version_arg_string_good() {
        let input = vec!["cargo-bump", "bump", "1.2.3"];
        test_config(
            input,
            NewVersion::Replace(Version::parse("1.2.3").unwrap()),
            true,
            "v%s",
        )
    }
}
<commit_msg>fix tests that referred to missing features<commit_after>const VERSION: &'static str = env!("CARGO_PKG_VERSION");

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use clap::{App, AppSettings, Arg, ArgMatches};
use semver::{SemVerError, Version};

pub fn get_config() -> Config {
    let matches = build_cli_parser().get_matches();
    Config::from_matches(matches)
}

fn build_cli_parser<'a, 'b>() -> App<'a, 'b> {
    App::new("cargo-bump")
        .version(VERSION)
        .author("Wraithan McCarroll <xwraithanx@gmail.com>")
        .usage("cargo bump [FLAGS] [<version> | major | minor | patch]")
        .about("Increments the version number in Cargo.toml as specified.")
        .setting(AppSettings::ArgRequiredElseHelp)
        .version_short("v")
        .arg(
            Arg::with_name("bump")
                .possible_value("bump")
                .index(1)
                .required(true)
                .hidden(true),
        )
        .arg(Arg::with_name("version").index(2).help(
            "Version should be a semver (https://semver.org/) string or the \
             position of the current version to increment: major, minor or patch.",
        ))
}

fn search_up_for(root: &Path, target: &str) -> Option<PathBuf> {
    let mut current = root;

    loop {
        let potential = current.join(target);

        if fs::metadata(&potential).is_ok() {
            return Some(potential);
        }

        match current.parent() {
            Some(parent) => current = parent,
            None => return None,
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct Config {
    pub version: NewVersion,
    pub root: PathBuf,
    pub manifest: PathBuf,
}

impl Config {
    fn from_matches(matches: ArgMatches) -> Config {
        let cwd = env::current_dir().unwrap();
        let manifest =
            search_up_for(&cwd, "Cargo.toml").unwrap_or_else(|| panic!("couldn't find Cargo.toml"));
        let mut root = manifest.clone();
        root.pop();
        Config {
            version: NewVersion::from_str(matches.value_of("version").unwrap_or("patch")).expect(
                "Invalid semver version, expected version or major, minor, patch",
            ),
            root: root,
            manifest: manifest,
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum NewVersion {
    Replace(Version),
    Major,
    Minor,
    Patch,
}

impl FromStr for NewVersion {
    type Err = SemVerError;
    fn from_str(input: &str) -> Result<NewVersion, Self::Err> {
        Ok(match input {
            "major" => NewVersion::Major,
            "minor" => NewVersion::Minor,
            "patch" => NewVersion::Patch,
            _ => NewVersion::Replace(Version::parse(input)?),
        })
    }
}

#[cfg(test)]
mod tests {
    use super::{build_cli_parser, Config, NewVersion};
    use std::env;
    use semver::Version;

    fn test_config(input: Vec<&str>, version: NewVersion) {
        let parser = build_cli_parser();
        let root = env::current_dir().unwrap();
        let mut manifest = root.clone();
        manifest.push("Cargo.toml");
        let matches = parser.get_matches_from_safe(input).unwrap();
        let config = Config::from_matches(matches);
        assert_eq!(config.version, version);
        assert_eq!(config.root, root);
        assert_eq!(config.manifest, manifest);
    }

    #[test]
    fn bump_arg_only() {
        let input = vec!["cargo-bump", "bump"];
        test_config(input, NewVersion::Patch)
    }

    #[test]
    fn version_arg_minor() {
        let input = vec!["cargo-bump", "bump", "minor"];
        test_config(input, NewVersion::Minor)
    }

    #[test]
    fn version_arg_string_good() {
        let input = vec!["cargo-bump", "bump", "1.2.3"];
        test_config(input, NewVersion::Replace(Version::parse("1.2.3").unwrap()))
    }
}
<|endoftext|>