<commit_before>use crc16;

pub const HASH_SLOTS: u16 = 16384;

/// RedisCluster style partitioning
pub fn hash_slot(key: &[u8]) -> u16 {
    crc16::State::<crc16::XMODEM>::calculate(key) % HASH_SLOTS
}
<commit_msg>make hash_slots detect hash{tags}<commit_after>use crc16;

pub const HASH_SLOTS: u16 = 16384;

/// RedisCluster style partitioning
pub fn hash_slot(mut key: &[u8]) -> u16 {
    if let Some(open) = key.iter().position(|&x| x == b'{') {
        // note that close will be relative to open due to the skip()
        if let Some(close) = key.iter().skip(open + 1).position(|&x| x == b'}') {
            if close > 0 {
                // found  { and } with something in between
                key = &key[open + 1..open + 1 + close];
            }
        }
    }
    crc16::State::<crc16::XMODEM>::calculate(key) % HASH_SLOTS
}

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

    fn raw_hash(key: &[u8]) -> u16 {
        crc16::State::<crc16::XMODEM>::calculate(key) % HASH_SLOTS
    }

    #[test]
    fn test_hash_slot() {
        assert_eq!(hash_slot(b"{}"), raw_hash(b"{}"));
        assert_eq!(hash_slot(b"_{abc}"), raw_hash(b"abc"));
        assert_eq!(hash_slot(b"{abc}_"), raw_hash(b"abc"));
        assert_eq!(hash_slot(b"_{abc}_"), raw_hash(b"abc"));
        assert_eq!(hash_slot(b"{abc}{def}"), raw_hash(b"abc"));
        assert_eq!(hash_slot(b"{}{abc}"), raw_hash(b"{}{abc}"));
        assert_eq!(hash_slot(b"{abc}{}"), raw_hash(b"abc"));
        assert_eq!(hash_slot(b"{{abc}}"), raw_hash(b"{abc"));
    }
}
<|endoftext|>


<commit_before>//! `GenericArray` iterator implementation.

use super::{ArrayLength, GenericArray};
use core::iter::FusedIterator;
use core::mem::ManuallyDrop;
use core::{cmp, fmt, ptr, mem};

/// An iterator that moves out of a `GenericArray`
pub struct GenericArrayIter<T, N: ArrayLength<T>> {
    // Invariants: index <= index_back <= N
    // Only values in array[index..index_back] are alive at any given time.
    // Values from array[..index] and array[index_back..] are already moved/dropped.
    array: ManuallyDrop<GenericArray<T, N>>,
    index: usize,
    index_back: usize,
}

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

    fn send<I: Send>(_iter: I) {}

    #[test]
    fn test_send_iter() {
        send(GenericArray::from([1, 2, 3, 4]).into_iter());
    }
}

impl<T, N> GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    /// Returns the remaining items of this iterator as a slice
    #[inline]
    pub fn as_slice(&self) -> &[T] {
        &self.array.as_slice()[self.index..self.index_back]
    }

    /// Returns the remaining items of this iterator as a mutable slice
    #[inline]
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        &mut self.array.as_mut_slice()[self.index..self.index_back]
    }
}

impl<T, N> IntoIterator for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    type Item = T;
    type IntoIter = GenericArrayIter<T, N>;

    fn into_iter(self) -> Self::IntoIter {
        GenericArrayIter {
            array: ManuallyDrop::new(self),
            index: 0,
            index_back: N::USIZE,
        }
    }
}

// Based on work in rust-lang/rust#49000
impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("GenericArrayIter")
            .field(&self.as_slice())
            .finish()
    }
}

impl<T, N> Drop for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    #[inline]
    fn drop(&mut self) {
        if mem::needs_drop::<T>() {
            // Drop values that are still alive.
            for p in self.as_mut_slice() {
                unsafe {
                    ptr::drop_in_place(p);
                }
            }
        }
    }
}

// Based on work in rust-lang/rust#49000
impl<T: Clone, N> Clone for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    fn clone(&self) -> Self {
        // This places all cloned elements at the start of the new array iterator,
        // not at their original indices.

            let mut array = unsafe {ptr::read(&self.array)};
            let mut index_back = 0;

            for (dst, src) in array.as_mut_slice().into_iter().zip(self.as_slice()) {
                unsafe {ptr::write(dst, src.clone())};
                index_back += 1;
            }

            GenericArrayIter {
                array,
                index: 0,
                index_back
            }

    }
}

impl<T, N> Iterator for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        if self.index < self.index_back {
            let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) };

            self.index += 1;

            p
        } else {
            None
        }
    }

    fn fold<B, F>(mut self, init: B, mut f: F) -> B
    where
        F: FnMut(B, Self::Item) -> B,
    {
        let ret = unsafe {
            let GenericArrayIter {
                ref array,
                ref mut index,
                index_back,
            } = self;

            let remaining = &array[*index..index_back];

            remaining.iter().fold(init, |acc, src| {
                let value = ptr::read(src);

                *index += 1;

                f(acc, value)
            })
        };

        // ensure the drop happens here after iteration
        drop(self);

        ret
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len();
        (len, Some(len))
    }

    #[inline]
    fn count(self) -> usize {
        self.len()
    }

    fn nth(&mut self, n: usize) -> Option<T> {
        // First consume values prior to the nth.
        let ndrop = cmp::min(n, self.len());

        for p in &mut self.array[self.index..self.index + ndrop] {
            self.index += 1;

            unsafe {
                ptr::drop_in_place(p);
            }
        }

        self.next()
    }

    #[inline]
    fn last(mut self) -> Option<T> {
        // Note, everything else will correctly drop first as `self` leaves scope.
        self.next_back()
    }
}

impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    fn next_back(&mut self) -> Option<T> {
        if self.index < self.index_back {
            self.index_back -= 1;

            unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) }
        } else {
            None
        }
    }

    fn rfold<B, F>(mut self, init: B, mut f: F) -> B
    where
        F: FnMut(B, Self::Item) -> B,
    {
        let ret = unsafe {
            let GenericArrayIter {
                ref array,
                index,
                ref mut index_back,
            } = self;

            let remaining = &array[index..*index_back];

            remaining.iter().rfold(init, |acc, src| {
                let value = ptr::read(src);

                *index_back -= 1;

                f(acc, value)
            })
        };

        // ensure the drop happens here after iteration
        drop(self);

        ret
    }
}

impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    fn len(&self) -> usize {
        self.index_back - self.index
    }
}

impl<T, N> FusedIterator for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
}

// TODO: Implement `TrustedLen` when stabilized
<commit_msg>Formatting<commit_after>//! `GenericArray` iterator implementation.

use super::{ArrayLength, GenericArray};
use core::iter::FusedIterator;
use core::mem::ManuallyDrop;
use core::{cmp, fmt, mem, ptr};

/// An iterator that moves out of a `GenericArray`
pub struct GenericArrayIter<T, N: ArrayLength<T>> {
    // Invariants: index <= index_back <= N
    // Only values in array[index..index_back] are alive at any given time.
    // Values from array[..index] and array[index_back..] are already moved/dropped.
    array: ManuallyDrop<GenericArray<T, N>>,
    index: usize,
    index_back: usize,
}

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

    fn send<I: Send>(_iter: I) {}

    #[test]
    fn test_send_iter() {
        send(GenericArray::from([1, 2, 3, 4]).into_iter());
    }
}

impl<T, N> GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    /// Returns the remaining items of this iterator as a slice
    #[inline]
    pub fn as_slice(&self) -> &[T] {
        &self.array.as_slice()[self.index..self.index_back]
    }

    /// Returns the remaining items of this iterator as a mutable slice
    #[inline]
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        &mut self.array.as_mut_slice()[self.index..self.index_back]
    }
}

impl<T, N> IntoIterator for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    type Item = T;
    type IntoIter = GenericArrayIter<T, N>;

    fn into_iter(self) -> Self::IntoIter {
        GenericArrayIter {
            array: ManuallyDrop::new(self),
            index: 0,
            index_back: N::USIZE,
        }
    }
}

// Based on work in rust-lang/rust#49000
impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("GenericArrayIter")
            .field(&self.as_slice())
            .finish()
    }
}

impl<T, N> Drop for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    #[inline]
    fn drop(&mut self) {
        if mem::needs_drop::<T>() {
            // Drop values that are still alive.
            for p in self.as_mut_slice() {
                unsafe {
                    ptr::drop_in_place(p);
                }
            }
        }
    }
}

// Based on work in rust-lang/rust#49000
impl<T: Clone, N> Clone for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    fn clone(&self) -> Self {
        // This places all cloned elements at the start of the new array iterator,
        // not at their original indices.

        let mut array = unsafe { ptr::read(&self.array) };
        let mut index_back = 0;

        for (dst, src) in array.as_mut_slice().into_iter().zip(self.as_slice()) {
            unsafe { ptr::write(dst, src.clone()) };
            index_back += 1;
        }

        GenericArrayIter {
            array,
            index: 0,
            index_back,
        }
    }
}

impl<T, N> Iterator for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        if self.index < self.index_back {
            let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) };

            self.index += 1;

            p
        } else {
            None
        }
    }

    fn fold<B, F>(mut self, init: B, mut f: F) -> B
    where
        F: FnMut(B, Self::Item) -> B,
    {
        let ret = unsafe {
            let GenericArrayIter {
                ref array,
                ref mut index,
                index_back,
            } = self;

            let remaining = &array[*index..index_back];

            remaining.iter().fold(init, |acc, src| {
                let value = ptr::read(src);

                *index += 1;

                f(acc, value)
            })
        };

        // ensure the drop happens here after iteration
        drop(self);

        ret
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len();
        (len, Some(len))
    }

    #[inline]
    fn count(self) -> usize {
        self.len()
    }

    fn nth(&mut self, n: usize) -> Option<T> {
        // First consume values prior to the nth.
        let ndrop = cmp::min(n, self.len());

        for p in &mut self.array[self.index..self.index + ndrop] {
            self.index += 1;

            unsafe {
                ptr::drop_in_place(p);
            }
        }

        self.next()
    }

    #[inline]
    fn last(mut self) -> Option<T> {
        // Note, everything else will correctly drop first as `self` leaves scope.
        self.next_back()
    }
}

impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    fn next_back(&mut self) -> Option<T> {
        if self.index < self.index_back {
            self.index_back -= 1;

            unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) }
        } else {
            None
        }
    }

    fn rfold<B, F>(mut self, init: B, mut f: F) -> B
    where
        F: FnMut(B, Self::Item) -> B,
    {
        let ret = unsafe {
            let GenericArrayIter {
                ref array,
                index,
                ref mut index_back,
            } = self;

            let remaining = &array[index..*index_back];

            remaining.iter().rfold(init, |acc, src| {
                let value = ptr::read(src);

                *index_back -= 1;

                f(acc, value)
            })
        };

        // ensure the drop happens here after iteration
        drop(self);

        ret
    }
}

impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>
where
    N: ArrayLength<T>,
{
    fn len(&self) -> usize {
        self.index_back - self.index
    }
}

impl<T, N> FusedIterator for GenericArrayIter<T, N> where N: ArrayLength<T> {}

// TODO: Implement `TrustedLen` when stabilized
<|endoftext|>


<commit_before>use std::fmt;
use std::str;

use column::Column;
use condition::ConditionExpression;
use select::{JoinClause, SelectStatement};
use table::Table;

#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum JoinRightSide {
    /// A single table.
    Table(Table),
    /// A comma-separated (and implicitly joined) sequence of tables.
    Tables(Vec<Table>),
    /// A nested selection, represented as (query, alias).
    NestedSelect(Box<SelectStatement>, Option<String>),
    /// A nested join clause.
    NestedJoin(Box<JoinClause>),
}

impl fmt::Display for JoinRightSide {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            JoinRightSide::Table(ref t) => write!(f, "{}", t)?,
            JoinRightSide::NestedSelect(ref q, ref a) => {
                write!(f, "({})", q)?;
                if a.is_some() {
                    write!(f, " AS {}", a.as_ref().unwrap())?;
                }
            }
            JoinRightSide::NestedJoin(ref jc) => write!(f, "({})", jc)?,
            _ => unimplemented!(),
        }
        Ok(())
    }
}

#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum JoinOperator {
    Join,
    LeftJoin,
    LeftOuterJoin,
    InnerJoin,
    CrossJoin,
    StraightJoin,
}

impl fmt::Display for JoinOperator {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            JoinOperator::Join => write!(f, "JOIN")?,
            JoinOperator::LeftJoin => write!(f, "LEFT JOIN")?,
            JoinOperator::LeftOuterJoin => write!(f, "LEFT OUTER JOIN")?,
            JoinOperator::InnerJoin => write!(f, "INNER JOIN")?,
            JoinOperator::CrossJoin => write!(f, "CROSS JOIN")?,
            JoinOperator::StraightJoin => write!(f, "STRAIGHT JOIN")?,
        }
        Ok(())
    }
}

#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum JoinConstraint {
    On(ConditionExpression),
    Using(Vec<Column>),
}

impl fmt::Display for JoinConstraint {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            JoinConstraint::On(ref ce) => write!(f, "ON {}", ce)?,
            JoinConstraint::Using(ref columns) => write!(
                f,
                "USING ({})",
                columns
                    .iter()
                    .map(|c| format!("{}", c))
                    .collect::<Vec<_>>()
                    .join(", ")
            )?,
        }
        Ok(())
    }
}

// Parse binary comparison operators
named!(pub join_operator<&[u8], JoinOperator>,
        alt!(
              map!(tag_no_case!("join"), |_| JoinOperator::Join)
            | map!(tag_no_case!("left join"), |_| JoinOperator::LeftJoin)
            | map!(tag_no_case!("left outer join"), |_| JoinOperator::LeftOuterJoin)
            | map!(tag_no_case!("inner join"), |_| JoinOperator::InnerJoin)
            | map!(tag_no_case!("cross join"), |_| JoinOperator::CrossJoin)
            | map!(tag_no_case!("straight_join"), |_| JoinOperator::StraightJoin)
        )
);

#[cfg(test)]
mod tests {
    use super::*;
    use common::{FieldDefinitionExpression, Operator};
    use condition::ConditionBase::*;
    use condition::ConditionExpression::{self, *};
    use condition::ConditionTree;
    use select::{selection, JoinClause, SelectStatement};

    #[test]
    fn inner_join() {
        let qstring = "SELECT tags.* FROM tags \
                       INNER JOIN taggings ON tags.id = taggings.tag_id";

        let res = selection(qstring.as_bytes());

        let ct = ConditionTree {
            left: Box::new(Base(Field(Column::from("tags.id")))),
            right: Box::new(Base(Field(Column::from("taggings.tag_id")))),
            operator: Operator::Equal,
        };
        let join_cond = ConditionExpression::ComparisonOp(ct);
        let expected_stmt = SelectStatement {
            tables: vec![Table::from("tags")],
            fields: vec![FieldDefinitionExpression::AllInTable("tags".into())],
            join: vec![JoinClause {
                operator: JoinOperator::InnerJoin,
                right: JoinRightSide::Table(Table::from("taggings")),
                constraint: JoinConstraint::On(join_cond),
            }],
            ..Default::default()
        };

        let q = res.unwrap().1;
        assert_eq!(q, expected_stmt);
        assert_eq!(qstring, format!("{}", q));
    }
}
<commit_msg>Update `join.rs` to use nom v5 functions<commit_after>use std::fmt;
use std::str;

use column::Column;
use condition::ConditionExpression;
use select::{JoinClause, SelectStatement};
use table::Table;
use nom::IResult;
use nom::branch::alt;
use nom::combinator::map;
use nom::bytes::complete::tag_no_case;

#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum JoinRightSide {
    /// A single table.
    Table(Table),
    /// A comma-separated (and implicitly joined) sequence of tables.
    Tables(Vec<Table>),
    /// A nested selection, represented as (query, alias).
    NestedSelect(Box<SelectStatement>, Option<String>),
    /// A nested join clause.
    NestedJoin(Box<JoinClause>),
}

impl fmt::Display for JoinRightSide {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            JoinRightSide::Table(ref t) => write!(f, "{}", t)?,
            JoinRightSide::NestedSelect(ref q, ref a) => {
                write!(f, "({})", q)?;
                if a.is_some() {
                    write!(f, " AS {}", a.as_ref().unwrap())?;
                }
            }
            JoinRightSide::NestedJoin(ref jc) => write!(f, "({})", jc)?,
            _ => unimplemented!(),
        }
        Ok(())
    }
}

#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum JoinOperator {
    Join,
    LeftJoin,
    LeftOuterJoin,
    InnerJoin,
    CrossJoin,
    StraightJoin,
}

impl fmt::Display for JoinOperator {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            JoinOperator::Join => write!(f, "JOIN")?,
            JoinOperator::LeftJoin => write!(f, "LEFT JOIN")?,
            JoinOperator::LeftOuterJoin => write!(f, "LEFT OUTER JOIN")?,
            JoinOperator::InnerJoin => write!(f, "INNER JOIN")?,
            JoinOperator::CrossJoin => write!(f, "CROSS JOIN")?,
            JoinOperator::StraightJoin => write!(f, "STRAIGHT JOIN")?,
        }
        Ok(())
    }
}

#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum JoinConstraint {
    On(ConditionExpression),
    Using(Vec<Column>),
}

impl fmt::Display for JoinConstraint {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            JoinConstraint::On(ref ce) => write!(f, "ON {}", ce)?,
            JoinConstraint::Using(ref columns) => write!(
                f,
                "USING ({})",
                columns
                    .iter()
                    .map(|c| format!("{}", c))
                    .collect::<Vec<_>>()
                    .join(", ")
            )?,
        }
        Ok(())
    }
}

// Parse binary comparison operators
pub fn join_operator(i: &[u8]) -> IResult<&[u8], JoinOperator> {
    alt((map(tag_no_case("join"), |_| JoinOperator::Join),
        map(tag_no_case("left join"), |_| JoinOperator::LeftJoin),
        map(tag_no_case("left outer join"), |_| JoinOperator::LeftOuterJoin),
        map(tag_no_case("inner join"), |_| JoinOperator::InnerJoin),
        map(tag_no_case("cross join"), |_| JoinOperator::CrossJoin),
        map(tag_no_case("straight_join"), |_| JoinOperator::StraightJoin)))(i)
}

#[cfg(test)]
mod tests {
    use super::*;
    use common::{FieldDefinitionExpression, Operator};
    use condition::ConditionBase::*;
    use condition::ConditionExpression::{self, *};
    use condition::ConditionTree;
    use select::{selection, JoinClause, SelectStatement};

    #[test]
    fn inner_join() {
        let qstring = "SELECT tags.* FROM tags \
                       INNER JOIN taggings ON tags.id = taggings.tag_id";

        let res = selection(qstring.as_bytes());

        let ct = ConditionTree {
            left: Box::new(Base(Field(Column::from("tags.id")))),
            right: Box::new(Base(Field(Column::from("taggings.tag_id")))),
            operator: Operator::Equal,
        };
        let join_cond = ConditionExpression::ComparisonOp(ct);
        let expected_stmt = SelectStatement {
            tables: vec![Table::from("tags")],
            fields: vec![FieldDefinitionExpression::AllInTable("tags".into())],
            join: vec![JoinClause {
                operator: JoinOperator::InnerJoin,
                right: JoinRightSide::Table(Table::from("taggings")),
                constraint: JoinConstraint::On(join_cond),
            }],
            ..Default::default()
        };

        let q = res.unwrap().1;
        assert_eq!(q, expected_stmt);
        assert_eq!(qstring, format!("{}", q));
    }
}
<|endoftext|>


<commit_before>//! Useful stuff for finding points in a line

use std::collections::HashSet;

use point::Point;

/// Find the points in a line between the current point and the one provided
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let set: HashSet<Point> = line(&point, &other);
///
/// assert_eq!(set.len(), 5);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(2, 3, 8)));
/// assert!(set.contains(&Point::new(3, 3, 9)));
/// assert!(set.contains(&Point::new(3, 4, 10)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(3, 4);
/// let set: HashSet<Point> = line(&point, &other);
///
/// assert_eq!(set.len(), 5);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(2, 3)));
/// assert!(set.contains(&Point::new_2d(3, 3)));
/// assert!(set.contains(&Point::new_2d(3, 4)));
/// ```
pub fn line(point: &Point, other: &Point) -> HashSet<Point> {
  util::line(&point, &other, None, None)
}

/// Find the points within range in a line through two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line_through, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(2, 2, 6);
/// let set: HashSet<Point> = line_through(&point, &other, 3);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(3, 2, 7)));
/// assert!(set.contains(&Point::new(4, 2, 8)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line_through, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(2, 2);
/// let set: HashSet<Point> = line_through(&point, &other, 3);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(3, 2)));
/// assert!(set.contains(&Point::new_2d(4, 2)));
/// ```
pub fn line_through(
  point: &Point,
  other: &Point,
  range: i32,
) -> HashSet<Point> {
  util::line(&point, &other, Some(range), None)
}

/// Find unblocked points in a line between two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new(3, 3, 9));
///
/// let set: HashSet<Point> = ray(&point, &other, &opaque);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(2, 3, 8)));
/// assert!(set.contains(&Point::new(3, 3, 9)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(3, 4);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new_2d(3, 3));
///
/// let set: HashSet<Point> = ray(&point, &other, &opaque);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(2, 3)));
/// assert!(set.contains(&Point::new_2d(3, 3)));
/// ```
pub fn ray(
  point: &Point,
  other: &Point,
  opaque: &HashSet<Point>,
) -> HashSet<Point> {
  util::line(&point, &other, None, Some(&opaque))
}

/// Find unblocked points within range in a line through two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray_through, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(2, 2, 6);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new(3, 2, 7));
///
/// let set: HashSet<Point> = ray_through(&point, &other, 3, &opaque);
///
/// assert_eq!(set.len(), 3);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(3, 2, 7)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray_through, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(2, 2);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new_2d(3, 2));
///
/// let set: HashSet<Point> = ray_through(&point, &other, 3, &opaque);
///
/// assert_eq!(set.len(), 3);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(3, 2)));
/// ```
pub fn ray_through(
  point: &Point,
  other: &Point,
  range: i32,
  opaque: &HashSet<Point>,
) -> HashSet<Point> {
  util::line(&point, &other, Some(range), Some(&opaque))
}

mod util {
  use std::collections::HashSet;

  use point::Point;
  use distance::{distance, distance_2d};

  /// Linear interpolation of floats with specified offset
  pub fn lerp(a: i32, b: i32, t: f32, o: f32) -> f32 {
    let a = a as f32 + o;
    let b = b as f32 + o;

    a + ((b - a) * t)
  }

  /// Linear interpolation of points with small offset
  ///
  /// The offset is used to prevent the interpolation from falling exactly
  /// on a border between two points. It is eliminated with rounding later.
  pub fn point_lerp(a: &Point, b: &Point, t: f32) -> (f32, f32, f32, f32) { (
    lerp(a.q, b.q, t, 1e-6),
    lerp(a.r, b.r, t, 1e-6),
    lerp(a.s, b.s, t, -2e-6),
    lerp(a.t, b.t, t, 1e-6),
  ) }

  /// Round a float point back to a standard point
  pub fn point_round((q, r, s, t): (f32, f32, f32, f32)) -> Point {
    let mut rq = q.round();
    let mut rr = r.round();

    let rs = s.round();
    let rt = t.round();

    let dq = (rq - q).abs();
    let dr = (rr - r).abs();
    let ds = (rs - s).abs();

    if (dq > ds) && (dq > dr) {
      rq = -rs - rr;
    } else if ds < dr {
      rr = -rq - rs;
    }

    let point: Point = Point::new(rq as i32, rr as i32, rt as i32);

    point
  }

  /// Find the points in a line between two points
  ///
  /// Optionally provide a range. The line will end at that range.
  ///
  /// Optionally provide a set of opaque point which are impassable.
  pub fn line(
    point: &Point,
    other: &Point,
    range: Option<i32>,
    opaque: Option<&HashSet<Point>>,
  ) -> HashSet<Point> {
    let mut set: HashSet<Point> = HashSet::new();

    if &point == &other {
      set.insert(point.clone());

      return set;
    }

    let distance: i32 = if point.values_2d() == other.values_2d() {
      distance(&point, &other)
    } else {
      distance_2d(&point, &other)
    };

    let empty: HashSet<Point> = HashSet::new();
    let opaque: &HashSet<Point> = opaque.unwrap_or(&empty);
    let should_check_opaque: bool = !opaque.is_empty();

    for index in 0..range.unwrap_or(distance) + 1 {
      let t: f32 = index as f32 / distance as f32;
      let lerp: (f32, f32, f32, f32) = point_lerp(&point, &other, t);
      let found: Point = point_round(lerp);

      set.insert(found);

      if should_check_opaque && opaque.contains(&found) {
        break;
      }
    }

    set
  }

}

#[cfg(test)]
mod tests {
  use std::collections::HashSet;

  use point::Point;

  use super::util;

  #[test]
  fn lerp() {
    let result = util::lerp(1, 2, 0.5, 1e-6);

    assert_eq!(result, 1.5 + 1e-6);
  }

  #[test]
  fn point_lerp() {
    let point: Point = Point::new(1, 2, 5);
    let other: Point = Point::new(3, 4, 10);
    let result = util::point_lerp(&point, &other, 0.5);
    let expect = (2f32 + 1e-6, 3f32 + 1e-6, -5f32 - 2e-6, 7.5f32 + 1e-6);

    assert_eq!(result, expect);
  }

  #[test]
  fn point_round() {
    let coordinates = (1.6, 1.6, -3.2, 2.5);
    let point: Point = util::point_round(coordinates);

    assert_eq!(point, Point::new(2, 1, 3));
  }

  #[test]
  fn line_vertical() {
    let point: Point = Point::new(1, 2, 5);
    let other: Point = Point::new(1, 2, 7);
    let line: HashSet<Point> = util::line(&point, &other, None, None);

    assert!(line.contains(&Point::new(1, 2, 5)));
    assert!(line.contains(&Point::new(1, 2, 6)));
    assert!(line.contains(&Point::new(1, 2, 7)));
  }

}

<commit_msg>Fix extra line break<commit_after>//! Useful stuff for finding points in a line

use std::collections::HashSet;

use point::Point;

/// Find the points in a line between the current point and the one provided
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let set: HashSet<Point> = line(&point, &other);
///
/// assert_eq!(set.len(), 5);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(2, 3, 8)));
/// assert!(set.contains(&Point::new(3, 3, 9)));
/// assert!(set.contains(&Point::new(3, 4, 10)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(3, 4);
/// let set: HashSet<Point> = line(&point, &other);
///
/// assert_eq!(set.len(), 5);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(2, 3)));
/// assert!(set.contains(&Point::new_2d(3, 3)));
/// assert!(set.contains(&Point::new_2d(3, 4)));
/// ```
pub fn line(point: &Point, other: &Point) -> HashSet<Point> {
  util::line(&point, &other, None, None)
}

/// Find the points within range in a line through two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line_through, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(2, 2, 6);
/// let set: HashSet<Point> = line_through(&point, &other, 3);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(3, 2, 7)));
/// assert!(set.contains(&Point::new(4, 2, 8)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{line_through, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(2, 2);
/// let set: HashSet<Point> = line_through(&point, &other, 3);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(3, 2)));
/// assert!(set.contains(&Point::new_2d(4, 2)));
/// ```
pub fn line_through(
  point: &Point,
  other: &Point,
  range: i32,
) -> HashSet<Point> {
  util::line(&point, &other, Some(range), None)
}

/// Find unblocked points in a line between two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new(3, 3, 9));
///
/// let set: HashSet<Point> = ray(&point, &other, &opaque);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(2, 3, 8)));
/// assert!(set.contains(&Point::new(3, 3, 9)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(3, 4);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new_2d(3, 3));
///
/// let set: HashSet<Point> = ray(&point, &other, &opaque);
///
/// assert_eq!(set.len(), 4);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(2, 3)));
/// assert!(set.contains(&Point::new_2d(3, 3)));
/// ```
pub fn ray(
  point: &Point,
  other: &Point,
  opaque: &HashSet<Point>,
) -> HashSet<Point> {
  util::line(&point, &other, None, Some(&opaque))
}

/// Find unblocked points within range in a line through two points
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray_through, Point};
///
/// let point: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(2, 2, 6);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new(3, 2, 7));
///
/// let set: HashSet<Point> = ray_through(&point, &other, 3, &opaque);
///
/// assert_eq!(set.len(), 3);
/// assert!(set.contains(&Point::new(1, 2, 5)));
/// assert!(set.contains(&Point::new(2, 2, 6)));
/// assert!(set.contains(&Point::new(3, 2, 7)));
/// ```
///
/// ```
/// use std::collections::HashSet;
///
/// use hex_math::{ray_through, Point};
///
/// let point: Point = Point::new_2d(1, 2);
/// let other: Point = Point::new_2d(2, 2);
/// let mut opaque: HashSet<Point> = HashSet::new();
///
/// opaque.insert(Point::new_2d(3, 2));
///
/// let set: HashSet<Point> = ray_through(&point, &other, 3, &opaque);
///
/// assert_eq!(set.len(), 3);
/// assert!(set.contains(&Point::new_2d(1, 2)));
/// assert!(set.contains(&Point::new_2d(2, 2)));
/// assert!(set.contains(&Point::new_2d(3, 2)));
/// ```
pub fn ray_through(
  point: &Point,
  other: &Point,
  range: i32,
  opaque: &HashSet<Point>,
) -> HashSet<Point> {
  util::line(&point, &other, Some(range), Some(&opaque))
}

mod util {
  use std::collections::HashSet;

  use point::Point;
  use distance::{distance, distance_2d};

  /// Linear interpolation of floats with specified offset
  pub fn lerp(a: i32, b: i32, t: f32, o: f32) -> f32 {
    let a = a as f32 + o;
    let b = b as f32 + o;

    a + ((b - a) * t)
  }

  /// Linear interpolation of points with small offset
  ///
  /// The offset is used to prevent the interpolation from falling exactly
  /// on a border between two points. It is eliminated with rounding later.
  pub fn point_lerp(a: &Point, b: &Point, t: f32) -> (f32, f32, f32, f32) { (
    lerp(a.q, b.q, t, 1e-6),
    lerp(a.r, b.r, t, 1e-6),
    lerp(a.s, b.s, t, -2e-6),
    lerp(a.t, b.t, t, 1e-6),
  ) }

  /// Round a float point back to a standard point
  pub fn point_round((q, r, s, t): (f32, f32, f32, f32)) -> Point {
    let mut rq = q.round();
    let mut rr = r.round();

    let rs = s.round();
    let rt = t.round();

    let dq = (rq - q).abs();
    let dr = (rr - r).abs();
    let ds = (rs - s).abs();

    if (dq > ds) && (dq > dr) {
      rq = -rs - rr;
    } else if ds < dr {
      rr = -rq - rs;
    }

    let point: Point = Point::new(rq as i32, rr as i32, rt as i32);

    point
  }

  /// Find the points in a line between two points
  ///
  /// Optionally provide a range. The line will end at that range.
  ///
  /// Optionally provide a set of opaque point which are impassable.
  pub fn line(
    point: &Point,
    other: &Point,
    range: Option<i32>,
    opaque: Option<&HashSet<Point>>,
  ) -> HashSet<Point> {
    let mut set: HashSet<Point> = HashSet::new();

    if &point == &other {
      set.insert(point.clone());

      return set;
    }

    let distance: i32 = if point.values_2d() == other.values_2d() {
      distance(&point, &other)
    } else {
      distance_2d(&point, &other)
    };

    let empty: HashSet<Point> = HashSet::new();
    let opaque: &HashSet<Point> = opaque.unwrap_or(&empty);
    let should_check_opaque: bool = !opaque.is_empty();

    for index in 0..range.unwrap_or(distance) + 1 {
      let t: f32 = index as f32 / distance as f32;
      let lerp: (f32, f32, f32, f32) = point_lerp(&point, &other, t);
      let found: Point = point_round(lerp);

      set.insert(found);

      if should_check_opaque && opaque.contains(&found) {
        break;
      }
    }

    set
  }

}

#[cfg(test)]
mod tests {
  use std::collections::HashSet;

  use point::Point;

  use super::util;

  #[test]
  fn lerp() {
    let result = util::lerp(1, 2, 0.5, 1e-6);

    assert_eq!(result, 1.5 + 1e-6);
  }

  #[test]
  fn point_lerp() {
    let point: Point = Point::new(1, 2, 5);
    let other: Point = Point::new(3, 4, 10);
    let result = util::point_lerp(&point, &other, 0.5);
    let expect = (2f32 + 1e-6, 3f32 + 1e-6, -5f32 - 2e-6, 7.5f32 + 1e-6);

    assert_eq!(result, expect);
  }

  #[test]
  fn point_round() {
    let coordinates = (1.6, 1.6, -3.2, 2.5);
    let point: Point = util::point_round(coordinates);

    assert_eq!(point, Point::new(2, 1, 3));
  }

  #[test]
  fn line_vertical() {
    let point: Point = Point::new(1, 2, 5);
    let other: Point = Point::new(1, 2, 7);
    let line: HashSet<Point> = util::line(&point, &other, None, None);

    assert!(line.contains(&Point::new(1, 2, 5)));
    assert!(line.contains(&Point::new(1, 2, 6)));
    assert!(line.contains(&Point::new(1, 2, 7)));
  }

}

<|endoftext|>


<commit_before>extern crate regex;

fn main() {
	// Execute script from the command line
}

fn parse(code: &str) -> Vec<&str> {
	// code.to_string()
	let leftParenRe = regex::Regex::new(r"\s*\(\s*").unwrap();
	let rightParenRe = regex::Regex::new(r"\s*\)\s*").unwrap();
	let partialParsedCode = leftParenRe.replace_all(code, r" ( ");
	let parsedCode = rightParenRe.replace_all(partialParsedCode.as_slice()," ) ");
	// let parsedCode = code.replace(" (", "(").replace("( ", "(").replace("(", " ( ").replace()
	parsedCode.as_slice().split(" ").collect()
}

fn tokenize() {

}

fn read_from_tokens() {

}

#[test]
fn it_works() {
	let parsedCode : Vec<&str> = parse("(begin (define r 10) (* pi (* r r)))");
	println!("{}", parsedCode);
}
<commit_msg>added more<commit_after>extern crate regex;

fn main() {
	// Execute script from the command line
}

fn parse(code: &str) -> Vec<&str> {
	// code.to_string()
	let leftParenRe = regex::Regex::new(r"\s*\(\s*").unwrap();
	let rightParenRe = regex::Regex::new(r"\s*\)\s*").unwrap();
	let partialParsedCode = leftParenRe.replace_all(&code, " ( ");
	let parsedCode = rightParenRe.replace_all(&partialParsedCode," ) ");
	// let parsedCode = code.replace(" (", "(").replace("( ", "(").replace("(", " ( ").replace()
	parsedCode.as_slice().split(" ").collect()
}

fn tokenize() {

}

fn read_from_tokens() {

}

#[test]
fn it_works() {
	let input = "(begin (define r 10) (* pi (* r r)))";
	let parsedCode = parse(input);
	println!("{}", parsedCode);
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate docopt;

mod display;
mod world;

use docopt::Docopt;
use std::thread::sleep_ms;

static USAGE: &'static str = "
Usage:
    golr [options]

Options:
    -h <height>, --height <height>              World height [default: 10]
    -w <width>, --width <width>                 World width  [default: 10]
    -f <fps>, --fps <fps>                       World fps    [default: 33]
";

#[derive(RustcDecodable, Debug)]
struct CliArgs {
    flag_width: isize,
    flag_height: isize,
    flag_fps: u32,
}

fn main() {
    let args = Docopt::new(USAGE).and_then(|d| d.decode::<CliArgs>())
                                 .unwrap_or_else(|e| e.exit());

    let mut world = world::World::new(args.flag_width, args.flag_height);

    world.randomize();

    loop {
        world = world.evolve();
        println!("\x1b[2J\n{}", world);
        std::thread::sleep_ms(args.flag_fps);
    }
}
<commit_msg>Rename fps to period, provide more suitable defaults<commit_after>extern crate rustc_serialize;
extern crate docopt;

mod display;
mod world;

use docopt::Docopt;
use std::thread::sleep_ms;

static USAGE: &'static str = "
Usage:
    golr [options]

Options:
    -h <height>, --height <height>  World height, points                 [default: 25]
    -w <width>, --width <width>     World width, points                  [default: 80]
    -p <period>, --period <period>  World generational change period, ms [default: 350]
";

#[derive(RustcDecodable, Debug)]
struct CliArgs {
    flag_width: isize,
    flag_height: isize,
    flag_period: u32,
}

fn main() {
    let args = Docopt::new(USAGE).and_then(|d| d.decode::<CliArgs>())
                                 .unwrap_or_else(|e| e.exit());

    let mut world = world::World::new(args.flag_width, args.flag_height);

    world.randomize();

    loop {
        world = world.evolve();
        println!("\x1b[2J\n{}", world);
        std::thread::sleep_ms(args.flag_period);
    }
}
<|endoftext|>


<commit_before>// In the name of Allah
// --------------------------------

extern crate clap;
extern crate git2;
#[macro_use]
extern crate json;
extern crate threadpool;
extern crate num_cpus;
extern crate futures;
extern crate futures_cpupool;
extern crate semver;
extern crate regex;
extern crate curl;

mod inner;
mod controller;
#[cfg(test)]
mod tests;

use clap::{Arg, App, SubCommand, AppSettings};
use std::process;
use controller::*;
use inner::logger::{Logger, Verbosity};

const VERSION: &'static str = "0.1.0";

fn main() {
    let matches = App::new("Rubigo")
        .version(VERSION)
        .name("Rubigo")
        .setting(AppSettings::VersionlessSubcommands)
        .about("Golang dependency tool and package manager\nFor more information, please visit https://github.com/yaa110/rubigo")
        .arg(Arg::with_name("verbose")
            .short("v")
            .long("verbose")
            .help("Use verbose output")
            .takes_value(false))
        .arg(Arg::with_name("no-prompt")
            .short("y")
            .long("yes")
            .help("Continue without prompt for a confirmation")
            .takes_value(false))
        .arg(Arg::with_name("quiet")
            .short("q")
            .long("quiet")
            .conflicts_with("verbose")
            .help("Print no output")
            .takes_value(false))
        .subcommand(SubCommand::with_name("new")
            .visible_alias("create")
            .arg(Arg::with_name("name")
                .help("The name of project")
                .required(true))
            .arg(Arg::with_name("library")
                .short("l")
                .long("lib")
                .help("Create a new library project")
                .conflicts_with("binary")
                .takes_value(false))
            .arg(Arg::with_name("binary")
                .short("b")
                .long("bin")
                .help("Create a new executable project (Default)")
                .takes_value(false))
            .about("Create a new Golang project"))
        .subcommand(SubCommand::with_name("init")
            .visible_alias("start")
            .about("Initialize Rubigo project in an existing directory"))
        .subcommand(SubCommand::with_name("reset")
            .visible_alias("sync")
            .about("Update `rubigo.json` and `rubigo.lock` to the list of packages in `vendor` directory"))
        .subcommand(SubCommand::with_name("get")
            .visible_alias("add")
            .arg(Arg::with_name("package")
                .help("The import path of package")
                .required(true))
            .arg(Arg::with_name("repository")
                .short("r")
                .long("repo")
                .value_name("repository")
                .help("Clone the package from the provided `repository` rather than its main url")
                .require_equals(true)
                .required(false)
                .conflicts_with_all(&["local", "global"])
                .takes_value(true))
            .arg(Arg::with_name("global")
                .short("g")
                .long("global")
                .help("Install the package in `GOPATH/src` directory")
                .required(false))
            .arg(Arg::with_name("local")
                .short("l")
                .long("local")
                .conflicts_with("global")
                .help("Create a new local package in `vendor` directory")
                .required(false))
            .about("Add a package to dependencies and clone it into `vendor` directory"))
        .subcommand(SubCommand::with_name("remove")
            .visible_alias("rm")
            .arg(Arg::with_name("package")
                .help("The import path of package")
                .required(true))
            .about("Remove a package from manifest and `vendor` directory"))
        .subcommand(SubCommand::with_name("update")
            .visible_alias("up")
            .arg(Arg::with_name("clean")
                .short("c")
                .long("clean")
                .help("Remove the package directory and clone from the repository")
                .takes_value(false))
            .arg(Arg::with_name("package")
                .help("The import path of package"))
            .arg(Arg::with_name("all")
                .short("a")
                .long("all")
                .help("Update all packages (Default)")
                .conflicts_with("package")
                .takes_value(false))
            .about("Update one or all packages and apply the changes of `rubigo.json` to `rubigo.lock` and packages in `vendor` directory"))
        .subcommand(SubCommand::with_name("list")
            .visible_alias("ls")
            .arg(Arg::with_name("all")
                .short("a")
                .long("all")
                .conflicts_with_all(&["global", "remote", "local"])
                .help("List all packages from `rubigo.lock` file (Default)")
                .takes_value(false))
            .arg(Arg::with_name("local")
                .short("l")
                .long("local")
                .help("List local packages from `rubigo.lock` file")
                .takes_value(false))
            .arg(Arg::with_name("global")
                .short("g")
                .long("global")
                .help("List global packages from `rubigo.lock` file")
                .takes_value(false))
            .arg(Arg::with_name("remote")
                .short("r")
                .long("remote")
                .help("List remote (git) packages from `rubigo.lock` file")
                .takes_value(false))
            .about("Display a list of dependencies from `rubigo.lock` file"))
        .subcommand(SubCommand::with_name("apply")
            .visible_alias("install")
            .arg(Arg::with_name("clean")
                .short("c")
                .long("clean")
                .help("Remove the package directory and clone from the repository")
                .takes_value(false))
            .about("Apply the changes of `rubigo.lock` to packages in `vendor` directory"))
        .subcommand(SubCommand::with_name("info")
            .visible_alias("about")
            .about("Display the information about this Rubigo project"))
        .get_matches();

    let logger = Logger::new(if matches.is_present("verbose") {
        Verbosity::High
    } else if matches.is_present("quiet") {
        Verbosity::None
    } else {
        Verbosity::Low
    });

    match matches.subcommand_name() {
        Some("apply") => {
            let apply_matches = match matches.subcommand_matches("apply") {
                Some(args) => args,
                None => {
                    logger.fatal("unable to get argument of `apply` sub command");
                    return
                },
            };
            project::apply(apply_matches.is_present("clean"), logger)
        },
        Some("get") => {
            let get_matches = match matches.subcommand_matches("get") {
                Some(args) => args,
                None => {
                    logger.fatal("unable to get argument of `get` sub command");
                    return
                },
            };
            package::get(match get_matches.value_of("package") {
                Some(pkg) => pkg,
                None => {
                    logger.fatal("unable to get `package` argument of `get` sub command");
                    return
                }
            }, get_matches.value_of("repository"), matches.is_present("no-prompt"), get_matches.is_present("global"), get_matches.is_present("local"), logger);
        },
        Some("info") => info::display(&logger),
        Some("init") => project::init(logger),
        Some("reset") => project::reset(matches.is_present("no-prompt"), logger),
        Some("list") => {
            let list_matches = match matches.subcommand_matches("list") {
                Some(args) => args,
                None => {
                    logger.fatal("unable to get argument of `list` sub command");
                    return
                },
            };
            list::list(list_matches.is_present("local"), list_matches.is_present("remote"), list_matches.is_present("global"), &logger);
        },
        Some("new") => {
            let new_matches = match matches.subcommand_matches("new") {
                Some(args) => args,
                None => {
                    logger.fatal("unable to get argument of `new` sub command");
                    return
                },
            };
            project::new(match new_matches.value_of("name") {
                Some(value) => value,
                None => {
                    logger.fatal("unable to get `name` argument of `new` sub command");
                    return
                },
            }, new_matches.is_present("library"), &logger)
        },
        Some("remove") => package::remove(match matches.subcommand_matches("remove") {
            Some(args) => match args.value_of("package") {
                Some(value) => value,
                None => {
                    logger.fatal("unable to get argument of `remove` sub command");
                    return
                },
            },
            None => {
                logger.fatal("unable to get argument of `remove` sub command");
                return
            },
        }, logger),
        Some("update") => {
            let update_matches = match matches.subcommand_matches("update") {
                Some(args) => args,
                None => {
                    logger.fatal("unable to get argument of `update` sub command");
                    return
                },
            };
            if update_matches.is_present("package") {
                package::update(Some(match update_matches.value_of("package") {
                    Some(value) => value,
                    None => {
                        logger.fatal("unable to get `package` argument of `update` sub command");
                        return
                    },
                }), update_matches.is_present("clean"), logger)
            } else {
                package::update(None, update_matches.is_present("clean"), logger)
            }
        },
        _ => {
            logger.error("No sub command has been provided. Please run `rubigo --help` for more information");
            process::exit(1)
        },
    }
}
<commit_msg>Update version to 1.0.0-beta<commit_after>// In the name of Allah
// --------------------------------

extern crate clap;
extern crate git2;
#[macro_use]
extern crate json;
extern crate threadpool;
extern crate num_cpus;
extern crate futures;
extern crate futures_cpupool;
extern crate semver;
extern crate regex;
extern crate curl;

mod inner;
mod controller;
#[cfg(test)]
mod tests;

use clap::{Arg, App, SubCommand, AppSettings};
use std::process;
use controller::*;
use inner::logger::{Logger, Verbosity};

const VERSION: &'static str = "1.0.0-beta";

fn main() {
    let matches = App::new("Rubigo")
        .version(VERSION)
        .name("Rubigo")
        .setting(AppSettings::VersionlessSubcommands)
        .about("Golang dependency tool and package manager\nFor more information, please visit https://github.com/yaa110/rubigo")
        .arg(Arg::with_name("verbose")
            .short("v")
            .long("verbose")
            .help("Use verbose output")
            .takes_value(false))
        .arg(Arg::with_name("no-prompt")
            .short("y")
            .long("yes")
            .help("Continue without prompt for a confirmation")
            .takes_value(false))
        .arg(Arg::with_name("quiet")
            .short("q")
            .long("quiet")
            .conflicts_with("verbose")
            .help("Print no output")
            .takes_value(false))
        .subcommand(SubCommand::with_name("new")
            .visible_alias("create")
            .arg(Arg::with_name("name")
                .help("The name of project")
                .required(true))
            .arg(Arg::with_name("library")
                .short("l")
                .long("lib")
                .help("Create a new library project")
                .conflicts_with("binary")
                .takes_value(false))
            .arg(Arg::with_name("binary")
                .short("b")
                .long("bin")
                .help("Create a new executable project (Default)")
                .takes_value(false))
            .about("Create a new Golang project"))
        .subcommand(SubCommand::with_name("init")
            .visible_alias("start")
            .about("Initialize Rubigo project in an existing directory"))
        .subcommand(SubCommand::with_name("reset")
            .visible_alias("sync")
            .about("Update `rubigo.json` and `rubigo.lock` to the list of packages in `vendor` directory"))
        .subcommand(SubCommand::with_name("get")
            .visible_alias("add")
            .arg(Arg::with_name("package")
                .help("The import path of package")
                .required(true))
            .arg(Arg::with_name("repository")
                .short("r")
                .long("repo")
                .value_name("repository")
                .help("Clone the package from the provided `repository` rather than its main url")
                .require_equals(true)
                .required(false)
                .conflicts_with_all(&["local", "global"])
                .takes_value(true))
            .arg(Arg::with_name("global")
                .short("g")
                .long("global")
                .help("Install the package in `GOPATH/src` directory")
                .required(false))
            .arg(Arg::with_name("local")
                .short("l")
                .long("local")
                .conflicts_with("global")
                .help("Create a new local package in `vendor` directory")
                .required(false))
            .about("Add a package to dependencies and clone it into `vendor` directory"))
        .subcommand(SubCommand::with_name("remove")
            .visible_alias("rm")
            .arg(Arg::with_name("package")
                .help("The import path of package")
                .required(true))
            .about("Remove a package from manifest and `vendor` directory"))
        .subcommand(SubCommand::with_name("update")
            .visible_alias("up")
            .arg(Arg::with_name("clean")
                .short("c")
                .long("clean")
                .help("Remove the package directory and clone from the repository")
                .takes_value(false))
            .arg(Arg::with_name("package")
                .help("The import path of package"))
            .arg(Arg::with_name("all")
                .short("a")
                .long("all")
                .help("Update all packages (Default)")
                .conflicts_with("package")
                .takes_value(false))
            .about("Update one or all packages and apply the changes of `rubigo.json` to `rubigo.lock` and packages in `vendor` directory"))
        .subcommand(SubCommand::with_name("list")
            .visible_alias("ls")
            .arg(Arg::with_name("all")
                .short("a")
                .long("all")
                .conflicts_with_all(&["global", "remote", "local"])
                .help("List all packages from `rubigo.lock` file (Default)")
                .takes_value(false))
            .arg(Arg::with_name("local")
                .short("l")
                .long("local")
                .help("List local packages from `rubigo.lock` file")
                .takes_value(false))
            .arg(Arg::with_name("global")
                .short("g")
                .long("global")
                .help("List global packages from `rubigo.lock` file")
                .takes_value(false))
            .arg(Arg::with_name("remote")
                .short("r")
                .long("remote")
                .help("List remote (git) packages from `rubigo.lock` file")
                .takes_value(false))
            .about("Display a list of dependencies from `rubigo.lock` file"))
        .subcommand(SubCommand::with_name("apply")
            .visible_alias("install")
            .arg(Arg::with_name("clean")
                .short("c")
                .long("clean")
                .help("Remove the package directory and clone from the repository")
                .takes_value(false))
            .about("Apply the changes of `rubigo.lock` to packages in `vendor` directory"))
        .subcommand(SubCommand::with_name("info")
            .visible_alias("about")
            .about("Display the information about this Rubigo project"))
        .get_matches();

    let logger = Logger::new(if matches.is_present("verbose") {
        Verbosity::High
    } else if matches.is_present("quiet") {
        Verbosity::None
    } else {
        Verbosity::Low
    });

    match matches.subcommand_name() {
        Some("apply") => {
            let apply_matches = match matches.subcommand_matches("apply") {
                Some(args) => args,
                None => {
                    logger.fatal("unable to get argument of `apply` sub command");
                    return
                },
            };
            project::apply(apply_matches.is_present("clean"), logger)
        },
        Some("get") => {
            let get_matches = match matches.subcommand_matches("get") {
                Some(args) => args,
                None => {
                    logger.fatal("unable to get argument of `get` sub command");
                    return
                },
            };
            package::get(match get_matches.value_of("package") {
                Some(pkg) => pkg,
                None => {
                    logger.fatal("unable to get `package` argument of `get` sub command");
                    return
                }
            }, get_matches.value_of("repository"), matches.is_present("no-prompt"), get_matches.is_present("global"), get_matches.is_present("local"), logger);
        },
        Some("info") => info::display(&logger),
        Some("init") => project::init(logger),
        Some("reset") => project::reset(matches.is_present("no-prompt"), logger),
        Some("list") => {
            let list_matches = match matches.subcommand_matches("list") {
                Some(args) => args,
                None => {
                    logger.fatal("unable to get argument of `list` sub command");
                    return
                },
            };
            list::list(list_matches.is_present("local"), list_matches.is_present("remote"), list_matches.is_present("global"), &logger);
        },
        Some("new") => {
            let new_matches = match matches.subcommand_matches("new") {
                Some(args) => args,
                None => {
                    logger.fatal("unable to get argument of `new` sub command");
                    return
                },
            };
            project::new(match new_matches.value_of("name") {
                Some(value) => value,
                None => {
                    logger.fatal("unable to get `name` argument of `new` sub command");
                    return
                },
            }, new_matches.is_present("library"), &logger)
        },
        Some("remove") => package::remove(match matches.subcommand_matches("remove") {
            Some(args) => match args.value_of("package") {
                Some(value) => value,
                None => {
                    logger.fatal("unable to get argument of `remove` sub command");
                    return
                },
            },
            None => {
                logger.fatal("unable to get argument of `remove` sub command");
                return
            },
        }, logger),
        Some("update") => {
            let update_matches = match matches.subcommand_matches("update") {
                Some(args) => args,
                None => {
                    logger.fatal("unable to get argument of `update` sub command");
                    return
                },
            };
            if update_matches.is_present("package") {
                package::update(Some(match update_matches.value_of("package") {
                    Some(value) => value,
                    None => {
                        logger.fatal("unable to get `package` argument of `update` sub command");
                        return
                    },
                }), update_matches.is_present("clean"), logger)
            } else {
                package::update(None, update_matches.is_present("clean"), logger)
            }
        },
        _ => {
            logger.error("No sub command has been provided. Please run `rubigo --help` for more information");
            process::exit(1)
        },
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate hyper;

use rustc_serialize::json;
use rustc_serialize::json::Json;
#[macro_use] extern crate nickel;

use nickel::status::StatusCode;
use nickel::{Nickel, HttpRouter, MediaType};

#[derive(RustcDecodable, RustcEncodable)]
struct Todo {
  status: i32,
  title: String,
}

fn main() {
  let mut server = Nickel::new();
  let mut router = Nickel::router();

  // index
  router.get("/api/todos", middleware! { |_, mut _res|
    let mut v: Vec<Todo> = vec![];
    let todo1 = Todo{
      status: 0,
      title: "Shopping".to_string(),
    };
    v.push(todo1);
    let todo2 = Todo{
      status: 1,
      title: "Movie".to_string(),
    };
    v.push(todo2);

    let json_obj = json::encode(&v).unwrap();
    _res.set(MediaType::Json);
    _res.set(StatusCode::Ok);
    return _res.send(json_obj);
  });

  // detail
  router.get("/api/todos/:id", middleware! { |_req, mut _res|
    let id = _req.param("id");
    println!("id: {:?}", id);

    let todo1 = Todo{
      status: 0,
      title: "Shopping".to_string(),
    };
    let json_obj = json::encode(&todo1).unwrap();
    _res.set(MediaType::Json);
    _res.set(StatusCode::Ok);
    return _res.send(json_obj);
  });

  // delete
  router.delete("/api/todos/:id", middleware! { |_req, mut _res|
    let id = _req.param("id");
    println!("delete id: {:?}", id);

    let json_obj = Json::from_str("{}").unwrap();
    _res.set(MediaType::Json);
    _res.set(StatusCode::Ok);
    return _res.send(json_obj);
  });

  // create

  // update

  server.utilize(router);
  server.listen("127.0.0.1:6767");
}
<commit_msg>add create<commit_after>extern crate rustc_serialize;
extern crate hyper;

use rustc_serialize::json;
use rustc_serialize::json::Json;
#[macro_use] extern crate nickel;

use nickel::status::StatusCode;
use nickel::{Nickel, HttpRouter, MediaType};

#[derive(RustcDecodable, RustcEncodable)]
struct Todo {
  status: i32,
  title: String,
}

fn main() {
  let mut server = Nickel::new();
  let mut router = Nickel::router();

  // index
  router.get("/api/todos", middleware! { |_, mut _res|
    let mut v: Vec<Todo> = vec![];
    let todo1 = Todo{
      status: 0,
      title: "Shopping".to_string(),
    };
    v.push(todo1);
    let todo2 = Todo{
      status: 1,
      title: "Movie".to_string(),
    };
    v.push(todo2);

    let json_obj = json::encode(&v).unwrap();
    _res.set(MediaType::Json);
    _res.set(StatusCode::Ok);
    return _res.send(json_obj);
  });

  // detail
  router.get("/api/todos/:id", middleware! { |_req, mut _res|
    let id = _req.param("id");
    println!("id: {:?}", id);

    let todo1 = Todo{
      status: 0,
      title: "Shopping".to_string(),
    };
    let json_obj = json::encode(&todo1).unwrap();
    _res.set(MediaType::Json);
    _res.set(StatusCode::Ok);
    return _res.send(json_obj);
  });

  // delete
  router.delete("/api/todos/:id", middleware! { |_req, mut _res|
    let id = _req.param("id");
    println!("delete id: {:?}", id);

    let json_obj = Json::from_str("{}").unwrap();
    _res.set(MediaType::Json);
    _res.set(StatusCode::Ok);
    return _res.send(json_obj);
  });

  // create
  router.post("/api/todos", middleware! { |_req, mut _res|

    let json_obj = Json::from_str("{}").unwrap();
    _res.set(MediaType::Json);
    _res.set(StatusCode::Created);
    return _res.send(json_obj);
  });

  // update

  server.utilize(router);
  server.listen("127.0.0.1:6767");
}
<|endoftext|>


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

extern crate libc;
extern crate getopts;
extern crate "rustc-serialize" as rustc_serialize;
extern crate crypto;
extern crate rpassword;
extern crate rand;

use color::Color;
use std::slice::AsSlice;
use std::fs::File;
use std::iter::IteratorExt;
use std::env;
use std::ffi::AsOsStr;
use std::path::MAIN_SEPARATOR as PATH_SEP;
use std::io::Result as IoResult;
use std::io::Error as IoError;
use std::io::ErrorKind as IoErrorKind;
use std::io::stdin;
use std::io::Write;
use std::path::Path;

mod macros;
mod aes;
mod commands;
mod ffi;
mod password;
mod color;

const PEEVEE_FILE_DEFAULT: &'static str = ".peevee_passwords.aes";

struct Command {
    name: &'static str,
    callback: fn(&[String], &mut File) -> ()
}

static COMMANDS: &'static [Command] = &[
    Command { name: "get", callback: commands::get::callback },
    Command { name: "add", callback: commands::add::callback },
    Command { name: "delete", callback: commands::delete::callback },
    Command { name: "generate", callback: commands::generate::callback },
    Command { name: "list", callback: commands::list::callback }
];

fn command_from_name(name: &str) -> Option<&'static Command> {
    for c in COMMANDS.iter() {
        if c.name == name {
            return Some(&c);
        }
    }
    None
}

fn open_password_file(filename: &str, create: bool) -> IoResult<File> {
    let mut options = std::fs::OpenOptions::new();
    options.read(true);
    options.write(true);
    options.create(create);
    options.open(&Path::new(filename))
}

fn get_password_file_from_input(filename: &str) -> IoResult<File> {
    println_stderr!(
        "I could not find the password file \"{}\". Would you like to create it now? [yes/no]",
        filename
    );
    loop {
        let mut line = String::new();
        match stdin().read_line(&mut line) {
            Ok(_) => {
                if line.as_slice().starts_with("yes") {
                    return open_password_file(filename, true);
                } else if line.as_slice().starts_with("no") {
                    return Err(IoError::last_os_error());
                } else {
                    errln!(
                        "I did not understand that. Would you like to create \
                        the password file \"{}\" now? [yes/no]",
                        filename
                    );
                }
            },
            Err(_) => {
                errln!(
                    "I was not able to read your answer. Would you like to create \
                    the password file \"{}\" now? [yes/no]",
                    filename
                );
            }
        }
    }
}

fn get_password_file(filename: &str) -> IoResult<File> {
    match open_password_file(filename, false) {
        Ok(file) => Ok(file),
        Err(err) => {
            match err.kind() {
                IoErrorKind::FileNotFound => get_password_file_from_input(filename),
                _ => Err(err)
            }
        }
    }
}

fn execute_command_from_filename(args: &[String], command: &Command, filename: &str) {
    match get_password_file(filename) {
        Ok(ref mut file) => {
            (command.callback)(args, file);
        },
        Err(err) => {
            match err.kind() {
                // This was already handled before.
                IoErrorKind::FileNotFound => {},
                _ => {
                    errln!("I could not open the password file \"{}\" :( ({})", filename, err);
                }
            }
            std::env::set_exit_status(1);
        }
    }
}

fn execute_command(args: &[String], command: &Command) {
    match env::var("PEEVEE_FILE") {
        Ok(filename) => {
            execute_command_from_filename(args, command, filename.as_slice());
        },
        Err(env::VarError::NotPresent) => {
            match env::home_dir() {
                Some(path) => {
                    match path.as_os_str().to_os_string().into_string() {
                        Ok(ref mut filename) => {
                            filename.push(PATH_SEP);
                            filename.push_str(PEEVEE_FILE_DEFAULT);
                            execute_command_from_filename(args, command, filename.as_slice());
                        },
                        Err(oss) => {
                            errln!("The password filename, {:?}, is invalid. It must be valid UTF8.", oss);
                            std::env::set_exit_status(1);
                        }
                    }
                },
                None => {
                    errln!("I couldn't figure out what file to use for the passwords.");
                    std::env::set_exit_status(1);
                }
            }
        },
        Err(env::VarError::NotUnicode(oss)) => {
            errln!("The password filename, {:?}, is invalid. It must be valid UTF8.", oss);
            std::env::set_exit_status(1);
        }
    };
}

fn main() {
    let args: Vec<String> = std::env::args().collect();

    match args.as_slice().get(1) {
        Some(command_name) => {
            match command_from_name(command_name.as_slice()) {
                Some(command) => {
                    execute_command(args.as_slice(), command);
                },
                None => {
                    errln!(
                        "I don't know the \"{}\" command. You can check \
                        existing commands at: https://github.com/conradkleinespel/peevee-cli.",
                        command_name
                    );
                    std::env::set_exit_status(1);
                }
            }
        },
        None => {
            errln!(
                "I didn't understand that. You can check the documentation \
                for Peevee at: https://github.com/conradkleinespel/peevee-cli"
            );
            std::env::set_exit_status(1);
        }
    }
}
<commit_msg>update serialize<commit_after>// Copyright 2014 The Peevee Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate libc;
extern crate getopts;
extern crate rustc_serialize;
extern crate crypto;
extern crate rpassword;
extern crate rand;

use color::Color;
use std::slice::AsSlice;
use std::fs::File;
use std::iter::IteratorExt;
use std::env;
use std::ffi::AsOsStr;
use std::path::MAIN_SEPARATOR as PATH_SEP;
use std::io::Result as IoResult;
use std::io::Error as IoError;
use std::io::ErrorKind as IoErrorKind;
use std::io::stdin;
use std::io::Write;
use std::path::Path;

mod macros;
mod aes;
mod commands;
mod ffi;
mod password;
mod color;

const PEEVEE_FILE_DEFAULT: &'static str = ".peevee_passwords.aes";

struct Command {
    name: &'static str,
    callback: fn(&[String], &mut File) -> ()
}

static COMMANDS: &'static [Command] = &[
    Command { name: "get", callback: commands::get::callback },
    Command { name: "add", callback: commands::add::callback },
    Command { name: "delete", callback: commands::delete::callback },
    Command { name: "generate", callback: commands::generate::callback },
    Command { name: "list", callback: commands::list::callback }
];

fn command_from_name(name: &str) -> Option<&'static Command> {
    for c in COMMANDS.iter() {
        if c.name == name {
            return Some(&c);
        }
    }
    None
}

fn open_password_file(filename: &str, create: bool) -> IoResult<File> {
    let mut options = std::fs::OpenOptions::new();
    options.read(true);
    options.write(true);
    options.create(create);
    options.open(&Path::new(filename))
}

fn get_password_file_from_input(filename: &str) -> IoResult<File> {
    println_stderr!(
        "I could not find the password file \"{}\". Would you like to create it now? [yes/no]",
        filename
    );
    loop {
        let mut line = String::new();
        match stdin().read_line(&mut line) {
            Ok(_) => {
                if line.as_slice().starts_with("yes") {
                    return open_password_file(filename, true);
                } else if line.as_slice().starts_with("no") {
                    return Err(IoError::last_os_error());
                } else {
                    errln!(
                        "I did not understand that. Would you like to create \
                        the password file \"{}\" now? [yes/no]",
                        filename
                    );
                }
            },
            Err(_) => {
                errln!(
                    "I was not able to read your answer. Would you like to create \
                    the password file \"{}\" now? [yes/no]",
                    filename
                );
            }
        }
    }
}

fn get_password_file(filename: &str) -> IoResult<File> {
    match open_password_file(filename, false) {
        Ok(file) => Ok(file),
        Err(err) => {
            match err.kind() {
                IoErrorKind::FileNotFound => get_password_file_from_input(filename),
                _ => Err(err)
            }
        }
    }
}

fn execute_command_from_filename(args: &[String], command: &Command, filename: &str) {
    match get_password_file(filename) {
        Ok(ref mut file) => {
            (command.callback)(args, file);
        },
        Err(err) => {
            match err.kind() {
                // This was already handled before.
                IoErrorKind::FileNotFound => {},
                _ => {
                    errln!("I could not open the password file \"{}\" :( ({})", filename, err);
                }
            }
            std::env::set_exit_status(1);
        }
    }
}

fn execute_command(args: &[String], command: &Command) {
    match env::var("PEEVEE_FILE") {
        Ok(filename) => {
            execute_command_from_filename(args, command, filename.as_slice());
        },
        Err(env::VarError::NotPresent) => {
            match env::home_dir() {
                Some(path) => {
                    match path.as_os_str().to_os_string().into_string() {
                        Ok(ref mut filename) => {
                            filename.push(PATH_SEP);
                            filename.push_str(PEEVEE_FILE_DEFAULT);
                            execute_command_from_filename(args, command, filename.as_slice());
                        },
                        Err(oss) => {
                            errln!("The password filename, {:?}, is invalid. It must be valid UTF8.", oss);
                            std::env::set_exit_status(1);
                        }
                    }
                },
                None => {
                    errln!("I couldn't figure out what file to use for the passwords.");
                    std::env::set_exit_status(1);
                }
            }
        },
        Err(env::VarError::NotUnicode(oss)) => {
            errln!("The password filename, {:?}, is invalid. It must be valid UTF8.", oss);
            std::env::set_exit_status(1);
        }
    };
}

fn main() {
    let args: Vec<String> = std::env::args().collect();

    match args.as_slice().get(1) {
        Some(command_name) => {
            match command_from_name(command_name.as_slice()) {
                Some(command) => {
                    execute_command(args.as_slice(), command);
                },
                None => {
                    errln!(
                        "I don't know the \"{}\" command. You can check \
                        existing commands at: https://github.com/conradkleinespel/peevee-cli.",
                        command_name
                    );
                    std::env::set_exit_status(1);
                }
            }
        },
        None => {
            errln!(
                "I didn't understand that. You can check the documentation \
                for Peevee at: https://github.com/conradkleinespel/peevee-cli"
            );
            std::env::set_exit_status(1);
        }
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate docopt;
use docopt::Docopt;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;

#[macro_use]
extern crate log;
extern crate env_logger;

use std::{process, env};
use std::io::{self, Read, Write};
use std::path::PathBuf;
use std::fs::File;
use std::error::Error;

mod keepasshttp;

const VERSION: &'static str = "0.1.1";
const USAGE: &'static str = "
cmdipass

Usage:
  cmdipass get <search-string>
  cmdipass get-one <search-string> (--index=<index> | --uuid=<uuid>) [--password-only | --username-only]
  cmdipass --version
  cmdipass (-h | --help)

Options:
  -h --help         Show this screen.
  --version         Show version.
  --index=<index>   Select the entry at this 0-indexed location.
  --uuid=<uuid>     Select the entry with this uuid.
  --password-only   Print only the password.
  --username-only   Print only the username.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_get: bool,
    cmd_get_one: bool,
    flag_version: bool,
    flag_help: bool,
    arg_search_string: String,
    flag_index: Option<usize>,
    flag_uuid: Option<String>,
    flag_password_only: bool,
    flag_username_only: bool
}

fn config_path() -> PathBuf {
    env::var("CMDIPASS_CONFIG").map(|e| PathBuf::from(e)).unwrap_or_else(|_| {
        let mut pathbuf = env::home_dir().unwrap_or(PathBuf::from(""));
        pathbuf.push(".cmdipass");
        pathbuf
    })
}

fn config_exists() -> bool {
    config_path().as_path().exists()
}

fn load_config() -> io::Result<keepasshttp::Config> {
    let mut res = File::open(config_path())?;
    let mut buf = String::new();
    res.read_to_string(&mut buf)?;

    let config: keepasshttp::Config = serde_json::from_str(buf.as_str())
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, format!("Invalid JSON: {}", e.description())))?;
    Ok(config)
}

fn write_config_file(config: &keepasshttp::Config) {
    let mut file = File::create(config_path()).unwrap();
    file.write_all(serde_json::to_string(&config).unwrap().as_bytes()).unwrap();
}

fn show_all(entries: &Vec<keepasshttp::Entry>) {
    for(i, entry) in entries.iter().enumerate() {
        println!("{}: {}", i, entry);
    }
}

fn show_one(entries: &Vec<keepasshttp::Entry>, args: &Args) {
    let entry = if args.flag_uuid.is_some() {
        entry_by_uuid(entries, &args.flag_uuid.clone().unwrap())
    } else if args.flag_index.is_some() {
        entry_by_index(entries, &args.flag_index.clone().unwrap())
    } else {
        None
    }.unwrap_or_else(|| {
        process::exit(1);
    });

    if args.flag_password_only {
        println!("{}", entry.password);
    } else if args.flag_username_only {
        println!("{}", entry.login);
    } else {
        println!("{}", entry);
    }

}

fn entry_by_index<'a>(entries: &'a Vec<keepasshttp::Entry>, index: &usize) -> Option<&'a keepasshttp::Entry> {
    let entry = entries.get(*index);

    if entry.is_none() {
        writeln!(io::stderr(), "Could not find an entry at index {}", index).unwrap();
    }

    entry
}

fn entry_by_uuid<'a, T: AsRef<str>>(entries: &'a Vec<keepasshttp::Entry>, uuid: T) -> Option<&'a keepasshttp::Entry> {
    let entry = entries.iter().find(|e| e.uuid == uuid.as_ref());

    if entry.is_none() {
        writeln!(io::stderr(), "Could not find an entry with UUID {}", uuid.as_ref()).unwrap();
    }

    entry
}

fn get_entries<T: AsRef<str>>(search_string: T) -> Vec<keepasshttp::Entry> {
    let config = load_config().unwrap();
    let success = keepasshttp::test_associate(&config);
    if !success {
        writeln!(io::stderr(), "Config rejected by keepasshttp. Make sure that the correct database is open, or delete your config file ({}) and re-associate", config_path().to_string_lossy()).unwrap();
        process::exit(1);
    }

    keepasshttp::get_logins(&config, &search_string).unwrap_or_else(|e| {
        writeln!(io::stderr(), "Error - Server said: '{}'", e).unwrap();
        process::exit(1);
    })
}

fn main() {
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit());

    env_logger::init().unwrap();

    if args.flag_help {
        println!("{}", USAGE);
        process::exit(0);
    }

    if args.flag_version {
        println!("cmdipass-{}", VERSION);
        process::exit(0);
    }

    if !config_exists() {
        writeln!(io::stderr(), "Config file not found at '{}', generating new key and registering with server", config_path().to_string_lossy()).unwrap();
        write_config_file(&keepasshttp::associate().unwrap());
        writeln!(io::stderr(), "Config file written.").unwrap();
    }

    let entries = get_entries(&args.arg_search_string);

    if args.cmd_get {
        show_all(&entries);
    } else if args.cmd_get_one {
        show_one(&entries, &args);
    }
}
<commit_msg>Config file now created with owner-only read and write<commit_after>extern crate rustc_serialize;
extern crate docopt;
use docopt::Docopt;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;

#[macro_use]
extern crate log;
extern crate env_logger;

use std::{process, env};
use std::io::{self, Read, Write};
use std::path::PathBuf;
use std::fs::{self, File};
use std::os::unix::fs::OpenOptionsExt;
use std::error::Error;

mod keepasshttp;

const VERSION: &'static str = "0.1.1";
const USAGE: &'static str = "
cmdipass

Usage:
  cmdipass get <search-string>
  cmdipass get-one <search-string> (--index=<index> | --uuid=<uuid>) [--password-only | --username-only]
  cmdipass --version
  cmdipass (-h | --help)

Options:
  -h --help         Show this screen.
  --version         Show version.
  --index=<index>   Select the entry at this 0-indexed location.
  --uuid=<uuid>     Select the entry with this uuid.
  --password-only   Print only the password.
  --username-only   Print only the username.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_get: bool,
    cmd_get_one: bool,
    flag_version: bool,
    flag_help: bool,
    arg_search_string: String,
    flag_index: Option<usize>,
    flag_uuid: Option<String>,
    flag_password_only: bool,
    flag_username_only: bool
}

fn config_path() -> PathBuf {
    env::var("CMDIPASS_CONFIG").map(|e| PathBuf::from(e)).unwrap_or_else(|_| {
        let mut pathbuf = env::home_dir().unwrap_or(PathBuf::from(""));
        pathbuf.push(".cmdipass");
        pathbuf
    })
}

fn config_exists() -> bool {
    config_path().as_path().exists()
}

fn load_config() -> io::Result<keepasshttp::Config> {
    let mut res = File::open(config_path())?;
    let mut buf = String::new();
    res.read_to_string(&mut buf)?;

    let config: keepasshttp::Config = serde_json::from_str(buf.as_str())
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, format!("Invalid JSON: {}", e.description())))?;
    Ok(config)
}

fn write_config_file(config: &keepasshttp::Config) {
    let mut file = fs::OpenOptions::new().write(true).create(true).mode(0o600).open(config_path()).unwrap();
    file.write_all(serde_json::to_string(&config).unwrap().as_bytes()).unwrap();
}

fn show_all(entries: &Vec<keepasshttp::Entry>) {
    for(i, entry) in entries.iter().enumerate() {
        println!("{}: {}", i, entry);
    }
}

fn show_one(entries: &Vec<keepasshttp::Entry>, args: &Args) {
    let entry = if args.flag_uuid.is_some() {
        entry_by_uuid(entries, &args.flag_uuid.clone().unwrap())
    } else if args.flag_index.is_some() {
        entry_by_index(entries, &args.flag_index.clone().unwrap())
    } else {
        None
    }.unwrap_or_else(|| {
        process::exit(1);
    });

    if args.flag_password_only {
        println!("{}", entry.password);
    } else if args.flag_username_only {
        println!("{}", entry.login);
    } else {
        println!("{}", entry);
    }

}

fn entry_by_index<'a>(entries: &'a Vec<keepasshttp::Entry>, index: &usize) -> Option<&'a keepasshttp::Entry> {
    let entry = entries.get(*index);

    if entry.is_none() {
        writeln!(io::stderr(), "Could not find an entry at index {}", index).unwrap();
    }

    entry
}

fn entry_by_uuid<'a, T: AsRef<str>>(entries: &'a Vec<keepasshttp::Entry>, uuid: T) -> Option<&'a keepasshttp::Entry> {
    let entry = entries.iter().find(|e| e.uuid == uuid.as_ref());

    if entry.is_none() {
        writeln!(io::stderr(), "Could not find an entry with UUID {}", uuid.as_ref()).unwrap();
    }

    entry
}

fn get_entries<T: AsRef<str>>(search_string: T) -> Vec<keepasshttp::Entry> {
    let config = load_config().unwrap();
    let success = keepasshttp::test_associate(&config);
    if !success {
        writeln!(io::stderr(), "Config rejected by keepasshttp. Make sure that the correct database is open, or delete your config file ({}) and re-associate", config_path().to_string_lossy()).unwrap();
        process::exit(1);
    }

    keepasshttp::get_logins(&config, &search_string).unwrap_or_else(|e| {
        writeln!(io::stderr(), "Error - Server said: '{}'", e).unwrap();
        process::exit(1);
    })
}

fn main() {
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit());

    env_logger::init().unwrap();

    if args.flag_help {
        println!("{}", USAGE);
        process::exit(0);
    }

    if args.flag_version {
        println!("cmdipass-{}", VERSION);
        process::exit(0);
    }

    if !config_exists() {
        writeln!(io::stderr(), "Config file not found at '{}', generating new key and registering with server", config_path().to_string_lossy()).unwrap();
        write_config_file(&keepasshttp::associate().unwrap());
        writeln!(io::stderr(), "Config file written.").unwrap();
    }

    let entries = get_entries(&args.arg_search_string);

    if args.cmd_get {
        show_all(&entries);
    } else if args.cmd_get_one {
        show_one(&entries, &args);
    }
}
<|endoftext|>