<commit_before>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// i2c_ds3231.rs - Set and retrieve the time on a DS3231 RTC using I2C.

use std::process::exit;
use std::thread::sleep;
use std::time::Duration;

use rppal::i2c::I2c;

// DS3231 I2C default slave address.
const ADDR_DS3231: u16 = 0x68;

// DS3231 register addresses.
const SECONDS: usize = 0x00;
const MINUTES: usize = 0x01;
const HOURS: usize = 0x02;

// Helper functions to encode and decode binary-coded decimal (BCD) values.
fn bcd2dec(bcd: u8) -> u8 {
    (((bcd & 0xF0) >> 4) * 10) + (bcd & 0x0F)
}

fn dec2bcd(dec: u8) -> u8 {
    ((dec / 10) << 4) | (dec % 10)
}

fn main() {
    let mut i2c = I2c::new().unwrap_or_else(|e| {
        eprintln!("Error: Can't access I2C peripheral ({})", e);
        exit(1);
    });

    // Set the I2C slave address to the device we're communicating with.
    i2c.set_slave_address(ADDR_DS3231).unwrap();

    // Set the time to 11:59:50 AM. Start at register address 0x00 (Seconds) and
    // write 3 bytes, overwriting the Seconds, Minutes and Hours registers.
    // Setting bit 6 of the Hours register indicates we're using a 12-hour
    // format. Leaving bit 5 unset indicates AM.
    i2c.block_write(
        SECONDS as u8,
        &[dec2bcd(50), dec2bcd(59), dec2bcd(11) | (1 << 6)],
    )
    .unwrap();

    let mut reg: [u8; 3] = [0; 3];
    loop {
        // Start at the Seconds register (0x00) and read the values for the next
        // 3 registers (Seconds, Minutes, Hours) into the reg variable.
        i2c.block_read(SECONDS as u8, &mut reg).unwrap();

        // Display the retrieved time in the appropriate format based on bit 6 of
        // the Hours register.
        if reg[HOURS] & (1 << 6) > 0 {
            // 12-hour format.
            println!(
                "{:0>2}:{:0>2}:{:0>2} {}",
                bcd2dec(reg[HOURS] & 0x1F),
                bcd2dec(reg[MINUTES]),
                bcd2dec(reg[SECONDS]),
                if reg[HOURS] & (1 << 5) > 0 {
                    "PM"
                } else {
                    "AM"
                }
            );
        } else {
            // 24-hour format.
            println!(
                "{:0>2}:{:0>2}:{:0>2}",
                bcd2dec(reg[HOURS] & 0x3F),
                bcd2dec(reg[MINUTES]),
                bcd2dec(reg[SECONDS])
            );
        }

        sleep(Duration::from_secs(1));
    }
}
<commit_msg>Add error handling<commit_after>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// i2c_ds3231.rs - Sets and retrieves the time on a DS3231 RTC using I2C.

use std::process::exit;
use std::thread::sleep;
use std::time::Duration;

use rppal::i2c::I2c;

// DS3231 I2C default slave address.
const ADDR_DS3231: u16 = 0x68;

// DS3231 register addresses.
const REG_SECONDS: usize = 0x00;
const REG_MINUTES: usize = 0x01;
const REG_HOURS: usize = 0x02;

// Helper functions to encode and decode binary-coded decimal (BCD) values.
fn bcd2dec(bcd: u8) -> u8 {
    (((bcd & 0xF0) >> 4) * 10) + (bcd & 0x0F)
}

fn dec2bcd(dec: u8) -> u8 {
    ((dec / 10) << 4) | (dec % 10)
}

fn main() {
    let mut i2c = I2c::new().unwrap_or_else(|e| {
        eprintln!("Error: Can't access I2C peripheral ({})", e);
        exit(1);
    });

    // Set the I2C slave address to the device we're communicating with.
    i2c.set_slave_address(ADDR_DS3231).unwrap_or_else(|e| {
        eprintln!("Error: Unable to set slave address ({})", e);
        exit(1);
    });

    // Set the time to 11:59:50 AM. Start at register address 0x00 (Seconds) and
    // write 3 bytes, overwriting the Seconds, Minutes and Hours registers.
    // Setting bit 6 of the Hours register indicates we're using a 12-hour
    // format. Leaving bit 5 unset indicates AM.
    i2c.block_write(
        REG_SECONDS as u8,
        &[dec2bcd(50), dec2bcd(59), dec2bcd(11) | (1 << 6)],
    )
    .unwrap_or_else(|e| {
        eprintln!("Error: I2C block write failed ({})", e);
        exit(1);
    });

    let mut reg: [u8; 3] = [0; 3];
    loop {
        // Start at register address 0x00 (Seconds) and read the values of the
        // next 3 registers (Seconds, Minutes, Hours) into the reg variable.
        i2c.block_read(REG_SECONDS as u8, &mut reg)
            .unwrap_or_else(|e| {
                eprintln!("Error: I2C block read failed ({})", e);
                exit(1);
            });

        // Display the retrieved time in the appropriate format based on bit 6 of
        // the Hours register.
        if reg[REG_HOURS] & (1 << 6) > 0 {
            // 12-hour format.
            println!(
                "{:0>2}:{:0>2}:{:0>2} {}",
                bcd2dec(reg[REG_HOURS] & 0x1F),
                bcd2dec(reg[REG_MINUTES]),
                bcd2dec(reg[REG_SECONDS]),
                if reg[REG_HOURS] & (1 << 5) > 0 {
                    "PM"
                } else {
                    "AM"
                }
            );
        } else {
            // 24-hour format.
            println!(
                "{:0>2}:{:0>2}:{:0>2}",
                bcd2dec(reg[REG_HOURS] & 0x3F),
                bcd2dec(reg[REG_MINUTES]),
                bcd2dec(reg[REG_SECONDS])
            );
        }

        sleep(Duration::from_secs(1));
    }
}
<|endoftext|>


<commit_before>use serde::{self, Deserialize, Serialize};
use std::fmt::Debug;
use std::mem;
use std::ops::Deref;

/// An object that can be incrementally updated with events.
pub trait Incremental<E>: Sized {
    /// Try to update the object with an event.
    fn update(self, e: &E) -> Self;
}

/// An incremental object that can fail when updated.
///
/// Use the `Incremental` implementation on a `Result` type with `FailingIncremental` value to use
/// this.
pub trait FailingIncremental<E>: Sized {
    /// Error in case an event couldn't be handled.
    type Error: Debug;

    /// Try to update the object with an event.
    fn update(self, e: &E) -> Result<Self, Self::Error>;
}

impl<T: FailingIncremental<E>, E> Incremental<E> for Result<T, T::Error> {
    fn update(self, e: &E) -> Self {
        match self {
            Ok(state) => state.update(e),
            err => err,
        }
    }
}

/// Handle that stores an `Incremental` object and the event sequence used to build it.
///
/// Serializes itself by only storing the log.
pub struct IncrementalState<T: Incremental<E> + Default, E> {
    log: Vec<E>,
    state: T,
}

// Implemented manually instead of derived so that T::Event doesn't need to implement Default.
impl<T: Incremental<E> + Default, E> Default for IncrementalState<T, E> {
    fn default() -> Self {
        IncrementalState {
            log: Vec::new(),
            state: Default::default(),
        }
    }
}

impl<T: Incremental<E> + Default, E> IncrementalState<T, E> {
    pub fn push(&mut self, e: E) {
        // XXX: Need to get state away from borrow checker for updating, is there a better way than
        // ugly unsafe tricks?
        let state = mem::replace(&mut self.state, unsafe { mem::uninitialized() }).update(&e);
        self.state = state;
        self.log.push(e);
    }

    pub fn pop(&mut self) -> Option<E> {
        // TODO: Way to pop several items without O(n) delay for each.
        let ret = self.log.pop();
        self.replay();
        ret
    }

    fn replay(&mut self) {
        let mut state: T = Default::default();

        for e in &self.log {
            state = state.update(e);
        }

        self.state = state;
    }
}

impl<T: Incremental<E> + Default, E> Deref for IncrementalState<T, E> {
    type Target = T;

    fn deref(&self) -> &T { &self.state }
}

impl<T: Incremental<E> + Default, E: Serialize> Serialize for IncrementalState<T, E> {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.log.serialize(s)
    }
}

impl<'a, T: Incremental<E> + Default, E: Deserialize<'a>> Deserialize<'a>
    for IncrementalState<T, E>
{
    fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
        let mut ret: Self = IncrementalState {
            log: Vec::deserialize(d)?,
            state: Default::default(),
        };
        ret.replay();
        Ok(ret)
    }
}
<commit_msg>Add documentation test for IncrementalState<commit_after>use serde::{self, Deserialize, Serialize};
use std::fmt::Debug;
use std::mem;
use std::ops::Deref;

/// An object that can be incrementally updated with events.
pub trait Incremental<E>: Sized {
    /// Try to update the object with an event.
    fn update(self, e: &E) -> Self;
}

/// An incremental object that can fail when updated.
///
/// Use the `Incremental` implementation on a `Result` type with `FailingIncremental` value to use
/// this.
pub trait FailingIncremental<E>: Sized {
    /// Error in case an event couldn't be handled.
    type Error: Debug;

    /// Try to update the object with an event.
    fn update(self, e: &E) -> Result<Self, Self::Error>;
}

impl<T: FailingIncremental<E>, E> Incremental<E> for Result<T, T::Error> {
    fn update(self, e: &E) -> Self {
        match self {
            Ok(state) => state.update(e),
            err => err,
        }
    }
}

/// Handle that stores an `Incremental` object and the event sequence used to build it.
///
/// Serializes itself by only storing the log.
///
/// # Examples
///
/// ```
/// use calx::{Incremental, IncrementalState};
///
/// #[derive(Default)]
/// struct State(u32);
///
/// impl Incremental<u32> for State {
///     fn update(self, e: &u32) -> State { State(self.0 + *e) }
/// }
///
/// let mut handle: IncrementalState<State, u32> = Default::default();
/// assert_eq!(handle.0, 0);
///
/// for x in &[1, 2, 3, 4] { handle.push(*x); }
/// assert_eq!(handle.0, 10);
/// handle.pop();
/// assert_eq!(handle.0, 6);
/// ```
pub struct IncrementalState<T: Incremental<E> + Default, E> {
    log: Vec<E>,
    state: T,
}

// Implemented manually instead of derived so that T::Event doesn't need to implement Default.
impl<T: Incremental<E> + Default, E> Default for IncrementalState<T, E> {
    fn default() -> Self {
        IncrementalState {
            log: Vec::new(),
            state: Default::default(),
        }
    }
}

impl<T: Incremental<E> + Default, E> IncrementalState<T, E> {
    pub fn push(&mut self, e: E) {
        // XXX: Need to get state away from borrow checker for updating, is there a better way than
        // ugly unsafe tricks?
        let state = mem::replace(&mut self.state, unsafe { mem::uninitialized() }).update(&e);
        self.state = state;
        self.log.push(e);
    }

    pub fn pop(&mut self) -> Option<E> {
        // TODO: Way to pop several items without O(n) delay for each.
        let ret = self.log.pop();
        self.replay();
        ret
    }

    fn replay(&mut self) {
        let mut state: T = Default::default();

        for e in &self.log {
            state = state.update(e);
        }

        self.state = state;
    }
}

impl<T: Incremental<E> + Default, E> Deref for IncrementalState<T, E> {
    type Target = T;

    fn deref(&self) -> &T { &self.state }
}

impl<T: Incremental<E> + Default, E: Serialize> Serialize for IncrementalState<T, E> {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.log.serialize(s)
    }
}

impl<'a, T: Incremental<E> + Default, E: Deserialize<'a>> Deserialize<'a>
    for IncrementalState<T, E>
{
    fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
        let mut ret: Self = IncrementalState {
            log: Vec::deserialize(d)?,
            state: Default::default(),
        };
        ret.replay();
        Ok(ret)
    }
}
<|endoftext|>


<commit_before>use assert_cmd::prelude::*;
use std::process::{Command, Stdio};

use anyhow::{Context, Result};
use nix::sys::signal::{kill, Signal};
use nix::unistd::Pid;

mod helper;

use helper::*;

#[test]
/// Spin up the daemon and send a SIGTERM shortly afterwards.
/// This should trigger the graceful shutdown and kill the process.
fn test_ctrlc() -> Result<()> {
    let (_settings, tempdir) = helper::base_setup()?;

    let mut child = Command::cargo_bin("pueued")?
        .arg("--config")
        .arg(tempdir.path().join("pueue.yml").to_str().unwrap())
        .arg("-vvv")
        .stdout(Stdio::piped())
        .spawn()?;

    let pid = get_pid(tempdir.path())?;

    // Send SIGTERM signal to process via nix
    let nix_pid = Pid::from_raw(pid);
    kill(nix_pid, Signal::SIGTERM).context("Failed to send SIGTERM to pid")?;

    // Sleep for 500ms and give the daemon time to shut down
    helper::sleep_ms(500);

    let result = child.try_wait();
    assert!(matches!(result, Ok(Some(_))));
    let code = result.unwrap().unwrap();
    assert!(matches!(code.code(), Some(1)));

    Ok(())
}
<commit_msg>bug: Only run shutdown test on unix<commit_after>use assert_cmd::prelude::*;
use std::process::{Command, Stdio};

use anyhow::{Context, Result};
use nix::sys::signal::{kill, Signal};
use nix::unistd::Pid;

mod helper;

use helper::*;

#[cfg(target_os = "linux")]
#[test]
/// Spin up the daemon and send a SIGTERM shortly afterwards.
/// This should trigger the graceful shutdown and kill the process.
fn test_ctrlc() -> Result<()> {
    let (_settings, tempdir) = helper::base_setup()?;

    let mut child = Command::cargo_bin("pueued")?
        .arg("--config")
        .arg(tempdir.path().join("pueue.yml").to_str().unwrap())
        .arg("-vvv")
        .stdout(Stdio::piped())
        .spawn()?;

    let pid = get_pid(tempdir.path())?;

    // Send SIGTERM signal to process via nix
    let nix_pid = Pid::from_raw(pid);
    kill(nix_pid, Signal::SIGTERM).context("Failed to send SIGTERM to pid")?;

    // Sleep for 500ms and give the daemon time to shut down
    helper::sleep_ms(500);

    let result = child.try_wait();
    assert!(matches!(result, Ok(Some(_))));
    let code = result.unwrap().unwrap();
    assert!(matches!(code.code(), Some(1)));

    Ok(())
}
<|endoftext|>


<commit_before>use super::errors::{
    IndexedAttestationInvalid as Invalid, IndexedAttestationValidationError as Error,
};
use std::collections::HashSet;
use std::iter::FromIterator;
use tree_hash::TreeHash;
use types::*;

/// Verify an `IndexedAttestation`.
///
/// Spec v0.6.1
pub fn verify_indexed_attestation<T: EthSpec>(
    state: &BeaconState<T>,
    indexed_attestation: &IndexedAttestation,
    spec: &ChainSpec,
) -> Result<(), Error> {
    verify_indexed_attestation_parametric(state, indexed_attestation, spec, true)
}

/// Verify but don't check the signature.
///
/// Spec v0.6.1
pub fn verify_indexed_attestation_without_signature<T: EthSpec>(
    state: &BeaconState<T>,
    indexed_attestation: &IndexedAttestation,
    spec: &ChainSpec,
) -> Result<(), Error> {
    verify_indexed_attestation_parametric(state, indexed_attestation, spec, false)
}

/// Optionally check the signature.
///
/// Spec v0.6.1
fn verify_indexed_attestation_parametric<T: EthSpec>(
    state: &BeaconState<T>,
    indexed_attestation: &IndexedAttestation,
    spec: &ChainSpec,
    verify_signature: bool,
) -> Result<(), Error> {
    let custody_bit_0_indices = &indexed_attestation.custody_bit_0_indices;
    let custody_bit_1_indices = &indexed_attestation.custody_bit_1_indices;

    // Ensure no duplicate indices across custody bits
    let custody_bit_intersection: HashSet<&u64> =
        &HashSet::from_iter(custody_bit_0_indices) & &HashSet::from_iter(custody_bit_1_indices);
    verify!(
        custody_bit_intersection.is_empty(),
        Invalid::CustodyBitValidatorsIntersect
    );

    // Check that nobody signed with custody bit 1 (to be removed in phase 1)
    if custody_bit_1_indices.len() > 0 {
        invalid!(Invalid::CustodyBitfieldHasSetBits);
    }

    let total_indices = custody_bit_0_indices.len() + custody_bit_1_indices.len();
    verify!(1 <= total_indices, Invalid::NoValidatorIndices);
    verify!(
        total_indices as u64 <= spec.max_indices_per_attestation,
        Invalid::MaxIndicesExceed(spec.max_indices_per_attestation, total_indices)
    );

    // Check that both vectors of indices are sorted
    let check_sorted = |list: &Vec<u64>| {
        for i in 0..list.len() - 1 {
            if list[i] >= list[i + 1] {
                invalid!(Invalid::BadValidatorIndicesOrdering(i));
            }
        }
        Ok(())
    };
    check_sorted(custody_bit_0_indices)?;
    check_sorted(custody_bit_1_indices)?;

    if verify_signature {
        verify_indexed_attestation_signature(state, indexed_attestation, spec)?;
    }

    Ok(())
}

/// Create an aggregate public key for a list of validators, failing if any key can't be found.
fn create_aggregate_pubkey<'a, T, I>(
    state: &BeaconState<T>,
    validator_indices: I,
) -> Result<AggregatePublicKey, Error>
where
    I: IntoIterator<Item = &'a u64>,
    T: EthSpec,
{
    validator_indices.into_iter().try_fold(
        AggregatePublicKey::new(),
        |mut aggregate_pubkey, &validator_idx| {
            state
                .validator_registry
                .get(validator_idx as usize)
                .ok_or(Error::Invalid(Invalid::UnknownValidator(validator_idx)))
                .map(|validator| {
                    aggregate_pubkey.add(&validator.pubkey);
                    aggregate_pubkey
                })
        },
    )
}

/// Verify the signature of an IndexedAttestation.
///
/// Spec v0.6.1
fn verify_indexed_attestation_signature<T: EthSpec>(
    state: &BeaconState<T>,
    indexed_attestation: &IndexedAttestation,
    spec: &ChainSpec,
) -> Result<(), Error> {
    let bit_0_pubkey = create_aggregate_pubkey(state, &indexed_attestation.custody_bit_0_indices)?;
    let bit_1_pubkey = create_aggregate_pubkey(state, &indexed_attestation.custody_bit_1_indices)?;

    let message_0 = AttestationDataAndCustodyBit {
        data: indexed_attestation.data.clone(),
        custody_bit: false,
    }
    .tree_hash_root();
    let message_1 = AttestationDataAndCustodyBit {
        data: indexed_attestation.data.clone(),
        custody_bit: true,
    }
    .tree_hash_root();

    let mut messages = vec![];
    let mut keys = vec![];

    if !indexed_attestation.custody_bit_0_indices.is_empty() {
        messages.push(&message_0[..]);
        keys.push(&bit_0_pubkey);
    }
    if !indexed_attestation.custody_bit_1_indices.is_empty() {
        messages.push(&message_1[..]);
        keys.push(&bit_1_pubkey);
    }

    let domain = spec.get_domain(
        indexed_attestation.data.target_epoch,
        Domain::Attestation,
        &state.fork,
    );

    verify!(
        indexed_attestation
            .signature
            .verify_multiple(&messages[..], domain, &keys[..]),
        Invalid::BadSignature
    );

    Ok(())
}
<commit_msg>Fix underflow in verify_indexed_attestation<commit_after>use super::errors::{
    IndexedAttestationInvalid as Invalid, IndexedAttestationValidationError as Error,
};
use std::collections::HashSet;
use std::iter::FromIterator;
use tree_hash::TreeHash;
use types::*;

/// Verify an `IndexedAttestation`.
///
/// Spec v0.6.1
pub fn verify_indexed_attestation<T: EthSpec>(
    state: &BeaconState<T>,
    indexed_attestation: &IndexedAttestation,
    spec: &ChainSpec,
) -> Result<(), Error> {
    verify_indexed_attestation_parametric(state, indexed_attestation, spec, true)
}

/// Verify but don't check the signature.
///
/// Spec v0.6.1
pub fn verify_indexed_attestation_without_signature<T: EthSpec>(
    state: &BeaconState<T>,
    indexed_attestation: &IndexedAttestation,
    spec: &ChainSpec,
) -> Result<(), Error> {
    verify_indexed_attestation_parametric(state, indexed_attestation, spec, false)
}

/// Optionally check the signature.
///
/// Spec v0.6.1
fn verify_indexed_attestation_parametric<T: EthSpec>(
    state: &BeaconState<T>,
    indexed_attestation: &IndexedAttestation,
    spec: &ChainSpec,
    verify_signature: bool,
) -> Result<(), Error> {
    let custody_bit_0_indices = &indexed_attestation.custody_bit_0_indices;
    let custody_bit_1_indices = &indexed_attestation.custody_bit_1_indices;

    // Ensure no duplicate indices across custody bits
    let custody_bit_intersection: HashSet<&u64> =
        &HashSet::from_iter(custody_bit_0_indices) & &HashSet::from_iter(custody_bit_1_indices);
    verify!(
        custody_bit_intersection.is_empty(),
        Invalid::CustodyBitValidatorsIntersect
    );

    // Check that nobody signed with custody bit 1 (to be removed in phase 1)
    if custody_bit_1_indices.len() > 0 {
        invalid!(Invalid::CustodyBitfieldHasSetBits);
    }

    let total_indices = custody_bit_0_indices.len() + custody_bit_1_indices.len();
    verify!(1 <= total_indices, Invalid::NoValidatorIndices);
    verify!(
        total_indices as u64 <= spec.max_indices_per_attestation,
        Invalid::MaxIndicesExceed(spec.max_indices_per_attestation, total_indices)
    );

    // Check that both vectors of indices are sorted
    let check_sorted = |list: &Vec<u64>| {
        list.windows(2).enumerate().try_for_each(|(i, pair)| {
            if pair[0] >= pair[1] {
                invalid!(Invalid::BadValidatorIndicesOrdering(i));
            } else {
                Ok(())
            }
        })?;
        Ok(())
    };
    check_sorted(custody_bit_0_indices)?;
    check_sorted(custody_bit_1_indices)?;

    if verify_signature {
        verify_indexed_attestation_signature(state, indexed_attestation, spec)?;
    }

    Ok(())
}

/// Create an aggregate public key for a list of validators, failing if any key can't be found.
fn create_aggregate_pubkey<'a, T, I>(
    state: &BeaconState<T>,
    validator_indices: I,
) -> Result<AggregatePublicKey, Error>
where
    I: IntoIterator<Item = &'a u64>,
    T: EthSpec,
{
    validator_indices.into_iter().try_fold(
        AggregatePublicKey::new(),
        |mut aggregate_pubkey, &validator_idx| {
            state
                .validator_registry
                .get(validator_idx as usize)
                .ok_or(Error::Invalid(Invalid::UnknownValidator(validator_idx)))
                .map(|validator| {
                    aggregate_pubkey.add(&validator.pubkey);
                    aggregate_pubkey
                })
        },
    )
}

/// Verify the signature of an IndexedAttestation.
///
/// Spec v0.6.1
fn verify_indexed_attestation_signature<T: EthSpec>(
    state: &BeaconState<T>,
    indexed_attestation: &IndexedAttestation,
    spec: &ChainSpec,
) -> Result<(), Error> {
    let bit_0_pubkey = create_aggregate_pubkey(state, &indexed_attestation.custody_bit_0_indices)?;
    let bit_1_pubkey = create_aggregate_pubkey(state, &indexed_attestation.custody_bit_1_indices)?;

    let message_0 = AttestationDataAndCustodyBit {
        data: indexed_attestation.data.clone(),
        custody_bit: false,
    }
    .tree_hash_root();
    let message_1 = AttestationDataAndCustodyBit {
        data: indexed_attestation.data.clone(),
        custody_bit: true,
    }
    .tree_hash_root();

    let mut messages = vec![];
    let mut keys = vec![];

    if !indexed_attestation.custody_bit_0_indices.is_empty() {
        messages.push(&message_0[..]);
        keys.push(&bit_0_pubkey);
    }
    if !indexed_attestation.custody_bit_1_indices.is_empty() {
        messages.push(&message_1[..]);
        keys.push(&bit_1_pubkey);
    }

    let domain = spec.get_domain(
        indexed_attestation.data.target_epoch,
        Domain::Attestation,
        &state.fork,
    );

    verify!(
        indexed_attestation
            .signature
            .verify_multiple(&messages[..], domain, &keys[..]),
        Invalid::BadSignature
    );

    Ok(())
}
<|endoftext|>


<commit_before>use std::str::FromStr;
use std::collections::HashMap;

type Stack<T> = Vec<T>;

#[derive(Default)]
pub struct Interpreter<'a, 'b, T: 'b> {
    data_stack: Stack<T>,
    vocabulary: HashMap<&'a str, &'b Word<T>>,
}

impl<'a, 'b, T: 'b> Interpreter<'a, 'b, T> where T: FromStr {

    fn push(&mut self, value: T) {
        self.data_stack.push(value)
    }

    fn pop(&mut self) -> Option<T> {
        self.data_stack.pop()
    }

    fn eval_token(&mut self, token: &str) {
        if let Ok(literal) = token.parse::<T>() {
            self.push(literal);
        } else {
            if let Some(&word) = self.lookup(token) {
                word.eval_within(self);
            }
        }
    }

    fn define_word(&mut self, name: &'a str, word: &'b Word<T>) {
        self.vocabulary.insert(name, word);
    }

    fn lookup(&self, token: &str) -> Option<&&'b Word<T>> {
        self.vocabulary.get(token)
    }
}

struct Word<T> {
    entry: Box<Fn(&mut Interpreter<T>) -> ()>,
}

impl<T> Word<T> {
    fn eval_within(&self, mut i: &mut Interpreter<T>) {
      (self.entry)(&mut i)
    }
}

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

    fn fixture_plus() -> Word<i32> {
        Word {
            entry: Box::new(|ref mut i| {
                if let (Some(b), Some(a)) = (i.pop(), i.pop()) {
                    i.push(a + b)
                } else { panic!("Stack underflow") }
            })
        }
    }

    #[test]
    fn register_word() {
        let plus = fixture_plus();
        let mut interpreter = Interpreter::<i32>::default();
        interpreter.define_word("+", &plus);
        interpreter.push(51);
        interpreter.push(42);
        interpreter.eval_token("+");
        assert_eq!(Some(93), interpreter.pop())
    }

    #[test]
    fn plus_word() {
        let mut interpreter = Interpreter::<i32>::default();
        let plus = fixture_plus();
        interpreter.push(42);
        interpreter.push(51);
        plus.eval_within(&mut interpreter);
        assert_eq!(Some(93), interpreter.pop())
    }

    #[test]
    fn push_literal() {
        let mut interpreter = Interpreter::<i32>::default();
        interpreter.eval_token("42");
        assert_eq!(Some(42), interpreter.pop());
    }

    #[test]
    fn pops_nothing() {
        let mut interpreter = Interpreter::<i32>::default();
        assert_eq!(None, interpreter.pop())
    }

    #[test]
    fn pops_as_pushed() {
        let mut interpreter = Interpreter::<i32>::default();
        interpreter.push(42);
        assert_eq!(Some(42), interpreter.pop());
        assert_eq!(None, interpreter.pop())
    }

    #[test]
    fn pops_in_reverse_order() {
        let mut interpreter = Interpreter::<i32>::default();
        interpreter.push(42);
        interpreter.push(51);
        assert_eq!(Some(51), interpreter.pop());
        assert_eq!(Some(42), interpreter.pop());
        assert_eq!(None, interpreter.pop())
    }
}
<commit_msg>Words shouldn't replace the whole interpreter<commit_after>use std::str::FromStr;
use std::collections::HashMap;

type Stack<T> = Vec<T>;

#[derive(Default)]
pub struct Interpreter<'a, 'b, T: 'b> {
    data_stack: Stack<T>,
    vocabulary: HashMap<&'a str, &'b Word<T>>,
}

impl<'a, 'b, T: 'b> Interpreter<'a, 'b, T> where T: FromStr {

    fn push(&mut self, value: T) {
        self.data_stack.push(value)
    }

    fn pop(&mut self) -> Option<T> {
        self.data_stack.pop()
    }

    fn eval_token(&mut self, token: &str) {
        if let Ok(literal) = token.parse::<T>() {
            self.push(literal);
        } else {
            if let Some(&word) = self.lookup(token) {
                word.eval_within(self);
            }
        }
    }

    fn define_word(&mut self, name: &'a str, word: &'b Word<T>) {
        self.vocabulary.insert(name, word);
    }

    fn lookup(&self, token: &str) -> Option<&&'b Word<T>> {
        self.vocabulary.get(token)
    }
}

struct Word<T> {
    entry: Box<Fn(&mut Interpreter<T>) -> ()>,
}

impl<T> Word<T> {
    fn eval_within(&self, i: &mut Interpreter<T>) {
      (self.entry)(i)
    }
}

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

    fn fixture_plus() -> Word<i32> {
        Word {
            entry: Box::new(|ref mut i| {
                if let (Some(b), Some(a)) = (i.pop(), i.pop()) {
                    i.push(a + b)
                } else { panic!("Stack underflow") }
            })
        }
    }

    #[test]
    fn register_word() {
        let plus = fixture_plus();
        let mut interpreter = Interpreter::<i32>::default();
        interpreter.define_word("+", &plus);
        interpreter.push(51);
        interpreter.push(42);
        interpreter.eval_token("+");
        assert_eq!(Some(93), interpreter.pop())
    }

    #[test]
    fn plus_word() {
        let mut interpreter = Interpreter::<i32>::default();
        let plus = fixture_plus();
        interpreter.push(42);
        interpreter.push(51);
        plus.eval_within(&mut interpreter);
        assert_eq!(Some(93), interpreter.pop())
    }

    #[test]
    fn push_literal() {
        let mut interpreter = Interpreter::<i32>::default();
        interpreter.eval_token("42");
        assert_eq!(Some(42), interpreter.pop());
    }

    #[test]
    fn pops_nothing() {
        let mut interpreter = Interpreter::<i32>::default();
        assert_eq!(None, interpreter.pop())
    }

    #[test]
    fn pops_as_pushed() {
        let mut interpreter = Interpreter::<i32>::default();
        interpreter.push(42);
        assert_eq!(Some(42), interpreter.pop());
        assert_eq!(None, interpreter.pop())
    }

    #[test]
    fn pops_in_reverse_order() {
        let mut interpreter = Interpreter::<i32>::default();
        interpreter.push(42);
        interpreter.push(51);
        assert_eq!(Some(51), interpreter.pop());
        assert_eq!(Some(42), interpreter.pop());
        assert_eq!(None, interpreter.pop())
    }
}
<|endoftext|>


<commit_before>//! Commands from the user to manipulate the tree

use super::{try_lock_tree, try_lock_action};
use super::{Action, ActionErr, Container, ContainerType, Direction, Handle, Layout, TreeError};
use super::Tree;

use uuid::Uuid;
use rustwlc::{Point, ResizeEdge, WlcView, WlcOutput, ViewType};
use rustc_serialize::json::{Json, ToJson};

use std::collections::HashSet;

pub type CommandResult = Result<(), TreeError>;

/* These commands are exported to take nothing and return nothing,
 * since they are the commands actually registered and usable over
 * the IPC/Lua thread.
 */

pub fn remove_active() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Some(container) = tree.0.get_active_container_mut() {
            match *container {
                Container::View { ref handle, .. } => {
                    handle.close();
                    // Thanks borrowck
                    // Views shouldn't be removed from tree, that's handled by
                    // view_destroyed callback
                    return
                },
                _ => {}
            }
        }
        tree.0.remove_active();
    }
}

pub fn toggle_float() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.toggle_float().ok();
    }
}

pub fn toggle_float_focus() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Err(err) = tree.toggle_floating_focus() {
            warn!("Could not float focus: {:#?}", err);
        }
    }
}

pub fn tile_switch() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Some(id) = tree.active_id() {
            tree.toggle_cardinal_tiling(id).unwrap_or_else(|err| {
                warn!("Could not toggle cardinal tiling: {:#?}", err);
            });
        }
    }
}

pub fn split_vertical() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Vertical).ok();
    }
}

pub fn split_horizontal() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Horizontal).ok();
    }
}

pub fn focus_left() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Left)
            .unwrap_or_else(|_| {
                warn!("Could not focus left");
            });
    }
}

pub fn focus_right() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Right)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            });
    }
}

pub fn focus_up() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Up)
            .unwrap_or_else(|_| {
                warn!("Could not focus up");
            });
    }
}

pub fn focus_down() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Down)
            .unwrap_or_else(|_| {
                warn!("Could not focus down");
            });
    }
}

pub fn move_active_left() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Left)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn move_active_right() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Right)
            .unwrap_or_else(|_| {
                error!("Could not focus right");
            })
    }
}

pub fn move_active_up() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Up)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn move_active_down() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Down)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn tree_as_json() -> Json {
    if let Ok(tree) = try_lock_tree() {
        tree.0.to_json()
    } else {
        Json::Null
    }
}

/// Returns a copy of the action behind the lock.
pub fn performing_action() -> Option<Action> {
    if let Ok(action) = try_lock_action() {
        *action
    } else {
        error!("Could not lock action mutex!");
        None
    }
}

/// Sets the value behind the lock to the provided value.
///
/// Note that this method blocks until the lock is released
///
/// None means an action is done being performed.
pub fn set_performing_action(val: Option<Action>) {
    if let Ok(mut action) = try_lock_action() {
        *action = val;
    } else {
        error!("Action mutex was poisoned");
        panic!("Action mutex was poisoned");
    }
}

/* These commands are the interface that the rest of Way Cooler has to the
 * tree. Any action done, whether through a callback, or from the IPC/Lua thread
 * it will have to go through one of these methods.
 */

impl Tree {
    /// Gets the uuid of the active container, if there is an active container
    pub fn active_id(&self) -> Option<Uuid> {
        self.0.active_container
            .map(|active_ix| self.0.tree[active_ix].get_id())
    }

    pub fn lookup_view(&self, view: WlcView) -> Option<Uuid> {
        self.0.lookup_view(view).map(|c| c.get_id())
    }

    pub fn toggle_float(&mut self) -> CommandResult {
        if let Some(uuid) = self.active_id() {
            let is_floating: Result<bool, _> = self.0.lookup(uuid)
                .and_then(|container| Ok(container.floating()));
            try!(match is_floating {
                Ok(true) => self.ground_container(uuid),
                Ok(false) => self.float_container(uuid),
                Err(err) => return Err(err)
            });
        }
        Ok(())
    }

    pub fn toggle_cardinal_tiling(&mut self, id: Uuid) -> CommandResult {
        self.0.toggle_cardinal_tiling(id)
            .and_then(|_| self.layout_active_of(ContainerType::Workspace))
    }

    pub fn toggle_floating_focus(&mut self) -> CommandResult {
        self.0.toggle_floating_focus()
    }

    pub fn move_active(&mut self, maybe_uuid: Option<Uuid>, direction: Direction) -> CommandResult {
        let uuid = try!(maybe_uuid
                        .or_else(|| self.0.get_active_container()
                                 .and_then(|container| Some(container.get_id())))
                        .ok_or(TreeError::NoActiveContainer));
        try!(self.0.move_container(uuid, direction));
        // NOTE Make this not layout the active, but actually the node index's workspace.
        try!(self.layout_active_of(ContainerType::Output));
        Ok(())
    }

    /// Attempts to drag the window around the screen.
    pub fn try_drag_active(&mut self, point: Point) -> CommandResult {
        if let Some(mut action) = performing_action() {
            let old_point = action.grab;
            let active_ix = try!(self.0.active_container
                                .ok_or(TreeError::NoActiveContainer));
            try!(self.0.drag_floating(active_ix, point, old_point));
            action.grab = point;
            set_performing_action(Some(action));
            Ok(())
        } else {
            Err(TreeError::PerformingAction(false))
        }
    }

    /// Adds an Output to the tree. Never fails
    pub fn add_output(&mut self, output: WlcOutput) -> CommandResult {
        self.0.add_output(output);
        Ok(())
    }

    /// Binds a view to be the background for all outputs.
    ///
    /// If there was a previous background, it is removed and deallocated.
    pub fn add_background(&mut self, view: WlcView) -> CommandResult {
        let outputs = self.0.tree.children_of(self.0.tree.root_ix());
        let mut to_remove = HashSet::with_capacity(outputs.len());
        for output_ix in outputs {
            match self.0.tree[output_ix] {
                Container::Output { ref mut background, .. } => {
                    if let Some(view) = background.take() {
                        to_remove.insert(view);
                    }
                    *background = Some(view);
                },
                _ => unreachable!()
            }
        }
        for view in to_remove {
            view.close();
        }
        Ok(())
    }

    /// Adds a Workspace to the tree. Never fails
    pub fn switch_to_workspace(&mut self, name: &str) -> CommandResult {
        self.0.switch_to_workspace(name);
        Ok(())
    }

    /// Tiles the active container of some container type. Never fails
    pub fn layout_active_of(&mut self, c_type: ContainerType) -> CommandResult {
        self.0.layout_active_of(c_type);
        Ok(())
    }

    /// Attempts to set the node behind the id to be floating
    pub fn float_container(&mut self, id: Uuid) -> CommandResult {
        self.0.float_container(id)
    }

    /// Attempts to set the node behind the id to be not floating
    pub fn ground_container(&mut self, id: Uuid) -> CommandResult {
        self.0.ground_container(id)
    }

    /// Adds a view to the workspace of the active container
    pub fn add_view(&mut self, view: WlcView) -> CommandResult {
        let tree = &mut self.0;
        let output = view.get_output();
        if tree.get_active_container().is_none() {
            return Err(TreeError::NoActiveContainer)
        }
        view.set_mask(output.get_mask());
        if view.get_type() != ViewType::empty() {
            try!(tree.add_floating_view(view));
        } else {
            try!(tree.add_view(view));
            tree.normalize_view(view);
        }
        tree.layout_active_of(ContainerType::Workspace);
        Ok(())
    }

    /// Attempts to remove a view from the tree. If it is not in the tree it fails.
    ///
    /// This will close the handle behind the view.
    pub fn remove_view(&mut self, view: WlcView) -> CommandResult {
        let result;
        match self.0.remove_view(&view) {
            Err(err)  => {
                result = Err(err)
            },
            Ok(Container::View { handle, id, .. }) => {
                trace!("Removed container {:?}", id);
                handle.close();
                trace!("Close wlc view {:?}", handle);
                result = Ok(())
            },
            _ => unreachable!()
        }
        let root_ix = self.0.tree.root_ix();
        self.0.layout(root_ix);
        result
    }

    /// Attempts to remove a container based on UUID. Fails if the container
    /// cannot be removed or if the container does not exist.
    ///
    /// This WILL close the view, and should never be called from the
    /// `view_destroyed` callback, as it's possible the view from that callback is invalid.
    pub fn remove_view_by_id(&mut self, id: Uuid) -> CommandResult {
        match try!(self.0.lookup(id)).get_handle() {
            Some(Handle::View(view)) => return self.remove_view(view),
            Some(Handle::Output(_)) | None => {
                Err(TreeError::UuidNotAssociatedWith(ContainerType::View))
            }
        }
    }

    /// Sets the view to be the new active container.
    /// Will fail if the container is floating.
    pub fn set_active_view(&mut self, view: WlcView) -> CommandResult {
        try!(self.0.set_active_view(view.clone()));
        view.focus();
        Ok(())
    }

    #[allow(dead_code)]
    /// Sets the active container to be the container at the UUID
    /// Fails if the container is not a container or view, or if the
    /// container does not exist
    ///
    /// Can also not set floating containers to be active.
    pub fn set_active_container_by_id(&mut self, id: Uuid) -> CommandResult {
        self.0.set_active_container(id)
    }

    /// Focuses on the container. If the container is not floating and is a
    /// Container or a View, then it is also made the active container.
    pub fn focus(&mut self, id: Uuid) -> CommandResult {
        self.set_active_container_by_id(id)
            .or_else(|_| {
                self.0.focus_on(id)
            })
    }

    /// Destroy the tree
    pub fn destroy_tree(&mut self) -> CommandResult {
        self.0.destroy_tree();
        Ok(())
    }

    pub fn move_focus(&mut self, dir: Direction) -> CommandResult {
        try!(self.0.move_focus(dir));
        Ok(())
    }

    /// Moves the active container to a workspace
    pub fn send_active_to_workspace(&mut self, workspace_name: &str) -> CommandResult {
        self.0.send_active_to_workspace(workspace_name);
        Ok(())
    }

    /// Resizes the container, as if it was dragged at the edge to a certain point
    /// on the screen.
    pub fn resize_container(&mut self, id: Uuid, edge: ResizeEdge, pointer: Point) -> CommandResult {
        match try_lock_action() {
            Ok(mut lock) => {
                if let Some(ref mut action) = *lock {
                    if try!(self.0.lookup(id)).floating() {
                        self.0.resize_floating(id, edge, pointer, action)
                    } else {
                        self.0.resize_tiled(id, edge, pointer, action)
                    }
                } else {
                    Err(TreeError::Action(ActionErr::ActionNotInProgress))
                }
            },
            _ => Err(TreeError::Action(ActionErr::ActionLocked))
        }
    }

    pub fn send_to_workspace(&mut self, id: Uuid, workspace_name: &str) -> CommandResult {
        self.0.send_to_workspace(id, workspace_name);
        Ok(())
    }

    pub fn set_pointer_pos(&mut self, point: Point) -> CommandResult {
        self.0.set_pointer_pos(point)
    }

    pub fn grab_at_corner(&mut self, id: Uuid, edge: ResizeEdge) -> CommandResult {
        self.0.grab_at_corner(id, edge)
            .and(Ok(()))
    }
}
<commit_msg>Backgrounds no longer clobber older backgrounds<commit_after>//! Commands from the user to manipulate the tree

use super::{try_lock_tree, try_lock_action};
use super::{Action, ActionErr, Container, ContainerType, Direction, Handle, Layout, TreeError};
use super::Tree;

use uuid::Uuid;
use rustwlc::{Point, ResizeEdge, WlcView, WlcOutput, ViewType};
use rustc_serialize::json::{Json, ToJson};

pub type CommandResult = Result<(), TreeError>;

/* These commands are exported to take nothing and return nothing,
 * since they are the commands actually registered and usable over
 * the IPC/Lua thread.
 */

pub fn remove_active() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Some(container) = tree.0.get_active_container_mut() {
            match *container {
                Container::View { ref handle, .. } => {
                    handle.close();
                    // Thanks borrowck
                    // Views shouldn't be removed from tree, that's handled by
                    // view_destroyed callback
                    return
                },
                _ => {}
            }
        }
        tree.0.remove_active();
    }
}

pub fn toggle_float() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.toggle_float().ok();
    }
}

pub fn toggle_float_focus() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Err(err) = tree.toggle_floating_focus() {
            warn!("Could not float focus: {:#?}", err);
        }
    }
}

pub fn tile_switch() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Some(id) = tree.active_id() {
            tree.toggle_cardinal_tiling(id).unwrap_or_else(|err| {
                warn!("Could not toggle cardinal tiling: {:#?}", err);
            });
        }
    }
}

pub fn split_vertical() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Vertical).ok();
    }
}

pub fn split_horizontal() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Horizontal).ok();
    }
}

pub fn focus_left() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Left)
            .unwrap_or_else(|_| {
                warn!("Could not focus left");
            });
    }
}

pub fn focus_right() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Right)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            });
    }
}

pub fn focus_up() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Up)
            .unwrap_or_else(|_| {
                warn!("Could not focus up");
            });
    }
}

pub fn focus_down() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Down)
            .unwrap_or_else(|_| {
                warn!("Could not focus down");
            });
    }
}

pub fn move_active_left() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Left)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn move_active_right() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Right)
            .unwrap_or_else(|_| {
                error!("Could not focus right");
            })
    }
}

pub fn move_active_up() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Up)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn move_active_down() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Down)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn tree_as_json() -> Json {
    if let Ok(tree) = try_lock_tree() {
        tree.0.to_json()
    } else {
        Json::Null
    }
}

/// Returns a copy of the action behind the lock.
pub fn performing_action() -> Option<Action> {
    if let Ok(action) = try_lock_action() {
        *action
    } else {
        error!("Could not lock action mutex!");
        None
    }
}

/// Sets the value behind the lock to the provided value.
///
/// Note that this method blocks until the lock is released
///
/// None means an action is done being performed.
pub fn set_performing_action(val: Option<Action>) {
    if let Ok(mut action) = try_lock_action() {
        *action = val;
    } else {
        error!("Action mutex was poisoned");
        panic!("Action mutex was poisoned");
    }
}

/* These commands are the interface that the rest of Way Cooler has to the
 * tree. Any action done, whether through a callback, or from the IPC/Lua thread
 * it will have to go through one of these methods.
 */

impl Tree {
    /// Gets the uuid of the active container, if there is an active container
    pub fn active_id(&self) -> Option<Uuid> {
        self.0.active_container
            .map(|active_ix| self.0.tree[active_ix].get_id())
    }

    pub fn lookup_view(&self, view: WlcView) -> Option<Uuid> {
        self.0.lookup_view(view).map(|c| c.get_id())
    }

    pub fn toggle_float(&mut self) -> CommandResult {
        if let Some(uuid) = self.active_id() {
            let is_floating: Result<bool, _> = self.0.lookup(uuid)
                .and_then(|container| Ok(container.floating()));
            try!(match is_floating {
                Ok(true) => self.ground_container(uuid),
                Ok(false) => self.float_container(uuid),
                Err(err) => return Err(err)
            });
        }
        Ok(())
    }

    pub fn toggle_cardinal_tiling(&mut self, id: Uuid) -> CommandResult {
        self.0.toggle_cardinal_tiling(id)
            .and_then(|_| self.layout_active_of(ContainerType::Workspace))
    }

    pub fn toggle_floating_focus(&mut self) -> CommandResult {
        self.0.toggle_floating_focus()
    }

    pub fn move_active(&mut self, maybe_uuid: Option<Uuid>, direction: Direction) -> CommandResult {
        let uuid = try!(maybe_uuid
                        .or_else(|| self.0.get_active_container()
                                 .and_then(|container| Some(container.get_id())))
                        .ok_or(TreeError::NoActiveContainer));
        try!(self.0.move_container(uuid, direction));
        // NOTE Make this not layout the active, but actually the node index's workspace.
        try!(self.layout_active_of(ContainerType::Output));
        Ok(())
    }

    /// Attempts to drag the window around the screen.
    pub fn try_drag_active(&mut self, point: Point) -> CommandResult {
        if let Some(mut action) = performing_action() {
            let old_point = action.grab;
            let active_ix = try!(self.0.active_container
                                .ok_or(TreeError::NoActiveContainer));
            try!(self.0.drag_floating(active_ix, point, old_point));
            action.grab = point;
            set_performing_action(Some(action));
            Ok(())
        } else {
            Err(TreeError::PerformingAction(false))
        }
    }

    /// Adds an Output to the tree. Never fails
    pub fn add_output(&mut self, output: WlcOutput) -> CommandResult {
        self.0.add_output(output);
        Ok(())
    }

    /// Binds a view to be the background for all outputs.
    ///
    /// If there was a previous background, it is removed and deallocated.
    pub fn add_background(&mut self, view: WlcView) -> CommandResult {
        let outputs = self.0.tree.children_of(self.0.tree.root_ix());
        for output_ix in outputs {
            match self.0.tree[output_ix] {
                Container::Output { ref mut background, .. } => {
                    if background.is_none() {
                        *background = Some(view);
                    }
                },
                _ => unreachable!()
            }
        }
        Ok(())
    }

    /// Adds a Workspace to the tree. Never fails
    pub fn switch_to_workspace(&mut self, name: &str) -> CommandResult {
        self.0.switch_to_workspace(name);
        Ok(())
    }

    /// Tiles the active container of some container type. Never fails
    pub fn layout_active_of(&mut self, c_type: ContainerType) -> CommandResult {
        self.0.layout_active_of(c_type);
        Ok(())
    }

    /// Attempts to set the node behind the id to be floating
    pub fn float_container(&mut self, id: Uuid) -> CommandResult {
        self.0.float_container(id)
    }

    /// Attempts to set the node behind the id to be not floating
    pub fn ground_container(&mut self, id: Uuid) -> CommandResult {
        self.0.ground_container(id)
    }

    /// Adds a view to the workspace of the active container
    pub fn add_view(&mut self, view: WlcView) -> CommandResult {
        let tree = &mut self.0;
        let output = view.get_output();
        if tree.get_active_container().is_none() {
            return Err(TreeError::NoActiveContainer)
        }
        view.set_mask(output.get_mask());
        if view.get_type() != ViewType::empty() {
            try!(tree.add_floating_view(view));
        } else {
            try!(tree.add_view(view));
            tree.normalize_view(view);
        }
        tree.layout_active_of(ContainerType::Workspace);
        Ok(())
    }

    /// Attempts to remove a view from the tree. If it is not in the tree it fails.
    ///
    /// This will close the handle behind the view.
    pub fn remove_view(&mut self, view: WlcView) -> CommandResult {
        let result;
        match self.0.remove_view(&view) {
            Err(err)  => {
                result = Err(err)
            },
            Ok(Container::View { handle, id, .. }) => {
                trace!("Removed container {:?}", id);
                handle.close();
                trace!("Close wlc view {:?}", handle);
                result = Ok(())
            },
            _ => unreachable!()
        }
        let root_ix = self.0.tree.root_ix();
        self.0.layout(root_ix);
        result
    }

    /// Attempts to remove a container based on UUID. Fails if the container
    /// cannot be removed or if the container does not exist.
    ///
    /// This WILL close the view, and should never be called from the
    /// `view_destroyed` callback, as it's possible the view from that callback is invalid.
    pub fn remove_view_by_id(&mut self, id: Uuid) -> CommandResult {
        match try!(self.0.lookup(id)).get_handle() {
            Some(Handle::View(view)) => return self.remove_view(view),
            Some(Handle::Output(_)) | None => {
                Err(TreeError::UuidNotAssociatedWith(ContainerType::View))
            }
        }
    }

    /// Sets the view to be the new active container.
    /// Will fail if the container is floating.
    pub fn set_active_view(&mut self, view: WlcView) -> CommandResult {
        try!(self.0.set_active_view(view.clone()));
        view.focus();
        Ok(())
    }

    #[allow(dead_code)]
    /// Sets the active container to be the container at the UUID
    /// Fails if the container is not a container or view, or if the
    /// container does not exist
    ///
    /// Can also not set floating containers to be active.
    pub fn set_active_container_by_id(&mut self, id: Uuid) -> CommandResult {
        self.0.set_active_container(id)
    }

    /// Focuses on the container. If the container is not floating and is a
    /// Container or a View, then it is also made the active container.
    pub fn focus(&mut self, id: Uuid) -> CommandResult {
        self.set_active_container_by_id(id)
            .or_else(|_| {
                self.0.focus_on(id)
            })
    }

    /// Destroy the tree
    pub fn destroy_tree(&mut self) -> CommandResult {
        self.0.destroy_tree();
        Ok(())
    }

    pub fn move_focus(&mut self, dir: Direction) -> CommandResult {
        try!(self.0.move_focus(dir));
        Ok(())
    }

    /// Moves the active container to a workspace
    pub fn send_active_to_workspace(&mut self, workspace_name: &str) -> CommandResult {
        self.0.send_active_to_workspace(workspace_name);
        Ok(())
    }

    /// Resizes the container, as if it was dragged at the edge to a certain point
    /// on the screen.
    pub fn resize_container(&mut self, id: Uuid, edge: ResizeEdge, pointer: Point) -> CommandResult {
        match try_lock_action() {
            Ok(mut lock) => {
                if let Some(ref mut action) = *lock {
                    if try!(self.0.lookup(id)).floating() {
                        self.0.resize_floating(id, edge, pointer, action)
                    } else {
                        self.0.resize_tiled(id, edge, pointer, action)
                    }
                } else {
                    Err(TreeError::Action(ActionErr::ActionNotInProgress))
                }
            },
            _ => Err(TreeError::Action(ActionErr::ActionLocked))
        }
    }

    pub fn send_to_workspace(&mut self, id: Uuid, workspace_name: &str) -> CommandResult {
        self.0.send_to_workspace(id, workspace_name);
        Ok(())
    }

    pub fn set_pointer_pos(&mut self, point: Point) -> CommandResult {
        self.0.set_pointer_pos(point)
    }

    pub fn grab_at_corner(&mut self, id: Uuid, edge: ResizeEdge) -> CommandResult {
        self.0.grab_at_corner(id, edge)
            .and(Ok(()))
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Base64 binary-to-text encoding

use core::prelude::*;

pub trait ToBase64 {
    fn to_base64(&self) -> ~str;
}

static CHARS: [char, ..64] = [
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
];

impl<'self> ToBase64 for &'self [u8] {
    /**
     * Turn a vector of `u8` bytes into a base64 string.
     *
     * # Example
     *
     * ~~~ {.rust}
     * extern mod std;
     * use std::base64::ToBase64;
     *
     * fn main () {
     *     let str = [52,32].to_base64();
     *     println(fmt!("%s", str));
     * }
     * ~~~
     */
    fn to_base64(&self) -> ~str {
        let mut s = ~"";
        let len = self.len();
        str::reserve(&mut s, ((len + 3u) / 4u) * 3u);

        let mut i = 0u;

        while i < len - (len % 3u) {
            let n = (self[i] as uint) << 16u |
                    (self[i + 1u] as uint) << 8u |
                    (self[i + 2u] as uint);

            // This 24-bit number gets separated into four 6-bit numbers.
            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
            str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
            str::push_char(&mut s, CHARS[n & 63u]);

            i += 3u;
        }

        // Heh, would be cool if we knew this was exhaustive
        // (the dream of bounded integer types)
        match len % 3 {
          0 => (),
          1 => {
            let n = (self[i] as uint) << 16u;
            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
            str::push_char(&mut s, '=');
            str::push_char(&mut s, '=');
          }
          2 => {
            let n = (self[i] as uint) << 16u |
                (self[i + 1u] as uint) << 8u;
            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
            str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
            str::push_char(&mut s, '=');
          }
          _ => fail!("Algebra is broken, please alert the math police")
        }
        s
    }
}

impl<'self> ToBase64 for &'self str {
    /**
     * Convert any string (literal, `@`, `&`, or `~`) to base64 encoding.
     *
     *
     * # Example
     *
     * ~~~ {.rust}
     * extern mod std;
     * use std::base64::ToBase64;
     *
     * fn main () {
     *     let str = "Hello, World".to_base64();
     *     println(fmt!("%s",str));
     * }
     * ~~~
     *
     */
    fn to_base64(&self) -> ~str {
        str::to_bytes(*self).to_base64()
    }
}

pub trait FromBase64 {
    fn from_base64(&self) -> ~[u8];
}

impl FromBase64 for ~[u8] {
    /**
     * Convert base64 `u8` vector into u8 byte values.
     * Every 4 encoded characters is converted into 3 octets, modulo padding.
     *
     * # Example
     *
     * ~~~ {.rust}
     * extern mod std;
     * use std::base64::ToBase64;
     * use std::base64::FromBase64;
     *
     * fn main () {
     *     let str = [52,32].to_base64();
     *     println(fmt!("%s", str));
     *     let bytes = str.from_base64();
     *     println(fmt!("%?",bytes));
     * }
     * ~~~
     */
    fn from_base64(&self) -> ~[u8] {
        if self.len() % 4u != 0u { fail!("invalid base64 length"); }

        let len = self.len();
        let mut padding = 0u;

        if len != 0u {
            if self[len - 1u] == '=' as u8 { padding += 1u; }
            if self[len - 2u] == '=' as u8 { padding += 1u; }
        }

        let mut r = vec::with_capacity((len / 4u) * 3u - padding);

        let mut i = 0u;
        while i < len {
            let mut n = 0u;

            for 4u.times {
                let ch = self[i] as char;
                n <<= 6u;

                match ch {
                    'A'..'Z' => n |= (ch as uint) - 0x41,
                    'a'..'z' => n |= (ch as uint) - 0x47,
                    '0'..'9' => n |= (ch as uint) + 0x04,
                    '+'      => n |= 0x3E,
                    '/'      => n |= 0x3F,
                    '='      => {
                        match len - i {
                            1u => {
                                r.push(((n >> 16u) & 0xFFu) as u8);
                                r.push(((n >> 8u ) & 0xFFu) as u8);
                                return copy r;
                            }
                            2u => {
                                r.push(((n >> 10u) & 0xFFu) as u8);
                                return copy r;
                            }
                            _ => fail!("invalid base64 padding")
                        }
                    }
                    _ => fail!("invalid base64 character")
                }

                i += 1u;
            };

            r.push(((n >> 16u) & 0xFFu) as u8);
            r.push(((n >> 8u ) & 0xFFu) as u8);
            r.push(((n       ) & 0xFFu) as u8);
        }
        r
    }
}

impl FromBase64 for ~str {
    /**
     * Convert any base64 encoded string (literal, `@`, `&`, or `~`)
     * to the byte values it encodes.
     *
     * You can use the `from_bytes` function in `core::str`
     * to turn a `[u8]` into a string with characters corresponding to those values.
     *
     * # Example
     *
     * This converts a string literal to base64 and back.
     *
     * ~~~ {.rust}
     * extern mod std;
     * use std::base64::ToBase64;
     * use std::base64::FromBase64;
     * use core::str;
     *
     * fn main () {
     *     let hello_str = "Hello, World".to_base64();
     *     println(fmt!("%s",hello_str));
     *     let bytes = hello_str.from_base64();
     *     println(fmt!("%?",bytes));
     *     let result_str = str::from_bytes(bytes);
     *     println(fmt!("%s",result_str));
     * }
     * ~~~
     */
    fn from_base64(&self) -> ~[u8] {
        str::to_bytes(*self).from_base64()
    }
}

#[cfg(test)]
mod tests {
    use core::str;

    #[test]
    fn test_to_base64() {
        assert_eq!((~"").to_base64(), ~"");
        assert!((~"f").to_base64()      == ~"Zg==");
        assert_eq!((~"fo").to_base64(), ~"Zm8=");
        assert_eq!((~"foo").to_base64(), ~"Zm9v");
        assert!((~"foob").to_base64()   == ~"Zm9vYg==");
        assert_eq!((~"fooba").to_base64(), ~"Zm9vYmE=");
        assert_eq!((~"foobar").to_base64(), ~"Zm9vYmFy");
    }

    #[test]
    fn test_from_base64() {
        assert_eq!((~"").from_base64(), str::to_bytes(""));
        assert!((~"Zg==").from_base64() == str::to_bytes("f"));
        assert_eq!((~"Zm8=").from_base64(), str::to_bytes("fo"));
        assert_eq!((~"Zm9v").from_base64(), str::to_bytes("foo"));
        assert!((~"Zm9vYg==").from_base64() == str::to_bytes("foob"));
        assert_eq!((~"Zm9vYmE=").from_base64(), str::to_bytes("fooba"))
        assert_eq!((~"Zm9vYmFy").from_base64(), str::to_bytes("foobar"));
    }
}
<commit_msg>Generalized implementation of FromBase64<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Base64 binary-to-text encoding

use core::prelude::*;

pub trait ToBase64 {
    fn to_base64(&self) -> ~str;
}

static CHARS: [char, ..64] = [
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
];

impl<'self> ToBase64 for &'self [u8] {
    /**
     * Turn a vector of `u8` bytes into a base64 string.
     *
     * # Example
     *
     * ~~~ {.rust}
     * extern mod std;
     * use std::base64::ToBase64;
     *
     * fn main () {
     *     let str = [52,32].to_base64();
     *     println(fmt!("%s", str));
     * }
     * ~~~
     */
    fn to_base64(&self) -> ~str {
        let mut s = ~"";
        let len = self.len();
        str::reserve(&mut s, ((len + 3u) / 4u) * 3u);

        let mut i = 0u;

        while i < len - (len % 3u) {
            let n = (self[i] as uint) << 16u |
                    (self[i + 1u] as uint) << 8u |
                    (self[i + 2u] as uint);

            // This 24-bit number gets separated into four 6-bit numbers.
            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
            str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
            str::push_char(&mut s, CHARS[n & 63u]);

            i += 3u;
        }

        // Heh, would be cool if we knew this was exhaustive
        // (the dream of bounded integer types)
        match len % 3 {
          0 => (),
          1 => {
            let n = (self[i] as uint) << 16u;
            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
            str::push_char(&mut s, '=');
            str::push_char(&mut s, '=');
          }
          2 => {
            let n = (self[i] as uint) << 16u |
                (self[i + 1u] as uint) << 8u;
            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
            str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
            str::push_char(&mut s, '=');
          }
          _ => fail!("Algebra is broken, please alert the math police")
        }
        s
    }
}

impl<'self> ToBase64 for &'self str {
    /**
     * Convert any string (literal, `@`, `&`, or `~`) to base64 encoding.
     *
     *
     * # Example
     *
     * ~~~ {.rust}
     * extern mod std;
     * use std::base64::ToBase64;
     *
     * fn main () {
     *     let str = "Hello, World".to_base64();
     *     println(fmt!("%s",str));
     * }
     * ~~~
     *
     */
    fn to_base64(&self) -> ~str {
        str::to_bytes(*self).to_base64()
    }
}

pub trait FromBase64 {
    fn from_base64(&self) -> ~[u8];
}

impl<'self> FromBase64 for &'self [u8] {
    /**
     * Convert base64 `u8` vector into u8 byte values.
     * Every 4 encoded characters is converted into 3 octets, modulo padding.
     *
     * # Example
     *
     * ~~~ {.rust}
     * extern mod std;
     * use std::base64::ToBase64;
     * use std::base64::FromBase64;
     *
     * fn main () {
     *     let str = [52,32].to_base64();
     *     println(fmt!("%s", str));
     *     let bytes = str.from_base64();
     *     println(fmt!("%?",bytes));
     * }
     * ~~~
     */
    fn from_base64(&self) -> ~[u8] {
        if self.len() % 4u != 0u { fail!("invalid base64 length"); }

        let len = self.len();
        let mut padding = 0u;

        if len != 0u {
            if self[len - 1u] == '=' as u8 { padding += 1u; }
            if self[len - 2u] == '=' as u8 { padding += 1u; }
        }

        let mut r = vec::with_capacity((len / 4u) * 3u - padding);

        let mut i = 0u;
        while i < len {
            let mut n = 0u;

            for 4u.times {
                let ch = self[i] as char;
                n <<= 6u;

                match ch {
                    'A'..'Z' => n |= (ch as uint) - 0x41,
                    'a'..'z' => n |= (ch as uint) - 0x47,
                    '0'..'9' => n |= (ch as uint) + 0x04,
                    '+'      => n |= 0x3E,
                    '/'      => n |= 0x3F,
                    '='      => {
                        match len - i {
                            1u => {
                                r.push(((n >> 16u) & 0xFFu) as u8);
                                r.push(((n >> 8u ) & 0xFFu) as u8);
                                return copy r;
                            }
                            2u => {
                                r.push(((n >> 10u) & 0xFFu) as u8);
                                return copy r;
                            }
                            _ => fail!("invalid base64 padding")
                        }
                    }
                    _ => fail!("invalid base64 character")
                }

                i += 1u;
            };

            r.push(((n >> 16u) & 0xFFu) as u8);
            r.push(((n >> 8u ) & 0xFFu) as u8);
            r.push(((n       ) & 0xFFu) as u8);
        }
        r
    }
}

impl<'self> FromBase64 for &'self str {
    /**
     * Convert any base64 encoded string (literal, `@`, `&`, or `~`)
     * to the byte values it encodes.
     *
     * You can use the `from_bytes` function in `core::str`
     * to turn a `[u8]` into a string with characters corresponding to those values.
     *
     * # Example
     *
     * This converts a string literal to base64 and back.
     *
     * ~~~ {.rust}
     * extern mod std;
     * use std::base64::ToBase64;
     * use std::base64::FromBase64;
     * use core::str;
     *
     * fn main () {
     *     let hello_str = "Hello, World".to_base64();
     *     println(fmt!("%s",hello_str));
     *     let bytes = hello_str.from_base64();
     *     println(fmt!("%?",bytes));
     *     let result_str = str::from_bytes(bytes);
     *     println(fmt!("%s",result_str));
     * }
     * ~~~
     */
    fn from_base64(&self) -> ~[u8] {
        str::to_bytes(*self).from_base64()
    }
}

#[cfg(test)]
mod tests {
    use core::str;

    #[test]
    fn test_to_base64() {
        assert_eq!("".to_base64(), ~"");
        assert_eq!("f".to_base64(), ~"Zg==");
        assert_eq!("fo".to_base64(), ~"Zm8=");
        assert_eq!("foo".to_base64(), ~"Zm9v");
        assert_eq!("foob".to_base64(), ~"Zm9vYg==");
        assert_eq!("fooba".to_base64(), ~"Zm9vYmE=");
        assert_eq!("foobar".to_base64(), ~"Zm9vYmFy");
    }

    #[test]
    fn test_from_base64() {
        assert_eq!("".from_base64(), str::to_bytes(""));
        assert_eq!("Zg==".from_base64(), str::to_bytes("f"));
        assert_eq!("Zm8=".from_base64(), str::to_bytes("fo"));
        assert_eq!("Zm9v".from_base64(), str::to_bytes("foo"));
        assert_eq!("Zm9vYg==".from_base64(), str::to_bytes("foob"));
        assert_eq!("Zm9vYmE=".from_base64(), str::to_bytes("fooba"))
        assert_eq!("Zm9vYmFy".from_base64(), str::to_bytes("foobar"));
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

use toml::Value;

use libimagstore::storeid::StoreId;
use libimagstore::hook::Hook;
use libimagstore::hook::result::HookResult;
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::accessor::StoreIdAccessor;

use vcs::git::runtime::Runtime as GRuntime;

pub struct UpdateHook {
    storepath: PathBuf,

    runtime: GRuntime,

    position: HookPosition,
}

impl UpdateHook {

    pub fn new(storepath: PathBuf, p: HookPosition) -> UpdateHook {
        UpdateHook {
            runtime: GRuntime::new(&storepath),
            storepath: storepath,
            position: p,
        }
    }

}

impl Debug for UpdateHook {
    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "UpdateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?}",
               self.storepath,
               (if self.runtime.has_repository() { "Some(_)" } else { "None" }),
               self.position,
               self.runtime.has_config())
    }
}

impl Hook for UpdateHook {

    fn name(&self) -> &'static str {
        "stdhook_git_update"
    }

    fn set_config(&mut self, config: &Value) {
        if let Err(e) = self.runtime.set_config(config) {
            trace_error(&e);
        }
    }

}

impl HookDataAccessorProvider for UpdateHook {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl StoreIdAccessor for UpdateHook {

    fn access(&self, id: &StoreId) -> HookResult<()> {
        debug!("[GIT UPDATE HOOK]: {:?}", id);
        Ok(())
    }

}

<commit_msg>Add initial implementation for UpdateHook<commit_after>use std::path::PathBuf;
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use toml::Value;

use libimagerror::into::IntoError;
use libimagerror::trace::trace_error;
use libimagstore::hook::Hook;
use libimagstore::hook::accessor::StoreIdAccessor;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::result::HookResult;
use libimagstore::storeid::StoreId;
use libimagutil::debug_result::*;

use vcs::git::error::GitHookError as GHE;
use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::error::MapIntoHookError;
use vcs::git::result::Result;
use vcs::git::runtime::Runtime as GRuntime;

pub struct UpdateHook {
    storepath: PathBuf,

    runtime: GRuntime,

    position: HookPosition,
}

impl UpdateHook {

    pub fn new(storepath: PathBuf, p: HookPosition) -> UpdateHook {
        UpdateHook {
            runtime: GRuntime::new(&storepath),
            storepath: storepath,
            position: p,
        }
    }

}

impl Debug for UpdateHook {
    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "UpdateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?}",
               self.storepath,
               (if self.runtime.has_repository() { "Some(_)" } else { "None" }),
               self.position,
               self.runtime.has_config())
    }
}

impl Hook for UpdateHook {

    fn name(&self) -> &'static str {
        "stdhook_git_update"
    }

    fn set_config(&mut self, config: &Value) {
        if let Err(e) = self.runtime.set_config(config) {
            trace_error(&e);
        }
    }

}

impl HookDataAccessorProvider for UpdateHook {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl StoreIdAccessor for UpdateHook {

    /// The implementation of the UpdateHook
    ///
    /// # Scope
    ///
    /// This hook takes the git index and commits it either interactively or with a default message,
    /// if there is no configuration for an interactive commit.
    ///
    fn access(&self, id: &StoreId) -> HookResult<()> {
        use vcs::git::action::StoreAction;
        use vcs::git::config::commit_message;
        use vcs::git::error::MapIntoHookError;

        debug!("[GIT UPDATE HOOK]: {:?}", id);

        let cfg = try!(
            self.runtime
                .config_value_or_err()
                .map_dbg_err_str("[GIT UPDATE HOOK]: Couldn't get Value object from config")
        );

        debug!("[GIT UPDATE HOOK]: Getting repository");
        let repo = try!(
            self.runtime
                .repository()
                .map_dbg_err_str("[GIT UPDATE HOOK]: Couldn't fetch Repository")
                .map_err_into(GHEK::RepositoryError)
                .map_into_hook_error()
        );
        debug!("[GIT UPDATE HOOK]: Repository object fetched");

        let mut index = try!(
            repo
                .index()
                .map_err_into(GHEK::RepositoryIndexFetchingError)
                .map_into_hook_error()
        );

        let tree_id = try!(
            index.write_tree()
                .map_err_into(GHEK::RepositoryIndexWritingError)
                .map_into_hook_error()
        );

        let signature = try!(
            repo.signature()
                .map_err_into(GHEK::MkSignature)
                .map_into_hook_error()
        );

        let head = try!(
            repo.head()
                .map_err_into(GHEK::HeadFetchError)
                .map_into_hook_error()
        );

        let mut parents = Vec::new();
        {
            let commit = try!(
                repo.find_commit(head.target().unwrap())
                    .map_err_into(GHEK::RepositoryParentFetchingError)
                    .map_into_hook_error()
            );
            parents.push(commit);
        }

        // for converting from Vec<Commit> to Vec<&Commit>
        let parents = parents.iter().collect::<Vec<_>>();

        let tree = try!(
            repo.find_tree(tree_id)
                .map_err_into(GHEK::RepositoryParentFetchingError)
                .map_into_hook_error()
        );

        let message = try!(commit_message(cfg, StoreAction::Update));

        repo.commit(Some("HEAD"), &signature, &signature, &message, &tree, &parents)
            .map_err_into(GHEK::RepositoryCommittingError)
            .map_into_hook_error()
            .map(|_| ())

    }

}

<|endoftext|>


<commit_before>//! Main module to handle the layout.
//! This is where the i3-specific code is.

use std::sync::{Mutex, MutexGuard, TryLockError};
use std::ptr;

use super::container::{Container, Handle, ContainerType};
use super::node::{Node};
use super::super::rustwlc::{WlcView, WlcOutput, Geometry, Point, ResizeEdge};

pub type TreeErr = TryLockError<MutexGuard<'static, Tree>>;
pub type TreeResult = Result<MutexGuard<'static, Tree>, TreeErr>;

const ERR_BAD_TREE: &'static str = "Layout tree was in an invalid configuration";

lazy_static! {
    static ref TREE: Mutex<Tree> = {
        Mutex::new(Tree{
            root: Node::new(Container::new_root()),
            active_container: ptr::null(),
        })
    };
}

pub struct Tree {
    root: Node,
    active_container: *const Node,
}

unsafe impl Send for Tree {}

impl Tree {
    /// Switch to the workspace with the give name
    pub fn switch_workspace(&mut self, name: &str ) {
        trace!("Switching to workspace {}", name);
        if let Some(old_workspace) = self.get_active_workspace() {
            old_workspace.set_visibility(false);
        }
        let current_workspace: *const Node;
        {
            if let Some(_) = self.get_workspace_by_name(name) {
                trace!("Found workspace {}", name);
            } else {
                trace!("Adding workspace {}", name);
                self.add_workspace(name.to_string());
            }
            let new_current_workspace = self.get_workspace_by_name_mut(name).expect(ERR_BAD_TREE);
            new_current_workspace.set_visibility(true);
            // Set the first view to be focused, so the screen refreshes itself
            if new_current_workspace.get_children()[0].get_children().len() > 0 {
                trace!("Focusing view");
                match new_current_workspace.get_children_mut()[0].get_children_mut()[0]
                    .get_val().get_handle().expect(ERR_BAD_TREE) {
                    Handle::View(view) => view.focus(),
                    _ => {},
                }
            } else {
                WlcView::root().focus();
            }
            // Update the tree's pointer to the currently focused container
            current_workspace = &new_current_workspace.get_children()[0] as *const Node;
        }
        self.active_container = current_workspace;
    }

    /// Returns the currently viewed container.
    /// If multiple views are selected, the parent container they share is returned
    pub fn get_active_container(&self) -> Option<&Node> {
        if self.active_container.is_null() {
            None
        } else {
            unsafe {
                Some(&*self.active_container)
            }
        }
    }

    /// Get the monitor (output) that the active container is located on
    pub fn get_active_output(&self) -> Option<&mut Node> {
        if let Some(node) = self.get_active_container() {
            node.get_ancestor_of_type(ContainerType::Output)
        } else {
            None
        }
    }

    /// Get the workspace that the active container is located on
    pub fn get_active_workspace(&self) -> Option<&mut Node> {
        if let Some(container) = self.get_active_container() {
            if let Some(workspace) = container.get_ancestor_of_type(ContainerType::Workspace) {
                return Some(workspace)
            }
        }
        return None
    }

    /// Find the workspace node that has the given name
    pub fn get_workspace_by_name(&self, name: &str) -> Option<&Node> {
        for child in self.root.get_children()[0].get_children() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    /// Find the workspace node that has the given name, with a mutable reference
    pub fn get_workspace_by_name_mut(&mut self, name: &str) -> Option<&mut Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    /// Make a new output container with the given WlcOutput.
    /// This is done when a new monitor is added
    pub fn add_output(&mut self, wlc_output: WlcOutput) {
        match self.root.new_child(Container::new_output(wlc_output)) {
            Ok(_) => {},
            Err(e) => error!("Could not add output: {:?}", e),
        }
    }

    /// Make a new workspace container with the given name.
    pub fn add_workspace(&mut self, name: String) {
        if let Some(output) = self.get_active_output() {
            let size = output.get_val().get_geometry()
                .expect("Output did not have a geometry").size;
            let workspace = Container::new_workspace(name.to_string(),
                                                     size.clone());
            match output.new_child(workspace) {
                Ok(workspace) => {
                    trace!("Added workspace {:?}", workspace);
                    let geometry = Geometry {
                        size: size,
                        origin: Point { x: 0, y: 0}
                    };
                    if let Err(e) = workspace.new_child(Container::new_container(geometry)) {
                        error!("Could not add container to workspace: {:?}",e );
                    }
                },
                Err(e) => error!("Could not add workspace: {:?}", e),
            }
        }
    }

    /// Make a new view container with the given WlcView, and adds it to
    /// the active workspace.
    pub fn add_view(&mut self, wlc_view: WlcView) {
        let mut maybe_new_view: *const Node = ptr::null();
        if let Some(current_workspace) = self.get_active_workspace() {
            trace!("Adding view {:?} to {:?}", wlc_view, current_workspace);
            if current_workspace.get_children().len() == 0 {
                let output = self.get_active_output()
                    .expect("Could not get active output");
                let output_size = output.get_val().get_geometry()
                    .expect("Could not get geometry from output").size;
                let mut geometry = wlc_view.get_geometry()
                    .expect("Could not get geometry from wlc view").clone();
                // Ensure that it starts within the bounds
                // Width
                if geometry.origin.x > output_size.w as i32 {
                    geometry.origin.x = output_size.w as i32 ;
                } else if geometry.origin.x < 0 {
                    geometry.origin.x = 0;
                }
                // Height
                if geometry.origin.y > output_size.h as i32 {
                    geometry.origin.y = output_size.h as i32;
                } else if geometry.origin.y < 0 {
                    geometry.origin.y = 0;
                }
                wlc_view.set_geometry(ResizeEdge::empty(), &geometry);
                match current_workspace.new_child(Container::new_container(geometry)) {
                    Ok(_) => {},
                    Err(e) => {
                        error!("Could not add workspace: {:?}", e);
                        return;
                    }
                }
            }
            let container = &mut current_workspace.get_children_mut()[0];
            match container.new_child(Container::new_view(wlc_view)) {
                Ok(view_node) => maybe_new_view = view_node as *const Node,
                Err(e) => {
                    error!("Could not add view to current workspace: {:?}", e);
                    return;
                }
            }
        };
        if ! maybe_new_view.is_null() {
            self.active_container = maybe_new_view as *const Node;
        }
    }

    /// Remove the view container with the given view
    pub fn remove_view(&self, wlc_view: &WlcView) {
        if let Some(view) = self.root.find_view_by_handle(&wlc_view) {
            let parent = view.get_parent().expect(ERR_BAD_TREE);
            parent.remove_child(view);
        }
    }
}

pub fn try_lock_tree() -> TreeResult {
    trace!("Locking the tree!");
    TREE.try_lock()
}
<commit_msg>Added move_container_to_workspace, active_container went from *const to *mut Node<commit_after>//! Main module to handle the layout.
//! This is where the i3-specific code is.

use std::sync::{Mutex, MutexGuard, TryLockError};
use std::ptr;

use super::container::{Container, Handle, ContainerType};
use super::node::{Node};
use super::super::rustwlc::{WlcView, WlcOutput, Geometry, Point, ResizeEdge};

pub type TreeErr = TryLockError<MutexGuard<'static, Tree>>;
pub type TreeResult = Result<MutexGuard<'static, Tree>, TreeErr>;

const ERR_BAD_TREE: &'static str = "Layout tree was in an invalid configuration";

lazy_static! {
    static ref TREE: Mutex<Tree> = {
        Mutex::new(Tree{
            root: Node::new(Container::new_root()),
            active_container: ptr::null_mut(),
        })
    };
}

pub struct Tree {
    root: Node,
    active_container: *mut Node,
}

unsafe impl Send for Tree {}

impl Tree {

    /// Moves the current active container to a new workspace
    pub fn move_container_to_workspace(&mut self, name: &str) {
        let container: Option<Node> = None;
        if let Some(sub_container) = self.get_active_container() {
            // NOTE Assumes workspace exists, fix this
            // NOTE Should not do this, because floating windows
            // Should do an if let
            let container = Some(sub_container.remove_from_parent()
                .expect("Could not remove container, was not part of tree"));
        }
        if let Some(container) = container {
            if let Some(workspace) = self.get_workspace_by_name(name) {
                // Assume workspace has a container
                let output = &mut workspace.get_children_mut()[0];
                output.new_child(container.get_val().clone());
            }
        }
    }

    /// Switch to the workspace with the give name
    pub fn switch_workspace(&mut self, name: &str ) {
        trace!("Switching to workspace {}", name);
        if let Some(old_workspace) = self.get_active_workspace() {
            old_workspace.set_visibility(false);
        }
        let current_workspace: *mut Node;
        {
            if let Some(_) = self.get_workspace_by_name(name) {
                trace!("Found workspace {}", name);
            } else {
                trace!("Adding workspace {}", name);
                self.add_workspace(name.to_string());
            }
            let new_current_workspace = self.get_workspace_by_name_mut(name).expect(ERR_BAD_TREE);
            new_current_workspace.set_visibility(true);
            // Set the first view to be focused, so the screen refreshes itself
            if new_current_workspace.get_children()[0].get_children().len() > 0 {
                trace!("Focusing view");
                match new_current_workspace.get_children_mut()[0].get_children_mut()[0]
                    .get_val().get_handle().expect(ERR_BAD_TREE) {
                    Handle::View(view) => view.focus(),
                    _ => {},
                }
            } else {
                WlcView::root().focus();
            }
            // Update the tree's pointer to the currently focused container
            current_workspace = &mut new_current_workspace.get_children_mut()[0] as *mut Node;
        }
        self.active_container = current_workspace;
    }

    /// Returns the currently viewed container.
    /// If multiple views are selected, the parent container they share is returned
    pub fn get_active_container(&self) -> Option<&mut Node> {
        if self.active_container.is_null() {
            None
        } else {
            unsafe {
                Some(&mut *self.active_container)
            }
        }
    }

    /// Get the monitor (output) that the active container is located on
    pub fn get_active_output(&self) -> Option<&mut Node> {
        if let Some(node) = self.get_active_container() {
            node.get_ancestor_of_type(ContainerType::Output)
        } else {
            None
        }
    }

    /// Get the workspace that the active container is located on
    pub fn get_active_workspace(&self) -> Option<&mut Node> {
        if let Some(container) = self.get_active_container() {
            if let Some(workspace) = container.get_ancestor_of_type(ContainerType::Workspace) {
                return Some(workspace)
            }
        }
        return None
    }

    /// Find the workspace node that has the given name
    pub fn get_workspace_by_name(&mut self, name: &str) -> Option<&mut Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    /// Find the workspace node that has the given name, with a mutable reference
    pub fn get_workspace_by_name_mut(&mut self, name: &str) -> Option<&mut Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    /// Make a new output container with the given WlcOutput.
    /// This is done when a new monitor is added
    pub fn add_output(&mut self, wlc_output: WlcOutput) {
        match self.root.new_child(Container::new_output(wlc_output)) {
            Ok(_) => {},
            Err(e) => error!("Could not add output: {:?}", e),
        }
    }

    /// Make a new workspace container with the given name.
    pub fn add_workspace(&mut self, name: String) {
        if let Some(output) = self.get_active_output() {
            let size = output.get_val().get_geometry()
                .expect("Output did not have a geometry").size;
            let workspace = Container::new_workspace(name.to_string(),
                                                     size.clone());
            match output.new_child(workspace) {
                Ok(workspace) => {
                    trace!("Added workspace {:?}", workspace);
                    let geometry = Geometry {
                        size: size,
                        origin: Point { x: 0, y: 0}
                    };
                    if let Err(e) = workspace.new_child(Container::new_container(geometry)) {
                        error!("Could not add container to workspace: {:?}",e );
                    }
                },
                Err(e) => error!("Could not add workspace: {:?}", e),
            }
        }
    }

    /// Make a new view container with the given WlcView, and adds it to
    /// the active workspace.
    pub fn add_view(&mut self, wlc_view: WlcView) {
        let mut maybe_new_view: *const Node = ptr::null();
        if let Some(current_workspace) = self.get_active_workspace() {
            trace!("Adding view {:?} to {:?}", wlc_view, current_workspace);
            if current_workspace.get_children().len() == 0 {
                let output = self.get_active_output()
                    .expect("Could not get active output");
                let output_size = output.get_val().get_geometry()
                    .expect("Could not get geometry from output").size;
                let mut geometry = wlc_view.get_geometry()
                    .expect("Could not get geometry from wlc view").clone();
                // Ensure that it starts within the bounds
                // Width
                if geometry.origin.x > output_size.w as i32 {
                    geometry.origin.x = output_size.w as i32 ;
                } else if geometry.origin.x < 0 {
                    geometry.origin.x = 0;
                }
                // Height
                if geometry.origin.y > output_size.h as i32 {
                    geometry.origin.y = output_size.h as i32;
                } else if geometry.origin.y < 0 {
                    geometry.origin.y = 0;
                }
                wlc_view.set_geometry(ResizeEdge::empty(), &geometry);
                match current_workspace.new_child(Container::new_container(geometry)) {
                    Ok(_) => {},
                    Err(e) => {
                        error!("Could not add workspace: {:?}", e);
                        return;
                    }
                }
            }
            let container = &mut current_workspace.get_children_mut()[0];
            match container.new_child(Container::new_view(wlc_view)) {
                Ok(view_node) => maybe_new_view = view_node as *const Node,
                Err(e) => {
                    error!("Could not add view to current workspace: {:?}", e);
                    return;
                }
            }
        };
        if ! maybe_new_view.is_null() {
            self.active_container = maybe_new_view as *mut Node;
        }
    }

    /// Remove the view container with the given view
    pub fn remove_view(&self, wlc_view: &WlcView) {
        if let Some(view) = self.root.find_view_by_handle(&wlc_view) {
            let parent = view.get_parent().expect(ERR_BAD_TREE);
            parent.remove_child(view);
        }
    }
}

pub fn try_lock_tree() -> TreeResult {
    trace!("Locking the tree!");
    TREE.try_lock()
}
<|endoftext|>