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

use prost::Message;
use tink::{subtle::random::get_random_bytes, TinkError};

#[test]
fn test_aes_siv_primitive() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    let serialized_key = km.new_key(&[]).unwrap();
    let p = km.primitive(&serialized_key).unwrap();
    assert!(validate_aes_siv_primitive(p).is_ok());
}

#[test]
fn test_aes_siv_primitive_with_invalid_keys() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    let invalid_keys = gen_invalid_aes_siv_keys();
    for key in invalid_keys {
        let mut serialized_key = Vec::new();
        key.encode(&mut serialized_key).unwrap();
        assert!(km.primitive(&serialized_key).is_err());
    }
    assert!(km.primitive(&[]).is_err());
}

#[test]
fn test_aes_siv_primitive_with_wrong_primary_key() {
    tink_daead::init();
    tink_signature::init();

    let kh = tink::keyset::Handle::new(&tink_signature::ecdsa_p256_key_template()).unwrap();
    let signature_km =
        tink::registry::get_key_manager(tink_testutil::ECDSA_SIGNER_TYPE_URL).unwrap();
    let result = tink_daead::new_with_key_manager(&kh, Some(signature_km));
    tink_testutil::expect_err(result, "not a DeterministicAEAD");
}

#[test]
fn test_aes_siv_primitive_with_wrong_later_key() {
    tink_daead::init();
    tink_signature::init();

    // Build a keyset with a primary ECDSA key plus an AES-SIV key.
    let mut ksm = tink::keyset::Manager::new();
    ksm.rotate(&tink_daead::aes_siv_key_template()).unwrap();
    ksm.add(
        &tink_signature::ecdsa_p256_key_template(),
        /* primary= */ false,
    )
    .unwrap();
    let kh = ksm.handle().unwrap();

    let result = tink_daead::new(&kh);
    tink_testutil::expect_err(result, "not a DeterministicAEAD");
}

#[test]
fn test_aes_siv_new_key() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    let sk = km.new_key(&[]).unwrap();
    let key = tink::proto::AesSivKey::decode(sk.as_ref()).unwrap();
    assert!(validate_aes_siv_key(&key).is_ok());
}

#[test]
fn test_aes_siv_new_key_data() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    let kd = km.new_key_data(&[]).unwrap();
    assert_eq!(kd.type_url, tink_testutil::AES_SIV_TYPE_URL);
    assert_eq!(
        kd.key_material_type,
        tink::proto::key_data::KeyMaterialType::Symmetric as i32
    );

    let key = tink::proto::AesSivKey::decode(kd.value.as_ref()).unwrap();
    assert!(validate_aes_siv_key(&key).is_ok());
}

#[test]
fn test_aes_siv_new_key_invalid() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    let key_format = tink::proto::AesSivKeyFormat {
        key_size: (tink_daead::subtle::AES_SIV_KEY_SIZE - 1) as u32,
    };
    let mut serialized_key_format = Vec::new();
    key_format.encode(&mut serialized_key_format).unwrap();
    let result = km.new_key(&serialized_key_format);
    tink_testutil::expect_err(result, "key_size != 64");
}

#[test]
fn test_aes_siv_does_support() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");

    assert!(
        km.does_support(tink_testutil::AES_SIV_TYPE_URL),
        "AESSIVKeyManager must support {}",
        tink_testutil::AES_SIV_TYPE_URL
    );
    assert!(
        !km.does_support("some bad type"),
        "AESSIVKeyManager must only support {}",
        tink_testutil::AES_SIV_TYPE_URL
    );
}

#[test]
fn test_aes_siv_type_url() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    assert_eq!(km.type_url(), tink_testutil::AES_SIV_TYPE_URL);

    // Also check other parameters.
    assert_eq!(
        km.key_material_type(),
        tink::proto::key_data::KeyMaterialType::Symmetric
    );
    assert!(!km.supports_private_keys());
}

fn validate_aes_siv_primitive(p: tink::Primitive) -> Result<(), TinkError> {
    let cipher = match p {
        tink::Primitive::DeterministicAead(c) => c,
        _ => panic!("not a DeterministicAEAD"),
    };

    // try to encrypt and decrypt
    let pt = get_random_bytes(32);
    let aad = get_random_bytes(32);
    let ct = cipher
        .encrypt_deterministically(&pt, &aad)
        .expect("encryption failed");
    let decrypted = cipher.decrypt_deterministically(&ct, &aad)?;
    assert_eq!(decrypted, pt, "decryption failed");
    Ok(())
}

fn validate_aes_siv_key(key: &tink::proto::AesSivKey) -> Result<(), TinkError> {
    if key.version != tink_testutil::AES_SIV_KEY_VERSION {
        return Err(format!(
            "incorrect key version: key_version != {}",
            tink_testutil::AES_SIV_KEY_VERSION,
        )
        .into());
    }
    if key.key_value.len() != tink_daead::subtle::AES_SIV_KEY_SIZE {
        return Err(format!(
            "incorrect key size: key_size != {}",
            tink_daead::subtle::AES_SIV_KEY_SIZE,
        )
        .into());
    }

    // Try to encrypt and decrypt.
    let p = tink_daead::subtle::AesSiv::new(&key.key_value)?;
    validate_aes_siv_primitive(tink::Primitive::DeterministicAead(Box::new(p)))
}

fn gen_invalid_aes_siv_keys() -> Vec<tink::proto::AesSivKey> {
    vec![
        // Bad key size.
        tink::proto::AesSivKey {
            version: tink_testutil::AES_SIV_KEY_VERSION,
            key_value: get_random_bytes(16),
        },
        tink::proto::AesSivKey {
            version: tink_testutil::AES_SIV_KEY_VERSION,
            key_value: get_random_bytes(32),
        },
        tink::proto::AesSivKey {
            version: tink_testutil::AES_SIV_KEY_VERSION,
            key_value: get_random_bytes(63),
        },
        tink::proto::AesSivKey {
            version: tink_testutil::AES_SIV_KEY_VERSION,
            key_value: get_random_bytes(65),
        },
        // Bad version.
        tink::proto::AesSivKey {
            version: tink_testutil::AES_SIV_KEY_VERSION + 1,
            key_value: get_random_bytes(tink_daead::subtle::AES_SIV_KEY_SIZE),
        },
    ]
}
<commit_msg>tink-daead: fix test comment<commit_after>// Copyright 2020 The Tink-Rust Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

use prost::Message;
use tink::{subtle::random::get_random_bytes, TinkError};

#[test]
fn test_aes_siv_primitive() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    let serialized_key = km.new_key(&[]).unwrap();
    let p = km.primitive(&serialized_key).unwrap();
    assert!(validate_aes_siv_primitive(p).is_ok());
}

#[test]
fn test_aes_siv_primitive_with_invalid_keys() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    let invalid_keys = gen_invalid_aes_siv_keys();
    for key in invalid_keys {
        let mut serialized_key = Vec::new();
        key.encode(&mut serialized_key).unwrap();
        assert!(km.primitive(&serialized_key).is_err());
    }
    assert!(km.primitive(&[]).is_err());
}

#[test]
fn test_aes_siv_primitive_with_wrong_primary_key() {
    tink_daead::init();
    tink_signature::init();

    let kh = tink::keyset::Handle::new(&tink_signature::ecdsa_p256_key_template()).unwrap();
    let signature_km =
        tink::registry::get_key_manager(tink_testutil::ECDSA_SIGNER_TYPE_URL).unwrap();
    let result = tink_daead::new_with_key_manager(&kh, Some(signature_km));
    tink_testutil::expect_err(result, "not a DeterministicAEAD");
}

#[test]
fn test_aes_siv_primitive_with_wrong_later_key() {
    tink_daead::init();
    tink_signature::init();

    // Build a keyset with a primary AES-SIV key plus a later ECDSA key.
    let mut ksm = tink::keyset::Manager::new();
    ksm.rotate(&tink_daead::aes_siv_key_template()).unwrap();
    ksm.add(
        &tink_signature::ecdsa_p256_key_template(),
        /* primary= */ false,
    )
    .unwrap();
    let kh = ksm.handle().unwrap();

    let result = tink_daead::new(&kh);
    tink_testutil::expect_err(result, "not a DeterministicAEAD");
}

#[test]
fn test_aes_siv_new_key() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    let sk = km.new_key(&[]).unwrap();
    let key = tink::proto::AesSivKey::decode(sk.as_ref()).unwrap();
    assert!(validate_aes_siv_key(&key).is_ok());
}

#[test]
fn test_aes_siv_new_key_data() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    let kd = km.new_key_data(&[]).unwrap();
    assert_eq!(kd.type_url, tink_testutil::AES_SIV_TYPE_URL);
    assert_eq!(
        kd.key_material_type,
        tink::proto::key_data::KeyMaterialType::Symmetric as i32
    );

    let key = tink::proto::AesSivKey::decode(kd.value.as_ref()).unwrap();
    assert!(validate_aes_siv_key(&key).is_ok());
}

#[test]
fn test_aes_siv_new_key_invalid() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    let key_format = tink::proto::AesSivKeyFormat {
        key_size: (tink_daead::subtle::AES_SIV_KEY_SIZE - 1) as u32,
    };
    let mut serialized_key_format = Vec::new();
    key_format.encode(&mut serialized_key_format).unwrap();
    let result = km.new_key(&serialized_key_format);
    tink_testutil::expect_err(result, "key_size != 64");
}

#[test]
fn test_aes_siv_does_support() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");

    assert!(
        km.does_support(tink_testutil::AES_SIV_TYPE_URL),
        "AESSIVKeyManager must support {}",
        tink_testutil::AES_SIV_TYPE_URL
    );
    assert!(
        !km.does_support("some bad type"),
        "AESSIVKeyManager must only support {}",
        tink_testutil::AES_SIV_TYPE_URL
    );
}

#[test]
fn test_aes_siv_type_url() {
    tink_daead::init();
    let km = tink::registry::get_key_manager(tink_testutil::AES_SIV_TYPE_URL)
        .expect("cannot obtain AESSIV key manager");
    assert_eq!(km.type_url(), tink_testutil::AES_SIV_TYPE_URL);

    // Also check other parameters.
    assert_eq!(
        km.key_material_type(),
        tink::proto::key_data::KeyMaterialType::Symmetric
    );
    assert!(!km.supports_private_keys());
}

fn validate_aes_siv_primitive(p: tink::Primitive) -> Result<(), TinkError> {
    let cipher = match p {
        tink::Primitive::DeterministicAead(c) => c,
        _ => panic!("not a DeterministicAEAD"),
    };

    // try to encrypt and decrypt
    let pt = get_random_bytes(32);
    let aad = get_random_bytes(32);
    let ct = cipher
        .encrypt_deterministically(&pt, &aad)
        .expect("encryption failed");
    let decrypted = cipher.decrypt_deterministically(&ct, &aad)?;
    assert_eq!(decrypted, pt, "decryption failed");
    Ok(())
}

fn validate_aes_siv_key(key: &tink::proto::AesSivKey) -> Result<(), TinkError> {
    if key.version != tink_testutil::AES_SIV_KEY_VERSION {
        return Err(format!(
            "incorrect key version: key_version != {}",
            tink_testutil::AES_SIV_KEY_VERSION,
        )
        .into());
    }
    if key.key_value.len() != tink_daead::subtle::AES_SIV_KEY_SIZE {
        return Err(format!(
            "incorrect key size: key_size != {}",
            tink_daead::subtle::AES_SIV_KEY_SIZE,
        )
        .into());
    }

    // Try to encrypt and decrypt.
    let p = tink_daead::subtle::AesSiv::new(&key.key_value)?;
    validate_aes_siv_primitive(tink::Primitive::DeterministicAead(Box::new(p)))
}

fn gen_invalid_aes_siv_keys() -> Vec<tink::proto::AesSivKey> {
    vec![
        // Bad key size.
        tink::proto::AesSivKey {
            version: tink_testutil::AES_SIV_KEY_VERSION,
            key_value: get_random_bytes(16),
        },
        tink::proto::AesSivKey {
            version: tink_testutil::AES_SIV_KEY_VERSION,
            key_value: get_random_bytes(32),
        },
        tink::proto::AesSivKey {
            version: tink_testutil::AES_SIV_KEY_VERSION,
            key_value: get_random_bytes(63),
        },
        tink::proto::AesSivKey {
            version: tink_testutil::AES_SIV_KEY_VERSION,
            key_value: get_random_bytes(65),
        },
        // Bad version.
        tink::proto::AesSivKey {
            version: tink_testutil::AES_SIV_KEY_VERSION + 1,
            key_value: get_random_bytes(tink_daead::subtle::AES_SIV_KEY_SIZE),
        },
    ]
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::panic::UnwindSafe;

pub trait AsDynError<'a> {
    fn as_dyn_error(&self) -> &(dyn Error + 'a);
}

impl<'a, T: Error + 'a> AsDynError<'a> for T {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + Sync + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + Sync + UnwindSafe + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}
<commit_msg>Add Sealed supertrait to private AsDynError trait<commit_after>use self::private::Sealed;
use std::error::Error;
use std::panic::UnwindSafe;

pub trait AsDynError<'a>: Sealed {
    fn as_dyn_error(&self) -> &(dyn Error + 'a);
}

impl<'a, T: Error + 'a> AsDynError<'a> for T {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + Sync + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + Sync + UnwindSafe + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

mod private {
    use super::*;

    pub trait Sealed {}
    impl<'a, T: Error + 'a> Sealed for T {}
    impl<'a> Sealed for dyn Error + 'a {}
    impl<'a> Sealed for dyn Error + Send + 'a {}
    impl<'a> Sealed for dyn Error + Send + Sync + 'a {}
    impl<'a> Sealed for dyn Error + Send + Sync + UnwindSafe + 'a {}
}
<|endoftext|>


<commit_before>use {Action, InputTranslator, InputRebind, MouseTranslationData};
use input::Button;
use window::Size;
use std::convert::Into;
use std::default::Default;

/// Convenience object for constructing an InputMap
pub struct RebindBuilder<A: Action> {
    input_remappings: Vec<(Button, A)>,
    mouse_data: MouseTranslationData
}

impl<A: Action> RebindBuilder<A> {
    #[allow(missing_docs)]
    pub fn new(size: Size) -> Self {
        RebindBuilder {
            input_remappings: vec![],
            mouse_data: MouseTranslationData::new(size)
        }
    }

    #[allow(missing_docs)]
    pub fn x_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_scroll_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    #[allow(missing_docs)]
    pub fn y_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_scroll_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    #[allow(missing_docs)]
    pub fn x_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_motion_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }

    #[allow(missing_docs)]
    pub fn y_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_motion_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    #[allow(missing_docs)]
    pub fn viewport_size(mut self, sz: Size) -> Self {
        self.mouse_data.viewport_size = sz;
        self
    }

    #[allow(missing_docs)]
    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    #[allow(missing_docs)]
    pub fn with_action_mapping(mut self, but: Button, act: A) -> Self {
        self.input_remappings.push((but, act));
        self
    }

    #[allow(missing_docs)]
    pub fn build_translator(self) -> InputTranslator<A> { self.into() }

    #[allow(missing_docs)]
    pub fn build_rebind(self) -> InputRebind<A> { self.into() }
}

impl<A: Action> Default for RebindBuilder<A> {
    fn default() -> Self {
        Self::new((800, 600).into())
    }
}

impl<A: Action> Into<InputTranslator<A>> for RebindBuilder<A> {
    fn into(self) -> InputTranslator<A> {
        let mut input_map = InputTranslator::new(self.mouse_data.viewport_size);

        input_map.mouse_translator.data = self.mouse_data;
        input_map.keymap = self.input_remappings.iter().cloned().collect();

        input_map
    }
}

impl<A: Action> Into<InputRebind<A>> for RebindBuilder<A> {
    #[allow(dead_code, unused_variables, unreachable_code)]
    fn into(self) -> InputRebind<A> {
        unimplemented!();

        let mut input_rebind = InputRebind::new(self.mouse_data.viewport_size);

        input_rebind.mouse_data = self.mouse_data;
        //input_rebind.keymap.btn_map = self.input_remappings.iter().map(|x| x.clone()).collect();

        input_rebind
    }
}

<commit_msg>Add trailing period to doc comment<commit_after>use {Action, InputTranslator, InputRebind, MouseTranslationData};
use input::Button;
use window::Size;
use std::convert::Into;
use std::default::Default;

/// Convenience object for constructing an InputMap.
pub struct RebindBuilder<A: Action> {
    input_remappings: Vec<(Button, A)>,
    mouse_data: MouseTranslationData
}

impl<A: Action> RebindBuilder<A> {
    #[allow(missing_docs)]
    pub fn new(size: Size) -> Self {
        RebindBuilder {
            input_remappings: vec![],
            mouse_data: MouseTranslationData::new(size)
        }
    }

    #[allow(missing_docs)]
    pub fn x_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_scroll_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    #[allow(missing_docs)]
    pub fn y_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_scroll_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    #[allow(missing_docs)]
    pub fn x_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_motion_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }

    #[allow(missing_docs)]
    pub fn y_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_motion_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    #[allow(missing_docs)]
    pub fn viewport_size(mut self, sz: Size) -> Self {
        self.mouse_data.viewport_size = sz;
        self
    }

    #[allow(missing_docs)]
    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    #[allow(missing_docs)]
    pub fn with_action_mapping(mut self, but: Button, act: A) -> Self {
        self.input_remappings.push((but, act));
        self
    }

    #[allow(missing_docs)]
    pub fn build_translator(self) -> InputTranslator<A> { self.into() }

    #[allow(missing_docs)]
    pub fn build_rebind(self) -> InputRebind<A> { self.into() }
}

impl<A: Action> Default for RebindBuilder<A> {
    fn default() -> Self {
        Self::new((800, 600).into())
    }
}

impl<A: Action> Into<InputTranslator<A>> for RebindBuilder<A> {
    fn into(self) -> InputTranslator<A> {
        let mut input_map = InputTranslator::new(self.mouse_data.viewport_size);

        input_map.mouse_translator.data = self.mouse_data;
        input_map.keymap = self.input_remappings.iter().cloned().collect();

        input_map
    }
}

impl<A: Action> Into<InputRebind<A>> for RebindBuilder<A> {
    #[allow(dead_code, unused_variables, unreachable_code)]
    fn into(self) -> InputRebind<A> {
        unimplemented!();

        let mut input_rebind = InputRebind::new(self.mouse_data.viewport_size);

        input_rebind.mouse_data = self.mouse_data;
        //input_rebind.keymap.btn_map = self.input_remappings.iter().map(|x| x.clone()).collect();

        input_rebind
    }
}

<|endoftext|>


<commit_before>extern crate ndarray;
extern crate ndarray_linalg;

use ndarray::*;
use ndarray_linalg::*;

fn main() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]);
    let (e, vecs): (Array1<_>, Array2<_>) = a.clone().eigh(UPLO::Upper).unwrap();
    println!("eigenvalues = \n{:?}", e);
    println!("V = \n{:?}", vecs);
    let av = a.dot(&vecs);
    println!("AV = \n{:?}", av);
}
<commit_msg>Drop type annotation from example<commit_after>extern crate ndarray;
extern crate ndarray_linalg;

use ndarray::*;
use ndarray_linalg::*;

fn main() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]);
    let (e, vecs) = a.clone().eigh(UPLO::Upper).unwrap();
    println!("eigenvalues = \n{:?}", e);
    println!("V = \n{:?}", vecs);
    let av = a.dot(&vecs);
    println!("AV = \n{:?}", av);
}
<|endoftext|>


<commit_before>#![feature(old_io, std_misc)]

extern crate glutin;
extern crate glium;
extern crate image;
extern crate clock_ticks;
extern crate uil;

use std::io::BufReader;
use std::fs::File;
use std::path::Path;
use glium::DisplayBuild;
use std::old_io::timer;
use std::time::duration::Duration;

use uil::RenderBackbend;

fn main() {

    //////////////////////////////////////////////////////////////////////////////
    // uil related code
    //
    let library = {
        let file = File::open(&Path::new("./examples/menu.markup")).unwrap();
        let reader = BufReader::new(file);
        uil::markup::parse(uil::StdOutErrorReporter, reader)
    };

    let defs = uil::deps::parse_file(uil::StdOutErrorReporter, "./examples/menu.deps");

    //////////////////////////////////////////////////////////////////////////////
    // glium display start
    //
    let display = glutin::WindowBuilder::new()
        .with_vsync()
        .with_title("uil - menu example".to_string())
        .build_glium()
        .unwrap();

    //////////////////////////////////////////////////////////////////////////////
    // uil resource manager and final tree
    //

    let mut resource_manager = uil::ResourceManager::new(&display);

    let stylesheet = {
        let file = File::open(&Path::new("./examples/menu.style")).unwrap();
        let reader = BufReader::new(file);
        uil::style::parse(uil::StdOutErrorReporter, reader, &defs, &mut resource_manager)
    };

    let (width, height) = display.get_window().unwrap().get_inner_size().unwrap();

    let mut renderer = uil::backend::GliumRenderer::new(&display);
    let mut router = uil::Router::from_library_and_stylesheet(
        &display,
        &resource_manager,
        library,
        &stylesheet
    );

    //////////////////////////////////////////////////////////////////////////////
    // main loop (modified example from glium lib)
    //
    start_loop(|| {

        let vp = uil::Viewport { width: width as f32, height: height as f32 };

        // Update views
        router.update(&display, vp);

        // Render views
        let mut f = renderer.prepare_frame(vp);
        router.render_views(&renderer, &mut f, &resource_manager);
        renderer.flush_frame(f);

        // polling and handling the events received by the window
        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return Action::Stop,
                _ => ()
            }
        }

        Action::Continue
    });
}

pub enum Action {
    Stop,
    Continue,
}

pub fn start_loop<F>(mut callback: F) where F: FnMut() -> Action {
    let mut accumulator = 0;
    let mut previous_clock = clock_ticks::precise_time_ns();
    loop {
        match callback() {
            Action::Stop => break,
            Action::Continue => ()
        };
        let now = clock_ticks::precise_time_ns();
        accumulator += now - previous_clock;
        previous_clock = now;
        const FIXED_TIME_STAMP: u64 = 16666667;
        while accumulator >= FIXED_TIME_STAMP {
            accumulator -= FIXED_TIME_STAMP;
            // if you have a game, update the state here
        }
        timer::sleep(Duration::nanoseconds((FIXED_TIME_STAMP - accumulator) as i64));
    }
}
<commit_msg>Updated example to previous refactoring.<commit_after>#![feature(old_io, std_misc)]

extern crate glutin;
extern crate glium;
extern crate image;
extern crate clock_ticks;
extern crate uil;

use std::io::BufReader;
use std::fs::File;
use std::path::Path;
use glium::DisplayBuild;
use std::old_io::timer;
use std::time::duration::Duration;

use uil::RenderBackbend;

fn main() {

    //////////////////////////////////////////////////////////////////////////////
    // uil related code
    //
    let library = {
        let file = File::open(&Path::new("./examples/menu.markup")).unwrap();
        let reader = BufReader::new(file);
        uil::markup::parse(uil::StdOutErrorReporter, reader)
    };

    let defs = uil::deps::parse_file(uil::StdOutErrorReporter, "./examples/menu.deps");

    //////////////////////////////////////////////////////////////////////////////
    // glium display start
    //
    let display = glutin::WindowBuilder::new()
        .with_vsync()
        .with_title("uil - menu example".to_string())
        .build_glium()
        .unwrap();

    //////////////////////////////////////////////////////////////////////////////
    // uil resource manager and final tree
    //

    let mut resource_manager = uil::ResourceManager::new(&display);

    let stylesheet = {
        let file = File::open(&Path::new("./examples/menu.style")).unwrap();
        let reader = BufReader::new(file);
        uil::style::parse(uil::StdOutErrorReporter, reader, &defs, &mut resource_manager)
    };

    let (width, height) = display.get_window().unwrap().get_inner_size().unwrap();

    let mut renderer = uil::rendering::backend::GliumRenderer::new(&display);
    let mut router = uil::Router::from_library_and_stylesheet(
        &display,
        &resource_manager,
        library,
        &stylesheet
    );

    //////////////////////////////////////////////////////////////////////////////
    // main loop (modified example from glium lib)
    //
    start_loop(|| {

        let vp = uil::Viewport { width: width as f32, height: height as f32 };

        // Update views
        router.update(&display, vp);

        // Render views
        let mut f = renderer.prepare_frame(vp);
        router.render_views(&renderer, &mut f, &resource_manager);
        renderer.flush_frame(f);

        // polling and handling the events received by the window
        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return Action::Stop,
                _ => ()
            }
        }

        Action::Continue
    });
}

pub enum Action {
    Stop,
    Continue,
}

pub fn start_loop<F>(mut callback: F) where F: FnMut() -> Action {
    let mut accumulator = 0;
    let mut previous_clock = clock_ticks::precise_time_ns();
    loop {
        match callback() {
            Action::Stop => break,
            Action::Continue => ()
        };
        let now = clock_ticks::precise_time_ns();
        accumulator += now - previous_clock;
        previous_clock = now;
        const FIXED_TIME_STAMP: u64 = 16666667;
        while accumulator >= FIXED_TIME_STAMP {
            accumulator -= FIXED_TIME_STAMP;
            // if you have a game, update the state here
        }
        timer::sleep(Duration::nanoseconds((FIXED_TIME_STAMP - accumulator) as i64));
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate rustbox;
extern crate termbox_sys;
extern crate tiny;

use std::fs::File;
use std::io::Read;
use std::mem;
use std::time::Duration;

use rustbox::{RustBox, InitOptions, InputMode, Event, Key};

use tiny::tui::msg_area::MsgArea;
use tiny::tui::style;

fn loop_() -> Option<String> {
    let rustbox = RustBox::init(InitOptions {
        input_mode: InputMode::Esc,
        buffer_stderr: false,
    }).unwrap();

    let mut msg_area = MsgArea::new(rustbox.width() as i32, rustbox.height() as i32);

    {
        let mut text = String::new();
        let mut file = File::open("test/lipsum.txt").unwrap();
        file.read_to_string(&mut text).unwrap();
        let single_line_text = text.lines().collect::<Vec<&str>>().join("");
        msg_area.add_text(&single_line_text, &style::USER_MSG_SS);
        msg_area.flush_line();

        for line in text.lines() {
            msg_area.add_text(">>>", &style::TOPIC_SS);
            msg_area.add_text("  ", &style::SERVER_MSG_SS);
            msg_area.add_text(line, &style::SERVER_MSG_SS);
            msg_area.flush_line();
        }
    }

    // I'm using select() here to test for signals/interrupts. Namely, SIGWINCH
    // needs to be handled somehow for resizing.

    let mut fd_set : libc::fd_set = unsafe { mem::zeroed() };
    unsafe { libc::FD_SET(0, &mut fd_set); }
    let nfds = 1; // stdin + 1

    loop {
        rustbox.clear();
        msg_area.draw(&rustbox, 0, 0);
        rustbox.present();

        let mut fd_set_ = fd_set.clone();
        let ret = unsafe {
            libc::select(nfds,
                         &mut fd_set_,           // read fds
                         std::ptr::null_mut(),   // write fds
                         std::ptr::null_mut(),   // error fds
                         std::ptr::null_mut())   // timeval
        };

        if unsafe { ret == -1 || libc::FD_ISSET(0, &mut fd_set_) } {
            match rustbox.peek_event(Duration::new(0, 0), false) {
                Ok(Event::KeyEvent(Key::Esc)) => {
                    break;
                },

                Ok(Event::KeyEvent(Key::Ctrl('p'))) => {
                    msg_area.scroll_up();
                },

                Ok(Event::KeyEvent(Key::Ctrl('n'))) => {
                    msg_area.scroll_down();
                },

                // Ok(Event::KeyEvent(Key::Char(ch))) => {
                // }

                Ok(Event::ResizeEvent(width, height)) => {
                    msg_area.resize(width, height);
                }

                _ => {}
            }
        }
    }

    None
}

fn main() {
    loop_().map(|err| println!("{}", err));
}
<commit_msg>fix text example<commit_after>extern crate libc;
extern crate rustbox;
extern crate termbox_sys;
extern crate tiny;

use std::fs::File;
use std::io::Read;
use std::mem;
use std::time::Duration;

use std::io;
use std::io::Write;

use rustbox::{RustBox, InitOptions, InputMode, Event, Key};

use tiny::tui::msg_area::MsgArea;
use tiny::tui::style;

fn loop_() -> Option<String> {
    let rustbox = RustBox::init(InitOptions {
        input_mode: InputMode::Esc,
        buffer_stderr: false,
    }).unwrap();

    let mut msg_area = MsgArea::new(rustbox.width() as i32, rustbox.height() as i32);

    {
        let mut text = String::new();
        let mut file = File::open("test/lipsum.txt").unwrap();
        file.read_to_string(&mut text).unwrap();
        let single_line_text = text.lines().collect::<Vec<&str>>().join("");
        msg_area.set_style(&style::ERR_MSG);
        msg_area.add_text(&single_line_text);
        writeln!(io::stderr(), "full text added: {}", single_line_text).unwrap();
        msg_area.flush_line();

        for line in text.lines() {
            msg_area.set_style(&style::TOPIC);
            msg_area.add_text(">>>");
            msg_area.set_style(&style::SERVER_MSG);
            msg_area.add_text("  ");
            msg_area.add_text(line);
            msg_area.flush_line();
        }
    }

    // I'm using select() here to test for signals/interrupts. Namely, SIGWINCH
    // needs to be handled somehow for resizing.

    let mut fd_set : libc::fd_set = unsafe { mem::zeroed() };
    unsafe { libc::FD_SET(0, &mut fd_set); }
    let nfds = 1; // stdin + 1

    loop {
        rustbox.clear();
        msg_area.draw(&rustbox, 0, 0);
        rustbox.present();

        let mut fd_set_ = fd_set.clone();
        let ret = unsafe {
            libc::select(nfds,
                         &mut fd_set_,           // read fds
                         std::ptr::null_mut(),   // write fds
                         std::ptr::null_mut(),   // error fds
                         std::ptr::null_mut())   // timeval
        };

        if unsafe { ret == -1 || libc::FD_ISSET(0, &mut fd_set_) } {
            match rustbox.peek_event(Duration::new(0, 0), false) {
                Ok(Event::KeyEvent(Key::Esc)) => {
                    break;
                },

                Ok(Event::KeyEvent(Key::Ctrl('p'))) => {
                    msg_area.scroll_up();
                },

                Ok(Event::KeyEvent(Key::Ctrl('n'))) => {
                    msg_area.scroll_down();
                },

                Ok(Event::KeyEvent(Key::PageUp)) => {
                    msg_area.page_up();
                },

                Ok(Event::KeyEvent(Key::PageDown)) => {
                    msg_area.page_down();
                },

                // Ok(Event::KeyEvent(Key::Char(ch))) => {
                // }

                Ok(Event::ResizeEvent(width, height)) => {
                    msg_area.resize(width, height);
                }

                _ => {}
            }
        }
    }

    None
}

fn main() {
    loop_().map(|err| println!("{}", err));
}
<|endoftext|>


<commit_before>use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::collections::HashMap;

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("04.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
struct DateTime {
    year: usize,
    month: usize,
    day: usize,
    hour: usize,
    minute: usize
}

impl fmt::Debug for DateTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}-{}-{} {}:{}", self.year, self.month, self.day, self.hour, self.minute)
    }
}

#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
enum Event {
    Begin(usize),
    Sleep,
    WakeUp
}

#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
struct LogEntry {
    time: DateTime,
    event: Event
}

type AsleepPlan = HashMap<usize, Vec<DateTime>>;

fn create_log(input: &str) -> Vec<LogEntry> {
    let mut result: Vec<LogEntry> = input.lines()
        .filter_map(|line| {
            let mut tokens = line.split(' ');

            let mut date = match tokens.next() {
                Some(x) => x[1..].split('-').filter_map(|x| x.parse::<usize>().ok()),
                _ => return None
            };

            let mut time = match tokens.next() {
                Some(x) => x[..x.len() - 1].split(':').filter_map(|x| x.parse::<usize>().ok()),
                _ => return None
            };

            let event = match (tokens.next(), tokens.next()) {
                (Some("wakes"), _) => Event::WakeUp,
                (Some("falls"), _) => Event::Sleep,
                (Some("Guard"), Some(token)) => match token[1..].parse::<usize>() {
                    Ok(id) => Event::Begin(id),
                    _ => return None
                },
                _ => return None
            };

            match (date.next(), date.next(), date.next(), time.next(), time.next()) {
                (Some(year), Some(month), Some(day), Some(hour), Some(minute)) => {
                    Some(LogEntry {
                        time: DateTime {year, month, day, hour, minute},
                        event
                    })
                },
                _ => None
            }
        })
        .collect();

    result.sort();
    result
}

fn create_plan(log: &Vec<LogEntry>) -> AsleepPlan {
    let mut plan = AsleepPlan::new();

    if log.len() == 0 {
        return plan;
    }

    let mut id = 0;
    let mut last_time = log[0].time;
    let mut asleep = true;

    for &LogEntry {time, event} in log.iter() {
        match event {
            Event::Begin(x) => {
                id = x;

                if !plan.contains_key(&id) {
                    plan.insert(id, vec![]);
                }
            },
            Event::WakeUp if asleep => {
                if let Some(asleep_vec) = plan.get_mut(&id) {
                    for i in last_time.minute..time.minute {
                        asleep_vec.push(DateTime {
                            year: time.year,
                            month: time.month,
                            day: time.day,
                            hour: time.hour,
                            minute: i
                        });
                    }
                }

                asleep = false;
            },
            Event::Sleep => {
                last_time = time;
                asleep = true;
            },
            _ => {}
        };
    }

    plan
}

fn main() {
    let data = create_log(&get_input().unwrap());
    let plan = create_plan(&data);

    let vec = vec![];
    let (candidate_id, asleep_vec) = plan.iter()
        .fold(None, |acc, (&id, asleep_vec)| match acc {
            None => Some((id, asleep_vec)),
            Some((_, x)) => if x.len() > asleep_vec.len() {
                acc
            } else {
                Some((id, asleep_vec))
            }
        })
        .unwrap_or((0, &vec));

    let candidate_minute = asleep_vec.iter()
        .fold(HashMap::new(), |mut acc, &time| {
            let value = match acc.get(&time.minute) {
                Some(&x) => x,
                _ => 0
            };

            acc.insert(time.minute, value + 1);
            acc
        })
        .iter()
        .fold(None, |acc, (&minute, &n)| match acc {
            None => Some((minute, n)),
            Some((_, m)) => if m > n {
                acc
            } else {
                Some((minute, n))
            }
        })
        .unwrap_or((0, 0)).0;

    println!("Part 1: {}", candidate_id * candidate_minute);
}
<commit_msg>Add 2018 day 4 part 2 solution<commit_after>use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::collections::HashMap;

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("04.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
struct DateTime {
    year: usize,
    month: usize,
    day: usize,
    hour: usize,
    minute: usize
}

impl fmt::Debug for DateTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}-{}-{} {}:{}", self.year, self.month, self.day, self.hour, self.minute)
    }
}

#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
enum Event {
    Begin(usize),
    Sleep,
    WakeUp
}

#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
struct LogEntry {
    time: DateTime,
    event: Event
}

type AsleepPlan = HashMap<usize, HashMap<usize, Vec<DateTime>>>;

fn create_log(input: &str) -> Vec<LogEntry> {
    let mut result: Vec<LogEntry> = input.lines()
        .filter_map(|line| {
            let mut tokens = line.split(' ');

            let mut date = match tokens.next() {
                Some(x) => x[1..].split('-').filter_map(|x| x.parse::<usize>().ok()),
                _ => return None
            };

            let mut time = match tokens.next() {
                Some(x) => x[..x.len() - 1].split(':').filter_map(|x| x.parse::<usize>().ok()),
                _ => return None
            };

            let event = match (tokens.next(), tokens.next()) {
                (Some("wakes"), _) => Event::WakeUp,
                (Some("falls"), _) => Event::Sleep,
                (Some("Guard"), Some(token)) => match token[1..].parse::<usize>() {
                    Ok(id) => Event::Begin(id),
                    _ => return None
                },
                _ => return None
            };

            match (date.next(), date.next(), date.next(), time.next(), time.next()) {
                (Some(year), Some(month), Some(day), Some(hour), Some(minute)) => {
                    Some(LogEntry {
                        time: DateTime {year, month, day, hour, minute},
                        event
                    })
                },
                _ => None
            }
        })
        .collect();

    result.sort();
    result
}

fn create_plan(log: &Vec<LogEntry>) -> AsleepPlan {
    let mut plan = AsleepPlan::new();

    if log.len() == 0 {
        return plan;
    }

    let mut id = 0;
    let mut last_time = log[0].time;
    let mut asleep = true;

    for &LogEntry {time, event} in log.iter() {
        match event {
            Event::Begin(x) => {
                id = x;

                if !plan.contains_key(&id) {
                    plan.insert(id, HashMap::new());
                }
            },
            Event::WakeUp if asleep => {
                if let Some(asleep_map) = plan.get_mut(&id) {
                    for i in last_time.minute..time.minute {
                        if !asleep_map.contains_key(&i) {
                            asleep_map.insert(i, vec![]);
                        }

                        let asleep_vec = asleep_map.get_mut(&i).unwrap();

                        asleep_vec.push(DateTime {
                            year: time.year,
                            month: time.month,
                            day: time.day,
                            hour: time.hour,
                            minute: i
                        });
                    }
                }

                asleep = false;
            },
            Event::Sleep => {
                last_time = time;
                asleep = true;
            },
            _ => {}
        };
    }

    plan
}

fn main() {
    let data = create_log(&get_input().unwrap());
    let plan = create_plan(&data);

    let empty_map = HashMap::new();
    let empty_vec = Vec::new();

    let (&candidate_id, asleep_map) = plan.iter()
        .max_by_key(|&(_, asleep_map)| asleep_map.values().flatten().count())
        .unwrap_or((&0, &empty_map));

    let (&candidate_minute, _) = asleep_map.iter()
        .max_by_key(|&(_, asleep_vec)| asleep_vec.len())
        .unwrap_or((&0, &empty_vec));

    println!("Part 1: {}", candidate_id * candidate_minute);

    let (candidate_id, candidate_minute, _) = plan.iter()
        .map(|(&id, asleep_map)| (
            id,
            asleep_map.iter()
                .map(|(&id, asleep_vec)| (id, asleep_vec.len()))
                .max_by_key(|&(_, value)| value)
                .unwrap_or((0, 0))
        ))
        .map(|(x, (y, z))| (x, y, z))
        .max_by_key(|&(_, _, value)| value)
        .unwrap_or((0, 0, 0));

    println!("Part 2: {}", candidate_id * candidate_minute);
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! An intrusive linked list implementation using `RawLink`s.
//!
//! An _intrusive_ list is a list structure wherein the type of element stored
//! in the list holds references to other nodes. This means that we don't have
//! to store a separate node data type that holds the stored elements and
//! pointers to other nodes, reducing the amount of memory allocated. We can
//! use intrusive lists in code that runs without the kernel memory allocator,
//! like the allocator implementation itself, since each list element manages
//! its own memory.
use super::rawlink::RawLink;

use core::marker::PhantomData;
use core::ptr::Unique;
#[cfg(test)] mod test;

pub unsafe trait OwnedRef<T> {
    unsafe fn from_raw(ptr: *mut T) -> Self;
    unsafe fn take(self);
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;
}

/// This trait defines a node in an intrusive list.
///
/// A Node must be capable of providing mutable and immutable references to
/// the previous and next nodes in the list.
pub trait Node: Sized {
    fn next(&self) -> &RawLink<Self>;
    fn prev(&self) -> &RawLink<Self>;

    fn next_mut(&mut self) -> &mut RawLink<Self>;
    fn prev_mut(&mut self) -> &mut RawLink<Self>;
}

/// The `List` struct is our way of interacting with an intrusive list.
///
/// It stores a pointer to the head and tail of the list, the length of the
/// list, and a `PhantomData` marker for the list's `OwnedRef` type. It
/// provides the methods for pushing, popping, and indexing the list.
pub struct List<T, N>
where T: OwnedRef<N>
    , N: Node {
    head: RawLink<N>
  , tail: RawLink<N>
  , _ty_marker: PhantomData<T>
  , length: usize
 }

 // impl<T> Node for List<T>
 // where T: OwnedRef
 //     , T: Node {
 //
 //    fn next(&self) -> &RawLink<Self> { &self.head }
 //    fn prev(&self) -> &RawLink<Self> { &self.tail }
 //
 //    fn next_mut(&mut self) -> &mut RawLink<Self> { self.head }
 //    fn prev_mut(&mut self) -> &mut RawLink<Self> { self.tail }
 // }
impl<T, N> List<T, N>
where T: OwnedRef<N>
    , N: Node {

    /// Construct a new `List<T, N>` with zero elements
    pub const fn new() -> Self {
        List { head: RawLink::none()
             , tail: RawLink::none()
             , _ty_marker: PhantomData
             , length: 0 }
    }

    /// Returns the length of the list
    #[inline] pub fn len(&self) -> usize {
        self.length
    }

    /// Borrows the first element of the list as an `Option`
    ///
    /// # Returns:
    ///   - `Some(&N)` if the list has elements
    ///   - `None` if the list is empty.
    #[inline] pub fn front(&self) -> Option<&N> {
        unsafe { self.head.resolve() }
    }

    /// Borrows the last element of the list as an `Option`
    ///
    /// # Returns:
    ///   - `Some(&N)` if the list has elements
    ///   - `None` if the list is empty.
    #[inline] pub fn back(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }

    /// Mutably borrows the first element of the list as an `Option`
    ///
    /// # Returns:
    ///   - `Some(&mut N)` if the list has elements
    ///   - `None` if the list is empty.
    #[inline] pub fn front_mut(&mut self) -> Option<&mut N> {
        unsafe { self.head.resolve_mut() }
    }

    /// Mutably borrows the last element of the list as an `Option`
    ///
    /// # Returns:
    ///   - `Some(&mut N)` if the list has elements
    ///   - `None` if the list is empty.
    #[inline] pub fn back_mut(&mut self) -> Option<&mut N> {
        unsafe { self.tail.resolve_mut() }
    }

    /// Returns true if the list is empty.
    #[inline] pub fn is_empty(&self) -> bool {
        self.head.is_none()
    }

    /// Push an element to the front of the list.
    // TODO: should this really be called "prepend"?
    pub fn push_front(&mut self, mut item: T) {
        unsafe {
            match self.head.resolve_mut() {
                None => {
                    // If this node's head is empty, set the pushed item's
                    // links to None, and make this node's tail point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.tail = RawLink::some(item.get_mut());
                }
              , Some(head) => {
                    // If this node is not empty, set the pushed item's tail
                    // to point at the head node, and make the head node's tail
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::some(head);
                    *item.get_mut().prev_mut() = RawLink::none();
                    *head.prev_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.head = RawLink::some(item.get_mut());
            item.take();
            self.length += 1;
        }
    }

    /// Push an element to the back of the list.
    //  TODO: should this really be called "append"?
    //  (the Rust standard library uses `append` to refer to the "drain all the
    //  elements of another list and push them to this list" operation, but I
    //  think that that function is more properly called `concat`...)
    pub fn push_back(&mut self, mut item: T) {
        unsafe {
            match self.tail.resolve_mut() {
                None => {
                    // If this node's tail is empty, set the pushed item's
                    // links to  None, and make this node's head point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.head = RawLink::some(item.get_mut());
                }
              , Some(tail) => {
                    // If this node is not empty, set the pushed item's head
                    // to point at the tail node, and make the tail node's head
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::some(tail);
                    *tail.next_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.tail = RawLink::some(item.get_mut());
            item.take();
            self.length += 1;
        }
    }

    /// Removes and returns the element at the front of the list.
    ///
    /// # Returns:
    ///   - `Some(T)` containing the element at the front of the list if the
    ///     list is not empty
    ///   - `None` if the list is empty
    pub fn pop_front(&mut self) -> Option<T> {
        unsafe {
            self.head.take().resolve_mut()
                .map(|head| {
                    // mem::swap( &mut self.head
                    //          , head.next_mut().resolve_mut()
                    //                .map(|next| next.prev_mut())
                    //                .unwrap_or(&mut RawLink::none()) );
                    match head.next_mut().resolve_mut() {
                        None => self.tail = RawLink::none()
                      , Some(next) => {
                            *next.prev_mut() = RawLink::none();
                            self.head = RawLink::some(next);
                        }
                    }
                    self.length -= 1;
                    T::from_raw(head)
                })
        }
    }

    /// Removes and returns the element at the end of the list.
    ///
    /// # Returns:
    ///   - `Some(T)` containing the element at the end of the list if the
    ///     list is not empty
    ///   - `None` if the list is empty
    pub fn pop_back(&mut self) -> Option<T> {
        unsafe {
            self.tail.take().resolve_mut()
                .map(|tail| {
                    match tail.prev_mut().resolve_mut() {
                        None => self.head = RawLink::none()
                      , Some(prev) => {
                            *prev.next_mut() = RawLink::none();
                            self.tail = RawLink::some(prev);
                        }
                    }
                    self.length -= 1;
                    T::from_raw(tail)
                })
        }
    }

    /// Borrows the element at the front of the list
    ///
    /// # Returns:
    ///   - `Some(&T)` containing the element at the end of the list if the
    ///     list is not empty
    ///   - `None` if the list is empty
    pub fn peek_front(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }

    /// Returns a cursor for iterating over or modifying the list.
    pub fn cursor<'a>(&'a mut self) -> ListCursor<'a, T, N> {
        ListCursor { list: self
                   , current: RawLink::none() }
    }

}

// TODO: can we implement `Iterator` for cursors?
pub struct ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {
        list: &'a mut List<T, N>
      , current: RawLink<N>
}

impl<'a, T, N> ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {

    pub fn next(&mut self) -> Option<&mut N> {
        unsafe {
            match self.current.take().resolve_mut() {
                None => self.list.head.resolve_mut()
                            .and_then(|head| {
                                self.current = RawLink::some(head);
                                self.current.resolve_mut()
                            })
              , Some(thing) => {
                    self.current = match thing.next_mut().resolve_mut() {
                        None => RawLink::none()
                      , Some(other_thing) => RawLink::some(other_thing)
                    };
                    self.current.resolve_mut()
                }
            }
        }
    }

    pub fn peek_next(&self) -> Option<&N> {
        unsafe {
            self.current.resolve()
                .map_or( self.list.front()
                       , |curr| curr.next().resolve())
        }
    }

    pub fn remove(&mut self) -> Option<T> {
        unsafe {
            match self.current.resolve_mut() {
                None    => self.list.pop_front()
              , Some(c) =>
                    c.next_mut().take().resolve_mut()
                     .map(|p| {
                        match p.next_mut().resolve_mut() {
                            None => self.list.tail = RawLink::some(c)
                          , Some(n) => {
                                *n.prev_mut() = RawLink::some(c);
                                *c.next_mut() = RawLink::some(n);
                            }
                        }
                        T::from_raw(p)
                    })
            }
        }
    }

    pub fn find_and_remove<P>(&mut self, predicate: P) -> Option<T>
    where P: Fn(&N) -> bool {
        while self.peek_next().is_some() {
            if predicate(self.peek_next().unwrap()) == true {
                return self.remove()
            } else {
                self.next();
            }
        }
        None
    }

}

// impl<'a, T, N> Iterator for ListCursor<'a, T, N>
// where T: OwnedRef<N>
//     , T: 'a
//     , N: Node
//     , N: 'a {
//     type Item = &'a mut N;
//
//     fn next<'b: 'a>(&'b mut self) -> Option<&'a mut N> {
//         self.next()
//     }
// }

//
// unsafe impl<T> OwnedRef for Unique<T> where T: Node {
//
//     #[inline]
//     fn take(self) {}
//
//     unsafe fn from_raw(ptr: *mut T) -> Self {
//         Unique::new(ptr)
//     }
// }
//
// unsafe impl<'a, T> OwnedRef<T> for &'a mut T {
//     #
//     #[inline] unsafe fn from_raw(raw: *mut T) -> &'a mut T {
//         &mut *raw
//     }
//
//     #[inline] unsafe fn take(self) {
//         forget(self);
//     }
// }
//

unsafe impl<T> OwnedRef<T> for Unique<T>  {
    #[inline]
    fn get(&self) -> &T { unsafe { self.get() } }

    #[inline]
    fn get_mut(&mut self) -> &mut T { unsafe { self.get_mut() } }

    #[inline]
    unsafe fn take(self) {}

    unsafe fn from_raw(ptr: *mut T) -> Self {
        Unique::new(ptr)
    }
}

#[cfg(any(test, feature = "use-std"))]
unsafe impl<T> OwnedRef<T> for ::std::boxed::Box<T> {

    fn get(&self) -> &T { &**self }
    fn get_mut(&mut self) -> &mut T { &mut **self }

    #[inline] unsafe fn take(self) {
        ::std::boxed::Box::into_raw(self);
    }

    unsafe fn from_raw(ptr: *mut T) -> Self {
        ::std::boxed::Box::from_raw(ptr)
    }
}
<commit_msg>[intrusive] Added more documentation to `list`<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! An intrusive linked list implementation using `RawLink`s.
//!
//! An _intrusive_ list is a list structure wherein the type of element stored
//! in the list holds references to other nodes. This means that we don't have
//! to store a separate node data type that holds the stored elements and
//! pointers to other nodes, reducing the amount of memory allocated. We can
//! use intrusive lists in code that runs without the kernel memory allocator,
//! like the allocator implementation itself, since each list element manages
//! its own memory.
use super::rawlink::RawLink;

use core::marker::PhantomData;
use core::ptr::Unique;
#[cfg(test)] mod test;

pub unsafe trait OwnedRef<T> {
    unsafe fn from_raw(ptr: *mut T) -> Self;
    unsafe fn take(self);
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;
}

/// This trait defines a node in an intrusive list.
///
/// A Node must be capable of providing mutable and immutable references to
/// the previous and next nodes in the list.
pub trait Node: Sized {
    fn next(&self) -> &RawLink<Self>;
    fn prev(&self) -> &RawLink<Self>;

    fn next_mut(&mut self) -> &mut RawLink<Self>;
    fn prev_mut(&mut self) -> &mut RawLink<Self>;
}

/// The `List` struct is our way of interacting with an intrusive list.
///
/// It stores a pointer to the head and tail of the list, the length of the
/// list, and a `PhantomData` marker for the list's `OwnedRef` type. It
/// provides the methods for pushing, popping, and indexing the list.
pub struct List<T, N>
where T: OwnedRef<N>
    , N: Node {
    head: RawLink<N>
  , tail: RawLink<N>
  , _ty_marker: PhantomData<T>
  , length: usize
 }

 // impl<T> Node for List<T>
 // where T: OwnedRef
 //     , T: Node {
 //
 //    fn next(&self) -> &RawLink<Self> { &self.head }
 //    fn prev(&self) -> &RawLink<Self> { &self.tail }
 //
 //    fn next_mut(&mut self) -> &mut RawLink<Self> { self.head }
 //    fn prev_mut(&mut self) -> &mut RawLink<Self> { self.tail }
 // }
impl<T, N> List<T, N>
where T: OwnedRef<N>
    , N: Node {

    /// Construct a new `List<T, N>` with zero elements
    pub const fn new() -> Self {
        List { head: RawLink::none()
             , tail: RawLink::none()
             , _ty_marker: PhantomData
             , length: 0 }
    }

    /// Returns the length of the list
    #[inline] pub fn len(&self) -> usize {
        self.length
    }

    /// Borrows the first element of the list as an `Option`
    ///
    /// # Returns
    ///   - `Some(&N)` if the list has elements
    ///   - `None` if the list is empty.
    #[inline] pub fn front(&self) -> Option<&N> {
        unsafe { self.head.resolve() }
    }

    /// Borrows the last element of the list as an `Option`
    ///
    /// # Returns
    ///   - `Some(&N)` if the list has elements
    ///   - `None` if the list is empty.
    #[inline] pub fn back(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }

    /// Mutably borrows the first element of the list as an `Option`
    ///
    /// # Returns
    ///   - `Some(&mut N)` if the list has elements
    ///   - `None` if the list is empty.
    #[inline] pub fn front_mut(&mut self) -> Option<&mut N> {
        unsafe { self.head.resolve_mut() }
    }

    /// Mutably borrows the last element of the list as an `Option`
    ///
    /// # Returns
    ///   - `Some(&mut N)` if the list has elements
    ///   - `None` if the list is empty.
    #[inline] pub fn back_mut(&mut self) -> Option<&mut N> {
        unsafe { self.tail.resolve_mut() }
    }

    /// Returns true if the list is empty.
    #[inline] pub fn is_empty(&self) -> bool {
        self.head.is_none()
    }

    /// Push an element to the front of the list.
    // TODO: should this really be called "prepend"?
    pub fn push_front(&mut self, mut item: T) {
        unsafe {
            match self.head.resolve_mut() {
                None => {
                    // If this node's head is empty, set the pushed item's
                    // links to None, and make this node's tail point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.tail = RawLink::some(item.get_mut());
                }
              , Some(head) => {
                    // If this node is not empty, set the pushed item's tail
                    // to point at the head node, and make the head node's tail
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::some(head);
                    *item.get_mut().prev_mut() = RawLink::none();
                    *head.prev_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.head = RawLink::some(item.get_mut());
            item.take();
            self.length += 1;
        }
    }

    /// Push an element to the back of the list.
    //  TODO: should this really be called "append"?
    //  (the Rust standard library uses `append` to refer to the "drain all the
    //  elements of another list and push them to this list" operation, but I
    //  think that that function is more properly called `concat`...)
    pub fn push_back(&mut self, mut item: T) {
        unsafe {
            match self.tail.resolve_mut() {
                None => {
                    // If this node's tail is empty, set the pushed item's
                    // links to  None, and make this node's head point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.head = RawLink::some(item.get_mut());
                }
              , Some(tail) => {
                    // If this node is not empty, set the pushed item's head
                    // to point at the tail node, and make the tail node's head
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::some(tail);
                    *tail.next_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.tail = RawLink::some(item.get_mut());
            item.take();
            self.length += 1;
        }
    }

    /// Removes and returns the element at the front of the list.
    ///
    /// # Returns
    ///   - `Some(T)` containing the element at the front of the list if the
    ///     list is not empty
    ///   - `None` if the list is empty
    pub fn pop_front(&mut self) -> Option<T> {
        unsafe {
            self.head.take().resolve_mut()
                .map(|head| {
                    // mem::swap( &mut self.head
                    //          , head.next_mut().resolve_mut()
                    //                .map(|next| next.prev_mut())
                    //                .unwrap_or(&mut RawLink::none()) );
                    match head.next_mut().resolve_mut() {
                        None => self.tail = RawLink::none()
                      , Some(next) => {
                            *next.prev_mut() = RawLink::none();
                            self.head = RawLink::some(next);
                        }
                    }
                    self.length -= 1;
                    T::from_raw(head)
                })
        }
    }

    /// Removes and returns the element at the end of the list.
    ///
    /// # Returns
    ///   - `Some(T)` containing the element at the end of the list if the
    ///     list is not empty
    ///   - `None` if the list is empty
    pub fn pop_back(&mut self) -> Option<T> {
        unsafe {
            self.tail.take().resolve_mut()
                .map(|tail| {
                    match tail.prev_mut().resolve_mut() {
                        None => self.head = RawLink::none()
                      , Some(prev) => {
                            *prev.next_mut() = RawLink::none();
                            self.tail = RawLink::some(prev);
                        }
                    }
                    self.length -= 1;
                    T::from_raw(tail)
                })
        }
    }

    /// Borrows the element at the front of the list
    ///
    /// # Returns
    ///   - `Some(&T)` containing the element at the end of the list if the
    ///     list is not empty
    ///   - `None` if the list is empty
    pub fn peek_front(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }

    /// Returns a cursor for iterating over or modifying the list.
    pub fn cursor<'a>(&'a mut self) -> ListCursor<'a, T, N> {
        ListCursor { list: self
                   , current: RawLink::none() }
    }

}

/// A cursor for an intrusive linked list.
///
/// A cursor functions similarly to an iterator, except that it can seek back
/// and forth rather than just advancing through the list, and it can mutate
/// the element "under" the cursor.
// TODO: can we implement `Iterator` for cursors?
pub struct ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {
        list: &'a mut List<T, N>
      , current: RawLink<N>
}

impl<'a, T, N> ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {

    /// Advances the cursor to the next element and borrows it mutably.
    ///
    /// If the cursor is at the end of the list, this advances it back to the
    /// first element.
    ///
    /// # Returns
    ///   - `Some(&mut N)` if the list is not empty
    ///   - `None` if the list is empty
    pub fn next(&mut self) -> Option<&mut N> {
        unsafe {
            match self.current.take().resolve_mut() {
                None => self.list.head.resolve_mut()
                            .and_then(|head| {
                                self.current = RawLink::some(head);
                                self.current.resolve_mut()
                            })
              , Some(thing) => {
                    self.current = match thing.next_mut().resolve_mut() {
                        None => RawLink::none()
                      , Some(other_thing) => RawLink::some(other_thing)
                    };
                    self.current.resolve_mut()
                }
            }
        }
    }

    /// Borrows the next element in the list without advancing the cursor.
    ///
    /// If the cursor is at the end of the list, this returns the first element
    /// instead.
    ///
    /// # Returns
    ///   - `Some(&N)` if the list is not empty
    ///   - `None` if the list is empty
    pub fn peek_next(&self) -> Option<&N> {
        unsafe {
            self.current.resolve()
                .map_or( self.list.front()
                       , |curr| curr.next().resolve())
        }
    }

    /// Removes the element currently under the cursor and returns it.
    ///
    /// # Returns
    ///   - `Some(T)` if the there is an element currently under the cursor
    ///     (i.e., the list is not empty)
    ///   - `None` if the list is empty.
    pub fn remove(&mut self) -> Option<T> {
        unsafe {
            match self.current.resolve_mut() {
                None    => self.list.pop_front()
              , Some(c) =>
                    c.next_mut().take().resolve_mut()
                     .map(|p| {
                        match p.next_mut().resolve_mut() {
                            None => self.list.tail = RawLink::some(c)
                          , Some(n) => {
                                *n.prev_mut() = RawLink::some(c);
                                *c.next_mut() = RawLink::some(n);
                            }
                        }
                        T::from_raw(p)
                    })
            }
        }
    }

    /// Searches for and removes the first element matching a predicate.
    ///
    /// # Arguments
    ///   - `p`: A predicate (function of the form `&N -> bool`) that returns
    ///     true if the element should be removed and false if it should not.
    ///
    /// # Returns
    ///   - `Some(T)` if an element matching the predicate was found
    ///   - `None` if no elements matched the predicate (or if the list is
    ///     empty.)
    pub fn find_and_remove<P>(&mut self, predicate: P) -> Option<T>
    where P: Fn(&N) -> bool {
        while self.peek_next().is_some() {
            if predicate(self.peek_next().unwrap()) == true {
                return self.remove()
            } else {
                self.next();
            }
        }
        None
    }

}

// impl<'a, T, N> Iterator for ListCursor<'a, T, N>
// where T: OwnedRef<N>
//     , T: 'a
//     , N: Node
//     , N: 'a {
//     type Item = &'a mut N;
//
//     fn next<'b: 'a>(&'b mut self) -> Option<&'a mut N> {
//         self.next()
//     }
// }

//
// unsafe impl<T> OwnedRef for Unique<T> where T: Node {
//
//     #[inline]
//     fn take(self) {}
//
//     unsafe fn from_raw(ptr: *mut T) -> Self {
//         Unique::new(ptr)
//     }
// }
//
// unsafe impl<'a, T> OwnedRef<T> for &'a mut T {
//     #
//     #[inline] unsafe fn from_raw(raw: *mut T) -> &'a mut T {
//         &mut *raw
//     }
//
//     #[inline] unsafe fn take(self) {
//         forget(self);
//     }
// }
//

unsafe impl<T> OwnedRef<T> for Unique<T>  {
    #[inline]
    fn get(&self) -> &T { unsafe { self.get() } }

    #[inline]
    fn get_mut(&mut self) -> &mut T { unsafe { self.get_mut() } }

    #[inline]
    unsafe fn take(self) {}

    unsafe fn from_raw(ptr: *mut T) -> Self {
        Unique::new(ptr)
    }
}

#[cfg(any(test, feature = "use-std"))]
unsafe impl<T> OwnedRef<T> for ::std::boxed::Box<T> {

    fn get(&self) -> &T { &**self }
    fn get_mut(&mut self) -> &mut T { &mut **self }

    #[inline] unsafe fn take(self) {
        ::std::boxed::Box::into_raw(self);
    }

    unsafe fn from_raw(ptr: *mut T) -> Self {
        ::std::boxed::Box::from_raw(ptr)
    }
}
<|endoftext|>


<commit_before>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::{File,fs};
use std::io::process::Command;
use std::path::posix::Path;
use std::os::homedir;
use libc::funcs::c95::stdlib::system;
#[cfg(test)] use std::rand::random;
#[cfg(test)] use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = match muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        true  => Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string())),
        false => create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path);

        match default_editor_set() {
            true  => open_project_file(path),
            false => println!("Default editor is not set.")
        }
    } else {
        println!("Project already exists.");
    }
}

fn default_editor_set() -> bool {
  let output = match Command::new("which").arg("$EDITOR").output() {
      Ok(output) => output.output.to_string(),
      Err(e) => fail!("failed to execute process: {}", e),
  };

  !output.is_empty()
}

#[cfg(not(test))] fn open_project_file(path: &Path) {
    let method = format!("$EDITOR {}", path.display()).to_c_str();
    unsafe { system(method.unwrap()); };
}

#[cfg(test)] fn open_project_file(_path: &Path) { }

/// Copy and create the new project file from a template. Attempt to open the
/// users default editor to make changes.
fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
}

/// Create the muxed directory and return the path if creation is successful.
fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    match fs::mkdir(path, ::std::io::UserRWX) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }

    path.clone()
}

/// Return a boolean if the ~/.muxed/ dir exists.
fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

/// Return the users current homedir as a string.
fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

/// Test helper to standardize how random files and directories are generated.
#[cfg(test)]
fn random_name() -> String {
    format!("test_{}", random::<f64>())
}

#[test]
fn muxed_dir_exists_returns_false() {
    assert!(!muxed_dir_exists(&random_name()));
}

#[test]
fn muxed_dir_exists_returns_true() {
    let dir = random_name();
    create_muxed_dir(&dir);
    assert!(muxed_dir_exists(&dir));

    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn creates_muxed_dir() {
    let dir = random_name();
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    match fs::unlink(path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
    }
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        match fs::unlink(path) {
            Ok(()) => (), // succeeded
            Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
        }
    })
}
<commit_msg>Better error message.<commit_after>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::{File,fs};
use std::io::process::Command;
use std::path::posix::Path;
use std::os::homedir;
use libc::funcs::c95::stdlib::system;
#[cfg(test)] use std::rand::random;
#[cfg(test)] use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = match muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        true  => Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string())),
        false => create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path);

        match default_editor_set() {
            true  => open_project_file(path),
            false => println!("Default editor is not set. Please define $EDITOR in your ~/.bashrc or similar file.")
        }
    } else {
        println!("Project already exists.");
    }
}

fn default_editor_set() -> bool {
  let output = match Command::new("which").arg("$EDITOR").output() {
      Ok(output) => output.output.to_string(),
      Err(e) => fail!("failed to execute process: {}", e),
  };

  !output.is_empty()
}

#[cfg(not(test))] fn open_project_file(path: &Path) {
    let method = format!("$EDITOR {}", path.display()).to_c_str();
    unsafe { system(method.unwrap()); };
}

#[cfg(test)] fn open_project_file(_path: &Path) { }

/// Copy and create the new project file from a template. Attempt to open the
/// users default editor to make changes.
fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
}

/// Create the muxed directory and return the path if creation is successful.
fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    match fs::mkdir(path, ::std::io::UserRWX) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }

    path.clone()
}

/// Return a boolean if the ~/.muxed/ dir exists.
fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

/// Return the users current homedir as a string.
fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

/// Test helper to standardize how random files and directories are generated.
#[cfg(test)]
fn random_name() -> String {
    format!("test_{}", random::<f64>())
}

#[test]
fn muxed_dir_exists_returns_false() {
    assert!(!muxed_dir_exists(&random_name()));
}

#[test]
fn muxed_dir_exists_returns_true() {
    let dir = random_name();
    create_muxed_dir(&dir);
    assert!(muxed_dir_exists(&dir));

    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn creates_muxed_dir() {
    let dir = random_name();
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    match fs::unlink(path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
    }
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        match fs::unlink(path) {
            Ok(()) => (), // succeeded
            Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
        }
    })
}
<|endoftext|>