<commit_before>//! Contains Value and ValueRef structs and its conversion traits.

use std::convert::From;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

impl Value {
    pub fn is_nil(&self) -> bool {
        return if let Value::Nil = *self {
            true
        } else {
            false
        }
    }
}

impl From<bool> for Value {
    fn from(v: bool) -> Value {
        Value::Boolean(v)
    }
}

impl From<u8> for Value {
    fn from(v: u8) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u16> for Value {
    fn from(v: u16) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u32> for Value {
    fn from(v: u32) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u64> for Value {
    fn from(v: u64) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<usize> for Value {
    fn from(v: usize) -> Value {
        Value::Integer(Integer::U64(v as u64))
    }
}

impl From<i8> for Value {
    fn from(v: i8) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i16> for Value {
    fn from(v: i16) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i32> for Value {
    fn from(v: i32) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i64> for Value {
    fn from(v: i64) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<isize> for Value {
    fn from(v: isize) -> Value {
        Value::Integer(Integer::I64(v as i64))
    }
}

impl From<f32> for Value {
    fn from(v: f32) -> Value {
        Value::Float(Float::F32(v))
    }
}

impl From<f64> for Value {
    fn from(v: f64) -> Value {
        Value::Float(Float::F64(v))
    }
}

/// Implements human-readable value formatting.
impl ::std::fmt::Display for Value {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Integer(Integer::U64(val)) => write!(f, "{}", val),
            Value::Integer(Integer::I64(val)) => write!(f, "{}", val),
            Value::Float(Float::F32(val)) => write!(f, "{}", val),
            Value::Float(Float::F64(val)) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "\"{}\"", val),
            Value::Binary(ref val) => write!(f, "{:?}", val),
            Value::Array(ref vec) => {
                // TODO: This can be slower than naive implementation. Need benchmarks for more
                // information.
                let res = vec.iter()
                    .map(|val| format!("{}", val))
                    .collect::<Vec<String>>()
                    .join(", ");

                write!(f, "[{}]", res)
            }
            Value::Map(ref vec) => {
                try!(write!(f, "{{"));

                match vec.iter().take(1).next() {
                    Some(&(ref k, ref v)) => {
                        try!(write!(f, "{}: {}", k, v));
                    }
                    None => {
                        try!(write!(f, ""));
                    }
                }

                for &(ref k, ref v) in vec.iter().skip(1) {
                    try!(write!(f, ", {}: {}", k, v));
                }

                write!(f, "}}")
            }
            Value::Ext(ty, ref data) => {
                write!(f, "[{}, {:?}]", ty, data)
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(&'a str),
    /// Binary extending Raw type represents a byte array.
    Binary(&'a [u8]),
    /// Array represents a sequence of objects.
    Array(Vec<ValueRef<'a>>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to an owned Value.
    ///
    /// This is achieved by deep copying all underlying structures and borrowed buffers.
    ///
    /// # Panics
    ///
    /// Panics in unable to allocate memory to keep all internal structures and buffers.
    ///
    /// # Examples
    /// ```
    /// use rmp::{Value, ValueRef};
    /// use rmp::value::Integer;
    ///
    /// let val = ValueRef::Array(vec![
    ///    ValueRef::Nil,
    ///    ValueRef::Integer(Integer::U64(42)),
    ///    ValueRef::Array(vec![
    ///        ValueRef::String("le message"),
    ///    ])
    /// ]);
    ///
    /// let expected = Value::Array(vec![
    ///     Value::Nil,
    ///     Value::Integer(Integer::U64(42)),
    ///     Value::Array(vec![
    ///         Value::String("le message".to_string())
    ///     ])
    /// ]);
    ///
    /// assert_eq!(expected, val.to_owned());
    /// ```
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_owned()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                Value::Array(val.iter().map(|v| v.to_owned()).collect())
            }
            &ValueRef::Map(ref val) => {
                Value::Map(val.iter().map(|&(ref k, ref v)| (k.to_owned(), v.to_owned())).collect())
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<commit_msg>feat: add conversion into bool<commit_after>//! Contains Value and ValueRef structs and its conversion traits.

use std::convert::From;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

impl Value {
    /// Returns true if the `Value` is a Null. Returns false otherwise.
    pub fn is_nil(&self) -> bool {
        if let Value::Nil = *self {
            true
        } else {
            false
        }
    }

    /// If the `Value` is a Boolean, returns the associated bool.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    ///
    /// assert_eq!(Some(true), Value::Boolean(true).as_bool());
    /// assert_eq!(None, Value::Nil.as_bool());
    /// ```
    pub fn as_bool(&self) -> Option<bool> {
        if let Value::Boolean(val) = *self {
            Some(val)
        } else {
            None
        }
    }
}

impl From<bool> for Value {
    fn from(v: bool) -> Value {
        Value::Boolean(v)
    }
}

impl From<u8> for Value {
    fn from(v: u8) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u16> for Value {
    fn from(v: u16) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u32> for Value {
    fn from(v: u32) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u64> for Value {
    fn from(v: u64) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<usize> for Value {
    fn from(v: usize) -> Value {
        Value::Integer(Integer::U64(v as u64))
    }
}

impl From<i8> for Value {
    fn from(v: i8) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i16> for Value {
    fn from(v: i16) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i32> for Value {
    fn from(v: i32) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i64> for Value {
    fn from(v: i64) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<isize> for Value {
    fn from(v: isize) -> Value {
        Value::Integer(Integer::I64(v as i64))
    }
}

impl From<f32> for Value {
    fn from(v: f32) -> Value {
        Value::Float(Float::F32(v))
    }
}

impl From<f64> for Value {
    fn from(v: f64) -> Value {
        Value::Float(Float::F64(v))
    }
}

/// Implements human-readable value formatting.
impl ::std::fmt::Display for Value {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Integer(Integer::U64(val)) => write!(f, "{}", val),
            Value::Integer(Integer::I64(val)) => write!(f, "{}", val),
            Value::Float(Float::F32(val)) => write!(f, "{}", val),
            Value::Float(Float::F64(val)) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "\"{}\"", val),
            Value::Binary(ref val) => write!(f, "{:?}", val),
            Value::Array(ref vec) => {
                // TODO: This can be slower than naive implementation. Need benchmarks for more
                // information.
                let res = vec.iter()
                    .map(|val| format!("{}", val))
                    .collect::<Vec<String>>()
                    .join(", ");

                write!(f, "[{}]", res)
            }
            Value::Map(ref vec) => {
                try!(write!(f, "{{"));

                match vec.iter().take(1).next() {
                    Some(&(ref k, ref v)) => {
                        try!(write!(f, "{}: {}", k, v));
                    }
                    None => {
                        try!(write!(f, ""));
                    }
                }

                for &(ref k, ref v) in vec.iter().skip(1) {
                    try!(write!(f, ", {}: {}", k, v));
                }

                write!(f, "}}")
            }
            Value::Ext(ty, ref data) => {
                write!(f, "[{}, {:?}]", ty, data)
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(&'a str),
    /// Binary extending Raw type represents a byte array.
    Binary(&'a [u8]),
    /// Array represents a sequence of objects.
    Array(Vec<ValueRef<'a>>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to an owned Value.
    ///
    /// This is achieved by deep copying all underlying structures and borrowed buffers.
    ///
    /// # Panics
    ///
    /// Panics in unable to allocate memory to keep all internal structures and buffers.
    ///
    /// # Examples
    /// ```
    /// use rmp::{Value, ValueRef};
    /// use rmp::value::Integer;
    ///
    /// let val = ValueRef::Array(vec![
    ///    ValueRef::Nil,
    ///    ValueRef::Integer(Integer::U64(42)),
    ///    ValueRef::Array(vec![
    ///        ValueRef::String("le message"),
    ///    ])
    /// ]);
    ///
    /// let expected = Value::Array(vec![
    ///     Value::Nil,
    ///     Value::Integer(Integer::U64(42)),
    ///     Value::Array(vec![
    ///         Value::String("le message".to_string())
    ///     ])
    /// ]);
    ///
    /// assert_eq!(expected, val.to_owned());
    /// ```
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_owned()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                Value::Array(val.iter().map(|v| v.to_owned()).collect())
            }
            &ValueRef::Map(ref val) => {
                Value::Map(val.iter().map(|&(ref k, ref v)| (k.to_owned(), v.to_owned())).collect())
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<|endoftext|>


<commit_before>//! Contains Value and ValueRef structs and its conversion traits.

use std::convert::From;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

impl Value {
    /// Returns true if the `Value` is a Null. Returns false otherwise.
    pub fn is_nil(&self) -> bool {
        if let Value::Nil = *self {
            true
        } else {
            false
        }
    }

    /// If the `Value` is a Boolean, returns the associated bool.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    ///
    /// assert_eq!(Some(true), Value::Boolean(true).as_bool());
    /// assert_eq!(None, Value::Nil.as_bool());
    /// ```
    pub fn as_bool(&self) -> Option<bool> {
        if let Value::Boolean(val) = *self {
            Some(val)
        } else {
            None
        }
    }

    /// If the `Value` is an integer, return or cast it to a i64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42i64), Value::Integer(Integer::I64(42)).as_i64());
    /// assert_eq!(Some(42i64), Value::Integer(Integer::U64(42)).as_i64());
    ///
    /// assert_eq!(None, Value::Float(Float::F64(42.0)).as_i64());
    /// ```
    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::Integer(Integer::I64(n)) => Some(n),
            Value::Integer(Integer::U64(n)) if n <= i64::max_value() as u64 => Some(n as i64),
            _ => None,
        }
    }
}

impl From<bool> for Value {
    fn from(v: bool) -> Value {
        Value::Boolean(v)
    }
}

impl From<u8> for Value {
    fn from(v: u8) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u16> for Value {
    fn from(v: u16) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u32> for Value {
    fn from(v: u32) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u64> for Value {
    fn from(v: u64) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<usize> for Value {
    fn from(v: usize) -> Value {
        Value::Integer(Integer::U64(v as u64))
    }
}

impl From<i8> for Value {
    fn from(v: i8) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i16> for Value {
    fn from(v: i16) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i32> for Value {
    fn from(v: i32) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i64> for Value {
    fn from(v: i64) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<isize> for Value {
    fn from(v: isize) -> Value {
        Value::Integer(Integer::I64(v as i64))
    }
}

impl From<f32> for Value {
    fn from(v: f32) -> Value {
        Value::Float(Float::F32(v))
    }
}

impl From<f64> for Value {
    fn from(v: f64) -> Value {
        Value::Float(Float::F64(v))
    }
}

/// Implements human-readable value formatting.
impl ::std::fmt::Display for Value {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Integer(Integer::U64(val)) => write!(f, "{}", val),
            Value::Integer(Integer::I64(val)) => write!(f, "{}", val),
            Value::Float(Float::F32(val)) => write!(f, "{}", val),
            Value::Float(Float::F64(val)) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "\"{}\"", val),
            Value::Binary(ref val) => write!(f, "{:?}", val),
            Value::Array(ref vec) => {
                // TODO: This can be slower than naive implementation. Need benchmarks for more
                // information.
                let res = vec.iter()
                    .map(|val| format!("{}", val))
                    .collect::<Vec<String>>()
                    .join(", ");

                write!(f, "[{}]", res)
            }
            Value::Map(ref vec) => {
                try!(write!(f, "{{"));

                match vec.iter().take(1).next() {
                    Some(&(ref k, ref v)) => {
                        try!(write!(f, "{}: {}", k, v));
                    }
                    None => {
                        try!(write!(f, ""));
                    }
                }

                for &(ref k, ref v) in vec.iter().skip(1) {
                    try!(write!(f, ", {}: {}", k, v));
                }

                write!(f, "}}")
            }
            Value::Ext(ty, ref data) => {
                write!(f, "[{}, {:?}]", ty, data)
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(&'a str),
    /// Binary extending Raw type represents a byte array.
    Binary(&'a [u8]),
    /// Array represents a sequence of objects.
    Array(Vec<ValueRef<'a>>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to an owned Value.
    ///
    /// This is achieved by deep copying all underlying structures and borrowed buffers.
    ///
    /// # Panics
    ///
    /// Panics in unable to allocate memory to keep all internal structures and buffers.
    ///
    /// # Examples
    /// ```
    /// use rmp::{Value, ValueRef};
    /// use rmp::value::Integer;
    ///
    /// let val = ValueRef::Array(vec![
    ///    ValueRef::Nil,
    ///    ValueRef::Integer(Integer::U64(42)),
    ///    ValueRef::Array(vec![
    ///        ValueRef::String("le message"),
    ///    ])
    /// ]);
    ///
    /// let expected = Value::Array(vec![
    ///     Value::Nil,
    ///     Value::Integer(Integer::U64(42)),
    ///     Value::Array(vec![
    ///         Value::String("le message".to_string())
    ///     ])
    /// ]);
    ///
    /// assert_eq!(expected, val.to_owned());
    /// ```
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_owned()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                Value::Array(val.iter().map(|v| v.to_owned()).collect())
            }
            &ValueRef::Map(ref val) => {
                Value::Map(val.iter().map(|&(ref k, ref v)| (k.to_owned(), v.to_owned())).collect())
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<commit_msg>feat: add as u64 conversion<commit_after>//! Contains Value and ValueRef structs and its conversion traits.

use std::convert::From;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

impl Value {
    /// Returns true if the `Value` is a Null. Returns false otherwise.
    pub fn is_nil(&self) -> bool {
        if let Value::Nil = *self {
            true
        } else {
            false
        }
    }

    /// If the `Value` is a Boolean, returns the associated bool.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    ///
    /// assert_eq!(Some(true), Value::Boolean(true).as_bool());
    /// assert_eq!(None, Value::Nil.as_bool());
    /// ```
    pub fn as_bool(&self) -> Option<bool> {
        if let Value::Boolean(val) = *self {
            Some(val)
        } else {
            None
        }
    }

    /// If the `Value` is an integer, return or cast it to a i64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42i64), Value::Integer(Integer::I64(42)).as_i64());
    /// assert_eq!(Some(42i64), Value::Integer(Integer::U64(42)).as_i64());
    ///
    /// assert_eq!(None, Value::Float(Float::F64(42.0)).as_i64());
    /// ```
    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::Integer(Integer::I64(n)) => Some(n),
            Value::Integer(Integer::U64(n)) if n <= i64::max_value() as u64 => Some(n as i64),
            _ => None,
        }
    }

    /// If the `Value` is an integer, return or cast it to a u64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42u64), Value::Integer(Integer::I64(42)).as_u64());
    /// assert_eq!(Some(42u64), Value::Integer(Integer::U64(42)).as_u64());
    ///
    /// assert_eq!(None, Value::Integer(Integer::I64(-42)).as_u64());
    /// assert_eq!(None, Value::Float(Float::F64(42.0)).as_i64());
    /// ```
    pub fn as_u64(&self) -> Option<u64> {
        match *self {
            Value::Integer(Integer::I64(n)) if 0 <= n => Some(n as u64),
            Value::Integer(Integer::U64(n)) => Some(n),
            _ => None,
        }
    }
}

impl From<bool> for Value {
    fn from(v: bool) -> Value {
        Value::Boolean(v)
    }
}

impl From<u8> for Value {
    fn from(v: u8) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u16> for Value {
    fn from(v: u16) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u32> for Value {
    fn from(v: u32) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u64> for Value {
    fn from(v: u64) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<usize> for Value {
    fn from(v: usize) -> Value {
        Value::Integer(Integer::U64(v as u64))
    }
}

impl From<i8> for Value {
    fn from(v: i8) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i16> for Value {
    fn from(v: i16) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i32> for Value {
    fn from(v: i32) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i64> for Value {
    fn from(v: i64) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<isize> for Value {
    fn from(v: isize) -> Value {
        Value::Integer(Integer::I64(v as i64))
    }
}

impl From<f32> for Value {
    fn from(v: f32) -> Value {
        Value::Float(Float::F32(v))
    }
}

impl From<f64> for Value {
    fn from(v: f64) -> Value {
        Value::Float(Float::F64(v))
    }
}

/// Implements human-readable value formatting.
impl ::std::fmt::Display for Value {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Integer(Integer::U64(val)) => write!(f, "{}", val),
            Value::Integer(Integer::I64(val)) => write!(f, "{}", val),
            Value::Float(Float::F32(val)) => write!(f, "{}", val),
            Value::Float(Float::F64(val)) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "\"{}\"", val),
            Value::Binary(ref val) => write!(f, "{:?}", val),
            Value::Array(ref vec) => {
                // TODO: This can be slower than naive implementation. Need benchmarks for more
                // information.
                let res = vec.iter()
                    .map(|val| format!("{}", val))
                    .collect::<Vec<String>>()
                    .join(", ");

                write!(f, "[{}]", res)
            }
            Value::Map(ref vec) => {
                try!(write!(f, "{{"));

                match vec.iter().take(1).next() {
                    Some(&(ref k, ref v)) => {
                        try!(write!(f, "{}: {}", k, v));
                    }
                    None => {
                        try!(write!(f, ""));
                    }
                }

                for &(ref k, ref v) in vec.iter().skip(1) {
                    try!(write!(f, ", {}: {}", k, v));
                }

                write!(f, "}}")
            }
            Value::Ext(ty, ref data) => {
                write!(f, "[{}, {:?}]", ty, data)
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(&'a str),
    /// Binary extending Raw type represents a byte array.
    Binary(&'a [u8]),
    /// Array represents a sequence of objects.
    Array(Vec<ValueRef<'a>>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to an owned Value.
    ///
    /// This is achieved by deep copying all underlying structures and borrowed buffers.
    ///
    /// # Panics
    ///
    /// Panics in unable to allocate memory to keep all internal structures and buffers.
    ///
    /// # Examples
    /// ```
    /// use rmp::{Value, ValueRef};
    /// use rmp::value::Integer;
    ///
    /// let val = ValueRef::Array(vec![
    ///    ValueRef::Nil,
    ///    ValueRef::Integer(Integer::U64(42)),
    ///    ValueRef::Array(vec![
    ///        ValueRef::String("le message"),
    ///    ])
    /// ]);
    ///
    /// let expected = Value::Array(vec![
    ///     Value::Nil,
    ///     Value::Integer(Integer::U64(42)),
    ///     Value::Array(vec![
    ///         Value::String("le message".to_string())
    ///     ])
    /// ]);
    ///
    /// assert_eq!(expected, val.to_owned());
    /// ```
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_owned()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                Value::Array(val.iter().map(|v| v.to_owned()).collect())
            }
            &ValueRef::Map(ref val) => {
                Value::Map(val.iter().map(|&(ref k, ref v)| (k.to_owned(), v.to_owned())).collect())
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<|endoftext|>


<commit_before>pub struct Point {
  x: u8,
  y: u8
}
<commit_msg>Removed unused struct.<commit_after><|endoftext|>


<commit_before>//! Queue handling
//!
//! The queue handle and callback,
//! analagous to <http://netfilter.org/projects/libnetfilter_queue/doxygen/group__Queue.html>

use libc::*;
use std::mem;
use std::ptr::null;

use error::*;
use util::*;
use verdict::{PacketHandler, VerdictHandler};
use message::Message;
use lock::NFQ_LOCK as LOCK;

use ffi::*;

enum NFQCopyMode {
    NONE = 0,
    META = 1,
    PACKET = 2
}

/// The amount of data to be copied to userspace for each packet queued.
pub enum CopyMode {
    /// None
    None,
    /// Packet metadata only
    Metadata,
    /// If you copy the packet, you must also specify the size of the packet to copy
    Packet(u16)
}

extern fn queue_callback<A, F: PacketHandler<A>>(qh: *mut nfq_q_handle,
                               nfmsg: *mut nfgenmsg,
                               nfad: *mut nfq_data,
                               cdata: *mut c_void) -> c_int {

    let queue_ptr: *mut Queue<A, F> = unsafe { mem::transmute(cdata) };
    let queue: &mut Queue<A, F> = unsafe { as_mut(&queue_ptr).unwrap() };
    let message = Message::new(nfmsg, nfad);

    queue.callback.handle(qh, message.as_ref(), &mut queue.data) as c_int
}

/// A handle to an NFQueue queue
///
/// This is used to set queue-specific settings, such as copy-mode and max-length.
pub struct Queue<A, F: PacketHandler<A>> {
    ptr: *mut nfq_q_handle,
    data: A,
    callback: F
}

impl<A, F: PacketHandler<A>> Drop for Queue<A, F> {
    fn drop(&mut self) {
        let ret = unsafe { nfq_destroy_queue(self.ptr) };
        if ret != 0 {
            panic!("Failed to destroy nfq queue");
        }
    }
}

impl<A, F: PacketHandler<A>> Queue<A, F> {
    fn new(handle: *mut nfq_handle,
           queue_number: u16,
           data: A,
           packet_handler: F) -> Result<Box<Queue<A, F>>, Error> {
        let _lock = LOCK.lock().unwrap();

        let nfq_ptr: *const nfq_q_handle = null();
        let mut queue: Box<Queue<A, F>> = Box::new(Queue {
            ptr: nfq_ptr as *mut nfq_q_handle, // set after nfq_create_queue
            data: data,
            callback: packet_handler,
        });
        let queue_ptr: *mut Queue<A, F> = &mut *queue;

        let ptr = unsafe {
            nfq_create_queue(handle,
                             queue_number,
                             queue_callback::<A, F>,
                             mem::transmute(queue_ptr))
        };

        if ptr.is_null() {
            Err(error(Reason::CreateQueue, "Failed to create queue", None))
        } else {
            queue.ptr = ptr;
            Ok(queue)
        }
    }

    /// Set the copy-mode for this queue
    pub fn set_mode(&mut self, mode: CopyMode) -> Result<(), Error> {
        let copy_mode = match mode {
            CopyMode::None => NFQCopyMode::NONE,
            CopyMode::Metadata => NFQCopyMode::META,
            CopyMode::Packet(_) => NFQCopyMode::PACKET
        } as uint8_t;
        let range = match mode {
            CopyMode::Packet(r) => r,
            _ => 0
        } as uint16_t as uint32_t;

        let res = unsafe { nfq_set_mode(self.ptr, copy_mode, range) };
        if res != 0 {
            Err(error(Reason::SetQueueMode, "Failed to set queue mode", Some(res)))
        } else {
            Ok(())
        }
    }

    /// Set the max-length for this queue
    ///
    /// Once `length` packets are enqueued, packets will be dropped until enqueued packets are processed.
    pub fn set_max_length(&mut self, length: u32) -> Result<(), Error> {
        let res = unsafe { nfq_set_queue_maxlen(self.ptr, length) };
        if res != 0 {
            Err(error(Reason::SetQueueMaxlen, "Failed to set queue maxlen", Some(res)))
        } else {
            Ok(())
        }
    }
}

/// A builder for `Queue`
pub struct QueueBuilder<A> {
    ptr: *mut nfq_handle,
    queue_number: uint16_t,
    data: A
}

impl<A> QueueBuilder<A> {
    #[doc(hidden)]
    pub fn new(ptr: *mut nfq_handle, data: A) -> QueueBuilder<A> {
        QueueBuilder {
            ptr: ptr,
            queue_number: 0,
            data: data
        }
    }

    /// Set the queue from which the `Queue` will take packets
    pub fn queue_number(self, queue_number: u16) -> QueueBuilder<A> {
        QueueBuilder {
            ptr: self.ptr,
            queue_number: queue_number,
            data: self.data
        }
    }

    /// Create the `Queue` with the provided callback
    pub fn callback_and_finalize<F: PacketHandler<A>>(self, callback: F)
            -> Result<Box<Queue<A, F>>, Error> {
        Queue::new(self.ptr, self.queue_number, self.data, callback)
    }

    /// Create the `Queue` with the provided decider
    ///
    /// A decider is similar to a callback, except that the verdict must be set at the end of the fn.
    /// It is an abstraction suitable for most use cases.
    pub fn decider_and_finalize<F: PacketHandler<A> + VerdictHandler<A>>(self, decider: F)
            -> Result<Box<Queue<A, F>>, Error> {
        Queue::new(self.ptr, self.queue_number, self.data, decider)
    }
}
<commit_msg>Add mode and length to QueueBuilder<commit_after>//! Queue handling
//!
//! The queue handle and callback,
//! analagous to <http://netfilter.org/projects/libnetfilter_queue/doxygen/group__Queue.html>

use libc::*;
use std::mem;
use std::ptr::null;

use error::*;
use util::*;
use verdict::{PacketHandler, VerdictHandler};
use message::Message;
use lock::NFQ_LOCK as LOCK;

use ffi::*;

enum NFQCopyMode {
    NONE = 0,
    META = 1,
    PACKET = 2
}

/// The amount of data to be copied to userspace for each packet queued.
pub enum CopyMode {
    /// None
    None,
    /// Packet metadata only
    Metadata,
    /// If you copy the packet, you must also specify the size of the packet to copy
    Packet(u16)
}

extern fn queue_callback<A, F: PacketHandler<A>>(qh: *mut nfq_q_handle,
                               nfmsg: *mut nfgenmsg,
                               nfad: *mut nfq_data,
                               cdata: *mut c_void) -> c_int {

    let queue_ptr: *mut Queue<A, F> = unsafe { mem::transmute(cdata) };
    let queue: &mut Queue<A, F> = unsafe { as_mut(&queue_ptr).unwrap() };
    let message = Message::new(nfmsg, nfad);

    queue.callback.handle(qh, message.as_ref(), &mut queue.data) as c_int
}

/// A handle to an NFQueue queue
///
/// This is used to set queue-specific settings, such as copy-mode and max-length.
pub struct Queue<A, F: PacketHandler<A>> {
    ptr: *mut nfq_q_handle,
    data: A,
    callback: F
}

impl<A, F: PacketHandler<A>> Drop for Queue<A, F> {
    fn drop(&mut self) {
        let ret = unsafe { nfq_destroy_queue(self.ptr) };
        if ret != 0 {
            panic!("Failed to destroy nfq queue");
        }
    }
}

impl<A, F: PacketHandler<A>> Queue<A, F> {
    fn new(builder: QueueBuilder<A>, packet_handler: F) -> Result<Box<Queue<A, F>>, Error> {
        let _lock = LOCK.lock().unwrap();

        let nfq_ptr: *const nfq_q_handle = null();
        let mut queue: Box<Queue<A, F>> = Box::new(Queue {
            ptr: nfq_ptr as *mut nfq_q_handle, // set after nfq_create_queue
            data: builder.data,
            callback: packet_handler,
        });
        let queue_ptr: *mut Queue<A, F> = &mut *queue;

        let ptr = unsafe {
            nfq_create_queue(builder.ptr,
                             builder.queue_number,
                             queue_callback::<A, F>,
                             mem::transmute(queue_ptr))
        };

        if ptr.is_null() {
            return Err(error(Reason::CreateQueue, "Failed to create queue", None));
        } else {
            queue.ptr = ptr;
        }

        match builder.copy_mode {
            Some(cm) => try!(queue.set_mode(cm)),
            None => ()
        }

        match builder.max_length {
            Some(ml) => try!(queue.set_max_length(ml)),
            None => ()
        }

        Ok(queue)
    }

    /// Set the copy-mode for this queue
    pub fn set_mode(&mut self, mode: CopyMode) -> Result<(), Error> {
        let copy_mode = match mode {
            CopyMode::None => NFQCopyMode::NONE,
            CopyMode::Metadata => NFQCopyMode::META,
            CopyMode::Packet(_) => NFQCopyMode::PACKET
        } as uint8_t;
        let range = match mode {
            CopyMode::Packet(r) => r,
            _ => 0
        } as uint16_t as uint32_t;

        let res = unsafe { nfq_set_mode(self.ptr, copy_mode, range) };
        if res != 0 {
            Err(error(Reason::SetQueueMode, "Failed to set queue mode", Some(res)))
        } else {
            Ok(())
        }
    }

    /// Set the max-length for this queue
    ///
    /// Once `length` packets are enqueued, packets will be dropped until enqueued packets are processed.
    pub fn set_max_length(&mut self, length: u32) -> Result<(), Error> {
        let res = unsafe { nfq_set_queue_maxlen(self.ptr, length) };
        if res != 0 {
            Err(error(Reason::SetQueueMaxlen, "Failed to set queue maxlen", Some(res)))
        } else {
            Ok(())
        }
    }
}

/// A builder for `Queue`
pub struct QueueBuilder<A> {
    ptr: *mut nfq_handle,
    queue_number: uint16_t,
    copy_mode: Option<CopyMode>,
    max_length: Option<u32>,
    data: A
}

impl<A> QueueBuilder<A> {
    #[doc(hidden)]
    pub fn new(ptr: *mut nfq_handle, data: A) -> QueueBuilder<A> {
        QueueBuilder {
            ptr: ptr,
            queue_number: 0,
            copy_mode: None,
            max_length: None,
            data: data
        }
    }

    /// Set the queue from which the `Queue` will take packets
    pub fn queue_number(self, queue_number: u16) -> QueueBuilder<A> {
        QueueBuilder {
            ptr: self.ptr,
            queue_number: queue_number,
            copy_mode: self.copy_mode,
            max_length: self.max_length,
            data: self.data
        }
    }

    /// Set the copy-mode for the `Queue`
    ///
    /// Note that this can be changed later through the `Queue`'s methods
    pub fn copy_mode(self, copy_mode: CopyMode) -> QueueBuilder<A> {
        QueueBuilder {
            ptr: self.ptr,
            queue_number: self.queue_number,
            copy_mode: Some(copy_mode),
            max_length: self.max_length,
            data: self.data
        }
    }

    /// Set the max-length for the `Queue`
    ///
    /// Note that this can be changed later through the `Queue`'s methods
    pub fn max_length(self, max_length: u32) -> QueueBuilder<A> {
        QueueBuilder {
            ptr: self.ptr,
            queue_number: self.queue_number,
            copy_mode: self.copy_mode,
            max_length: Some(max_length),
            data: self.data
        }
    }

    /// Create the `Queue` with the provided callback
    pub fn callback_and_finalize<F: PacketHandler<A>>(self, callback: F)
            -> Result<Box<Queue<A, F>>, Error> {
        Queue::new(self, callback)
    }

    /// Create the `Queue` with the provided decider
    ///
    /// A decider is similar to a callback, except that the verdict must be set at the end of the fn.
    /// It is an abstraction suitable for most use cases.
    pub fn decider_and_finalize<F: PacketHandler<A> + VerdictHandler<A>>(self, decider: F)
            -> Result<Box<Queue<A, F>>, Error> {
        Queue::new(self, decider)
    }
}
<|endoftext|>


<commit_before>use buffer::{Buffer, Direction, Mark};
use input::Input;
use uibuf::{UIBuffer, CharColor};
use frontends::Frontend;

/// A View is an abstract Window (into a Buffer).
///
/// It draws a portion of a Buffer to a UIBuffer which in turn is drawn to the
/// screen. It maintains the status bar for the current view, the "dirty status"
/// which is whether the buffer has been modified or not and a number of other
/// pieces of information.
pub struct View<'v> {
    pub buffer: Buffer,     //Text buffer
    top_line: Mark,         //First character of the top line to be displayed.
    left_col: uint,         //Index into the top line to set the left column to.
    cursor: Mark,           //Cursor displayed by this buffer.
    uibuf: UIBuffer,        //UIBuffer
}

impl<'v> View<'v> {

    //----- CONSTRUCTORS ---------------------------------------------------------------------------

    pub fn new(source: Input, width: uint, height: uint) -> View<'v> {
        let mut buffer = match source {
            Input::Filename(path) => {
                match path {
                    Some(s) => Buffer::new_from_file(Path::new(s)),
                    None    => Buffer::new(),
                }
            },
            Input::Stdin(reader) => {
                Buffer::new_from_reader(reader)
            },
        };

        // NOTE(greg): this may not play well with resizing
        let uibuf = UIBuffer::new(width, height);

        let cursor = Mark::Cursor(0);
        buffer.set_mark(cursor, 0);
        let top_line = Mark::DisplayMark(0);
        buffer.set_mark(top_line, 0);

        View {
            buffer: buffer,
            top_line: top_line,
            left_col: 0,
            cursor: cursor,
            uibuf: uibuf,
        }
    }

    pub fn get_height(&self) -> uint {
        // NOTE(greg): when the status bar needs to move up, this value should be changed
        self.uibuf.get_height() -1
    }

    pub fn get_width(&self) -> uint {
        self.uibuf.get_width()
    }

    //----- DRAWING METHODS ------------------------------------------------------------------------
    /// Clear the buffer
    ///
    /// Fills every cell in the UIBuffer with the space (' ') char.
    pub fn clear<T: Frontend>(&mut self, frontend: &mut T) {
        self.uibuf.fill(' ');
        self.uibuf.draw_everything(frontend);
    }

    pub fn draw<T: Frontend>(&mut self, frontend: &mut T) {
        for (index,line) in self.buffer
                                .lines_from(self.top_line)
                                .unwrap()
                                .take(self.get_height())
                                .enumerate() {
            draw_line(&mut self.uibuf, line, index, self.left_col);
            if index == self.get_height() { break; }
        }
        self.uibuf.draw_everything(frontend);
    }

    pub fn draw_status<T: Frontend>(&mut self, frontend: &mut T) {
        let buffer_status = self.buffer.status_text();
        let mut cursor_status = self.buffer.get_mark_coords(self.cursor).unwrap_or((0,0));
        cursor_status = (cursor_status.0 + 1, cursor_status.1 + 1);
        let status_text = format!("{} {}", buffer_status, cursor_status).into_bytes();
        let status_text_len = status_text.len();
        let width = self.get_width();
        let height = self.get_height();

        for index in range(0, width) {
            let mut ch: char = ' ';
            if index < status_text_len {
                ch = status_text[index] as char;
            }
            self.uibuf.update_cell(index, height, ch, CharColor::Black, CharColor::Blue);
        }

        self.uibuf.draw_range(frontend, height, height+1);
    }

    pub fn draw_cursor<T: Frontend>(&mut self, frontend: &mut T) {
        if let Some((x, y)) = self.buffer.get_mark_coords(self.cursor) {
            frontend.draw_cursor(x as int, y as int);
        }
    }

    pub fn resize<T: Frontend>(&mut self, frontend: &mut T) {
        let width = self.uibuf.get_width();
        self.clear(frontend);
        self.uibuf = UIBuffer::new(width, 15);
    }

    //----- CURSOR METHODS -------------------------------------------------------------------------

    pub fn move_cursor(&mut self, direction: Direction) {
        self.buffer.shift_mark(self.cursor, direction);
        self.move_screen();
    }

    pub fn move_cursor_to_line_end(&mut self) {
        self.buffer.shift_mark(self.cursor, Direction::LineEnd);
        self.move_screen();
    }

    pub fn move_cursor_to_line_start(&mut self) {
        self.buffer.shift_mark(self.cursor, Direction::LineStart);
        self.move_screen();
    }

    //Update the top_line mark if necessary to keep the cursor on the screen.
    fn move_screen(&mut self) {
        if let (Some(cursor), Some(top_line)) = (self.buffer.get_mark_coords(self.cursor),
                                                 self.buffer.get_mark_coords(self.top_line)) {
            match cursor.0 as int - self.left_col as int {
                x if x < 0 => { self.left_col -= x as uint; }
                x if x > self.get_width() as int => { self.left_col += x as uint - self.get_width()}
                _ => { }
            }
            match cursor.1 as int - top_line.1 as int {
                y if y < 0 => { self.buffer.shift_mark(self.top_line, Direction::Up(y as uint)); }
                y if y > self.get_height() as int => {
                    let height = self.get_height();
                    self.buffer.shift_mark(self.top_line, Direction::Down(y as uint - height));
                }
                _ => { }
            }
        }
    }

    //----- TEXT EDIT METHODS ----------------------------------------------------------------------

    pub fn delete_char(&mut self, direction: Direction) {
        match direction {
            Direction::Left(1) if self.buffer.get_mark_idx(self.cursor) != Some(0) => {
                self.move_cursor(direction);
                self.buffer.remove_char(self.cursor);
            }
            Direction::Right(1) if self.buffer.get_mark_idx(self.cursor) != Some(self.buffer.len()) => {
                self.buffer.remove_char(self.cursor);
            }
            _ => {}
        }
    }

    pub fn insert_tab(&mut self) {
        // A tab is just 4 spaces
        for _ in range(0i, 4) {
            self.insert_char(' ');
        }
    }

    pub fn insert_char(&mut self, ch: char) {
        self.buffer.insert_char(self.cursor, ch as u8);
        self.move_cursor(Direction::Right(1))
    }

    pub fn undo(&mut self) {
        let point = if let Some(transaction) = self.buffer.undo() { transaction.end_point }
                    else { return; };
        self.buffer.set_mark(self.cursor, point);
    }

    pub fn redo(&mut self) {
        let point = if let Some(transaction) = self.buffer.redo() { transaction.end_point }
                    else { return; };
        self.buffer.set_mark(self.cursor, point);
    }

}

pub fn draw_line(buf: &mut UIBuffer, line: &[u8], idx: uint, left: uint) {
    let width = buf.get_width() - 1;
    let mut wide_chars = 0;
    for line_idx in range(left, left + width) {
        if line_idx < line.len() {
            match line[line_idx] {
                b'\t'   => {
                    let w = 4 - line_idx % 4;
                    for _ in range(0, w) {
                        buf.update_cell_content(line_idx + wide_chars - left, idx, ' ');
                    }
                }
                b'\n'   => buf.update_cell_content(line_idx + wide_chars - left, idx, ' '),
                _       => buf.update_cell_content(line_idx + wide_chars - left, idx,
                                                   line[line_idx] as char),
            }
            wide_chars += (line[line_idx] as char).width(false).unwrap_or(1) - 1;
        } else { buf.update_cell_content(line_idx + wide_chars - left, idx, ' '); }
    }
    if line.len() >= width {
        buf.update_cell_content(width + wide_chars, idx, '→');
    }

}

#[cfg(test)]
mod tests {

    use buffer::Direction;
    use view::View;
    use input::Input;

    fn setup_view<'v>(testcase: &'static str) -> View<'v> {
        let mut view = View::new(Input::Filename(None), 50, 50);
        for ch in testcase.chars() {
            view.insert_char(ch);
        }
        view.buffer.set_mark(view.cursor, 0);
        view
    }

    #[test]
    fn test_move_cursor_down() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down(1));
        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap().1, 1);
        assert_eq!(view.buffer.lines_from(view.cursor).unwrap().next().unwrap(), b"second"[]);
    }

    #[test]
    fn test_move_cursor_up() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down(1));
        view.move_cursor(Direction::Up(1));
        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap().1, 0);
        assert_eq!(view.buffer.lines_from(view.cursor).unwrap().next().unwrap(), b"test\n"[]);
    }

    #[test]
    fn test_insert_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right(1));
        view.insert_char('\n');

        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap(), (0, 1))
    }

    #[test]
    fn test_insert_char() {
        let mut view = setup_view("test\nsecond");
        view.insert_char('t');

        assert_eq!(view.buffer.lines().next().unwrap(), b"ttest\n"[]);
    }

    #[test]
    fn test_delete_char_to_right() {
        let mut view = setup_view("test\nsecond");
        view.delete_char(Direction::Right(1));

        assert_eq!(view.buffer.lines().next().unwrap(), b"est\n"[]);
    }

    #[test]
    fn test_delete_char_to_left() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right(1));
        view.delete_char(Direction::Left(1));

        assert_eq!(view.buffer.lines().next().unwrap(), b"est\n"[]);
    }

    #[test]
    fn test_delete_char_at_start_of_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down(1));
        view.delete_char(Direction::Left(1));

        assert_eq!(view.buffer.lines().next().unwrap(), b"testsecond"[]);
    }

    #[test]
    fn test_delete_char_at_end_of_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right(4));
        view.delete_char(Direction::Right(1));

        assert_eq!(view.buffer.lines().next().unwrap(), b"testsecond"[]);
    }

    #[test]
    fn deleting_backward_at_start_of_first_line_does_nothing() {
        let mut view = setup_view("test\nsecond");
        view.delete_char(Direction::Left(1));

        let lines: Vec<&[u8]> = view.buffer.lines().collect();

        assert_eq!(lines.len(), 2);
        assert_eq!(view.buffer.lines().next().unwrap(), b"test\n");
    }
}
<commit_msg>Fixed vertical scrolling<commit_after>use buffer::{Buffer, Direction, Mark};
use input::Input;
use uibuf::{UIBuffer, CharColor};
use frontends::Frontend;

/// A View is an abstract Window (into a Buffer).
///
/// It draws a portion of a Buffer to a UIBuffer which in turn is drawn to the
/// screen. It maintains the status bar for the current view, the "dirty status"
/// which is whether the buffer has been modified or not and a number of other
/// pieces of information.
pub struct View<'v> {
    pub buffer: Buffer,     //Text buffer
    top_line: Mark,         //First character of the top line to be displayed.
    left_col: uint,         //Index into the top line to set the left column to.
    cursor: Mark,           //Cursor displayed by this buffer.
    uibuf: UIBuffer,        //UIBuffer
}

impl<'v> View<'v> {

    //----- CONSTRUCTORS ---------------------------------------------------------------------------

    pub fn new(source: Input, width: uint, height: uint) -> View<'v> {
        let mut buffer = match source {
            Input::Filename(path) => {
                match path {
                    Some(s) => Buffer::new_from_file(Path::new(s)),
                    None    => Buffer::new(),
                }
            },
            Input::Stdin(reader) => {
                Buffer::new_from_reader(reader)
            },
        };

        // NOTE(greg): this may not play well with resizing
        let uibuf = UIBuffer::new(width, height);

        let cursor = Mark::Cursor(0);
        buffer.set_mark(cursor, 0);
        let top_line = Mark::DisplayMark(0);
        buffer.set_mark(top_line, 0);

        View {
            buffer: buffer,
            top_line: top_line,
            left_col: 0,
            cursor: cursor,
            uibuf: uibuf,
        }
    }

    pub fn get_height(&self) -> uint {
        // NOTE(greg): when the status bar needs to move up, this value should be changed
        self.uibuf.get_height() -1
    }

    pub fn get_width(&self) -> uint {
        self.uibuf.get_width()
    }

    //----- DRAWING METHODS ------------------------------------------------------------------------
    /// Clear the buffer
    ///
    /// Fills every cell in the UIBuffer with the space (' ') char.
    pub fn clear<T: Frontend>(&mut self, frontend: &mut T) {
        self.uibuf.fill(' ');
        self.uibuf.draw_everything(frontend);
    }

    pub fn draw<T: Frontend>(&mut self, frontend: &mut T) {
        for (index,line) in self.buffer
                                .lines_from(self.top_line)
                                .unwrap()
                                .take(self.get_height())
                                .enumerate() {
            draw_line(&mut self.uibuf, line, index, self.left_col);
            if index == self.get_height() { break; }
        }
        self.uibuf.draw_everything(frontend);
    }

    pub fn draw_status<T: Frontend>(&mut self, frontend: &mut T) {
        let buffer_status = self.buffer.status_text();
        let mut cursor_status = self.buffer.get_mark_coords(self.cursor).unwrap_or((0,0));
        cursor_status = (cursor_status.0 + 1, cursor_status.1 + 1);
        let status_text = format!("{} {}", buffer_status, cursor_status).into_bytes();
        let status_text_len = status_text.len();
        let width = self.get_width();
        let height = self.get_height();

        for index in range(0, width) {
            let mut ch: char = ' ';
            if index < status_text_len {
                ch = status_text[index] as char;
            }
            self.uibuf.update_cell(index, height, ch, CharColor::Black, CharColor::Blue);
        }

        self.uibuf.draw_range(frontend, height, height+1);
    }

    pub fn draw_cursor<T: Frontend>(&mut self, frontend: &mut T) {
        if let Some(top_line) = self.buffer.get_mark_coords(self.top_line) {
            if let Some((x, y)) = self.buffer.get_mark_coords(self.cursor) {
                frontend.draw_cursor(x as int, y as int - top_line.1 as int);
            }
        }
    }

    pub fn resize<T: Frontend>(&mut self, frontend: &mut T) {
        let width = self.uibuf.get_width();
        self.clear(frontend);
        self.uibuf = UIBuffer::new(width, 15);
    }

    //----- CURSOR METHODS -------------------------------------------------------------------------

    pub fn move_cursor(&mut self, direction: Direction) {
        self.buffer.shift_mark(self.cursor, direction);
        self.move_screen();
    }

    pub fn move_cursor_to_line_end(&mut self) {
        self.buffer.shift_mark(self.cursor, Direction::LineEnd);
        self.move_screen();
    }

    pub fn move_cursor_to_line_start(&mut self) {
        self.buffer.shift_mark(self.cursor, Direction::LineStart);
        self.move_screen();
    }

    //Update the top_line mark if necessary to keep the cursor on the screen.
    fn move_screen(&mut self) {
        if let (Some(cursor), Some(top_line)) = (self.buffer.get_mark_coords(self.cursor),
                                                 self.buffer.get_mark_coords(self.top_line)) {
            // FIXME
            // match cursor.0 as int - self.left_col as int {
            //     x if x < 0 => { self.left_col -= x as uint; }
            //     x if x > self.get_width() as int => { self.left_col += x as uint - self.get_width()}
            //     _ => { }
            // }

            let cursor_linenum = cursor.1 as int;
            let cursor_offset = cursor_linenum - top_line.1 as int;
            let height = self.get_height() as int;

            if cursor_offset >= (height - 5) {
                // moving down
                let times = cursor_offset - (height - 5) + 1;
                self.buffer.shift_mark(self.top_line, Direction::Down(times as uint));
            } else if cursor_offset < 5 {
                // moving up
                self.buffer.shift_mark(self.top_line, Direction::Up(1));
            }
        }
    }

    //----- TEXT EDIT METHODS ----------------------------------------------------------------------

    pub fn delete_char(&mut self, direction: Direction) {
        match direction {
            Direction::Left(1) if self.buffer.get_mark_idx(self.cursor) != Some(0) => {
                self.move_cursor(direction);
                self.buffer.remove_char(self.cursor);
            }
            Direction::Right(1) if self.buffer.get_mark_idx(self.cursor) != Some(self.buffer.len()) => {
                self.buffer.remove_char(self.cursor);
            }
            _ => {}
        }
    }

    pub fn insert_tab(&mut self) {
        // A tab is just 4 spaces
        for _ in range(0i, 4) {
            self.insert_char(' ');
        }
    }

    pub fn insert_char(&mut self, ch: char) {
        self.buffer.insert_char(self.cursor, ch as u8);
        self.move_cursor(Direction::Right(1))
    }

    pub fn undo(&mut self) {
        let point = if let Some(transaction) = self.buffer.undo() { transaction.end_point }
                    else { return; };
        self.buffer.set_mark(self.cursor, point);
    }

    pub fn redo(&mut self) {
        let point = if let Some(transaction) = self.buffer.redo() { transaction.end_point }
                    else { return; };
        self.buffer.set_mark(self.cursor, point);
    }

}

pub fn draw_line(buf: &mut UIBuffer, line: &[u8], idx: uint, left: uint) {
    let width = buf.get_width() - 1;
    let mut wide_chars = 0;
    for line_idx in range(left, left + width) {
        if line_idx < line.len() {
            match line[line_idx] {
                b'\t'   => {
                    let w = 4 - line_idx % 4;
                    for _ in range(0, w) {
                        buf.update_cell_content(line_idx + wide_chars - left, idx, ' ');
                    }
                }
                b'\n'   => buf.update_cell_content(line_idx + wide_chars - left, idx, ' '),
                _       => buf.update_cell_content(line_idx + wide_chars - left, idx,
                                                   line[line_idx] as char),
            }
            wide_chars += (line[line_idx] as char).width(false).unwrap_or(1) - 1;
        } else { buf.update_cell_content(line_idx + wide_chars - left, idx, ' '); }
    }
    if line.len() >= width {
        buf.update_cell_content(width + wide_chars, idx, '→');
    }

}

#[cfg(test)]
mod tests {

    use buffer::Direction;
    use view::View;
    use input::Input;

    fn setup_view<'v>(testcase: &'static str) -> View<'v> {
        let mut view = View::new(Input::Filename(None), 50, 50);
        for ch in testcase.chars() {
            view.insert_char(ch);
        }
        view.buffer.set_mark(view.cursor, 0);
        view
    }

    #[test]
    fn test_move_cursor_down() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down(1));
        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap().1, 1);
        assert_eq!(view.buffer.lines_from(view.cursor).unwrap().next().unwrap(), b"second"[]);
    }

    #[test]
    fn test_move_cursor_up() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down(1));
        view.move_cursor(Direction::Up(1));
        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap().1, 0);
        assert_eq!(view.buffer.lines_from(view.cursor).unwrap().next().unwrap(), b"test\n"[]);
    }

    #[test]
    fn test_insert_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right(1));
        view.insert_char('\n');

        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap(), (0, 1))
    }

    #[test]
    fn test_insert_char() {
        let mut view = setup_view("test\nsecond");
        view.insert_char('t');

        assert_eq!(view.buffer.lines().next().unwrap(), b"ttest\n"[]);
    }

    #[test]
    fn test_delete_char_to_right() {
        let mut view = setup_view("test\nsecond");
        view.delete_char(Direction::Right(1));

        assert_eq!(view.buffer.lines().next().unwrap(), b"est\n"[]);
    }

    #[test]
    fn test_delete_char_to_left() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right(1));
        view.delete_char(Direction::Left(1));

        assert_eq!(view.buffer.lines().next().unwrap(), b"est\n"[]);
    }

    #[test]
    fn test_delete_char_at_start_of_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down(1));
        view.delete_char(Direction::Left(1));

        assert_eq!(view.buffer.lines().next().unwrap(), b"testsecond"[]);
    }

    #[test]
    fn test_delete_char_at_end_of_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right(4));
        view.delete_char(Direction::Right(1));

        assert_eq!(view.buffer.lines().next().unwrap(), b"testsecond"[]);
    }

    #[test]
    fn deleting_backward_at_start_of_first_line_does_nothing() {
        let mut view = setup_view("test\nsecond");
        view.delete_char(Direction::Left(1));

        let lines: Vec<&[u8]> = view.buffer.lines().collect();

        assert_eq!(lines.len(), 2);
        assert_eq!(view.buffer.lines().next().unwrap(), b"test\n");
    }
}
<|endoftext|>


<commit_before>use alpha::Alpha;
use cipher;
use cipher::Cipher;
use cipher::CipherChar;

/// A Rotor implements an arbitrary substitution cipher using wires connecting the 26 inputs to the 26 outputs.
///
/// Each Rotor has an outer ring, and a core with the internal wiring.
///
/// The outer ring has each letter of the alphabet written on it. One of these letters will be visible in the window of the Enigma machine. As a message is being typed, the rotors rotate or 'step', changing which letter is visible. The visible letter is known as the 'window position'.
///
/// The Rotor's inner core can also be rotated with respect to the outer ring. This rotation is known as the 'ring setting' or 'Ringstellung'.
///
/// These two rotations affect the position of the internal wiring.
///
/// There also is a notch set into the outer ring, which affects when the Rotors 'turnover'.
///
/// This Rotor implementation is immutable. It does not keep track of its own rotation within the Enigma machine (the window position).
pub struct Rotor {
    wiring: Cipher,
    inverse_wiring: Cipher,

    ring_setting: CipherChar,
    notch_position: CipherChar,
}

impl Rotor {
    fn new(wiring: Cipher, notch_position: CipherChar, ring_setting: CipherChar) -> Rotor {
        Rotor {
            wiring: wiring,
            inverse_wiring: Rotor::inverse_wiring(wiring),

            notch_position: notch_position,
            ring_setting: ring_setting,
        }
    }

    pub fn sub(&self, c: CipherChar) -> CipherChar {
        (self.wiring[(c + self.ring_setting) % 26] + 26 - self.ring_setting) % 26
    }

    pub fn inverse_sub(&self, c: CipherChar) -> CipherChar {
        (self.inverse_wiring[(c + self.ring_setting) % 26] + 26 - self.ring_setting) % 26
    }

    pub fn notch_engaged(&self, window_position: CipherChar) -> bool {
        (self.notch_position + 18) % 26 == window_position
    }

    fn inverse_wiring(wiring: Cipher) -> Cipher {
        let mut inverse = [0; 26];
        for (i, v) in wiring.into_iter().enumerate() {
            inverse[*v] = i;
        }
        inverse
    }
}

pub struct RotorFactory {
    wiring: Cipher,
    notch_position: CipherChar,
}

impl RotorFactory {
    pub fn with_ring_setting(&self, ring_setting: Alpha) -> Rotor {
        Rotor::new(self.wiring, self.notch_position, usize::from(ring_setting))
    }
}

pub struct Rotors {
    pub i: RotorFactory,
    pub ii: RotorFactory,
    pub iii: RotorFactory,
    pub iv: RotorFactory,
    pub v: RotorFactory,
}

impl Default for Rotors {
    fn default() -> Self {
        Rotors {
            i: RotorFactory {
                wiring: cipher::from_string("EKMFLGDQVZNTOWYHXUSPAIBRCJ"),
                notch_position: cipher::from_char('Y'),
            },
            ii: RotorFactory {
                wiring: cipher::from_string("AJDKSIRUXBLHWTMCQGZNPYFVOE"),
                notch_position: cipher::from_char('M'),
            },
            iii: RotorFactory {
                wiring: cipher::from_string("BDFHJLCPRTXVZNYEIWGAKMUSQO"),
                notch_position: cipher::from_char('D'),
            },
            iv: RotorFactory {
                wiring: cipher::from_string("ESOVPZJAYQUIRHXLNFTGKDCMWB"),
                notch_position: cipher::from_char('R'),
            },
            v: RotorFactory {
                wiring: cipher::from_string("VZBRGITYUPSDNHLXAWMJQOFECK"),
                notch_position: cipher::from_char('H'),
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cipher as Cipher;
    use cipher::from_char as CC;

    #[test]
    fn noop_rotor() {
        let wiring = Cipher::from_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        let rotor = Rotor::new(wiring, CC('A'), CC('A'));

        assert_eq!(CC('A'), rotor.sub(CC('A')));
        assert_eq!(CC('A'), rotor.inverse_sub(CC('A')));
    }

    #[test]
    fn ring_position() {
        let wiring = Cipher::from_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        let rotor = Rotor::new(wiring, CC('A'), CC('B'));

        assert_eq!(CC('A'), rotor.sub(CC('A')));
        assert_eq!(CC('A'), rotor.inverse_sub(CC('A')));
    }

    #[test]
    fn a_b_flip() {
        let wiring = Cipher::from_string("BACDEFGHIJKLMNOPQRSTUVWXYZ");
        let rotor = Rotor::new(wiring, CC('A'), CC('A'));

        assert_eq!(CC('B'), rotor.sub(CC('A')));
        assert_eq!(CC('A'), rotor.sub(CC('B')));
        assert_eq!(CC('Z'), rotor.sub(CC('Z')));
        assert_eq!(CC('B'), rotor.inverse_sub(CC('A')));
        assert_eq!(CC('A'), rotor.inverse_sub(CC('B')));
        assert_eq!(CC('Z'), rotor.inverse_sub(CC('Z')));
    }

    #[test]
    fn a_b_flip_with_ring_position() {
        let wiring = Cipher::from_string("BACDEFGHIJKLMNOPQRSTUVWXYZ");
        let rotor = Rotor::new(wiring, CC('A'), CC('B'));

        assert_eq!(CC('Z'), rotor.sub(CC('A')));
        assert_eq!(CC('B'), rotor.sub(CC('B')));
        assert_eq!(CC('A'), rotor.sub(CC('Z')));
        assert_eq!(CC('Z'), rotor.inverse_sub(CC('A')));
        assert_eq!(CC('B'), rotor.inverse_sub(CC('B')));
        assert_eq!(CC('A'), rotor.inverse_sub(CC('Z')));
    }
}
<commit_msg>Fix doc line length<commit_after>use alpha::Alpha;
use cipher;
use cipher::Cipher;
use cipher::CipherChar;

/// A Rotor implements an arbitrary substitution cipher using wires connecting the 26 inputs to
/// the 26 outputs.
///
/// Each Rotor has an outer ring, and a core with the internal wiring.
///
/// The outer ring has each letter of the alphabet written on it. One of these letters will be
/// visible in the window of the Enigma machine. As a message is being typed, the rotors rotate or
/// 'step', changing which letter is visible. The visible letter is known as the 'window position'.
///
/// The Rotor's inner core can also be rotated with respect to the outer ring. This rotation is
/// known as the 'ring setting' or 'Ringstellung'.
///
/// These two rotations affect the position of the internal wiring.
///
/// There also is a notch set into the outer ring, which affects when the Rotors 'turnover'.
///
/// This Rotor implementation is immutable. It does not keep track of its own rotation within the
/// Enigma machine (the window position).
pub struct Rotor {
    wiring: Cipher,
    inverse_wiring: Cipher,

    ring_setting: CipherChar,
    notch_position: CipherChar,
}

impl Rotor {
    fn new(wiring: Cipher, notch_position: CipherChar, ring_setting: CipherChar) -> Rotor {
        Rotor {
            wiring: wiring,
            inverse_wiring: Rotor::inverse_wiring(wiring),

            notch_position: notch_position,
            ring_setting: ring_setting,
        }
    }

    pub fn sub(&self, c: CipherChar) -> CipherChar {
        (self.wiring[(c + self.ring_setting) % 26] + 26 - self.ring_setting) % 26
    }

    pub fn inverse_sub(&self, c: CipherChar) -> CipherChar {
        (self.inverse_wiring[(c + self.ring_setting) % 26] + 26 - self.ring_setting) % 26
    }

    pub fn notch_engaged(&self, window_position: CipherChar) -> bool {
        (self.notch_position + 18) % 26 == window_position
    }

    fn inverse_wiring(wiring: Cipher) -> Cipher {
        let mut inverse = [0; 26];
        for (i, v) in wiring.into_iter().enumerate() {
            inverse[*v] = i;
        }
        inverse
    }
}

pub struct RotorFactory {
    wiring: Cipher,
    notch_position: CipherChar,
}

impl RotorFactory {
    pub fn with_ring_setting(&self, ring_setting: Alpha) -> Rotor {
        Rotor::new(self.wiring, self.notch_position, usize::from(ring_setting))
    }
}

pub struct Rotors {
    pub i: RotorFactory,
    pub ii: RotorFactory,
    pub iii: RotorFactory,
    pub iv: RotorFactory,
    pub v: RotorFactory,
}

impl Default for Rotors {
    fn default() -> Self {
        Rotors {
            i: RotorFactory {
                wiring: cipher::from_string("EKMFLGDQVZNTOWYHXUSPAIBRCJ"),
                notch_position: cipher::from_char('Y'),
            },
            ii: RotorFactory {
                wiring: cipher::from_string("AJDKSIRUXBLHWTMCQGZNPYFVOE"),
                notch_position: cipher::from_char('M'),
            },
            iii: RotorFactory {
                wiring: cipher::from_string("BDFHJLCPRTXVZNYEIWGAKMUSQO"),
                notch_position: cipher::from_char('D'),
            },
            iv: RotorFactory {
                wiring: cipher::from_string("ESOVPZJAYQUIRHXLNFTGKDCMWB"),
                notch_position: cipher::from_char('R'),
            },
            v: RotorFactory {
                wiring: cipher::from_string("VZBRGITYUPSDNHLXAWMJQOFECK"),
                notch_position: cipher::from_char('H'),
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cipher as Cipher;
    use cipher::from_char as CC;

    #[test]
    fn noop_rotor() {
        let wiring = Cipher::from_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        let rotor = Rotor::new(wiring, CC('A'), CC('A'));

        assert_eq!(CC('A'), rotor.sub(CC('A')));
        assert_eq!(CC('A'), rotor.inverse_sub(CC('A')));
    }

    #[test]
    fn ring_position() {
        let wiring = Cipher::from_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        let rotor = Rotor::new(wiring, CC('A'), CC('B'));

        assert_eq!(CC('A'), rotor.sub(CC('A')));
        assert_eq!(CC('A'), rotor.inverse_sub(CC('A')));
    }

    #[test]
    fn a_b_flip() {
        let wiring = Cipher::from_string("BACDEFGHIJKLMNOPQRSTUVWXYZ");
        let rotor = Rotor::new(wiring, CC('A'), CC('A'));

        assert_eq!(CC('B'), rotor.sub(CC('A')));
        assert_eq!(CC('A'), rotor.sub(CC('B')));
        assert_eq!(CC('Z'), rotor.sub(CC('Z')));
        assert_eq!(CC('B'), rotor.inverse_sub(CC('A')));
        assert_eq!(CC('A'), rotor.inverse_sub(CC('B')));
        assert_eq!(CC('Z'), rotor.inverse_sub(CC('Z')));
    }

    #[test]
    fn a_b_flip_with_ring_position() {
        let wiring = Cipher::from_string("BACDEFGHIJKLMNOPQRSTUVWXYZ");
        let rotor = Rotor::new(wiring, CC('A'), CC('B'));

        assert_eq!(CC('Z'), rotor.sub(CC('A')));
        assert_eq!(CC('B'), rotor.sub(CC('B')));
        assert_eq!(CC('A'), rotor.sub(CC('Z')));
        assert_eq!(CC('Z'), rotor.inverse_sub(CC('A')));
        assert_eq!(CC('B'), rotor.inverse_sub(CC('B')));
        assert_eq!(CC('A'), rotor.inverse_sub(CC('Z')));
    }
}
<|endoftext|>


<commit_before>/*
Copyright (C) 2018-2019 de4dot@gmail.com

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.
*/

use super::super::super::test_utils::from_str_conv::to_vec_u8;
use super::super::super::test_utils::{create_decoder, get_formatter_unit_tests_dir};
use super::super::super::*;
use super::fmt_factory::create_resolver;
use super::sym_opts::*;
use super::sym_opts_parser::*;
#[cfg(not(feature = "std"))]
use alloc::string::String;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;

struct MySymbolResolver {
	flags: u32,
}

impl SymbolResolver for MySymbolResolver {
	fn symbol(
		&mut self, _instruction: &Instruction, _operand: u32, instruction_operand: Option<u32>, address: u64, _address_size: u32,
	) -> Option<SymbolResult> {
		if instruction_operand == Some(1) && (self.flags & SymbolTestFlags::SYMBOL) != 0 {
			Some(SymbolResult::with_str_kind_flags(
				address,
				"symbol",
				FormatterTextKind::Data,
				if (self.flags & SymbolTestFlags::SIGNED) != 0 { SymbolFlags::SIGNED } else { SymbolFlags::NONE },
			))
		} else {
			None
		}
	}
}

#[test]
fn symbol_options() {
	let mut path = get_formatter_unit_tests_dir();
	path.push("masm");
	path.push("SymbolOptions.txt");
	for tc in SymbolOptionsTestParser::new(&path) {
		let bytes = to_vec_u8(&tc.hex_bytes).unwrap();
		let mut decoder = create_decoder(tc.bitness, &bytes, DecoderOptions::NONE).0;
		let instruction = decoder.decode();

		let mut symbol_resolver = MySymbolResolver { flags: tc.flags };
		let mut formatter = create_resolver(&mut symbol_resolver);
		formatter.options_mut().set_masm_symbol_displ_in_brackets((tc.flags & SymbolTestFlags::SYMBOL_DISPL_IN_BRACKETS) != 0);
		formatter.options_mut().set_masm_displ_in_brackets((tc.flags & SymbolTestFlags::DISPL_IN_BRACKETS) != 0);
		formatter.options_mut().set_rip_relative_addresses((tc.flags & SymbolTestFlags::RIP) != 0);
		formatter.options_mut().set_show_zero_displacements((tc.flags & SymbolTestFlags::SHOW_ZERO_DISPLACEMENTS) != 0);
		formatter.options_mut().set_masm_add_ds_prefix32((tc.flags & SymbolTestFlags::NO_ADD_DS_PREFIX32) == 0);

		let mut output = String::new();
		formatter.format(&instruction, &mut output);
		assert_eq!(tc.formatted_string, output);
	}
}
<commit_msg>Fix dir name<commit_after>/*
Copyright (C) 2018-2019 de4dot@gmail.com

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.
*/

use super::super::super::test_utils::from_str_conv::to_vec_u8;
use super::super::super::test_utils::{create_decoder, get_formatter_unit_tests_dir};
use super::super::super::*;
use super::fmt_factory::create_resolver;
use super::sym_opts::*;
use super::sym_opts_parser::*;
#[cfg(not(feature = "std"))]
use alloc::string::String;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;

struct MySymbolResolver {
	flags: u32,
}

impl SymbolResolver for MySymbolResolver {
	fn symbol(
		&mut self, _instruction: &Instruction, _operand: u32, instruction_operand: Option<u32>, address: u64, _address_size: u32,
	) -> Option<SymbolResult> {
		if instruction_operand == Some(1) && (self.flags & SymbolTestFlags::SYMBOL) != 0 {
			Some(SymbolResult::with_str_kind_flags(
				address,
				"symbol",
				FormatterTextKind::Data,
				if (self.flags & SymbolTestFlags::SIGNED) != 0 { SymbolFlags::SIGNED } else { SymbolFlags::NONE },
			))
		} else {
			None
		}
	}
}

#[test]
fn symbol_options() {
	let mut path = get_formatter_unit_tests_dir();
	path.push("Masm");
	path.push("SymbolOptions.txt");
	for tc in SymbolOptionsTestParser::new(&path) {
		let bytes = to_vec_u8(&tc.hex_bytes).unwrap();
		let mut decoder = create_decoder(tc.bitness, &bytes, DecoderOptions::NONE).0;
		let instruction = decoder.decode();

		let mut symbol_resolver = MySymbolResolver { flags: tc.flags };
		let mut formatter = create_resolver(&mut symbol_resolver);
		formatter.options_mut().set_masm_symbol_displ_in_brackets((tc.flags & SymbolTestFlags::SYMBOL_DISPL_IN_BRACKETS) != 0);
		formatter.options_mut().set_masm_displ_in_brackets((tc.flags & SymbolTestFlags::DISPL_IN_BRACKETS) != 0);
		formatter.options_mut().set_rip_relative_addresses((tc.flags & SymbolTestFlags::RIP) != 0);
		formatter.options_mut().set_show_zero_displacements((tc.flags & SymbolTestFlags::SHOW_ZERO_DISPLACEMENTS) != 0);
		formatter.options_mut().set_masm_add_ds_prefix32((tc.flags & SymbolTestFlags::NO_ADD_DS_PREFIX32) == 0);

		let mut output = String::new();
		formatter.format(&instruction, &mut output);
		assert_eq!(tc.formatted_string, output);
	}
}
<|endoftext|>


<commit_before>use rope::Node;

/// An immutable view into part of a Rope.
pub struct RopeSlice<'a> {
    node: &'a Node,
    start: usize,
    end: usize,
}

impl<'a> RopeSlice<'a> {
    pub(crate) fn new_from_node<'b>(node: &'b Node, start: usize, end: usize) -> RopeSlice<'b> {
        assert!(start <= end);
        assert!(end < node.text_info().chars as usize);

        // Find the deepest node that still contains the full range given.
        let mut n_start = start;
        let mut n_end = end;
        let mut node = node;
        'outer: loop {
            match node as &Node {
                &Node::Empty | &Node::Leaf(_) => break,

                &Node::Internal {
                    ref info,
                    ref children,
                } => {
                    let mut start_char = 0;
                    for (i, inf) in info.iter().enumerate() {
                        if n_start >= start_char && n_end < (start_char + inf.chars as usize) {
                            n_start -= start_char;
                            n_end -= start_char;
                            node = &children[i];
                            continue 'outer;
                        }
                        start_char += inf.chars as usize;
                    }
                    break;
                }
            }
        }

        // Create the slice
        RopeSlice {
            node: node,
            start: n_start,
            end: n_end,
        }
    }

    /// Returns an immutable slice of the RopeSlice in the char range `start..end`.
    pub fn slice(&self, start: usize, end: usize) -> RopeSlice<'a> {
        assert!(start <= end);
        assert!(end < (self.end - self.start));
        RopeSlice::new_from_node(self.node, self.start + start, self.start + end)
    }
}
<commit_msg>Adding some placeholder methods for RopeSlices.<commit_after>use rope::Node;

/// An immutable view into part of a Rope.
pub struct RopeSlice<'a> {
    node: &'a Node,
    start: usize,
    end: usize,
}

impl<'a> RopeSlice<'a> {
    pub(crate) fn new_from_node<'b>(node: &'b Node, start: usize, end: usize) -> RopeSlice<'b> {
        assert!(start <= end);
        assert!(end < node.text_info().chars as usize);

        // Find the deepest node that still contains the full range given.
        let mut n_start = start;
        let mut n_end = end;
        let mut node = node;
        'outer: loop {
            match node as &Node {
                &Node::Empty | &Node::Leaf(_) => break,

                &Node::Internal {
                    ref info,
                    ref children,
                } => {
                    let mut start_char = 0;
                    for (i, inf) in info.iter().enumerate() {
                        if n_start >= start_char && n_end < (start_char + inf.chars as usize) {
                            n_start -= start_char;
                            n_end -= start_char;
                            node = &children[i];
                            continue 'outer;
                        }
                        start_char += inf.chars as usize;
                    }
                    break;
                }
            }
        }

        // Create the slice
        RopeSlice {
            node: node,
            start: n_start,
            end: n_end,
        }
    }

    /// Returns an immutable slice of the RopeSlice in the char range `start..end`.
    pub fn slice(&self, start: usize, end: usize) -> RopeSlice<'a> {
        assert!(start <= end);
        assert!(end < (self.end - self.start));
        RopeSlice::new_from_node(self.node, self.start + start, self.start + end)
    }

    /// Creates an iterator over the bytes of the RopeSlice.
    pub fn bytes<'a>(&'a self) -> RopeBytes<'a> {
        unimplemented!()
    }

    /// Creates an iterator over the chars of the RopeSlice.
    pub fn chars<'a>(&'a self) -> RopeChars<'a> {
        unimplemented!()
    }

    /// Creates an iterator over the lines of the RopeSlice.
    pub fn lines<'a>(&'a self) -> RopeLines<'a> {
        unimplemented!()
    }

    /// Creates an iterator over the chunks of the RopeSlice.
    pub fn chunks<'a>(&'a self) -> RopeChunks<'a> {
        unimplemented!()
    }
}
<|endoftext|>