<commit_before>use super::super::resource::*;
use super::super::HalLink;
use super::Test1;
use serde_json::{from_str, to_string};

//#[derive(Serialize, Deserialize)]
//struct Test1 {
//    a: String
//}

#[test]
fn check_data_gets_serialized() {
    let f: HalResource = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    let s = to_string(&f).unwrap();
    assert_eq!(s, r#"{"a":"Test"}"#);
}

#[test]
fn check_link_gets_serialized_without_empty_attributes() {
    let mut f: HalResource = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    f.with_link("self", "https://self.com");
    let s = to_string(&f).unwrap();
    assert_eq!(
        s,
        r#"{"_links":{"self":{"href":"https://self.com"}},"a":"Test"}"#
    );
}

#[test]
fn check_link_arrays_get_serialized() {
    let mut f: HalResource = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    f.with_link("self", "https://self.com")
        .with_link("alfa", "https://self.com/beta")
        .with_link("alfa", "https://self.com/gamma");
    let s = to_string(&f).unwrap();
    assert_eq!(s, r#"{"_links":{"alfa":[{"href":"https://self.com/beta"},{"href":"https://self.com/gamma"}],"self":{"href":"https://self.com"}},"a":"Test"}"#);
}

#[test]
fn check_links_get_fully_serialized() {
    let mut f: HalResource = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    f.with_link(
        "self",
        HalLink::new("https://self.com")
            .with_title("Self Link")
            .with_name("moi")
            .with_deprecation("http://explain.com/why"),
    );
    let s = to_string(&f).unwrap();
    assert_eq!(s, "{\"_links\":{\"self\":{\"href\":\"https://self.com\",\"deprecation\":\"http://explain.com/why\",\"name\":\"moi\",\"title\":\"Self Link\"}},\"a\":\"Test\"}");
}

#[test]
fn check_embedded_resource_gets_serialized() {
    let mut r1 = HalResource::new(Test1 {
        a: "Test2".to_string(),
    });
    r1.with_link("self", "https://self2.com");

    let mut f = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    f.with_link("self", "https://self.com")
        .with_resource("child", r1);

    let s = to_string(&f).unwrap();
    let target = "{\"_links\":{\"self\":{\"href\":\"https://self.com\"}},\"_embedded\":{\"child\":{\"_links\":{\"self\":{\"href\":\"https://self2.com\"}},\"a\":\"Test2\"}},\"a\":\"Test\"}";
    assert_eq!(s, target);
}

#[test]
fn check_curies_get_serialized_in_links() {
    let mut r1 = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    r1.with_curie("cur", "https://curie.org")
        .with_link("self", "https://self.com");
    let s = to_string(&r1).unwrap();
    let target = "{\"_links\":{\"curies\":[{\"href\":\"https://curie.org\",\"templated\":true,\"name\":\"cur\"}],\"self\":{\"href\":\"https://self.com\"}},\"a\":\"Test\"}";
    assert_eq!(s, target);
}

#[test]
fn check_simple_resource_gets_deserialized() {
    let source = r#"{ "_links":{"self":{"href": "https://www.test.com"}}, "a": "123"}"#;
    let hal: HalResource = from_str(source).unwrap();
    assert_eq!(hal.get_self(), Some(&HalLink::new("https://www.test.com")));
}

#[test]
fn check_extra_fields_get_serialized() {
    let mut f: HalResource = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    f.with_extra_data("int", 123);
    f.with_extra_data("string", "Hello!?");
    let s = to_string(&f).unwrap();
    assert_eq!(s, r#"{"a":"Test","int":123,"string":"Hello!?"}"#);
}

#[test]
fn check_extra_fields_get_deserialized() {
    let source = r#"{ "_links":{"self":{"href": "https://www.test.com"}}, "a": "123", "b":456}"#;
    let hal: HalResource = from_str(source).unwrap();
    assert_eq!(hal.get_extra_data::<i32>("b").unwrap(), 456);
}
<commit_msg>Add test<commit_after>use super::{
    super::{resource::*, HalLink},
    Test1,
};
use serde_json::{from_str, to_string};

//#[derive(Serialize, Deserialize)]
// struct Test1 {
//    a: String
//}

#[test]
fn check_data_gets_serialized() {
    let f: HalResource = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    let s = to_string(&f).unwrap();
    assert_eq!(s, r#"{"a":"Test"}"#);
}

#[test]
fn check_link_gets_serialized_without_empty_attributes() {
    let mut f: HalResource = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    f.with_link("self", "https://self.com");
    let s = to_string(&f).unwrap();
    assert_eq!(
        s,
        r#"{"_links":{"self":{"href":"https://self.com"}},"a":"Test"}"#
    );
}

#[test]
fn check_link_arrays_get_serialized() {
    let mut f: HalResource = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    f.with_link("self", "https://self.com")
        .with_link("alfa", "https://self.com/beta")
        .with_link("alfa", "https://self.com/gamma");
    let s = to_string(&f).unwrap();
    assert_eq!(s, r#"{"_links":{"alfa":[{"href":"https://self.com/beta"},{"href":"https://self.com/gamma"}],"self":{"href":"https://self.com"}},"a":"Test"}"#);
}

#[test]
fn check_links_get_fully_serialized() {
    let mut f: HalResource = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    f.with_link(
        "self",
        HalLink::new("https://self.com")
            .with_title("Self Link")
            .with_name("moi")
            .with_deprecation("http://explain.com/why"),
    );
    let s = to_string(&f).unwrap();
    assert_eq!(s, "{\"_links\":{\"self\":{\"href\":\"https://self.com\",\"deprecation\":\"http://explain.com/why\",\"name\":\"moi\",\"title\":\"Self Link\"}},\"a\":\"Test\"}");
}

#[test]
fn check_embedded_resource_gets_serialized() {
    let mut r1 = HalResource::new(Test1 {
        a: "Test2".to_string(),
    });
    r1.with_link("self", "https://self2.com");

    let mut f = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    f.with_link("self", "https://self.com")
        .with_resource("child", r1);

    let s = to_string(&f).unwrap();
    let target = "{\"_links\":{\"self\":{\"href\":\"https://self.com\"}},\"_embedded\":{\"child\":{\"_links\":{\"self\":{\"href\":\"https://self2.com\"}},\"a\":\"Test2\"}},\"a\":\"Test\"}";
    assert_eq!(s, target);
}

#[test]
fn check_curies_get_serialized_in_links() {
    let mut r1 = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    r1.with_curie("cur", "https://curie.org")
        .with_link("self", "https://self.com");
    let s = to_string(&r1).unwrap();
    let target = "{\"_links\":{\"curies\":[{\"href\":\"https://curie.org\",\"templated\":true,\"name\":\"cur\"}],\"self\":{\"href\":\"https://self.com\"}},\"a\":\"Test\"}";
    assert_eq!(s, target);
}

#[test]
fn check_simple_resource_gets_deserialized() {
    let source = r#"{ "_links":{"self":{"href": "https://www.test.com"}}, "a": "123"}"#;
    let hal: HalResource = from_str(source).unwrap();
    assert_eq!(hal.get_self(), Some(&HalLink::new("https://www.test.com")));
}

#[test]
fn check_extra_fields_get_serialized() {
    let mut f: HalResource = HalResource::new(Test1 {
        a: "Test".to_string(),
    });
    f.with_extra_data("int", 123);
    f.with_extra_data("string", "Hello!?");
    let s = to_string(&f).unwrap();
    assert_eq!(s, r#"{"a":"Test","int":123,"string":"Hello!?"}"#);
}

#[test]
fn check_extra_fields_get_deserialized() {
    let source = r#"{ "_links":{"self":{"href": "https://www.test.com"}}, "a": "123", "b":456}"#;
    let hal: HalResource = from_str(source).unwrap();
    assert_eq!(hal.get_extra_data::<i32>("b").unwrap(), 456);
}

#[test]
fn check_force_many_serializes_to_empty_array_if_empty_resources() {
    let mut resource = HalResource::new("");
    resource.with_resources("empty_array", Vec::new());

    let s = to_string(&resource).unwrap();
    assert_eq!(s, r#"{"_embedded":{"empty_array":[]}}"#);
}
<|endoftext|>


<commit_before>const BLOCK_SIZE: usize = 16;

use common::verify_length;

#[inline(always)]
unsafe fn transpose_block<T: Copy>(input: &[T], output: &mut [T], width: usize, height: usize, block_x: usize, block_y: usize) {
    for inner_x in 0..BLOCK_SIZE {
        for inner_y in 0..BLOCK_SIZE {
            let x = block_x * BLOCK_SIZE + inner_x;
            let y = block_y * BLOCK_SIZE + inner_y;

            let input_index = x + y * width;
            let output_index = y + x * height;

            *output.get_unchecked_mut(output_index) = *input.get_unchecked(input_index);
        }
    }
}

#[inline(always)]
unsafe fn transpose_endcap_block<T: Copy>(input: &[T], output: &mut [T], width: usize, height: usize, block_x: usize, block_y: usize, block_width: usize, block_height: usize) {
    for inner_x in 0..block_width {
        for inner_y in 0..block_height {
            let x = block_x * BLOCK_SIZE + inner_x;
            let y = block_y * BLOCK_SIZE + inner_y;

            let input_index = x + y * width;
            let output_index = y + x * height;

            *output.get_unchecked_mut(output_index) = *input.get_unchecked(input_index);
        }
    }
}

/// Given an array of size width * height, representing a flattened 2D array,
/// transpose the rows and columns of that 2D array into the output
// Use "Loop tiling" to improve cache-friendliness
pub fn transpose<T: Copy>(width: usize, height: usize, input: &[T], output: &mut [T]) {
    verify_length(input, output, width * height);

    let x_block_count = width / BLOCK_SIZE;
    let y_block_count = height / BLOCK_SIZE;

    let remainder_x = width - x_block_count * BLOCK_SIZE;
    let remainder_y = height - y_block_count * BLOCK_SIZE;

    for y_block in 0..y_block_count {
        for x_block in 0..x_block_count {
            unsafe {
                transpose_block(
                    input, output,
                    width, height,
                    x_block, y_block);
            }
        }

        //if the width is not cleanly divisible by block_size, there are still a few columns that haven't been transposed
        if remainder_x > 0 {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block_count, y_block,
                    remainder_x, BLOCK_SIZE);
            }
        }
    }

    //if the height is not cleanly divisible by BLOCK_SIZE, there are still a few columns that haven't been transposed
    if remainder_y > 0 {
        for x_block in 0..x_block_count {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block, y_block_count,
                    BLOCK_SIZE, remainder_y,
                    );
            }
        }

        //if the width is not cleanly divisible by block_size, there are still a few columns that haven't been transposed
        if remainder_x > 0 {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block_count, y_block_count,
                    remainder_x, remainder_y);
            }
        }
    }
}

/// Given an array of size width * height, representing a flattened 2D array,
/// transpose the rows and columns of that 2D array into the output
/// benchmarking shows that loop tiling isn't effective for small arrays (in the range of 50x50 or smaller)
pub unsafe fn transpose_small<T: Copy>(width: usize, height: usize, input: &[T], output: &mut [T]) {
    for x in 0..width {
        for y in 0..height {
            let input_index = x + y * width;
            let output_index = y + x * height;

            *output.get_unchecked_mut(output_index) = *input.get_unchecked(input_index);
        }
    }
}

#[cfg(test)]
mod unit_tests {
    use super::*;
    use test_utils::random_signal;
    use num::{Complex, Zero};

    #[test]
    fn test_transpose() {
        let sizes = [1, BLOCK_SIZE - 1, BLOCK_SIZE * 4, BLOCK_SIZE * 4 + 3];

        for &width in &sizes {
            for &height in &sizes {
                let len = width * height;

                let input: Vec<Complex<f32>> = random_signal(len);
                let mut output = vec![Zero::zero(); len];

                transpose(width, height, &input, &mut output);

                for x in 0..width {
                    for y in 0..height {
                        assert_eq!(input[x + y * width], output[y + x * height], "x = {}, y = {}", x, y);
                    }
                }

                transpose_small(width, height, &input, &mut output);

                for x in 0..width {
                    for y in 0..height {
                        assert_eq!(input[x + y * width], output[y + x * height], "x = {}, y = {}", x, y);
                    }
                }

            }
        }
    }
}
<commit_msg>Fixed failing test<commit_after>const BLOCK_SIZE: usize = 16;

use common::verify_length;

#[inline(always)]
unsafe fn transpose_block<T: Copy>(input: &[T], output: &mut [T], width: usize, height: usize, block_x: usize, block_y: usize) {
    for inner_x in 0..BLOCK_SIZE {
        for inner_y in 0..BLOCK_SIZE {
            let x = block_x * BLOCK_SIZE + inner_x;
            let y = block_y * BLOCK_SIZE + inner_y;

            let input_index = x + y * width;
            let output_index = y + x * height;

            *output.get_unchecked_mut(output_index) = *input.get_unchecked(input_index);
        }
    }
}

#[inline(always)]
unsafe fn transpose_endcap_block<T: Copy>(input: &[T], output: &mut [T], width: usize, height: usize, block_x: usize, block_y: usize, block_width: usize, block_height: usize) {
    for inner_x in 0..block_width {
        for inner_y in 0..block_height {
            let x = block_x * BLOCK_SIZE + inner_x;
            let y = block_y * BLOCK_SIZE + inner_y;

            let input_index = x + y * width;
            let output_index = y + x * height;

            *output.get_unchecked_mut(output_index) = *input.get_unchecked(input_index);
        }
    }
}

/// Given an array of size width * height, representing a flattened 2D array,
/// transpose the rows and columns of that 2D array into the output
// Use "Loop tiling" to improve cache-friendliness
pub fn transpose<T: Copy>(width: usize, height: usize, input: &[T], output: &mut [T]) {
    verify_length(input, output, width * height);

    let x_block_count = width / BLOCK_SIZE;
    let y_block_count = height / BLOCK_SIZE;

    let remainder_x = width - x_block_count * BLOCK_SIZE;
    let remainder_y = height - y_block_count * BLOCK_SIZE;

    for y_block in 0..y_block_count {
        for x_block in 0..x_block_count {
            unsafe {
                transpose_block(
                    input, output,
                    width, height,
                    x_block, y_block);
            }
        }

        //if the width is not cleanly divisible by block_size, there are still a few columns that haven't been transposed
        if remainder_x > 0 {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block_count, y_block,
                    remainder_x, BLOCK_SIZE);
            }
        }
    }

    //if the height is not cleanly divisible by BLOCK_SIZE, there are still a few columns that haven't been transposed
    if remainder_y > 0 {
        for x_block in 0..x_block_count {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block, y_block_count,
                    BLOCK_SIZE, remainder_y,
                    );
            }
        }

        //if the width is not cleanly divisible by block_size, there are still a few columns that haven't been transposed
        if remainder_x > 0 {
            unsafe {
                transpose_endcap_block(
                    input, output,
                    width, height,
                    x_block_count, y_block_count,
                    remainder_x, remainder_y);
            }
        }
    }
}

/// Given an array of size width * height, representing a flattened 2D array,
/// transpose the rows and columns of that 2D array into the output
/// benchmarking shows that loop tiling isn't effective for small arrays (in the range of 50x50 or smaller)
pub unsafe fn transpose_small<T: Copy>(width: usize, height: usize, input: &[T], output: &mut [T]) {
    for x in 0..width {
        for y in 0..height {
            let input_index = x + y * width;
            let output_index = y + x * height;

            *output.get_unchecked_mut(output_index) = *input.get_unchecked(input_index);
        }
    }
}

#[cfg(test)]
mod unit_tests {
    use super::*;
    use test_utils::random_signal;
    use num::{Complex, Zero};

    #[test]
    fn test_transpose() {
        let sizes = [1, BLOCK_SIZE - 1, BLOCK_SIZE * 4, BLOCK_SIZE * 4 + 3];

        for &width in &sizes {
            for &height in &sizes {
                let len = width * height;

                let input: Vec<Complex<f32>> = random_signal(len);
                let mut output = vec![Zero::zero(); len];

                transpose(width, height, &input, &mut output);

                for x in 0..width {
                    for y in 0..height {
                        assert_eq!(input[x + y * width], output[y + x * height], "x = {}, y = {}", x, y);
                    }
                }

                unsafe { transpose_small(width, height, &input, &mut output) };

                for x in 0..width {
                    for y in 0..height {
                        assert_eq!(input[x + y * width], output[y + x * height], "x = {}, y = {}", x, y);
                    }
                }

            }
        }
    }
}
<|endoftext|>


<commit_before>use llvm_sys::core::{LLVMInt1Type, LLVMInt8Type, LLVMInt16Type, LLVMInt32Type, LLVMInt64Type, LLVMConstInt, LLVMConstNull, LLVMConstAllOnes, LLVMIntType, LLVMGetIntTypeWidth, LLVMConstIntOfString};
use llvm_sys::execution_engine::LLVMCreateGenericValueOfInt;
use llvm_sys::prelude::LLVMTypeRef;

use std::ffi::{CString, CStr};

use context::ContextRef;
use types::traits::AsTypeRef;
use types::{Type, ArrayType, BasicType, VectorType, PointerType, FunctionType};
use values::{GenericValue, IntValue, PointerValue};

#[derive(Debug, PartialEq, Eq)]
pub struct IntType {
    int_type: Type,
}

impl IntType {
    pub(crate) fn new(int_type: LLVMTypeRef) -> Self {
        assert!(!int_type.is_null());

        IntType {
            int_type: Type::new(int_type),
        }
    }

    pub fn bool_type() -> Self {
        let type_ = unsafe {
            LLVMInt1Type()
        };

        IntType::new(type_)
    }

    pub fn i8_type() -> Self {
        let type_ = unsafe {
            LLVMInt8Type()
        };

        IntType::new(type_)
    }

    pub fn i16_type() -> Self {
        let type_ = unsafe {
            LLVMInt16Type()
        };

        IntType::new(type_)
    }

    pub fn i32_type() -> Self {
        let type_ = unsafe {
            LLVMInt32Type()
        };

        IntType::new(type_)
    }

    pub fn i64_type() -> Self {
        let type_ = unsafe {
            LLVMInt64Type()
        };

        IntType::new(type_)
    }

    pub fn i128_type() -> Self {
        // REVIEW: The docs says there's a LLVMInt128Type, but
        // it might only be in a newer version

        Self::custom_width_int_type(128)
    }

    pub fn custom_width_int_type(bits: u32) -> Self {
        let type_ = unsafe {
            LLVMIntType(bits)
        };

        IntType::new(type_)
    }

    pub fn const_int(&self, value: u64, sign_extend: bool) -> IntValue {
        let value = unsafe {
            LLVMConstInt(self.as_type_ref(), value, sign_extend as i32)
        };

        IntValue::new(value)
    }

    // REVIEW: What happens when string is invalid? Nullptr?
    // REVIEW: Difference of LLVMConstIntOfStringAndSize?
    pub fn const_int_from_string(&self, string: &str, radix: u8) -> IntValue {
        let c_string = CString::new(string).expect("Conversion to CString failed unexpectedly");

        let value = unsafe {
            LLVMConstIntOfString(self.as_type_ref(), c_string.as_ptr(), radix)
        };

        IntValue::new(value)
    }

    pub fn const_all_ones(&self) -> IntValue {
        let value = unsafe {
            LLVMConstAllOnes(self.as_type_ref())
        };

        IntValue::new(value)
    }

    pub fn const_null_ptr(&self) -> PointerValue {
        self.int_type.const_null_ptr()
    }

    pub fn const_null(&self) -> IntValue {
        let null = unsafe {
            LLVMConstNull(self.as_type_ref())
        };

        IntValue::new(null)
    }

    pub fn fn_type(&self, param_types: &[&BasicType], is_var_args: bool) -> FunctionType {
        self.int_type.fn_type(param_types, is_var_args)
    }

    pub fn array_type(&self, size: u32) -> ArrayType {
        self.int_type.array_type(size)
    }

    pub fn vec_type(&self, size: u32) -> VectorType {
        self.int_type.vec_type(size)
    }

    pub fn get_context(&self) -> ContextRef {
        self.int_type.get_context()
    }

    // REVIEW: Always true -> const fn?
    pub fn is_sized(&self) -> bool {
        self.int_type.is_sized()
    }

    pub fn size_of(&self) -> IntValue {
        self.int_type.size_of()
    }

    pub fn ptr_type(&self, address_space: u32) -> PointerType {
        self.int_type.ptr_type(address_space)
    }

    pub fn get_bit_width(&self) -> u32 {
        unsafe {
            LLVMGetIntTypeWidth(self.as_type_ref())
        }
    }

    pub fn print_to_string(&self) -> &CStr {
        self.int_type.print_to_string()
    }

    pub fn print_to_stderr(&self) {
        self.int_type.print_to_stderr()
    }

    pub fn get_undef(&self) -> IntValue {
        IntValue::new(self.int_type.get_undef())
    }

    pub fn create_generic_value(&self, value: u64, is_signed: bool) -> GenericValue {
        let value = unsafe {
            LLVMCreateGenericValueOfInt(self.as_type_ref(), value, is_signed as i32)
        };

        GenericValue::new(value)
    }
}

impl AsTypeRef for IntType {
    fn as_type_ref(&self) -> LLVMTypeRef {
        self.int_type.type_
    }
}
<commit_msg>Added doctests for IntTypes of the global context<commit_after>use llvm_sys::core::{LLVMInt1Type, LLVMInt8Type, LLVMInt16Type, LLVMInt32Type, LLVMInt64Type, LLVMConstInt, LLVMConstNull, LLVMConstAllOnes, LLVMIntType, LLVMGetIntTypeWidth, LLVMConstIntOfString};
use llvm_sys::execution_engine::LLVMCreateGenericValueOfInt;
use llvm_sys::prelude::LLVMTypeRef;

use std::ffi::{CString, CStr};

use context::ContextRef;
use types::traits::AsTypeRef;
use types::{Type, ArrayType, BasicType, VectorType, PointerType, FunctionType};
use values::{GenericValue, IntValue, PointerValue};

#[derive(Debug, PartialEq, Eq)]
pub struct IntType {
    int_type: Type,
}

impl IntType {
    pub(crate) fn new(int_type: LLVMTypeRef) -> Self {
        assert!(!int_type.is_null());

        IntType {
            int_type: Type::new(int_type),
        }
    }

    /// Gets the `IntType` representing 1 bit width. Will be automatically assigned the global context.
    ///
    /// To use your own context, see [inkwell::context::bool_type()](../../inkwell/context/struct.Context.html#method.bool_type)
    ///
    /// # Example
    /// ```
    /// use inkwell::context::Context;
    /// use inkwell::types::IntType;
    ///
    /// let bool_type = IntType::bool_type();
    ///
    /// assert_eq!(bool_type.get_bit_width(), 1);
    /// assert_eq!(bool_type.get_context(), Context::get_global());
    /// ```
    pub fn bool_type() -> Self {
        let type_ = unsafe {
            LLVMInt1Type()
        };

        IntType::new(type_)
    }

    /// Gets the `IntType` representing 8 bit width. Will be automatically assigned the global context.
    ///
    /// To use your own context, see [inkwell::context::i8_type()](../../inkwell/context/struct.Context.html#method.i8_type)
    ///
    /// # Example
    /// ```
    /// use inkwell::context::Context;
    /// use inkwell::types::IntType;
    ///
    /// let i8_type = IntType::i8_type();
    ///
    /// assert_eq!(i8_type.get_bit_width(), 8);
    /// assert_eq!(i8_type.get_context(), Context::get_global());
    /// ```
    pub fn i8_type() -> Self {
        let type_ = unsafe {
            LLVMInt8Type()
        };

        IntType::new(type_)
    }

    /// Gets the `IntType` representing 16 bit width. Will be automatically assigned the global context.
    ///
    /// To use your own context, see [inkwell::context::i16_type()](../../inkwell/context/struct.Context.html#method.i16_type)
    ///
    /// # Example
    /// ```
    /// use inkwell::context::Context;
    /// use inkwell::types::IntType;
    ///
    /// let i16_type = IntType::i16_type();
    ///
    /// assert_eq!(i16_type.get_bit_width(), 16);
    /// assert_eq!(i16_type.get_context(), Context::get_global());
    /// ```
    pub fn i16_type() -> Self {
        let type_ = unsafe {
            LLVMInt16Type()
        };

        IntType::new(type_)
    }

    /// Gets the `IntType` representing 32 bit width. Will be automatically assigned the global context.
    ///
    /// To use your own context, see [inkwell::context::i32_type()](../../inkwell/context/struct.Context.html#method.i32_type)
    ///
    /// # Example
    /// ```
    /// use inkwell::context::Context;
    /// use inkwell::types::IntType;
    ///
    /// let i32_type = IntType::i32_type();
    ///
    /// assert_eq!(i32_type.get_bit_width(), 32);
    /// assert_eq!(i32_type.get_context(), Context::get_global());
    /// ```
    pub fn i32_type() -> Self {
        let type_ = unsafe {
            LLVMInt32Type()
        };

        IntType::new(type_)
    }

    /// Gets the `IntType` representing 64 bit width. Will be automatically assigned the global context.
    ///
    /// To use your own context, see [inkwell::context::i64_type()](../../inkwell/context/struct.Context.html#method.i64_type)
    ///
    /// # Example
    /// ```
    /// use inkwell::context::Context;
    /// use inkwell::types::IntType;
    ///
    /// let i64_type = IntType::i64_type();
    ///
    /// assert_eq!(i64_type.get_bit_width(), 64);
    /// assert_eq!(i64_type.get_context(), Context::get_global());
    /// ```
    pub fn i64_type() -> Self {
        let type_ = unsafe {
            LLVMInt64Type()
        };

        IntType::new(type_)
    }

    /// Gets the `IntType` representing 128 bit width. Will be automatically assigned the global context.
    ///
    /// To use your own context, see [inkwell::context::i128_type()](../../inkwell/context/struct.Context.html#method.i128_type)
    ///
    /// # Example
    /// ```
    /// use inkwell::context::Context;
    /// use inkwell::types::IntType;
    ///
    /// let i128_type = IntType::i128_type();
    ///
    /// assert_eq!(i128_type.get_bit_width(), 128);
    /// assert_eq!(i128_type.get_context(), Context::get_global());
    /// ```
    pub fn i128_type() -> Self {
        // REVIEW: The docs says there's a LLVMInt128Type, but
        // it might only be in a newer version

        Self::custom_width_int_type(128)
    }

    /// Gets the `IntType` representing a custom bit width. Will be automatically assigned the global context.
    ///
    /// To use your own context, see [inkwell::context::custom_width_int_type()](../../inkwell/context/struct.Context.html#method.custom_width_int_type)
    ///
    /// # Example
    /// ```
    /// use inkwell::context::Context;
    /// use inkwell::types::IntType;
    ///
    /// let i42_type = IntType::custom_width_int_type(42);
    ///
    /// assert_eq!(i42_type.get_bit_width(), 42);
    /// assert_eq!(i42_type.get_context(), Context::get_global());
    /// ```
    pub fn custom_width_int_type(bits: u32) -> Self {
        let type_ = unsafe {
            LLVMIntType(bits)
        };

        IntType::new(type_)
    }

    pub fn const_int(&self, value: u64, sign_extend: bool) -> IntValue {
        let value = unsafe {
            LLVMConstInt(self.as_type_ref(), value, sign_extend as i32)
        };

        IntValue::new(value)
    }

    // REVIEW: What happens when string is invalid? Nullptr?
    // REVIEW: Difference of LLVMConstIntOfStringAndSize?
    pub fn const_int_from_string(&self, string: &str, radix: u8) -> IntValue {
        let c_string = CString::new(string).expect("Conversion to CString failed unexpectedly");

        let value = unsafe {
            LLVMConstIntOfString(self.as_type_ref(), c_string.as_ptr(), radix)
        };

        IntValue::new(value)
    }

    pub fn const_all_ones(&self) -> IntValue {
        let value = unsafe {
            LLVMConstAllOnes(self.as_type_ref())
        };

        IntValue::new(value)
    }

    pub fn const_null_ptr(&self) -> PointerValue {
        self.int_type.const_null_ptr()
    }

    pub fn const_null(&self) -> IntValue {
        let null = unsafe {
            LLVMConstNull(self.as_type_ref())
        };

        IntValue::new(null)
    }

    pub fn fn_type(&self, param_types: &[&BasicType], is_var_args: bool) -> FunctionType {
        self.int_type.fn_type(param_types, is_var_args)
    }

    pub fn array_type(&self, size: u32) -> ArrayType {
        self.int_type.array_type(size)
    }

    pub fn vec_type(&self, size: u32) -> VectorType {
        self.int_type.vec_type(size)
    }

    pub fn get_context(&self) -> ContextRef {
        self.int_type.get_context()
    }

    // REVIEW: Always true -> const fn?
    pub fn is_sized(&self) -> bool {
        self.int_type.is_sized()
    }

    pub fn size_of(&self) -> IntValue {
        self.int_type.size_of()
    }

    pub fn ptr_type(&self, address_space: u32) -> PointerType {
        self.int_type.ptr_type(address_space)
    }

    pub fn get_bit_width(&self) -> u32 {
        unsafe {
            LLVMGetIntTypeWidth(self.as_type_ref())
        }
    }

    pub fn print_to_string(&self) -> &CStr {
        self.int_type.print_to_string()
    }

    pub fn print_to_stderr(&self) {
        self.int_type.print_to_stderr()
    }

    pub fn get_undef(&self) -> IntValue {
        IntValue::new(self.int_type.get_undef())
    }

    pub fn create_generic_value(&self, value: u64, is_signed: bool) -> GenericValue {
        let value = unsafe {
            LLVMCreateGenericValueOfInt(self.as_type_ref(), value, is_signed as i32)
        };

        GenericValue::new(value)
    }
}

impl AsTypeRef for IntType {
    fn as_type_ref(&self) -> LLVMTypeRef {
        self.int_type.type_
    }
}
<|endoftext|>


<commit_before>//! TODO Documentation
use std::{fmt, panic};
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use errors::{UpgradeHandleErr, UpgradeHandleResult};
use wlroots_sys::{wlr_input_device, wlr_key_state, wlr_keyboard, wlr_keyboard_get_modifiers,
                  wlr_keyboard_led, wlr_keyboard_led_update, wlr_keyboard_modifier,
                  wlr_keyboard_set_keymap};

use xkbcommon::xkb::{self, Keycode, Keymap, LedIndex, ModIndex, ModMask};

use InputDevice;

pub type KeyState = wlr_key_state;

/// The masks for each group of modifiers.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct ModifierMasks {
    pub depressed: ModMask,
    pub latched: ModMask,
    pub locked: ModMask,
    pub group: ModMask
}

/// Information about repeated keypresses for a particular Keyboard.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct RepeatInfo {
    /// The rate at which extended keypresses will fire more events.
    rate: i32,
    /// How long it takes for a keypress to register on this device.
    delay: i32
}

pub struct Keyboard {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `KeyboardHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `KeyboardHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard,
    /// The keymap used by wlroots.
    /// Stored here so that we can ensure you can only borrow the keymap
    /// as long as the keyboard.
    ///
    /// NOTE We have it marked as manually drop because otherwise
    /// we'd unref it twice (once here and again in wlroots).
    keymap: Option<ManuallyDrop<Keymap>>,
    /// The keyboard state used by wlroots.
    /// Stored here so that we can ensure you can only borrow the state
    /// as long as the keyboard.
    ///
    /// NOTE We have it marked as manually drop because otherwise
    /// we'd unref it twice (once here and again in wlroots).
    #[allow(dead_code)]
    xkb_state: Option<ManuallyDrop<xkb::State>>
}

pub struct KeyboardHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the keyboard associated with this handle,
    handle: Weak<AtomicBool>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard,
    /// The keymap used by wlroots.
    /// Stored here so that we can ensure you can only borrow the keymap
    /// as long as the keyboard.
    ///
    /// NOTE We have it marked as manually drop because otherwise
    /// we'd unref it twice (once here and again in wlroots).
    #[allow(dead_code)]
    keymap: Option<ManuallyDrop<Keymap>>,
    /// The keyboard state used by wlroots.
    /// Stored here so that we can ensure you can only borrow the state
    /// as long as the keyboard.
    ///
    /// NOTE We have it marked as manually drop because otherwise
    /// we'd unref it twice (once here and again in wlroots).
    #[allow(dead_code)]
    xkb_state: Option<ManuallyDrop<xkb::State>>
}

impl Keyboard {
    /// Tries to convert an input device to a Keyboard
    ///
    /// Returns None if it is of a different type of input variant.
    ///
    /// # Safety
    /// This creates a totally new Keyboard (e.g with its own reference count)
    /// so only do this once per `wlr_input_device`!
    pub(crate) unsafe fn new_from_input_device(device: *mut wlr_input_device) -> Option<Self> {
        use wlroots_sys::wlr_input_device_type::*;
        match (*device).type_ {
            WLR_INPUT_DEVICE_KEYBOARD => {
                let keyboard = (*device).__bindgen_anon_1.keyboard;
                Some(Keyboard { liveliness: Some(Rc::new(AtomicBool::new(false))),
                                device: InputDevice::from_ptr(device),
                                keyboard,
                                keymap: None,
                                xkb_state: None })
            }
            _ => None
        }
    }

    unsafe fn from_handle(handle: &KeyboardHandle) -> Self {
        Keyboard { liveliness: None,
                   device: handle.input_device().clone(),
                   keyboard: handle.as_ptr(),
                   keymap: None,
                   xkb_state: None }
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Set the keymap for this Keyboard.
    pub fn set_keymap(&mut self, keymap: &Keymap) {
        unsafe {
            // NOTE wlr_keyboard_set_keymap updates the reference count,
            // so we don't need to mem::forget the key map here
            // or take it by value.
            wlr_keyboard_set_keymap(self.keyboard, keymap.get_raw_ptr() as _);
        }
    }

    /// Get the XKB keymap associated with this Keyboard.
    pub fn get_keymap(&mut self) -> Option<&Keymap> {
        unsafe {
            let keymap_ptr = (*self.keyboard).keymap as *mut _;
            if keymap_ptr.is_null() {
                None
            } else {
                self.keymap = Some(ManuallyDrop::new(Keymap::from_raw_ptr(keymap_ptr)));
                self.keymap.as_ref().map(Deref::deref)
            }
        }
    }

    /// Get the keycodes for this keyboard as reported by XKB.
    ///
    /// # Limitations
    /// wlroots limits this list to `WLR_KEYBOARD_KEYS_CAP` elements,
    /// which at the time of writing is `32`.
    pub fn keycodes(&self) -> Vec<Keycode> {
        unsafe {
            let mut result = (*self.keyboard).keycodes.to_vec();
            result.truncate((*self.keyboard).num_keycodes);
            result
        }
    }

    /// Get the list of LEDs for this keyboard as reported by XKB.
    pub fn led_list(&self) -> Vec<LedIndex> {
        unsafe { (*self.keyboard).led_indexes.to_vec() }
    }

    /// Get the list of modifiers for this keyboard as reported by XKB.
    pub fn modifier_list(&self) -> Vec<ModIndex> {
        unsafe { (*self.keyboard).mod_indexes.to_vec() }
    }

    /// Get the size of the keymap.
    pub fn keymap_size(&self) -> usize {
        unsafe { (*self.keyboard).keymap_size }
    }

    /// Get the XKB state associated with this `Keyboard`.
    pub fn get_xkb_state(&mut self) -> Option<&xkb::State> {
        unsafe {
            let xkb_state_ptr = (*self.keyboard).xkb_state as *mut _;
            if xkb_state_ptr.is_null() {
                None
            } else {
                self.xkb_state = Some(ManuallyDrop::new(xkb::State::from_raw_ptr(xkb_state_ptr)));
                self.xkb_state.as_ref().map(Deref::deref)
            }
        }
    }

    /// Get the repeat info for this keyboard.
    pub fn repeat_info(&self) -> RepeatInfo {
        unsafe {
            RepeatInfo { rate: (*self.keyboard).repeat_info.rate,
                         delay: (*self.keyboard).repeat_info.delay }
        }
    }

    /// Update the LED lights using the provided bitmap.
    ///
    /// 1 means one, 0 means off.
    pub fn update_led(&mut self, leds: KeyboardLed) {
        unsafe {
            wlr_keyboard_led_update(self.keyboard, leds.bits() as u32);
        }
    }

    /// Get the modifiers that are currently pressed on the keyboard.
    pub fn get_modifiers(&self) -> KeyboardModifier {
        unsafe {
            KeyboardModifier::from_bits_truncate(wlr_keyboard_get_modifiers(self.keyboard))
        }
    }

    /// Get the modifier masks for each group.
    pub fn get_modifier_masks(&self) -> ModifierMasks {
        unsafe {
            ModifierMasks { depressed: (*self.keyboard).modifiers.depressed,
                            latched: (*self.keyboard).modifiers.latched,
                            locked: (*self.keyboard).modifiers.locked,
                            group: (*self.keyboard).modifiers.group }
        }
    }

    /// Creates a weak reference to a `Keyboard`.
    ///
    /// # Panics
    /// If this `Keyboard` is a previously upgraded `KeyboardHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> KeyboardHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade previously upgraded KeyboardHandle!");
        KeyboardHandle { handle: Rc::downgrade(arc),
                         // NOTE Rationale for cloning:
                         // We can't use the keyboard handle unless the keyboard is alive,
                         // which means the device pointer is still alive.
                         device: unsafe { self.device.clone() },
                         keyboard: self.keyboard,
                         keymap: None,
                         xkb_state: None }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Keyboard")
            .store(val, Ordering::Release);
    }
}

impl Drop for Keyboard {
    fn drop(&mut self) {
        match self.liveliness {
            None => {}
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped Keyboard {:p}", self.keyboard);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Keyboard {:p}",
                                 weak_count,
                                 self.keyboard);
                    }
                }
            }
        }
    }
}

impl fmt::Debug for Keyboard {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f,
               "Keyboard {{ device: {:?}, keyboard: {:?} }}",
               self.device, self.keyboard)
    }
}

impl KeyboardHandle {
    /// Upgrades the keyboard handle to a reference to the backing `Keyboard`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbounded `Keyboard`
    /// which may live forever..
    /// But no keyboard lives forever and might be disconnected at any time.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Keyboard> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::DoubleUpgrade)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let keyboard = Keyboard::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(keyboard)
            })
    }

    /// Run a function on the referenced Keyboard, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Keyboard does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<Option<R>>
        where F: FnOnce(&mut Keyboard) -> R
    {
        let mut keyboard = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Some(runner(&mut keyboard))));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running keyboard callback, mutable \
                                                    lock was false for: {:?}",
                                                   keyboard);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }
}

impl fmt::Debug for KeyboardHandle {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f,
               "Keyboard {{ device: {:?}, keyboard: {:?} }}",
               self.device, self.keyboard)
    }
}

bitflags! {
    pub struct KeyboardLed: u32 {
        const WLR_LED_NUM_LOCK = wlr_keyboard_led::WLR_LED_NUM_LOCK as u32;
        const WLR_LED_CAPS_LOCK = wlr_keyboard_led::WLR_LED_CAPS_LOCK as u32;
        const WLR_LED_SCROLL_LOCK = wlr_keyboard_led::WLR_LED_SCROLL_LOCK as u32;
    }
}

bitflags! {
    pub struct KeyboardModifier: u32 {
        const WLR_MODIFIER_SHIFT = wlr_keyboard_modifier::WLR_MODIFIER_SHIFT as u32;
        const WLR_MODIFIER_CAPS = wlr_keyboard_modifier::WLR_MODIFIER_CAPS as u32;
        const WLR_MODIFIER_CTRL = wlr_keyboard_modifier::WLR_MODIFIER_CTRL as u32;
        const WLR_MODIFIER_ALT = wlr_keyboard_modifier::WLR_MODIFIER_ALT as u32;
        const WLR_MODIFIER_MOD2 = wlr_keyboard_modifier::WLR_MODIFIER_MOD2 as u32;
        const WLR_MODIFIER_MOD3 = wlr_keyboard_modifier::WLR_MODIFIER_MOD3 as u32;
        const WLR_MODIFIER_LOGO = wlr_keyboard_modifier::WLR_MODIFIER_LOGO as u32;
        const WLR_MODIFIER_MOD5 = wlr_keyboard_modifier::WLR_MODIFIER_MOD5 as u32;
    }
}

impl fmt::Display for KeyboardModifier {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let mod_vec = vec![("Shift", KeyboardModifier::WLR_MODIFIER_SHIFT),
                           ("Caps lock", KeyboardModifier::WLR_MODIFIER_CAPS),
                           ("Ctrl", KeyboardModifier::WLR_MODIFIER_CTRL),
                           ("Alt", KeyboardModifier::WLR_MODIFIER_ALT),
                           ("Mod2", KeyboardModifier::WLR_MODIFIER_MOD2),
                           ("Mod3", KeyboardModifier::WLR_MODIFIER_MOD3),
                           ("Logo", KeyboardModifier::WLR_MODIFIER_LOGO),
                           ("Mod5", KeyboardModifier::WLR_MODIFIER_MOD5)];

        let mods: Vec<&str> = mod_vec.into_iter()
                                     .filter(|&(_, flag)| self.contains(flag))
                                     .map(|(st, _)| st)
                                     .collect();

        write!(formatter, "{:?}", mods)
    }
}
<commit_msg>xkb stuff is reference counted, safe to return<commit_after>//! TODO Documentation
use std::{fmt, panic};
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use errors::{UpgradeHandleErr, UpgradeHandleResult};
use wlroots_sys::{wlr_input_device, wlr_key_state, wlr_keyboard, wlr_keyboard_get_modifiers,
                  wlr_keyboard_led, wlr_keyboard_led_update, wlr_keyboard_modifier,
                  wlr_keyboard_set_keymap};

use xkbcommon::xkb::{self, Keycode, Keymap, LedIndex, ModIndex, ModMask};

use InputDevice;

pub type KeyState = wlr_key_state;

/// The masks for each group of modifiers.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct ModifierMasks {
    pub depressed: ModMask,
    pub latched: ModMask,
    pub locked: ModMask,
    pub group: ModMask
}

/// Information about repeated keypresses for a particular Keyboard.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct RepeatInfo {
    /// The rate at which extended keypresses will fire more events.
    rate: i32,
    /// How long it takes for a keypress to register on this device.
    delay: i32
}

pub struct Keyboard {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `KeyboardHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `KeyboardHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

pub struct KeyboardHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the keyboard associated with this handle,
    handle: Weak<AtomicBool>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

impl Keyboard {
    /// Tries to convert an input device to a Keyboard
    ///
    /// Returns None if it is of a different type of input variant.
    ///
    /// # Safety
    /// This creates a totally new Keyboard (e.g with its own reference count)
    /// so only do this once per `wlr_input_device`!
    pub(crate) unsafe fn new_from_input_device(device: *mut wlr_input_device) -> Option<Self> {
        use wlroots_sys::wlr_input_device_type::*;
        match (*device).type_ {
            WLR_INPUT_DEVICE_KEYBOARD => {
                let keyboard = (*device).__bindgen_anon_1.keyboard;
                Some(Keyboard { liveliness: Some(Rc::new(AtomicBool::new(false))),
                                device: InputDevice::from_ptr(device),
                                keyboard })
            }
            _ => None
        }
    }

    unsafe fn from_handle(handle: &KeyboardHandle) -> Self {
        Keyboard { liveliness: None,
                   device: handle.input_device().clone(),
                   keyboard: handle.as_ptr() }
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Set the keymap for this Keyboard.
    pub fn set_keymap(&mut self, keymap: &Keymap) {
        unsafe {
            // NOTE wlr_keyboard_set_keymap updates the reference count,
            // so we don't need to mem::forget the key map here
            // or take it by value.
            wlr_keyboard_set_keymap(self.keyboard, keymap.get_raw_ptr() as _);
        }
    }

    /// Get the XKB keymap associated with this Keyboard.
    pub fn get_keymap(&mut self) -> Option<Keymap> {
        unsafe {
            let keymap_ptr = (*self.keyboard).keymap as *mut _;
            if keymap_ptr.is_null() {
                None
            } else {
                Some(Keymap::from_raw_ptr(keymap_ptr))
            }
        }
    }

    /// Get the keycodes for this keyboard as reported by XKB.
    ///
    /// # Limitations
    /// wlroots limits this list to `WLR_KEYBOARD_KEYS_CAP` elements,
    /// which at the time of writing is `32`.
    pub fn keycodes(&self) -> Vec<Keycode> {
        unsafe {
            let mut result = (*self.keyboard).keycodes.to_vec();
            result.truncate((*self.keyboard).num_keycodes);
            result
        }
    }

    /// Get the list of LEDs for this keyboard as reported by XKB.
    pub fn led_list(&self) -> Vec<LedIndex> {
        unsafe { (*self.keyboard).led_indexes.to_vec() }
    }

    /// Get the list of modifiers for this keyboard as reported by XKB.
    pub fn modifier_list(&self) -> Vec<ModIndex> {
        unsafe { (*self.keyboard).mod_indexes.to_vec() }
    }

    /// Get the size of the keymap.
    pub fn keymap_size(&self) -> usize {
        unsafe { (*self.keyboard).keymap_size }
    }

    /// Get the XKB state associated with this `Keyboard`.
    pub fn get_xkb_state(&mut self) -> Option<xkb::State> {
        unsafe {
            let xkb_state_ptr = (*self.keyboard).xkb_state as *mut _;
            if xkb_state_ptr.is_null() {
                None
            } else {
                Some(xkb::State::from_raw_ptr(xkb_state_ptr))
            }
        }
    }

    /// Get the repeat info for this keyboard.
    pub fn repeat_info(&self) -> RepeatInfo {
        unsafe {
            RepeatInfo { rate: (*self.keyboard).repeat_info.rate,
                         delay: (*self.keyboard).repeat_info.delay }
        }
    }

    /// Update the LED lights using the provided bitmap.
    ///
    /// 1 means one, 0 means off.
    pub fn update_led(&mut self, leds: KeyboardLed) {
        unsafe {
            wlr_keyboard_led_update(self.keyboard, leds.bits() as u32);
        }
    }

    /// Get the modifiers that are currently pressed on the keyboard.
    pub fn get_modifiers(&self) -> KeyboardModifier {
        unsafe {
            KeyboardModifier::from_bits_truncate(wlr_keyboard_get_modifiers(self.keyboard))
        }
    }

    /// Get the modifier masks for each group.
    pub fn get_modifier_masks(&self) -> ModifierMasks {
        unsafe {
            ModifierMasks { depressed: (*self.keyboard).modifiers.depressed,
                            latched: (*self.keyboard).modifiers.latched,
                            locked: (*self.keyboard).modifiers.locked,
                            group: (*self.keyboard).modifiers.group }
        }
    }

    /// Creates a weak reference to a `Keyboard`.
    ///
    /// # Panics
    /// If this `Keyboard` is a previously upgraded `KeyboardHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> KeyboardHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade previously upgraded KeyboardHandle!");
        KeyboardHandle { handle: Rc::downgrade(arc),
                         // NOTE Rationale for cloning:
                         // We can't use the keyboard handle unless the keyboard is alive,
                         // which means the device pointer is still alive.
                         device: unsafe { self.device.clone() },
                         keyboard: self.keyboard }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Keyboard")
            .store(val, Ordering::Release);
    }
}

impl Drop for Keyboard {
    fn drop(&mut self) {
        match self.liveliness {
            None => {}
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped Keyboard {:p}", self.keyboard);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Keyboard {:p}",
                                 weak_count,
                                 self.keyboard);
                    }
                }
            }
        }
    }
}

impl fmt::Debug for Keyboard {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f,
               "Keyboard {{ device: {:?}, keyboard: {:?} }}",
               self.device, self.keyboard)
    }
}

impl KeyboardHandle {
    /// Upgrades the keyboard handle to a reference to the backing `Keyboard`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbounded `Keyboard`
    /// which may live forever..
    /// But no keyboard lives forever and might be disconnected at any time.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Keyboard> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::DoubleUpgrade)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let keyboard = Keyboard::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(keyboard)
            })
    }

    /// Run a function on the referenced Keyboard, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Keyboard does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<Option<R>>
        where F: FnOnce(&mut Keyboard) -> R
    {
        let mut keyboard = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Some(runner(&mut keyboard))));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running keyboard callback, mutable \
                                                    lock was false for: {:?}",
                                                   keyboard);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }
}

impl fmt::Debug for KeyboardHandle {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f,
               "Keyboard {{ device: {:?}, keyboard: {:?} }}",
               self.device, self.keyboard)
    }
}

bitflags! {
    pub struct KeyboardLed: u32 {
        const WLR_LED_NUM_LOCK = wlr_keyboard_led::WLR_LED_NUM_LOCK as u32;
        const WLR_LED_CAPS_LOCK = wlr_keyboard_led::WLR_LED_CAPS_LOCK as u32;
        const WLR_LED_SCROLL_LOCK = wlr_keyboard_led::WLR_LED_SCROLL_LOCK as u32;
    }
}

bitflags! {
    pub struct KeyboardModifier: u32 {
        const WLR_MODIFIER_SHIFT = wlr_keyboard_modifier::WLR_MODIFIER_SHIFT as u32;
        const WLR_MODIFIER_CAPS = wlr_keyboard_modifier::WLR_MODIFIER_CAPS as u32;
        const WLR_MODIFIER_CTRL = wlr_keyboard_modifier::WLR_MODIFIER_CTRL as u32;
        const WLR_MODIFIER_ALT = wlr_keyboard_modifier::WLR_MODIFIER_ALT as u32;
        const WLR_MODIFIER_MOD2 = wlr_keyboard_modifier::WLR_MODIFIER_MOD2 as u32;
        const WLR_MODIFIER_MOD3 = wlr_keyboard_modifier::WLR_MODIFIER_MOD3 as u32;
        const WLR_MODIFIER_LOGO = wlr_keyboard_modifier::WLR_MODIFIER_LOGO as u32;
        const WLR_MODIFIER_MOD5 = wlr_keyboard_modifier::WLR_MODIFIER_MOD5 as u32;
    }
}

impl fmt::Display for KeyboardModifier {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let mod_vec = vec![("Shift", KeyboardModifier::WLR_MODIFIER_SHIFT),
                           ("Caps lock", KeyboardModifier::WLR_MODIFIER_CAPS),
                           ("Ctrl", KeyboardModifier::WLR_MODIFIER_CTRL),
                           ("Alt", KeyboardModifier::WLR_MODIFIER_ALT),
                           ("Mod2", KeyboardModifier::WLR_MODIFIER_MOD2),
                           ("Mod3", KeyboardModifier::WLR_MODIFIER_MOD3),
                           ("Logo", KeyboardModifier::WLR_MODIFIER_LOGO),
                           ("Mod5", KeyboardModifier::WLR_MODIFIER_MOD5)];

        let mods: Vec<&str> = mod_vec.into_iter()
                                     .filter(|&(_, flag)| self.contains(flag))
                                     .map(|(st, _)| st)
                                     .collect();

        write!(formatter, "{:?}", mods)
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidRowCount(usize),
    InvalidColumnCount(usize),
}

pub fn convert(input: &str) -> Result<String, Error> {
    let line_count = input.lines().count();
    if line_count % 4 != 0 {
        return Err(Error::InvalidRowCount(line_count));
    }
    for line in input.lines() {
        let char_count = line.chars().count();
        if char_count % 3 != 0 {
            return Err(Error::InvalidColumnCount(char_count));
        }
    }

    let y = input.lines().collect::<Vec<_>>();

    let mut converted_lines = vec![];

    for char_lines in y.chunks(4) {
        let mut unparsed_characters = BTreeMap::new();

        for line in char_lines {
            let line_chars = line.chars().collect::<Vec<_>>();

            for (char_number, char_chunk) in line_chars.chunks(3).enumerate() {
                let char_chars = unparsed_characters.entry(char_number).or_insert_with(Vec::new);
                for c in char_chunk {
                    char_chars.push(*c);
                }
            }
        }

        let mut parsed_characters = String::new();

        for (_, v) in unparsed_characters {
            parsed_characters.push(convert_character(&v));
        }

        converted_lines.push(parsed_characters.to_string());
    }

    Ok(converted_lines.join(","))
}

fn convert_character(input: &Vec<char>) -> char {
    if &input[..] == [' ', '_', ' ', '|', ' ', '|', '|', '_', '|', ' ', ' ', ' '] {
        '0'
    } else if &input[..] == [' ', ' ', ' ', ' ', ' ', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '1'
    } else if &input[..] == [' ', '_', ' ', ' ', '_', '|', '|', '_', ' ', ' ', ' ', ' '] {
        '2'
    } else if &input[..] == [' ', '_', ' ', ' ', '_', '|', ' ', '_', '|', ' ', ' ', ' '] {
        '3'
    } else if &input[..] == [' ', ' ', ' ', '|', '_', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '4'
    } else if &input[..] == [' ', '_', ' ', '|', '_', ' ', ' ', '_', '|', ' ', ' ', ' '] {
        '5'
    } else if &input[..] == [' ', '_', ' ', '|', '_', ' ', '|', '_', '|', ' ', ' ', ' '] {
        '6'
    } else if &input[..] == [' ', '_', ' ', ' ', ' ', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '7'
    } else if &input[..] == [' ', '_', ' ', '|', '_', '|', '|', '_', '|', ' ', ' ', ' '] {
        '8'
    } else if &input[..] == [' ', '_', ' ', '|', '_', '|', ' ', '_', '|', ' ', ' ', ' '] {
        '9'
    } else {
        '?'
    }
}
<commit_msg>ocr-numbers: Take `&[char]` instead of `&Vec<char>`<commit_after>use std::collections::BTreeMap;

#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidRowCount(usize),
    InvalidColumnCount(usize),
}

pub fn convert(input: &str) -> Result<String, Error> {
    let line_count = input.lines().count();
    if line_count % 4 != 0 {
        return Err(Error::InvalidRowCount(line_count));
    }
    for line in input.lines() {
        let char_count = line.chars().count();
        if char_count % 3 != 0 {
            return Err(Error::InvalidColumnCount(char_count));
        }
    }

    let y = input.lines().collect::<Vec<_>>();

    let mut converted_lines = vec![];

    for char_lines in y.chunks(4) {
        let mut unparsed_characters = BTreeMap::new();

        for line in char_lines {
            let line_chars = line.chars().collect::<Vec<_>>();

            for (char_number, char_chunk) in line_chars.chunks(3).enumerate() {
                let char_chars = unparsed_characters.entry(char_number).or_insert_with(Vec::new);
                for c in char_chunk {
                    char_chars.push(*c);
                }
            }
        }

        let mut parsed_characters = String::new();

        for (_, v) in unparsed_characters {
            parsed_characters.push(convert_character(&v));
        }

        converted_lines.push(parsed_characters.to_string());
    }

    Ok(converted_lines.join(","))
}

fn convert_character(input: &[char]) -> char {
    if &input[..] == [' ', '_', ' ', '|', ' ', '|', '|', '_', '|', ' ', ' ', ' '] {
        '0'
    } else if &input[..] == [' ', ' ', ' ', ' ', ' ', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '1'
    } else if &input[..] == [' ', '_', ' ', ' ', '_', '|', '|', '_', ' ', ' ', ' ', ' '] {
        '2'
    } else if &input[..] == [' ', '_', ' ', ' ', '_', '|', ' ', '_', '|', ' ', ' ', ' '] {
        '3'
    } else if &input[..] == [' ', ' ', ' ', '|', '_', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '4'
    } else if &input[..] == [' ', '_', ' ', '|', '_', ' ', ' ', '_', '|', ' ', ' ', ' '] {
        '5'
    } else if &input[..] == [' ', '_', ' ', '|', '_', ' ', '|', '_', '|', ' ', ' ', ' '] {
        '6'
    } else if &input[..] == [' ', '_', ' ', ' ', ' ', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '7'
    } else if &input[..] == [' ', '_', ' ', '|', '_', '|', '|', '_', '|', ' ', ' ', ' '] {
        '8'
    } else if &input[..] == [' ', '_', ' ', '|', '_', '|', ' ', '_', '|', ' ', ' ', ' '] {
        '9'
    } else {
        '?'
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::io::{stdout, stderr, Write};
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{dirname} */ r#"
NAME
    dirname - strip last component from file name

SYNOPSIS
    dirname [ -h | --help ] FILE...

DESCRIPTION
    Strip last component from file name.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        return;
    }

    for path in &parser.args[0..] {
        if let Some(end) = path.rfind('/') {
            println!("{}", &path[..end]);
        } else {
            println!(".");
        }
    }
}
<commit_msg>dirname: edge cases<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::io::{stdout, stderr, Write};
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{dirname} */ r#"
NAME
    dirname - strip last component from file name

SYNOPSIS
    dirname [ -h | --help ] FILE...

DESCRIPTION
    Strip last component from file name.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        return;
    }

    for path in &parser.args[0..] {
        if path.len() != 0 && path.chars().all(|c| c == '/') {
            println!("/");
        } else {
            let path = path.trim_right_matches('/');
            if let Some(end) = path.rfind('/') {
                println!("{}", &path[..end]);
            } else {
                println!(".");
            }
        }
    }
}
<|endoftext|>


<commit_before>mod version;
mod init;
mod config;
mod ignore;
mod sweep;
mod burn;
mod start;
mod end;
mod destroy;
mod patrol;

use self::version::Version;
use self::init::Init;
use self::config::Config;
use self::ignore::Ignore;
use self::sweep::Sweep;
use self::burn::Burn;
use self::start::Start;
use self::end::End;
use self::destroy::Destroy;
use self::patrol::Patrol;

use constant::BANNED_DIRS;
use error::{CliError, EssentialLack, EssentialKind, RunningPlaceError, Usage, UsageKind};
use lib::io::*;
use lib::setting;
use std::env;
use std::fmt::Display;
use std::io::Error as IoError;

trait Command {
    fn allow_to_check_current_dir(&self) -> bool { true }
    fn check_current_dir(&self) -> Result<(), CliError> {
        let current_dir = try!(env::current_dir());

        match BANNED_DIRS.iter().find(|d| current_dir.ends_with(d)) {
            Some(d) => Err(From::from(RunningPlaceError::new(d.to_string()))),
            None    => Ok(()),
        }
    }

    fn allow_to_check_settings(&self) -> bool { true }
    fn check_settings(&self) -> Result<(), EssentialLack> {
        if !setting::working_dir_exists() {
            return Err(EssentialLack::new(EssentialKind::WorkingDir));
        }
        if !setting::Storage::exist() {
            return Err(EssentialLack::new(EssentialKind::StorageDir));
        }
        if !setting::Config::exist() {
            return Err(EssentialLack::new(EssentialKind::ConfigFile));
        }
        if !setting::Ignore::exist() {
            return Err(EssentialLack::new(EssentialKind::IgnoreFile));
        }

        Ok(())
    }

    fn usage(&self) -> Usage;

    fn main(&self) -> Result<(), CliError>;

    fn exec(&self, need_help: bool) -> Result<(), CliError> {
        if need_help {
            return Err(From::from(self.usage()));
        }

        if self.allow_to_check_current_dir() {
            try!(self.check_current_dir());
        }

        if self.allow_to_check_settings() {
            try!(self.check_settings());
        }

        self.main()
    }

    fn run_after_confirmation<D: Display, F>(message: D, danger_exec: F) -> Result<(), CliError>
        where Self: Sized, F: FnOnce() -> Result<(), IoError>
    {
        echo(format_with_tag(Tag::Caution, format!("{} [yes/no]: ", message)));

        let input = try!(read_line_from_stdin()).to_lowercase();
        match input.as_ref() {
            "y" | "yes" => try!(danger_exec()),
            _           => print_with_tag(Tag::Notice, "Interrupted by user"),
        };

        Ok(())
    }
}

pub fn execute() -> Result<(), CliError> {
    let args = env::args()
        .skip(1)
        .collect::<Vec<String>>();

    let mut args = args.into_iter();

    let command = try!(args.next().ok_or(Usage::new(UsageKind::Nothing)));

    let (command, need_help) = if &command == "help" {
        (try!(args.next().ok_or(Usage::new(UsageKind::Help))), true)
    } else {
        (command, false)
    };

    match command.as_ref() {
        "version" => Version                                              .exec(need_help),
        "init"    => Init                                                 .exec(need_help),
        "config"  => Config::new(args.next(), args.next()   , args.next()).exec(need_help),
        "ignore"  => Ignore::new(args.next(), args.collect()             ).exec(need_help),
        "sweep"   => Sweep                                                .exec(need_help),
        "burn"    => Burn                                                 .exec(need_help),
        "start"   => Start                                                .exec(need_help),
        "end"     => End                                                  .exec(need_help),
        "destroy" => Destroy                                              .exec(need_help),
        "patrol"  => Patrol                                               .exec(need_help),
        _         => Err(From::from(Usage::new(UsageKind::Nothing))),
    }
}

pub fn clean_up_cron() -> Result<(), CliError> {
    if cfg!(unix) {
        End.main()
    } else {
        Ok(())
    }
}
<commit_msg>[Comment] Add a note<commit_after>mod version;
mod init;
mod config;
mod ignore;
mod sweep;
mod burn;
mod start;
mod end;
mod destroy;
mod patrol;

use self::version::Version;
use self::init::Init;
use self::config::Config;
use self::ignore::Ignore;
use self::sweep::Sweep;
use self::burn::Burn;
use self::start::Start;
use self::end::End;
use self::destroy::Destroy;
use self::patrol::Patrol;

use constant::BANNED_DIRS;
use error::{CliError, EssentialLack, EssentialKind, RunningPlaceError, Usage, UsageKind};
use lib::io::*;
use lib::setting;
use std::env;
use std::fmt::Display;
use std::io::Error as IoError;

trait Command {
    fn allow_to_check_current_dir(&self) -> bool { true }
    fn check_current_dir(&self) -> Result<(), CliError> {
        let current_dir = try!(env::current_dir());

        match BANNED_DIRS.iter().find(|d| current_dir.ends_with(d)) {
            Some(d) => Err(From::from(RunningPlaceError::new(d.to_string()))),
            None    => Ok(()),
        }
    }

    fn allow_to_check_settings(&self) -> bool { true }
    fn check_settings(&self) -> Result<(), EssentialLack> {
        if !setting::working_dir_exists() {
            return Err(EssentialLack::new(EssentialKind::WorkingDir));
        }
        if !setting::Storage::exist() {
            return Err(EssentialLack::new(EssentialKind::StorageDir));
        }
        if !setting::Config::exist() {
            return Err(EssentialLack::new(EssentialKind::ConfigFile));
        }
        if !setting::Ignore::exist() {
            return Err(EssentialLack::new(EssentialKind::IgnoreFile));
        }

        Ok(())
    }

    fn usage(&self) -> Usage;

    fn main(&self) -> Result<(), CliError>;

    fn exec(&self, need_help: bool) -> Result<(), CliError> {
        if need_help {
            return Err(From::from(self.usage()));
        }

        if self.allow_to_check_current_dir() {
            try!(self.check_current_dir());
        }

        if self.allow_to_check_settings() {
            try!(self.check_settings());
        }

        self.main()
    }

    fn run_after_confirmation<D: Display, F>(message: D, danger_exec: F) -> Result<(), CliError>
        where Self: Sized, F: FnOnce() -> Result<(), IoError>
    {
        echo(format_with_tag(Tag::Caution, format!("{} [yes/no]: ", message)));

        let input = try!(read_line_from_stdin()).to_lowercase();
        match input.as_ref() {
            "y" | "yes" => try!(danger_exec()),
            _           => print_with_tag(Tag::Notice, "Interrupted by user"),
        };

        Ok(())
    }
}

pub fn execute() -> Result<(), CliError> {
    let args = env::args()
        .skip(1)
        .collect::<Vec<String>>();

    let mut args = args.into_iter();

    let command = try!(args.next().ok_or(Usage::new(UsageKind::Nothing)));

    let (command, need_help) = if &command == "help" {
        (try!(args.next().ok_or(Usage::new(UsageKind::Help))), true)
    } else {
        (command, false)
    };

    match command.as_ref() {
        "version" => Version                                              .exec(need_help),
        "init"    => Init                                                 .exec(need_help),
        "config"  => Config::new(args.next(), args.next()   , args.next()).exec(need_help),
        "ignore"  => Ignore::new(args.next(), args.collect()             ).exec(need_help),
        "sweep"   => Sweep                                                .exec(need_help),
        "burn"    => Burn                                                 .exec(need_help),
        "start"   => Start                                                .exec(need_help),
        "end"     => End                                                  .exec(need_help),
        "destroy" => Destroy                                              .exec(need_help),
        "patrol"  => Patrol                                               .exec(need_help),
        _         => Err(From::from(Usage::new(UsageKind::Nothing))),
    }
}

pub fn clean_up_cron() -> Result<(), CliError> {
    // This is temporary "if" for avoiding the error except for "unix".
    if cfg!(unix) {
        End.main()
    } else {
        Ok(())
    }
}
<|endoftext|>