<commit_before>use crate::leb128::{self, read_signed_leb128, write_signed_leb128};
use crate::serialize;
use std::borrow::Cow;

// -----------------------------------------------------------------------------
// Encoder
// -----------------------------------------------------------------------------

pub type EncodeResult = Result<(), !>;

pub struct Encoder {
    pub data: Vec<u8>,
}

impl Encoder {
    pub fn new(data: Vec<u8>) -> Encoder {
        Encoder { data }
    }

    pub fn into_inner(self) -> Vec<u8> {
        self.data
    }

    #[inline]
    pub fn emit_raw_bytes(&mut self, s: &[u8]) {
        self.data.extend_from_slice(s);
    }
}

macro_rules! write_uleb128 {
    ($enc:expr, $value:expr, $fun:ident) => {{
        leb128::$fun(&mut $enc.data, $value);
        Ok(())
    }};
}

macro_rules! write_sleb128 {
    ($enc:expr, $value:expr) => {{
        write_signed_leb128(&mut $enc.data, $value as i128);
        Ok(())
    }};
}

impl serialize::Encoder for Encoder {
    type Error = !;

    #[inline]
    fn emit_unit(&mut self) -> EncodeResult {
        Ok(())
    }

    #[inline]
    fn emit_usize(&mut self, v: usize) -> EncodeResult {
        write_uleb128!(self, v, write_usize_leb128)
    }

    #[inline]
    fn emit_u128(&mut self, v: u128) -> EncodeResult {
        write_uleb128!(self, v, write_u128_leb128)
    }

    #[inline]
    fn emit_u64(&mut self, v: u64) -> EncodeResult {
        write_uleb128!(self, v, write_u64_leb128)
    }

    #[inline]
    fn emit_u32(&mut self, v: u32) -> EncodeResult {
        write_uleb128!(self, v, write_u32_leb128)
    }

    #[inline]
    fn emit_u16(&mut self, v: u16) -> EncodeResult {
        write_uleb128!(self, v, write_u16_leb128)
    }

    #[inline]
    fn emit_u8(&mut self, v: u8) -> EncodeResult {
        self.data.push(v);
        Ok(())
    }

    #[inline]
    fn emit_isize(&mut self, v: isize) -> EncodeResult {
        write_sleb128!(self, v)
    }

    #[inline]
    fn emit_i128(&mut self, v: i128) -> EncodeResult {
        write_sleb128!(self, v)
    }

    #[inline]
    fn emit_i64(&mut self, v: i64) -> EncodeResult {
        write_sleb128!(self, v)
    }

    #[inline]
    fn emit_i32(&mut self, v: i32) -> EncodeResult {
        write_sleb128!(self, v)
    }

    #[inline]
    fn emit_i16(&mut self, v: i16) -> EncodeResult {
        write_sleb128!(self, v)
    }

    #[inline]
    fn emit_i8(&mut self, v: i8) -> EncodeResult {
        let as_u8: u8 = unsafe { ::std::mem::transmute(v) };
        self.emit_u8(as_u8)
    }

    #[inline]
    fn emit_bool(&mut self, v: bool) -> EncodeResult {
        self.emit_u8(if v { 1 } else { 0 })
    }

    #[inline]
    fn emit_f64(&mut self, v: f64) -> EncodeResult {
        let as_u64: u64 = unsafe { ::std::mem::transmute(v) };
        self.emit_u64(as_u64)
    }

    #[inline]
    fn emit_f32(&mut self, v: f32) -> EncodeResult {
        let as_u32: u32 = unsafe { ::std::mem::transmute(v) };
        self.emit_u32(as_u32)
    }

    #[inline]
    fn emit_char(&mut self, v: char) -> EncodeResult {
        self.emit_u32(v as u32)
    }

    #[inline]
    fn emit_str(&mut self, v: &str) -> EncodeResult {
        self.emit_usize(v.len())?;
        self.emit_raw_bytes(v.as_bytes());
        Ok(())
    }
}

impl Encoder {
    #[inline]
    pub fn position(&self) -> usize {
        self.data.len()
    }
}

// -----------------------------------------------------------------------------
// Decoder
// -----------------------------------------------------------------------------

pub struct Decoder<'a> {
    pub data: &'a [u8],
    position: usize,
}

impl<'a> Decoder<'a> {
    #[inline]
    pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> {
        Decoder { data, position }
    }

    #[inline]
    pub fn position(&self) -> usize {
        self.position
    }

    #[inline]
    pub fn set_position(&mut self, pos: usize) {
        self.position = pos
    }

    #[inline]
    pub fn advance(&mut self, bytes: usize) {
        self.position += bytes;
    }

    #[inline]
    pub fn read_raw_bytes(&mut self, s: &mut [u8]) -> Result<(), String> {
        let start = self.position;
        let end = start + s.len();

        s.copy_from_slice(&self.data[start..end]);

        self.position = end;

        Ok(())
    }
}

macro_rules! read_uleb128 {
    ($dec:expr, $t:ty, $fun:ident) => {{
        let (value, bytes_read) = leb128::$fun(&$dec.data[$dec.position..]);
        $dec.position += bytes_read;
        Ok(value)
    }};
}

macro_rules! read_sleb128 {
    ($dec:expr, $t:ty) => {{
        let (value, bytes_read) = read_signed_leb128($dec.data, $dec.position);
        $dec.position += bytes_read;
        Ok(value as $t)
    }};
}

impl<'a> serialize::Decoder for Decoder<'a> {
    type Error = String;

    #[inline]
    fn read_nil(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }

    #[inline]
    fn read_u128(&mut self) -> Result<u128, Self::Error> {
        read_uleb128!(self, u128, read_u128_leb128)
    }

    #[inline]
    fn read_u64(&mut self) -> Result<u64, Self::Error> {
        read_uleb128!(self, u64, read_u64_leb128)
    }

    #[inline]
    fn read_u32(&mut self) -> Result<u32, Self::Error> {
        read_uleb128!(self, u32, read_u32_leb128)
    }

    #[inline]
    fn read_u16(&mut self) -> Result<u16, Self::Error> {
        read_uleb128!(self, u16, read_u16_leb128)
    }

    #[inline]
    fn read_u8(&mut self) -> Result<u8, Self::Error> {
        let value = self.data[self.position];
        self.position += 1;
        Ok(value)
    }

    #[inline]
    fn read_usize(&mut self) -> Result<usize, Self::Error> {
        read_uleb128!(self, usize, read_usize_leb128)
    }

    #[inline]
    fn read_i128(&mut self) -> Result<i128, Self::Error> {
        read_sleb128!(self, i128)
    }

    #[inline]
    fn read_i64(&mut self) -> Result<i64, Self::Error> {
        read_sleb128!(self, i64)
    }

    #[inline]
    fn read_i32(&mut self) -> Result<i32, Self::Error> {
        read_sleb128!(self, i32)
    }

    #[inline]
    fn read_i16(&mut self) -> Result<i16, Self::Error> {
        read_sleb128!(self, i16)
    }

    #[inline]
    fn read_i8(&mut self) -> Result<i8, Self::Error> {
        let as_u8 = self.data[self.position];
        self.position += 1;
        unsafe { Ok(::std::mem::transmute(as_u8)) }
    }

    #[inline]
    fn read_isize(&mut self) -> Result<isize, Self::Error> {
        read_sleb128!(self, isize)
    }

    #[inline]
    fn read_bool(&mut self) -> Result<bool, Self::Error> {
        let value = self.read_u8()?;
        Ok(value != 0)
    }

    #[inline]
    fn read_f64(&mut self) -> Result<f64, Self::Error> {
        let bits = self.read_u64()?;
        Ok(f64::from_bits(bits))
    }

    #[inline]
    fn read_f32(&mut self) -> Result<f32, Self::Error> {
        let bits = self.read_u32()?;
        Ok(f32::from_bits(bits))
    }

    #[inline]
    fn read_char(&mut self) -> Result<char, Self::Error> {
        let bits = self.read_u32()?;
        Ok(::std::char::from_u32(bits).unwrap())
    }

    #[inline]
    fn read_str(&mut self) -> Result<Cow<'_, str>, Self::Error> {
        let len = self.read_usize()?;
        let s = ::std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap();
        self.position += len;
        Ok(Cow::Borrowed(s))
    }

    #[inline]
    fn error(&mut self, err: &str) -> Self::Error {
        err.to_string()
    }
}
<commit_msg>Auto merge of #68661 - nnethercote:rm-unused-read_uleb128-param, r=Mark-Simulacrum<commit_after>use crate::leb128::{self, read_signed_leb128, write_signed_leb128};
use crate::serialize;
use std::borrow::Cow;

// -----------------------------------------------------------------------------
// Encoder
// -----------------------------------------------------------------------------

pub type EncodeResult = Result<(), !>;

pub struct Encoder {
    pub data: Vec<u8>,
}

impl Encoder {
    pub fn new(data: Vec<u8>) -> Encoder {
        Encoder { data }
    }

    pub fn into_inner(self) -> Vec<u8> {
        self.data
    }

    #[inline]
    pub fn emit_raw_bytes(&mut self, s: &[u8]) {
        self.data.extend_from_slice(s);
    }
}

macro_rules! write_uleb128 {
    ($enc:expr, $value:expr, $fun:ident) => {{
        leb128::$fun(&mut $enc.data, $value);
        Ok(())
    }};
}

macro_rules! write_sleb128 {
    ($enc:expr, $value:expr) => {{
        write_signed_leb128(&mut $enc.data, $value as i128);
        Ok(())
    }};
}

impl serialize::Encoder for Encoder {
    type Error = !;

    #[inline]
    fn emit_unit(&mut self) -> EncodeResult {
        Ok(())
    }

    #[inline]
    fn emit_usize(&mut self, v: usize) -> EncodeResult {
        write_uleb128!(self, v, write_usize_leb128)
    }

    #[inline]
    fn emit_u128(&mut self, v: u128) -> EncodeResult {
        write_uleb128!(self, v, write_u128_leb128)
    }

    #[inline]
    fn emit_u64(&mut self, v: u64) -> EncodeResult {
        write_uleb128!(self, v, write_u64_leb128)
    }

    #[inline]
    fn emit_u32(&mut self, v: u32) -> EncodeResult {
        write_uleb128!(self, v, write_u32_leb128)
    }

    #[inline]
    fn emit_u16(&mut self, v: u16) -> EncodeResult {
        write_uleb128!(self, v, write_u16_leb128)
    }

    #[inline]
    fn emit_u8(&mut self, v: u8) -> EncodeResult {
        self.data.push(v);
        Ok(())
    }

    #[inline]
    fn emit_isize(&mut self, v: isize) -> EncodeResult {
        write_sleb128!(self, v)
    }

    #[inline]
    fn emit_i128(&mut self, v: i128) -> EncodeResult {
        write_sleb128!(self, v)
    }

    #[inline]
    fn emit_i64(&mut self, v: i64) -> EncodeResult {
        write_sleb128!(self, v)
    }

    #[inline]
    fn emit_i32(&mut self, v: i32) -> EncodeResult {
        write_sleb128!(self, v)
    }

    #[inline]
    fn emit_i16(&mut self, v: i16) -> EncodeResult {
        write_sleb128!(self, v)
    }

    #[inline]
    fn emit_i8(&mut self, v: i8) -> EncodeResult {
        let as_u8: u8 = unsafe { ::std::mem::transmute(v) };
        self.emit_u8(as_u8)
    }

    #[inline]
    fn emit_bool(&mut self, v: bool) -> EncodeResult {
        self.emit_u8(if v { 1 } else { 0 })
    }

    #[inline]
    fn emit_f64(&mut self, v: f64) -> EncodeResult {
        let as_u64: u64 = unsafe { ::std::mem::transmute(v) };
        self.emit_u64(as_u64)
    }

    #[inline]
    fn emit_f32(&mut self, v: f32) -> EncodeResult {
        let as_u32: u32 = unsafe { ::std::mem::transmute(v) };
        self.emit_u32(as_u32)
    }

    #[inline]
    fn emit_char(&mut self, v: char) -> EncodeResult {
        self.emit_u32(v as u32)
    }

    #[inline]
    fn emit_str(&mut self, v: &str) -> EncodeResult {
        self.emit_usize(v.len())?;
        self.emit_raw_bytes(v.as_bytes());
        Ok(())
    }
}

impl Encoder {
    #[inline]
    pub fn position(&self) -> usize {
        self.data.len()
    }
}

// -----------------------------------------------------------------------------
// Decoder
// -----------------------------------------------------------------------------

pub struct Decoder<'a> {
    pub data: &'a [u8],
    position: usize,
}

impl<'a> Decoder<'a> {
    #[inline]
    pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> {
        Decoder { data, position }
    }

    #[inline]
    pub fn position(&self) -> usize {
        self.position
    }

    #[inline]
    pub fn set_position(&mut self, pos: usize) {
        self.position = pos
    }

    #[inline]
    pub fn advance(&mut self, bytes: usize) {
        self.position += bytes;
    }

    #[inline]
    pub fn read_raw_bytes(&mut self, s: &mut [u8]) -> Result<(), String> {
        let start = self.position;
        let end = start + s.len();

        s.copy_from_slice(&self.data[start..end]);

        self.position = end;

        Ok(())
    }
}

macro_rules! read_uleb128 {
    ($dec:expr, $fun:ident) => {{
        let (value, bytes_read) = leb128::$fun(&$dec.data[$dec.position..]);
        $dec.position += bytes_read;
        Ok(value)
    }};
}

macro_rules! read_sleb128 {
    ($dec:expr, $t:ty) => {{
        let (value, bytes_read) = read_signed_leb128($dec.data, $dec.position);
        $dec.position += bytes_read;
        Ok(value as $t)
    }};
}

impl<'a> serialize::Decoder for Decoder<'a> {
    type Error = String;

    #[inline]
    fn read_nil(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }

    #[inline]
    fn read_u128(&mut self) -> Result<u128, Self::Error> {
        read_uleb128!(self, read_u128_leb128)
    }

    #[inline]
    fn read_u64(&mut self) -> Result<u64, Self::Error> {
        read_uleb128!(self, read_u64_leb128)
    }

    #[inline]
    fn read_u32(&mut self) -> Result<u32, Self::Error> {
        read_uleb128!(self, read_u32_leb128)
    }

    #[inline]
    fn read_u16(&mut self) -> Result<u16, Self::Error> {
        read_uleb128!(self, read_u16_leb128)
    }

    #[inline]
    fn read_u8(&mut self) -> Result<u8, Self::Error> {
        let value = self.data[self.position];
        self.position += 1;
        Ok(value)
    }

    #[inline]
    fn read_usize(&mut self) -> Result<usize, Self::Error> {
        read_uleb128!(self, read_usize_leb128)
    }

    #[inline]
    fn read_i128(&mut self) -> Result<i128, Self::Error> {
        read_sleb128!(self, i128)
    }

    #[inline]
    fn read_i64(&mut self) -> Result<i64, Self::Error> {
        read_sleb128!(self, i64)
    }

    #[inline]
    fn read_i32(&mut self) -> Result<i32, Self::Error> {
        read_sleb128!(self, i32)
    }

    #[inline]
    fn read_i16(&mut self) -> Result<i16, Self::Error> {
        read_sleb128!(self, i16)
    }

    #[inline]
    fn read_i8(&mut self) -> Result<i8, Self::Error> {
        let as_u8 = self.data[self.position];
        self.position += 1;
        unsafe { Ok(::std::mem::transmute(as_u8)) }
    }

    #[inline]
    fn read_isize(&mut self) -> Result<isize, Self::Error> {
        read_sleb128!(self, isize)
    }

    #[inline]
    fn read_bool(&mut self) -> Result<bool, Self::Error> {
        let value = self.read_u8()?;
        Ok(value != 0)
    }

    #[inline]
    fn read_f64(&mut self) -> Result<f64, Self::Error> {
        let bits = self.read_u64()?;
        Ok(f64::from_bits(bits))
    }

    #[inline]
    fn read_f32(&mut self) -> Result<f32, Self::Error> {
        let bits = self.read_u32()?;
        Ok(f32::from_bits(bits))
    }

    #[inline]
    fn read_char(&mut self) -> Result<char, Self::Error> {
        let bits = self.read_u32()?;
        Ok(::std::char::from_u32(bits).unwrap())
    }

    #[inline]
    fn read_str(&mut self) -> Result<Cow<'_, str>, Self::Error> {
        let len = self.read_usize()?;
        let s = ::std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap();
        self.position += len;
        Ok(Cow::Borrowed(s))
    }

    #[inline]
    fn error(&mut self, err: &str) -> Self::Error {
        err.to_string()
    }
}
<|endoftext|>


<commit_before>use UndoCmd;

/// `UndoStack` maintains a stack of `UndoCmd`s that can be undone and redone by using methods
/// on the `UndoStack`.
///
/// `UndoStack` will notice when it's state changes to either dirty or clean, and the user can
/// set methods that should be called for either state change. This is useful for example if
/// you want to automatically enable or disable undo or redo buttons based on there are any
/// more actions that can be undone or redone.
pub struct UndoStack<'a> {
    // All commands on the stack.
    stack: Vec<Box<UndoCmd + 'a>>,
    // Current position in the stack.
    len: usize,
    // Called when the state changes from dirty to clean.
    on_clean: Option<Box<FnMut() + 'a>>,
    // Called when the state changes from clean to dirty.
    on_dirty: Option<Box<FnMut() + 'a>>,
}

impl<'a> UndoStack<'a> {
    /// Creates a new `UndoStack`.
    pub fn new() -> Self {
        UndoStack {
            stack: Vec::new(),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    /// Creates a new `UndoStack` with the specified capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        UndoStack {
            stack: Vec::with_capacity(capacity),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    /// Returns the capacity of the `UndoStack`.
    pub fn capacity(&self) -> usize {
        self.stack.capacity()
    }

    /// Reserves capacity for at least `additional` more commands to be inserted in the given stack.
    /// The stack may reserve more space to avoid frequent reallocations.
    ///
    /// # Panics
    /// Panics if the new capacity overflows usize.
    pub fn reserve(&mut self, additional: usize) {
        self.stack.reserve(additional);
    }

    /// Shrinks the capacity of the `UndoStack` as much as possible.
    pub fn shrink_to_fit(&mut self) {
        self.stack.shrink_to_fit();
    }

    /// Sets what should happen if the state changes from dirty to clean.
    /// By default the `UndoStack` does nothing when the state changes.
    ///
    /// Note: An empty `UndoStack` is clean, so the first push will not trigger the `on_clean` method.
    ///
    /// # Example
    /// ```
    /// # use undo::UndoStack;
    /// let mut x = 0;
    /// let stack = UndoStack::new()
    ///     .on_clean(|| x += 1);
    /// ```
    pub fn on_clean<F>(mut self, f: F) -> Self
        where F: FnMut() + 'a,
    {
        self.on_clean = Some(Box::new(f));
        self
    }

    /// Sets what should happen if the state changes from clean to dirty.
    /// By default the `UndoStack` does nothing when the state changes.
    ///
    /// # Example
    /// ```
    /// # use undo::UndoStack;
    /// let mut x = 0;
    /// let stack = UndoStack::new()
    ///     .on_dirty(|| x += 1);
    /// ```
    pub fn on_dirty<F>(mut self, f: F) -> Self
        where F: FnMut() + 'a,
    {
        self.on_dirty = Some(Box::new(f));
        self
    }

    /// Returns `true` if the state of the stack is clean.
    pub fn is_clean(&self) -> bool {
        self.len == self.stack.len()
    }

    /// Returns `true` if the state of the stack is dirty.
    pub fn is_dirty(&self) -> bool {
        !self.is_clean()
    }

    /// Pushes a `UndoCmd` to the top of the `UndoStack` and executes its [`redo`] method.
    /// This pops off all `UndoCmd`s that is above the active command from the `UndoStack`.
    ///
    /// If `cmd`s id is equal to the current top command, the two commands are merged.
    ///
    /// [`redo`]: trait.UndoCmd.html#tymethod.redo
    pub fn push<T>(&mut self, mut cmd: T)
        where T: UndoCmd + 'a,
    {
        let is_dirty = self.is_dirty();
        let len = self.len;
        // Pop off all elements after len from stack.
        self.stack.truncate(len);
        cmd.redo();

        // Check if we should merge cmd with the top command on stack.
        let id = cmd.id();
        if len > 0 && id.is_some() && id == unsafe { self.stack.get_unchecked(len - 1).id() } {

            // MergeCmd is the result of the merging.
            struct MergeCmd<'a> {
                cmd1: Box<UndoCmd + 'a>,
                cmd2: Box<UndoCmd + 'a>,
            }

            impl<'a> UndoCmd for MergeCmd<'a> {
                fn redo(&mut self) {
                    self.cmd1.redo();
                    self.cmd2.redo();
                }

                fn undo(&mut self) {
                    self.cmd2.undo();
                    self.cmd1.undo();
                }

                fn id(&self) -> Option<u64> {
                    self.cmd1.id()
                }
            }

            // Merge the command with the one on the top of the stack.
            let cmd = MergeCmd {
                cmd1: self.stack.pop().unwrap(),
                cmd2: Box::new(cmd),
            };
            self.stack.push(Box::new(cmd));
        } else {
            self.stack.push(Box::new(cmd));
            self.len += 1;
        }

        // State is always clean after a push, check if it was dirty before.
        if is_dirty {
            if let Some(ref mut f) = self.on_clean {
                f();
            }
        }
    }

    /// Calls the [`redo`] method for the active `UndoCmd` and sets the next `UndoCmd` as the new
    /// active one.
    ///
    /// Calling this method when the state is clean does nothing.
    ///
    /// [`redo`]: trait.UndoCmd.html#tymethod.redo
    pub fn redo(&mut self) {
        if self.len < self.stack.len() {
            let is_dirty = self.is_dirty();
            unsafe {
                let ref mut cmd = self.stack.get_unchecked_mut(self.len);
                cmd.redo();
            }
            self.len += 1;
            // Check if stack went from dirty to clean.
            if is_dirty && self.is_clean() {
                if let Some(ref mut f) = self.on_clean {
                    f();
                }
            }
        }
    }

    /// Calls the [`undo`] method for the active `UndoCmd` and sets the previous `UndoCmd` as the
    /// new active one.
    ///
    /// Calling this method when there are no more commands to undo does nothing.
    ///
    /// [`undo`]: trait.UndoCmd.html#tymethod.undo
    pub fn undo(&mut self) {
        if self.len > 0 {
            let is_clean = self.is_clean();
            self.len -= 1;
            unsafe {
                let ref mut cmd = self.stack.get_unchecked_mut(self.len);
                cmd.undo();
            }
            // Check if stack went from clean to dirty.
            if is_clean && self.is_dirty() {
                if let Some(ref mut f) = self.on_dirty {
                    f();
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use {UndoStack, UndoCmd};

    #[test]
    fn pop() {
        use std::rc::Rc;
        use std::cell::{Cell, RefCell};

        /// Pops an element from a vector.
        #[derive(Clone)]
        struct PopCmd {
            vec: Rc<RefCell<Vec<i32>>>,
            e: Option<i32>,
        }

        impl UndoCmd for PopCmd {
            fn redo(&mut self) {
                self.e = self.vec.borrow_mut().pop();
            }

            fn undo(&mut self) {
                self.vec.borrow_mut().push(self.e.unwrap());
                self.e = None;
            }
        }

        let a = Cell::new(0);
        let b = Cell::new(0);
        // We need to use Rc<RefCell> since all commands are going to mutate the vec.
        let vec = Rc::new(RefCell::new(vec![1, 2, 3]));
        let mut undo_stack = UndoStack::with_capacity(3)
            .on_clean(|| a.set(1))
            .on_dirty(|| b.set(1));

        let cmd = PopCmd { vec: vec.clone(), e: None };
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());

        assert!(vec.borrow().is_empty());

        assert_eq!(b.get(), 0);
        undo_stack.undo();
        assert_eq!(b.get(), 1);
        b.set(0);

        undo_stack.undo();
        undo_stack.undo();

        assert_eq!(vec, Rc::new(RefCell::new(vec![1, 2, 3])));

        assert_eq!(a.get(), 0);
        undo_stack.push(cmd.clone());
        assert_eq!(a.get(), 1);
        a.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![1, 2])));

        assert_eq!(b.get(), 0);
        undo_stack.undo();
        assert_eq!(b.get(), 1);
        b.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![1, 2, 3])));

        assert_eq!(a.get(), 0);
        undo_stack.redo();
        assert_eq!(a.get(), 1);
        a.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![1, 2])));
    }
}
<commit_msg>Remove len test from pop<commit_after>use UndoCmd;

/// `UndoStack` maintains a stack of `UndoCmd`s that can be undone and redone by using methods
/// on the `UndoStack`.
///
/// `UndoStack` will notice when it's state changes to either dirty or clean, and the user can
/// set methods that should be called for either state change. This is useful for example if
/// you want to automatically enable or disable undo or redo buttons based on there are any
/// more actions that can be undone or redone.
pub struct UndoStack<'a> {
    // All commands on the stack.
    stack: Vec<Box<UndoCmd + 'a>>,
    // Current position in the stack.
    len: usize,
    // Called when the state changes from dirty to clean.
    on_clean: Option<Box<FnMut() + 'a>>,
    // Called when the state changes from clean to dirty.
    on_dirty: Option<Box<FnMut() + 'a>>,
}

impl<'a> UndoStack<'a> {
    /// Creates a new `UndoStack`.
    pub fn new() -> Self {
        UndoStack {
            stack: Vec::new(),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    /// Creates a new `UndoStack` with the specified capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        UndoStack {
            stack: Vec::with_capacity(capacity),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    /// Returns the capacity of the `UndoStack`.
    pub fn capacity(&self) -> usize {
        self.stack.capacity()
    }

    /// Reserves capacity for at least `additional` more commands to be inserted in the given stack.
    /// The stack may reserve more space to avoid frequent reallocations.
    ///
    /// # Panics
    /// Panics if the new capacity overflows usize.
    pub fn reserve(&mut self, additional: usize) {
        self.stack.reserve(additional);
    }

    /// Shrinks the capacity of the `UndoStack` as much as possible.
    pub fn shrink_to_fit(&mut self) {
        self.stack.shrink_to_fit();
    }

    /// Sets what should happen if the state changes from dirty to clean.
    /// By default the `UndoStack` does nothing when the state changes.
    ///
    /// Note: An empty `UndoStack` is clean, so the first push will not trigger the `on_clean` method.
    ///
    /// # Example
    /// ```
    /// # use undo::UndoStack;
    /// let mut x = 0;
    /// let stack = UndoStack::new()
    ///     .on_clean(|| x += 1);
    /// ```
    pub fn on_clean<F>(mut self, f: F) -> Self
        where F: FnMut() + 'a,
    {
        self.on_clean = Some(Box::new(f));
        self
    }

    /// Sets what should happen if the state changes from clean to dirty.
    /// By default the `UndoStack` does nothing when the state changes.
    ///
    /// # Example
    /// ```
    /// # use undo::UndoStack;
    /// let mut x = 0;
    /// let stack = UndoStack::new()
    ///     .on_dirty(|| x += 1);
    /// ```
    pub fn on_dirty<F>(mut self, f: F) -> Self
        where F: FnMut() + 'a,
    {
        self.on_dirty = Some(Box::new(f));
        self
    }

    /// Returns `true` if the state of the stack is clean.
    pub fn is_clean(&self) -> bool {
        self.len == self.stack.len()
    }

    /// Returns `true` if the state of the stack is dirty.
    pub fn is_dirty(&self) -> bool {
        !self.is_clean()
    }

    /// Pushes a `UndoCmd` to the top of the `UndoStack` and executes its [`redo`] method.
    /// This pops off all `UndoCmd`s that is above the active command from the `UndoStack`.
    ///
    /// If `cmd`s id is equal to the current top command, the two commands are merged.
    ///
    /// [`redo`]: trait.UndoCmd.html#tymethod.redo
    pub fn push<T>(&mut self, mut cmd: T)
        where T: UndoCmd + 'a,
    {
        let is_dirty = self.is_dirty();
        let len = self.len;
        // Pop off all elements after len from stack.
        self.stack.truncate(len);
        cmd.redo();

        // Check if we should merge cmd with the top command on stack.
        let id = cmd.id();
        if len > 0 && id.is_some() && id == unsafe { self.stack.get_unchecked(len - 1).id() } {

            // MergeCmd is the result of the merging.
            struct MergeCmd<'a> {
                cmd1: Box<UndoCmd + 'a>,
                cmd2: Box<UndoCmd + 'a>,
            }

            impl<'a> UndoCmd for MergeCmd<'a> {
                fn redo(&mut self) {
                    self.cmd1.redo();
                    self.cmd2.redo();
                }

                fn undo(&mut self) {
                    self.cmd2.undo();
                    self.cmd1.undo();
                }

                fn id(&self) -> Option<u64> {
                    self.cmd1.id()
                }
            }

            // Merge the command with the one on the top of the stack.
            let cmd = MergeCmd {
                cmd1: unsafe {
                    self.stack.set_len(len - 1);
                    ::std::ptr::read(self.stack.get_unchecked(self.stack.len()))
                },
                cmd2: Box::new(cmd),
            };
            self.stack.push(Box::new(cmd));
        } else {
            self.stack.push(Box::new(cmd));
            self.len += 1;
        }

        // State is always clean after a push, check if it was dirty before.
        if is_dirty {
            if let Some(ref mut f) = self.on_clean {
                f();
            }
        }
    }

    /// Calls the [`redo`] method for the active `UndoCmd` and sets the next `UndoCmd` as the new
    /// active one.
    ///
    /// Calling this method when the state is clean does nothing.
    ///
    /// [`redo`]: trait.UndoCmd.html#tymethod.redo
    pub fn redo(&mut self) {
        if self.len < self.stack.len() {
            let is_dirty = self.is_dirty();
            unsafe {
                let ref mut cmd = self.stack.get_unchecked_mut(self.len);
                cmd.redo();
            }
            self.len += 1;
            // Check if stack went from dirty to clean.
            if is_dirty && self.is_clean() {
                if let Some(ref mut f) = self.on_clean {
                    f();
                }
            }
        }
    }

    /// Calls the [`undo`] method for the active `UndoCmd` and sets the previous `UndoCmd` as the
    /// new active one.
    ///
    /// Calling this method when there are no more commands to undo does nothing.
    ///
    /// [`undo`]: trait.UndoCmd.html#tymethod.undo
    pub fn undo(&mut self) {
        if self.len > 0 {
            let is_clean = self.is_clean();
            self.len -= 1;
            unsafe {
                let ref mut cmd = self.stack.get_unchecked_mut(self.len);
                cmd.undo();
            }
            // Check if stack went from clean to dirty.
            if is_clean && self.is_dirty() {
                if let Some(ref mut f) = self.on_dirty {
                    f();
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use {UndoStack, UndoCmd};

    #[test]
    fn pop() {
        use std::rc::Rc;
        use std::cell::{Cell, RefCell};

        /// Pops an element from a vector.
        #[derive(Clone)]
        struct PopCmd {
            vec: Rc<RefCell<Vec<i32>>>,
            e: Option<i32>,
        }

        impl UndoCmd for PopCmd {
            fn redo(&mut self) {
                self.e = self.vec.borrow_mut().pop();
            }

            fn undo(&mut self) {
                self.vec.borrow_mut().push(self.e.unwrap());
                self.e = None;
            }
        }

        let a = Cell::new(0);
        let b = Cell::new(0);
        // We need to use Rc<RefCell> since all commands are going to mutate the vec.
        let vec = Rc::new(RefCell::new(vec![1, 2, 3]));
        let mut undo_stack = UndoStack::with_capacity(3)
            .on_clean(|| a.set(1))
            .on_dirty(|| b.set(1));

        let cmd = PopCmd { vec: vec.clone(), e: None };
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());

        assert!(vec.borrow().is_empty());

        assert_eq!(b.get(), 0);
        undo_stack.undo();
        assert_eq!(b.get(), 1);
        b.set(0);

        undo_stack.undo();
        undo_stack.undo();

        assert_eq!(vec, Rc::new(RefCell::new(vec![1, 2, 3])));

        assert_eq!(a.get(), 0);
        undo_stack.push(cmd.clone());
        assert_eq!(a.get(), 1);
        a.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![1, 2])));

        assert_eq!(b.get(), 0);
        undo_stack.undo();
        assert_eq!(b.get(), 1);
        b.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![1, 2, 3])));

        assert_eq!(a.get(), 0);
        undo_stack.redo();
        assert_eq!(a.get(), 1);
        a.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![1, 2])));
    }
}
<|endoftext|>


<commit_before>use sass::output_style::SassOutputStyle;
use token::{Lexeme, Token};
use ast::number_value::NumberValue;
use context::Context;
use error::{Result, SassError, ErrorKind};

#[derive(Debug, Clone, PartialEq)]
pub enum Expression {
    List(Vec<Expression>),
    Number(NumberValue),
    Operator(Lexeme),
    String(Lexeme),
}

impl Expression {
    #[allow(unused_variables)]
    pub fn to_string(&self, style: SassOutputStyle) -> String {
        match *self {
            Expression::List(ref elements) => {
                elements.iter().map(|e|
                    e.to_string(style)
                ).collect::<Vec<_>>().join(" ")
            },
            Expression::Number(ref nv) => nv.to_string(),
            Expression::Operator(ref lex) => lex.token.to_string(),
            Expression::String(ref lex) => lex.token.to_string(),
        }
    }

    pub fn parse<T: Iterator<Item = Result<Lexeme>>>(tokenizer: &mut T) -> Result<Expression> {
        let mut list = vec![];
        while let Some(Ok(lexeme)) = tokenizer.next() {
            match lexeme.token {
                Token::Semicolon => {
                    if list.len() == 1 {
                        return Ok(list.pop().unwrap())
                    } else {
                        return Ok(Expression::List(list))
                    }
                },
                Token::Number(_, _) => {
                    list.push(Expression::Number(NumberValue::from_scalar(lexeme)));
                },
                Token::Plus | Token::Minus | Token::Star | Token::Slash | Token::Percent => {
                    list.push(Expression::Operator(lexeme));
                },
                _ => {
                    list.push(Expression::String(lexeme));
                }
            }
        }

        let error_offset = match list.pop() {
            Some(Expression::String(lexeme)) => lexeme.offset.unwrap_or(0),
            Some(Expression::Operator(lexeme)) => lexeme.offset.unwrap_or(0),
            Some(Expression::Number(nv)) => nv.offset().unwrap_or(0),
            Some(Expression::List(_)) => unreachable!(), // for now until nested lists
            None => 0,
        };
        Err(SassError {
            offset: error_offset,
            kind: ErrorKind::UnexpectedEof,
            message: String::from(
                "Expected semicolon while parsing a value expression; reached EOF instead."
            ),
        })
    }

    fn evaluate_list(self, context: &Context, _: bool) -> Expression {
        if let Expression::List(exprs) = self {
            let mut last_was_an_operator = true;
            // TODO: I'd love to have more types here, to ensure only values are
            // on the value stack and only operators are on the operator stack...
            let mut value_stack: Vec<Expression> = Vec::new();
            let mut op_stack: Vec<Expression> = Vec::new();

            // Split into value stacks and operator stacks

            let mut exprs = exprs.into_iter();
            while let Some(part) = exprs.next() {
                match part {
                    Expression::Number(nv) => {
                        if last_was_an_operator {
                            value_stack.push(Expression::Number(nv));
                        } else {
                            let list = create_list(
                                value_stack.pop(),
                                Expression::Number(nv),
                            );
                            value_stack.push(list);
                        }
                        last_was_an_operator = false;
                    },
                    Expression::Operator(op) => {
                        op_stack.push(Expression::Operator(op));
                        last_was_an_operator = true;
                    },
                    Expression::String(lex) => {
                        let var_eval = context.get_variable(&lex)
                                        .unwrap_or(Expression::String(lex));

                        if last_was_an_operator {
                            value_stack.push(var_eval);
                        } else {
                            let list = create_list(
                                value_stack.pop(),
                                var_eval,
                            );
                            value_stack.push(list);
                        }
                        last_was_an_operator = false;
                    },
                    Expression::List(list) => {
                        value_stack.push(Expression::List(list));
                        last_was_an_operator = false;
                    },
                }
            }

            // Process the stacks
            while !op_stack.is_empty() {
                let op = op_stack.pop().unwrap();
                let second = value_stack.pop().expect("Expected a second argument on the value stack");
                let first = value_stack.pop().expect("Expected a first argument on the value stack");

                debug!("Processing: \nfirst = {:#?}\nop = {:#?}\nsecond = {:#?}", first, op, second);

                value_stack.push(first.apply_math(op, second));
            }

            value_stack.pop().unwrap()
        } else {
            self
        }
    }

    pub fn evaluate(self, context: &Context) -> Expression {
        match self {
            Expression::Number(nv) => Expression::Number(nv),
            Expression::Operator(op) => Expression::Operator(op),
            Expression::String(lex) => {
                context.get_variable(&lex).unwrap_or(Expression::String(lex))
            },
            Expression::List(exprs) => {
                Expression::List(exprs).evaluate_list(context, false)
            },
        }
    }

    fn apply_math(self, operator: Expression, second: Expression) -> Expression {
        match (self.clone(), second.clone()) {
            (Expression::Number(f), Expression::Number(s)) => {
                match operator {
                    Expression::Operator(ref o) if o.token == Token::Slash => {
                        if f.computed || s.computed {
                            let result = f.apply_math(&o, &s);
                            Expression::Number(result)
                        } else {
                            Expression::List(vec![self, operator.clone(), second.clone()])
                        }
                    },
                    Expression::Operator(o) => {
                        let result = f.apply_math(&o, &s);
                        Expression::Number(result)
                    },
                    _ => unreachable!(),
                }
            },
            (Expression::List(f), Expression::List(s)) => {
                // let eval_first = Expression::List(f).evaluate()
                debug!("list list case");
                self
            },
            (Expression::List(f), Expression::Number(s)) => {
                debug!("list number case");
                self
            },
            (Expression::Number(f), Expression::List(s)) => {
                debug!("number list case");
                self
            },

            _ => unreachable!(),
        }
    }
}

fn create_list(head: Option<Expression>, tail: Expression) -> Expression {
    let mut list = match head {
        Some(Expression::List(v)) => v,
        Some(e) => vec![e],
        None => vec![],
    };
    list.push(tail);
    Expression::List(list)
}

#[cfg(test)]
mod tests {
    use super::*;
    use token::{Lexeme, Token};
    use ast::number_value::NumberValue;
    use context::Context;

    fn semicolon() -> Lexeme {
        Lexeme { token: Token::Semicolon, offset: None }
    }

    fn blue() -> Lexeme {
        Lexeme { token: Token::String("blue".into()), offset: None }
    }

    fn plus() -> Lexeme {
        Lexeme { token: Token::Plus, offset: None }
    }

    fn slash() -> Lexeme {
        Lexeme { token: Token::Slash, offset: None }
    }

    fn one() -> Lexeme {
        Lexeme { token: Token::Number(1.0, None), offset: None }
    }

    fn two() -> Lexeme {
        Lexeme { token: Token::Number(2.0, None), offset: None }
    }

    fn one_px() -> Lexeme {
        Lexeme { token: Token::Number(1.0, Some("px".into())), offset: None }
    }

    #[test]
    fn it_parses_a_single_string() {
        let mut fake_tokenizer = vec![Ok(blue()), Ok(semicolon())].into_iter();
        assert_eq!(
            Expression::parse(&mut fake_tokenizer),
            Ok(Expression::String(blue()))
        );
    }

    #[test]
    fn it_parses_a_list() {
        let mut fake_tokenizer = vec![
            Ok(one()),
            Ok(plus()),
            Ok(one()),
            Ok(semicolon())
        ].into_iter();
        assert_eq!(
            Expression::parse(&mut fake_tokenizer),
            Ok(Expression::List(vec![
                Expression::Number(NumberValue::from_scalar(one())),
                Expression::Operator(plus()),
                Expression::Number(NumberValue::from_scalar(one())),
            ]))
        );
    }

    #[test]
    fn it_parses_a_number_without_units() {
        let mut fake_tokenizer = vec![Ok(one()), Ok(semicolon())].into_iter();
        assert_eq!(
            Expression::parse(&mut fake_tokenizer),
            Ok(Expression::Number(NumberValue::from_scalar(one())))
        );
    }

    #[test]
    fn it_parses_a_number_with_units() {
        let mut fake_tokenizer = vec![Ok(one_px()), Ok(semicolon())].into_iter();
        assert_eq!(
            Expression::parse(&mut fake_tokenizer),
            Ok(Expression::Number(NumberValue::from_scalar(one_px())))
        );
    }

    #[test]
    fn it_evaluates_a_list() {
        let ex = Expression::List(vec![
            Expression::Number(NumberValue::from_scalar(one())),
            Expression::Operator(slash()),
            Expression::Number(NumberValue::from_scalar(two())),
            Expression::Operator(plus()),
            Expression::Number(NumberValue::from_scalar(one())),
            Expression::Operator(slash()),
            Expression::Number(NumberValue::from_scalar(two())),
        ]);
        let fake_context = Context::new();
        assert_eq!(
            ex.evaluate(&fake_context),
            Expression::Number(NumberValue { scalar: one(), computed: true })
        );
    }
}
<commit_msg>Make slashes in lists treated as division with other math<commit_after>use sass::output_style::SassOutputStyle;
use token::{Lexeme, Token};
use ast::number_value::NumberValue;
use context::Context;
use error::{Result, SassError, ErrorKind};

#[derive(Debug, Clone, PartialEq)]
pub enum Expression {
    List(Vec<Expression>),
    Number(NumberValue),
    Operator(Lexeme),
    String(Lexeme),
}

impl Expression {
    #[allow(unused_variables)]
    pub fn to_string(&self, style: SassOutputStyle) -> String {
        match *self {
            Expression::List(ref elements) => {
                elements.iter().map(|e|
                    e.to_string(style)
                ).collect::<Vec<_>>().join(" ")
            },
            Expression::Number(ref nv) => nv.to_string(),
            Expression::Operator(ref lex) => lex.token.to_string(),
            Expression::String(ref lex) => lex.token.to_string(),
        }
    }

    pub fn parse<T: Iterator<Item = Result<Lexeme>>>(tokenizer: &mut T) -> Result<Expression> {
        let mut list = vec![];
        while let Some(Ok(lexeme)) = tokenizer.next() {
            match lexeme.token {
                Token::Semicolon => {
                    if list.len() == 1 {
                        return Ok(list.pop().unwrap())
                    } else {
                        return Ok(Expression::List(list))
                    }
                },
                Token::Number(_, _) => {
                    list.push(Expression::Number(NumberValue::from_scalar(lexeme)));
                },
                Token::Plus | Token::Minus | Token::Star | Token::Slash | Token::Percent => {
                    list.push(Expression::Operator(lexeme));
                },
                _ => {
                    list.push(Expression::String(lexeme));
                }
            }
        }

        let error_offset = match list.pop() {
            Some(Expression::String(lexeme)) => lexeme.offset.unwrap_or(0),
            Some(Expression::Operator(lexeme)) => lexeme.offset.unwrap_or(0),
            Some(Expression::Number(nv)) => nv.offset().unwrap_or(0),
            Some(Expression::List(_)) => unreachable!(), // for now until nested lists
            None => 0,
        };
        Err(SassError {
            offset: error_offset,
            kind: ErrorKind::UnexpectedEof,
            message: String::from(
                "Expected semicolon while parsing a value expression; reached EOF instead."
            ),
        })
    }

    fn evaluate_list(self, context: &Context, force_slash: bool) -> Expression {
        if let Expression::List(exprs) = self {
            let mut last_was_an_operator = true;
            // TODO: I'd love to have more types here, to ensure only values are
            // on the value stack and only operators are on the operator stack...
            let mut value_stack: Vec<Expression> = Vec::new();
            let mut op_stack: Vec<Expression> = Vec::new();

            // Split into value stacks and operator stacks

            let mut exprs = exprs.into_iter();
            while let Some(part) = exprs.next() {
                match part {
                    Expression::Number(nv) => {
                        if last_was_an_operator {
                            value_stack.push(Expression::Number(nv));
                        } else {
                            let list = create_list(
                                value_stack.pop(),
                                Expression::Number(nv),
                            );
                            value_stack.push(list);
                        }
                        last_was_an_operator = false;
                    },
                    Expression::Operator(op) => {
                        op_stack.push(Expression::Operator(op));
                        last_was_an_operator = true;
                    },
                    Expression::String(lex) => {
                        let var_eval = context.get_variable(&lex)
                                        .unwrap_or(Expression::String(lex));

                        if last_was_an_operator {
                            value_stack.push(var_eval);
                        } else {
                            let list = create_list(
                                value_stack.pop(),
                                var_eval,
                            );
                            value_stack.push(list);
                        }
                        last_was_an_operator = false;
                    },
                    Expression::List(list) => {
                        value_stack.push(Expression::List(list));
                        last_was_an_operator = false;
                    },
                }
            }

            // Process the stacks
            while !op_stack.is_empty() {
                let op = op_stack.pop().unwrap();
                let second = value_stack.pop().expect("Expected a second argument on the value stack");
                let first = value_stack.pop().expect("Expected a first argument on the value stack");

                debug!("Processing: \nfirst = {:#?}\nop = {:#?}\nsecond = {:#?}", first, op, second);

                value_stack.push(first.apply_math(op, second, context, force_slash));
            }

            value_stack.pop().unwrap()
        } else {
            self
        }
    }

    pub fn evaluate(self, context: &Context) -> Expression {
        match self {
            Expression::Number(nv) => Expression::Number(nv),
            Expression::Operator(op) => Expression::Operator(op),
            Expression::String(lex) => {
                context.get_variable(&lex).unwrap_or(Expression::String(lex))
            },
            Expression::List(exprs) => {
                Expression::List(exprs).evaluate_list(context, false)
            },
        }
    }

    fn apply_math(self, operator: Expression, second: Expression, context: &Context, force_slash: bool) -> Expression {
        match (self.clone(), second.clone()) {
            (Expression::Number(f), Expression::Number(s)) => {
                match operator {
                    Expression::Operator(ref o) if o.token == Token::Slash => {
                        if force_slash || (f.computed || s.computed) {
                            let result = f.apply_math(&o, &s);
                            Expression::Number(result)
                        } else {
                            Expression::List(vec![self, operator.clone(), second.clone()])
                        }
                    },
                    Expression::Operator(o) => {
                        let result = f.apply_math(&o, &s);
                        Expression::Number(result)
                    },
                    _ => unreachable!(),
                }
            },
            (Expression::List(f), Expression::List(s)) => {
                debug!("list list case");
                let eval_first = Expression::List(f).evaluate_list(context, true);
                debug!("evaled first = {:#?}", eval_first);
                let eval_second = Expression::List(s).evaluate_list(context, true);
                debug!("evaled second = {:#?}", eval_second);
                eval_first.apply_math(operator, eval_second, context, true)
            },
            (Expression::List(f), Expression::Number(s)) => {
                debug!("list number case");
                self
            },
            (Expression::Number(f), Expression::List(s)) => {
                debug!("number list case");
                self
            },

            _ => unreachable!(),
        }
    }
}

fn create_list(head: Option<Expression>, tail: Expression) -> Expression {
    let mut list = match head {
        Some(Expression::List(v)) => v,
        Some(e) => vec![e],
        None => vec![],
    };
    list.push(tail);
    Expression::List(list)
}

#[cfg(test)]
mod tests {
    use super::*;
    use token::{Lexeme, Token};
    use ast::number_value::NumberValue;
    use context::Context;

    fn semicolon() -> Lexeme {
        Lexeme { token: Token::Semicolon, offset: None }
    }

    fn blue() -> Lexeme {
        Lexeme { token: Token::String("blue".into()), offset: None }
    }

    fn plus() -> Lexeme {
        Lexeme { token: Token::Plus, offset: None }
    }

    fn slash() -> Lexeme {
        Lexeme { token: Token::Slash, offset: None }
    }

    fn one() -> Lexeme {
        Lexeme { token: Token::Number(1.0, None), offset: None }
    }

    fn two() -> Lexeme {
        Lexeme { token: Token::Number(2.0, None), offset: None }
    }

    fn one_px() -> Lexeme {
        Lexeme { token: Token::Number(1.0, Some("px".into())), offset: None }
    }

    #[test]
    fn it_parses_a_single_string() {
        let mut fake_tokenizer = vec![Ok(blue()), Ok(semicolon())].into_iter();
        assert_eq!(
            Expression::parse(&mut fake_tokenizer),
            Ok(Expression::String(blue()))
        );
    }

    #[test]
    fn it_parses_a_list() {
        let mut fake_tokenizer = vec![
            Ok(one()),
            Ok(plus()),
            Ok(one()),
            Ok(semicolon())
        ].into_iter();
        assert_eq!(
            Expression::parse(&mut fake_tokenizer),
            Ok(Expression::List(vec![
                Expression::Number(NumberValue::from_scalar(one())),
                Expression::Operator(plus()),
                Expression::Number(NumberValue::from_scalar(one())),
            ]))
        );
    }

    #[test]
    fn it_parses_a_number_without_units() {
        let mut fake_tokenizer = vec![Ok(one()), Ok(semicolon())].into_iter();
        assert_eq!(
            Expression::parse(&mut fake_tokenizer),
            Ok(Expression::Number(NumberValue::from_scalar(one())))
        );
    }

    #[test]
    fn it_parses_a_number_with_units() {
        let mut fake_tokenizer = vec![Ok(one_px()), Ok(semicolon())].into_iter();
        assert_eq!(
            Expression::parse(&mut fake_tokenizer),
            Ok(Expression::Number(NumberValue::from_scalar(one_px())))
        );
    }

    #[test]
    fn it_evaluates_a_list() {
        let ex = Expression::List(vec![
            Expression::List(vec![
                Expression::Number(NumberValue::from_scalar(one())),
                Expression::Operator(slash()),
                Expression::Number(NumberValue::from_scalar(two())),
            ]),
            Expression::Operator(plus()),
            Expression::List(vec![
                Expression::Number(NumberValue::from_scalar(one())),
                Expression::Operator(slash()),
                Expression::Number(NumberValue::from_scalar(two())),
            ]),
        ]);
        let fake_context = Context::new();
        assert_eq!(
            ex.evaluate(&fake_context),
            Expression::Number(NumberValue { scalar: one(), computed: true })
        );
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::BlobBinding;
use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use dom::bindings::error::Fallible;
use dom::bindings::global::{GlobalField, GlobalRef};
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use num::ToPrimitive;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::cell::Cell;
use std::cmp::{max, min};
use std::sync::mpsc::Sender;
use util::str::DOMString;

// http://dev.w3.org/2006/webapi/FileAPI/#blob
#[dom_struct]
pub struct Blob {
    reflector_: Reflector,
    bytes: Option<Vec<u8>>,
    typeString: String,
    global: GlobalField,
    isClosed_: Cell<bool>,
}

fn is_ascii_printable(string: &str) -> bool {
    // Step 5.1 in Sec 5.1 of File API spec
    // http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob
    string.chars().all(|c| c >= '\x20' && c <= '\x7E')
}

impl Blob {
    pub fn new_inherited(global: GlobalRef, bytes: Option<Vec<u8>>, typeString: &str) -> Blob {
        Blob {
            reflector_: Reflector::new(),
            bytes: bytes,
            typeString: typeString.to_owned(),
            global: GlobalField::from_rooted(&global),
            isClosed_: Cell::new(false),
        }
    }

    pub fn new(global: GlobalRef, bytes: Option<Vec<u8>>, typeString: &str) -> Root<Blob> {
        reflect_dom_object(box Blob::new_inherited(global, bytes, typeString),
                           global,
                           BlobBinding::Wrap)
    }

    // http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob
    pub fn Constructor(global: GlobalRef) -> Fallible<Root<Blob>> {
        Ok(Blob::new(global, None, ""))
    }

    // http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob
    pub fn Constructor_(global: GlobalRef,
                        blobParts: DOMString,
                        blobPropertyBag: &BlobBinding::BlobPropertyBag)
                        -> Fallible<Root<Blob>> {
        // TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView or Blob
        // FIXME(ajeffrey): convert directly from a DOMString to a Vec<u8>
        let bytes: Option<Vec<u8>> = Some(String::from(blobParts).into_bytes());
        let typeString = if is_ascii_printable(&blobPropertyBag.type_) {
            &*blobPropertyBag.type_
        } else {
            ""
        };
        Ok(Blob::new(global, bytes, &typeString.to_ascii_lowercase()))
    }

    pub fn read_out_buffer(&self, send: Sender<Vec<u8>>) {
        send.send(self.bytes.clone().unwrap_or(vec![])).unwrap();
    }

    // simpler to use version of read_out_buffer
    pub fn clone_bytes(&self) -> Vec<u8> {
        self.bytes.clone().unwrap_or(vec![])
    }
}

impl BlobMethods for Blob {
    // https://dev.w3.org/2006/webapi/FileAPI/#dfn-size
    fn Size(&self) -> u64 {
        match self.bytes {
            None => 0,
            Some(ref bytes) => bytes.len() as u64,
        }
    }

    // https://dev.w3.org/2006/webapi/FileAPI/#dfn-type
    fn Type(&self) -> DOMString {
        DOMString::from(self.typeString.clone())
    }

    // https://dev.w3.org/2006/webapi/FileAPI/#slice-method-algo
    fn Slice(&self,
             start: Option<i64>,
             end: Option<i64>,
             contentType: Option<DOMString>)
             -> Root<Blob> {
        let size: i64 = self.Size().to_i64().unwrap();
        let relativeStart: i64 = match start {
            None => 0,
            Some(start) => {
                if start < 0 {
                    max(size.to_i64().unwrap() + start, 0)
                } else {
                    min(start, size)
                }
            }
        };
        let relativeEnd: i64 = match end {
            None => size,
            Some(end) => {
                if end < 0 {
                    max(size + end, 0)
                } else {
                    min(end, size)
                }
            }
        };
        let relativeContentType = match contentType {
            None => DOMString::new(),
            Some(mut str) => {
                if is_ascii_printable(&str) {
                    str.make_ascii_lowercase();
                    str
                } else {
                    DOMString::new()
                }
            }
        };
        let span: i64 = max(relativeEnd - relativeStart, 0);
        let global = self.global.root();
        match self.bytes {
            None => Blob::new(global.r(), None, &relativeContentType),
            Some(ref vec) => {
                let start = relativeStart.to_usize().unwrap();
                let end = (relativeStart + span).to_usize().unwrap();
                let mut bytes: Vec<u8> = Vec::new();
                bytes.extend_from_slice(&vec[start..end]);
                Blob::new(global.r(), Some(bytes), &relativeContentType)
            }
        }
    }

    // https://dev.w3.org/2006/webapi/FileAPI/#dfn-isClosed
    fn IsClosed(&self) -> bool {
        self.isClosed_.get()
    }

    // https://dev.w3.org/2006/webapi/FileAPI/#dfn-close
    fn Close(&self) {
        // Step 1
        if self.isClosed_.get() {
            return;
        }

        // Step 2
        self.isClosed_.set(true);

        // TODO Step 3 if Blob URL Store is implemented

    }
}
<commit_msg>Update FileAPI spec links<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::BlobBinding;
use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use dom::bindings::error::Fallible;
use dom::bindings::global::{GlobalField, GlobalRef};
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use num::ToPrimitive;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::cell::Cell;
use std::cmp::{max, min};
use std::sync::mpsc::Sender;
use util::str::DOMString;

// https://w3c.github.io/FileAPI/#blob
#[dom_struct]
pub struct Blob {
    reflector_: Reflector,
    bytes: Option<Vec<u8>>,
    typeString: String,
    global: GlobalField,
    isClosed_: Cell<bool>,
}

fn is_ascii_printable(string: &str) -> bool {
    // Step 5.1 in Sec 5.1 of File API spec
    // https://w3c.github.io/FileAPI/#constructorBlob
    string.chars().all(|c| c >= '\x20' && c <= '\x7E')
}

impl Blob {
    pub fn new_inherited(global: GlobalRef, bytes: Option<Vec<u8>>, typeString: &str) -> Blob {
        Blob {
            reflector_: Reflector::new(),
            bytes: bytes,
            typeString: typeString.to_owned(),
            global: GlobalField::from_rooted(&global),
            isClosed_: Cell::new(false),
        }
    }

    pub fn new(global: GlobalRef, bytes: Option<Vec<u8>>, typeString: &str) -> Root<Blob> {
        reflect_dom_object(box Blob::new_inherited(global, bytes, typeString),
                           global,
                           BlobBinding::Wrap)
    }

    // https://w3c.github.io/FileAPI/#constructorBlob
    pub fn Constructor(global: GlobalRef) -> Fallible<Root<Blob>> {
        Ok(Blob::new(global, None, ""))
    }

    // https://w3c.github.io/FileAPI/#constructorBlob
    pub fn Constructor_(global: GlobalRef,
                        blobParts: DOMString,
                        blobPropertyBag: &BlobBinding::BlobPropertyBag)
                        -> Fallible<Root<Blob>> {
        // TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView or Blob
        // FIXME(ajeffrey): convert directly from a DOMString to a Vec<u8>
        let bytes: Option<Vec<u8>> = Some(String::from(blobParts).into_bytes());
        let typeString = if is_ascii_printable(&blobPropertyBag.type_) {
            &*blobPropertyBag.type_
        } else {
            ""
        };
        Ok(Blob::new(global, bytes, &typeString.to_ascii_lowercase()))
    }

    pub fn read_out_buffer(&self, send: Sender<Vec<u8>>) {
        send.send(self.bytes.clone().unwrap_or(vec![])).unwrap();
    }

    // simpler to use version of read_out_buffer
    pub fn clone_bytes(&self) -> Vec<u8> {
        self.bytes.clone().unwrap_or(vec![])
    }
}

impl BlobMethods for Blob {
    // https://w3c.github.io/FileAPI/#dfn-size
    fn Size(&self) -> u64 {
        match self.bytes {
            None => 0,
            Some(ref bytes) => bytes.len() as u64,
        }
    }

    // https://w3c.github.io/FileAPI/#dfn-type
    fn Type(&self) -> DOMString {
        DOMString::from(self.typeString.clone())
    }

    // https://w3c.github.io/FileAPI/#slice-method-algo
    fn Slice(&self,
             start: Option<i64>,
             end: Option<i64>,
             contentType: Option<DOMString>)
             -> Root<Blob> {
        let size: i64 = self.Size().to_i64().unwrap();
        let relativeStart: i64 = match start {
            None => 0,
            Some(start) => {
                if start < 0 {
                    max(size.to_i64().unwrap() + start, 0)
                } else {
                    min(start, size)
                }
            }
        };
        let relativeEnd: i64 = match end {
            None => size,
            Some(end) => {
                if end < 0 {
                    max(size + end, 0)
                } else {
                    min(end, size)
                }
            }
        };
        let relativeContentType = match contentType {
            None => DOMString::new(),
            Some(mut str) => {
                if is_ascii_printable(&str) {
                    str.make_ascii_lowercase();
                    str
                } else {
                    DOMString::new()
                }
            }
        };
        let span: i64 = max(relativeEnd - relativeStart, 0);
        let global = self.global.root();
        match self.bytes {
            None => Blob::new(global.r(), None, &relativeContentType),
            Some(ref vec) => {
                let start = relativeStart.to_usize().unwrap();
                let end = (relativeStart + span).to_usize().unwrap();
                let mut bytes: Vec<u8> = Vec::new();
                bytes.extend_from_slice(&vec[start..end]);
                Blob::new(global.r(), Some(bytes), &relativeContentType)
            }
        }
    }

    // https://w3c.github.io/FileAPI/#dfn-isClosed
    fn IsClosed(&self) -> bool {
        self.isClosed_.get()
    }

    // https://w3c.github.io/FileAPI/#dfn-close
    fn Close(&self) {
        // Step 1
        if self.isClosed_.get() {
            return;
        }

        // Step 2
        self.isClosed_.set(true);

        // TODO Step 3 if Blob URL Store is implemented

    }
}
<|endoftext|>


<commit_before>pub trait BitFlags<T>:
    core::ops::BitOr<Output = Self>
    + core::ops::BitOrAssign
    + core::ops::BitXor<Output = Self>
    + core::ops::BitXorAssign
    + core::ops::BitAnd<Output = Self>
    + core::ops::BitAndAssign
    + core::ops::Sub<Output = Self>
    + core::ops::SubAssign
    + core::ops::Not<Output = Self>
    + core::iter::Extend<Self>
    + core::iter::FromIterator<Self>
{
    /// Returns an empty set of flags.
    fn empty() -> Self;
    /// Returns the set containing all flags.
    fn all() -> Self;
    /// Returns the raw value of the flags currently stored.
    fn bits(&self) -> T;
    /// Convert from underlying bit representation, unless that
    /// representation contains bits that do not correspond to a flag.
    fn from_bits(bits: T) -> core::option::Option<Self>;
    /// Convert from underlying bit representation, dropping any bits
    /// that do not correspond to flags.
    unsafe fn from_bits_truncate(bits: T) -> Self;
    /// Convert from underlying bit representation, preserving all
    /// bits (even those not corresponding to a defined flag).
    ///
    /// # Safety
    ///
    /// The caller of the `bitflags!` macro can chose to allow or
    /// disallow extra bits for their bitflags type.
    ///
    /// The caller of `from_bits_unchecked()` has to ensure that
    /// all bits correspond to a defined flag or that extra bits
    /// are valid for this bitflags type.
    unsafe fn from_bits_unchecked(bits: T) -> Self;
    /// Returns `true` if no flags are currently stored.
    fn is_empty(&self) -> bool;
    /// Returns `true` if all flags are currently set.
    fn is_all(&self) -> bool;
    /// Returns `true` if there are flags common to both `self` and `other`.
    fn intersects(&self, other: Self) -> bool;
    /// Returns `true` all of the flags in `other` are contained within `self`.
    fn contains(&self, other: Self) -> bool;
    /// Inserts the specified flags in-place.
    fn insert(&mut self, other: Self);
    /// Removes the specified flags in-place.
    fn remove(&mut self, other: Self);
    /// Toggles the specified flags in-place.
    fn toggle(&mut self, other: Self);
    /// Inserts or removes the specified flags depending on the passed value.
    fn set(&mut self, other: Self, value: bool);
}
<commit_msg>missing trait bounds for BitFlags trait<commit_after>pub trait BitFlags<T>:
    core::ops::BitOr<Output = Self>
    + core::ops::BitOrAssign
    + core::ops::BitXor<Output = Self>
    + core::ops::BitXorAssign
    + core::ops::BitAnd<Output = Self>
    + core::ops::BitAndAssign
    + core::ops::Sub<Output = Self>
    + core::ops::SubAssign
    + core::ops::Not<Output = Self>
    + core::iter::Extend<Self>
    + core::iter::FromIterator<Self>
    + core::fmt::Debug
    + core::cmp::PartialEq<Self>
    + core::cmp::Eq
    + core::cmp::PartialOrd<Self>
    + core::cmp::Ord
    + core::hash::Hash
    + Copy
    + core::fmt::Octal
    + core::fmt::Binary
    + core::fmt::LowerHex
    + core::fmt::UpperHex
    + Clone
{
    /// Returns an empty set of flags.
    fn empty() -> Self;
    /// Returns the set containing all flags.
    fn all() -> Self;
    /// Returns the raw value of the flags currently stored.
    fn bits(&self) -> T;
    /// Convert from underlying bit representation, unless that
    /// representation contains bits that do not correspond to a flag.
    fn from_bits(bits: T) -> core::option::Option<Self>;
    /// Convert from underlying bit representation, dropping any bits
    /// that do not correspond to flags.
    unsafe fn from_bits_truncate(bits: T) -> Self;
    /// Convert from underlying bit representation, preserving all
    /// bits (even those not corresponding to a defined flag).
    ///
    /// # Safety
    ///
    /// The caller of the `bitflags!` macro can chose to allow or
    /// disallow extra bits for their bitflags type.
    ///
    /// The caller of `from_bits_unchecked()` has to ensure that
    /// all bits correspond to a defined flag or that extra bits
    /// are valid for this bitflags type.
    unsafe fn from_bits_unchecked(bits: T) -> Self;
    /// Returns `true` if no flags are currently stored.
    fn is_empty(&self) -> bool;
    /// Returns `true` if all flags are currently set.
    fn is_all(&self) -> bool;
    /// Returns `true` if there are flags common to both `self` and `other`.
    fn intersects(&self, other: Self) -> bool;
    /// Returns `true` all of the flags in `other` are contained within `self`.
    fn contains(&self, other: Self) -> bool;
    /// Inserts the specified flags in-place.
    fn insert(&mut self, other: Self);
    /// Removes the specified flags in-place.
    fn remove(&mut self, other: Self);
    /// Toggles the specified flags in-place.
    fn toggle(&mut self, other: Self);
    /// Inserts or removes the specified flags depending on the passed value.
    fn set(&mut self, other: Self, value: bool);
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # Components are functions
//!
//! We can treat a component as a pair of functions: one to send data to it, and one to retrieve its
//! current status. This can be a convenient way to try them out.
//!
//! Components are asynchronous: they can receive or publish new results at any time. To accomodate this,
//! when a component is converted into a functional form, two functions result: `send()` to send data to
//! the component and `recv()` to retrieve the component's current state.
//!
//! # Endpoints
//!
//! Endpoints can be used to retrieve both a sending and a receiving function for a component.
//!
//! ## Example
//!
//! Here's the definition of a component that adds two numbers together:
//!
//! ```
//! # extern crate tametree;
//! # extern crate rustc_serialize;
//! # fn main() {
//! # use tametree::component::*;
//! # use tametree::component::immediate_publisher::*;
//! #
//! #[derive(RustcEncodable, RustcDecodable)]
//! struct InputTree {
//!     a: i32,
//!     b: i32,
//! };
//! impl EncodeToTreeNode for InputTree { }
//!
//! #[derive(RustcEncodable, RustcDecodable)]
//! struct ResultTree {
//!     result: i32
//! };
//! impl EncodeToTreeNode for ResultTree { }
//!
//! let component = component_fn(|input: &InputTree| {
//!    ResultTree { result: input.a + input.b }
//! });
//! # }
//! ```
//!
//! We can call `ComponentEndPoint::<InputTree, ResultTree>::new(component)` to turn this into
//! a pair of functions that are convenient to call:
//!
//! ```
//! # extern crate tametree;
//! # extern crate rustc_serialize;
//! # fn main() {
//! # use tametree::component::*;
//! # use tametree::component::immediate_publisher::*;
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct InputTree {
//! #     a: i32,
//! #     b: i32,
//! # };
//! # impl EncodeToTreeNode for InputTree { }
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct ResultTree {
//! #     result: i32
//! # };
//! # impl EncodeToTreeNode for ResultTree { }
//! #
//! # let component = component_fn(|input: &InputTree| {
//! #    ResultTree { result: input.a + input.b }
//! # });
//! #
//! let mut endpoint = ComponentEndPoint::<InputTree, ResultTree>::new(component);
//!
//! endpoint.send(InputTree { a: 4, b: 7 });
//! let result_tree = endpoint.recv();  // == Some({ result: 11 }) as this component updates immediately
//! # assert!(result_tree.unwrap().result == 11);
//! # }
//! ```
//!
//! # Receiver functions
//!
//! This adds the ability to call get_receiver() with a type on any consumer in order to create a function
//! that can be called to retrieve its current value as a tree or any object that can be decoded from a
//! tree.
//!
//! ## Example
//!
//! ```
//! # extern crate tametree;
//! # extern crate rustc_serialize;
//! # fn main() {
//! # use tametree::component::*;
//! # use tametree::component::immediate_publisher::*;
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct InputTree {
//! #     a: i32,
//! #     b: i32,
//! # };
//! # impl EncodeToTreeNode for InputTree { }
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct ResultTree {
//! #     result: i32
//! # };
//! # impl EncodeToTreeNode for ResultTree { }
//! #
//! # let component = component_fn(|input: &InputTree| {
//! #    ResultTree { result: input.a + input.b }
//! # });
//! #
//! # let mut publisher         = ImmediatePublisher::new();
//! # let mut input_consumer    = publisher.create_consumer();
//! # let mut output_publisher  = ImmediatePublisher::new();
//! # let mut consumer          = output_publisher.create_consumer();
//! # let _active_component     = component.into_component(input_consumer, output_publisher);
//! let mut receiver: RecvFn<ResultTree> = consumer.get_receiver();
//!
//! publisher.publish(TreeChange::new(&(), TreeChangeType::Child, Some(&InputTree { a: 4, b: 7 }.to_tree_node())));
//! let result_tree = receiver();           // == Some(12) for our test component
//! # assert!(result_tree.unwrap().result == 11);
//! # }
//!
//! ```

use std::rc::*;
use std::marker::PhantomData;

use super::super::tree::*;
use super::super::util::clonecell::*;
use super::component::*;
use super::immediate_publisher::*;
use super::output_tree_publisher::*;

///
/// Defines the type of a receiver function
///
pub type RecvFn<TOut> = Box<Fn() -> Option<TOut>>;

///
/// Trait implemented by objects that can call a receiving function
///
pub trait Receiver<TOut> {
    ///
    /// Retrieves a function that can be used to get the last known value of this receiver (or `None` if it can't be converted to `TOut`)
    ///
    fn get_receiver(&mut self) -> RecvFn<TOut>;
}

impl Receiver<TreeRef> for ConsumerRef {
    ///
    /// Retrieves a function that can be used to get the last known value of this receiver (or `None` if it can't be converted to `TOut`)
    ///
    fn get_receiver(&mut self) -> RecvFn<TreeRef> {
        let tree        = Rc::new(CloneCell::new("".to_tree_node()));
        let also_tree   = tree.clone();

        self.subscribe(TreeAddress::Here, TreeExtent::SubTree, Box::new(move |change| {
            let current_tree = (*tree).get();
            let altered_tree = change.apply(&current_tree);
            (*tree).set(altered_tree);
        }));

        Box::new(move || {
            Some((*also_tree).get())
        })
    }
}

impl<TOut: 'static + DecodeFromTreeNode + Sized> Receiver<TOut> for ConsumerRef {
    ///
    /// Retrieves a function that can be used to get the last known value of this receiver (or `None` if it can't be converted to `TOut`)
    ///
    fn get_receiver(&mut self) -> Box<Fn() -> Option<TOut>> {
        let tree_receiver: Box<Fn() -> Option<TreeRef>> = self.get_receiver();

        Box::new(move || {
            if let Some(tree) = tree_receiver() {
                if let Ok(result) = TOut::new_from_tree(&tree) {
                    Some(result)
                } else {
                    None
                }
            } else {
                None
            }
        })
    }
}

///
/// A component endpoint provides a basic input/output interface to a component, allowing data to be sent to it
/// and its output retrieved.
///
pub struct ComponentEndPoint<TIn, TOut>
    where   TIn: 'static + ToTreeNode,
            TOut: 'static + DecodeFromTreeNode {
    _component: ComponentRef,
    reader:     Box<Fn() -> TreeRef>,
    input:      PublisherRef,

    phantom_in: PhantomData<TIn>,
    phantom_out: PhantomData<TOut>
}

impl<TIn, TOut> ComponentEndPoint<TIn, TOut>
    where   TIn: 'static + ToTreeNode,
            TOut: 'static + DecodeFromTreeNode {
    ///
    /// Creates a new endpoint from an object that can create a component
    ///
    pub fn new<TComponent: ConvertToComponent>(component: TComponent) -> ComponentEndPoint<TIn, TOut> {
        let input       = ImmediatePublisher::new();
        let consumer    = input.create_consumer();
        let output      = OutputTreePublisher::new();
        let reader      = output.get_tree_reader();

        let component   = component.into_component(consumer, output);

        ComponentEndPoint { _component: component, reader: reader, input: input, phantom_in: PhantomData, phantom_out: PhantomData }
    }

    ///
    /// Sends new data to the component
    ///
    #[inline]
    pub fn send(&mut self, data: TIn) {
        self.input.publish(TreeChange::new(&(), TreeChangeType::Child, Some(&data.to_tree_node())));
    }

    ///
    /// Retrieves the current state of the component's output
    ///
    /// If the output does not conform to the type `TOut`, then this will return `None`
    ///
    #[inline]
    pub fn recv(&self) -> Option<TOut> {
        let reader = &self.reader;

        TOut::new_from_tree(&reader()).ok()
    }
}
<commit_msg>Fix the tree change generation in components_are_functions<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # Components are functions
//!
//! We can treat a component as a pair of functions: one to send data to it, and one to retrieve its
//! current status. This can be a convenient way to try them out.
//!
//! Components are asynchronous: they can receive or publish new results at any time. To accomodate this,
//! when a component is converted into a functional form, two functions result: `send()` to send data to
//! the component and `recv()` to retrieve the component's current state.
//!
//! # Endpoints
//!
//! Endpoints can be used to retrieve both a sending and a receiving function for a component.
//!
//! ## Example
//!
//! Here's the definition of a component that adds two numbers together:
//!
//! ```
//! # extern crate tametree;
//! # extern crate rustc_serialize;
//! # fn main() {
//! # use tametree::component::*;
//! # use tametree::component::immediate_publisher::*;
//! #
//! #[derive(RustcEncodable, RustcDecodable)]
//! struct InputTree {
//!     a: i32,
//!     b: i32,
//! };
//! impl EncodeToTreeNode for InputTree { }
//!
//! #[derive(RustcEncodable, RustcDecodable)]
//! struct ResultTree {
//!     result: i32
//! };
//! impl EncodeToTreeNode for ResultTree { }
//!
//! let component = component_fn(|input: &InputTree| {
//!    ResultTree { result: input.a + input.b }
//! });
//! # }
//! ```
//!
//! We can call `ComponentEndPoint::<InputTree, ResultTree>::new(component)` to turn this into
//! a pair of functions that are convenient to call:
//!
//! ```
//! # extern crate tametree;
//! # extern crate rustc_serialize;
//! # fn main() {
//! # use tametree::component::*;
//! # use tametree::component::immediate_publisher::*;
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct InputTree {
//! #     a: i32,
//! #     b: i32,
//! # };
//! # impl EncodeToTreeNode for InputTree { }
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct ResultTree {
//! #     result: i32
//! # };
//! # impl EncodeToTreeNode for ResultTree { }
//! #
//! # let component = component_fn(|input: &InputTree| {
//! #    ResultTree { result: input.a + input.b }
//! # });
//! #
//! let mut endpoint = ComponentEndPoint::<InputTree, ResultTree>::new(component);
//!
//! endpoint.send(InputTree { a: 4, b: 7 });
//! let result_tree = endpoint.recv();  // == Some({ result: 11 }) as this component updates immediately
//! # assert!(result_tree.unwrap().result == 11);
//! # }
//! ```
//!
//! # Receiver functions
//!
//! This adds the ability to call get_receiver() with a type on any consumer in order to create a function
//! that can be called to retrieve its current value as a tree or any object that can be decoded from a
//! tree.
//!
//! ## Example
//!
//! ```
//! # extern crate tametree;
//! # extern crate rustc_serialize;
//! # fn main() {
//! # use tametree::component::*;
//! # use tametree::component::immediate_publisher::*;
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct InputTree {
//! #     a: i32,
//! #     b: i32,
//! # };
//! # impl EncodeToTreeNode for InputTree { }
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct ResultTree {
//! #     result: i32
//! # };
//! # impl EncodeToTreeNode for ResultTree { }
//! #
//! # let component = component_fn(|input: &InputTree| {
//! #    ResultTree { result: input.a + input.b }
//! # });
//! #
//! # let mut publisher         = ImmediatePublisher::new();
//! # let mut input_consumer    = publisher.create_consumer();
//! # let mut output_publisher  = ImmediatePublisher::new();
//! # let mut consumer          = output_publisher.create_consumer();
//! # let _active_component     = component.into_component(input_consumer, output_publisher);
//! let mut receiver: RecvFn<ResultTree> = consumer.get_receiver();
//!
//! publisher.publish(TreeChange::new(&(), TreeChangeType::Child, Some(&InputTree { a: 4, b: 7 }.to_tree_node())));
//! let result_tree = receiver();           // == Some(12) for our test component
//! # assert!(result_tree.unwrap().result == 11);
//! # }
//!
//! ```

use std::rc::*;
use std::marker::PhantomData;

use super::super::tree::*;
use super::super::util::clonecell::*;
use super::component::*;
use super::immediate_publisher::*;
use super::output_tree_publisher::*;

///
/// Defines the type of a receiver function
///
pub type RecvFn<TOut> = Box<Fn() -> Option<TOut>>;

///
/// Trait implemented by objects that can call a receiving function
///
pub trait Receiver<TOut> {
    ///
    /// Retrieves a function that can be used to get the last known value of this receiver (or `None` if it can't be converted to `TOut`)
    ///
    fn get_receiver(&mut self) -> RecvFn<TOut>;
}

impl Receiver<TreeRef> for ConsumerRef {
    ///
    /// Retrieves a function that can be used to get the last known value of this receiver (or `None` if it can't be converted to `TOut`)
    ///
    fn get_receiver(&mut self) -> RecvFn<TreeRef> {
        let tree        = Rc::new(CloneCell::new("".to_tree_node()));
        let also_tree   = tree.clone();

        self.subscribe(TreeAddress::Here, TreeExtent::SubTree, Box::new(move |change| {
            let current_tree = (*tree).get();
            let altered_tree = change.apply(&current_tree);
            (*tree).set(altered_tree);
        }));

        Box::new(move || {
            Some((*also_tree).get())
        })
    }
}

impl<TOut: 'static + DecodeFromTreeNode + Sized> Receiver<TOut> for ConsumerRef {
    ///
    /// Retrieves a function that can be used to get the last known value of this receiver (or `None` if it can't be converted to `TOut`)
    ///
    fn get_receiver(&mut self) -> Box<Fn() -> Option<TOut>> {
        let tree_receiver: Box<Fn() -> Option<TreeRef>> = self.get_receiver();

        Box::new(move || {
            if let Some(tree) = tree_receiver() {
                if let Ok(result) = TOut::new_from_tree(&tree) {
                    Some(result)
                } else {
                    None
                }
            } else {
                None
            }
        })
    }
}

///
/// A component endpoint provides a basic input/output interface to a component, allowing data to be sent to it
/// and its output retrieved.
///
pub struct ComponentEndPoint<TIn, TOut>
    where   TIn: 'static + ToTreeNode,
            TOut: 'static + DecodeFromTreeNode {
    _component: ComponentRef,
    reader:     Box<Fn() -> TreeRef>,
    input:      PublisherRef,

    phantom_in: PhantomData<TIn>,
    phantom_out: PhantomData<TOut>
}

impl<TIn, TOut> ComponentEndPoint<TIn, TOut>
    where   TIn: 'static + ToTreeNode,
            TOut: 'static + DecodeFromTreeNode {
    ///
    /// Creates a new endpoint from an object that can create a component
    ///
    pub fn new<TComponent: ConvertToComponent>(component: TComponent) -> ComponentEndPoint<TIn, TOut> {
        let input       = ImmediatePublisher::new();
        let consumer    = input.create_consumer();
        let output      = OutputTreePublisher::new();
        let reader      = output.get_tree_reader();

        let component   = component.into_component(consumer, output);

        ComponentEndPoint { _component: component, reader: reader, input: input, phantom_in: PhantomData, phantom_out: PhantomData }
    }

    ///
    /// Sends new data to the component
    ///
    #[inline]
    pub fn send(&mut self, data: TIn) {
        self.input.publish(TreeChange::new(&(), &data.to_tree_node()));
    }

    ///
    /// Retrieves the current state of the component's output
    ///
    /// If the output does not conform to the type `TOut`, then this will return `None`
    ///
    #[inline]
    pub fn recv(&self) -> Option<TOut> {
        let reader = &self.reader;

        TOut::new_from_tree(&reader()).ok()
    }
}
<|endoftext|>


<commit_before>use compositor::{self, Server};
use wlroots::{Compositor, InputManagerHandler, KeyboardHandler, Keyboard, Capability};

pub struct InputManager;

impl InputManager {
    pub fn new() -> Self {
        InputManager
    }
}

impl InputManagerHandler for InputManager {
    fn keyboard_added(&mut self, compositor: &mut Compositor, keyboard: &mut Keyboard)
                      -> Option<Box<KeyboardHandler>> {
        let server: &mut Server = compositor.into();
        run_handles!([(seat: {&mut server.seat})] => {
            let mut capabilities = seat.capabilities();
            capabilities.insert(Capability::Keyboard);
            seat.set_capabilities(capabilities);
        }).expect("Seat was not initialized");
        // TODO Remove the keyboard when removed, should be able to but have to patch wlroots-rs
        server.keyboards.push(keyboard.weak_reference());
        Some(Box::new(compositor::Keyboard))
    }
}
<commit_msg>Removing keyboard destroys handle and updates seat<commit_after>use compositor::{self, Server};
use wlroots::{Compositor, InputManagerHandler, KeyboardHandler, Keyboard, Capability};

pub struct InputManager;

impl InputManager {
    pub fn new() -> Self {
        InputManager
    }
}

impl InputManagerHandler for InputManager {
    fn keyboard_added(&mut self, compositor: &mut Compositor, keyboard: &mut Keyboard)
                      -> Option<Box<KeyboardHandler>> {
        let server: &mut Server = compositor.into();
        run_handles!([(seat: {&mut server.seat})] => {
            let mut capabilities = seat.capabilities();
            capabilities.insert(Capability::Keyboard);
            seat.set_capabilities(capabilities);
        }).expect("Seat was destroyed");
        server.keyboards.push(keyboard.weak_reference());
        Some(Box::new(compositor::Keyboard))
    }

    fn keyboard_removed(&mut self, compositor: &mut Compositor, keyboard: &mut Keyboard) {
        let server: &mut Server = compositor.into();
        let weak_reference = keyboard.weak_reference();
        let index = server.keyboards.iter().position(|k| *k == weak_reference);
        if let Some(index) = index {
            server.keyboards.remove(index);
            if server.keyboards.len() == 0 {
                run_handles!([(seat: {&mut server.seat})] => {
                    let mut capabilities = seat.capabilities();
                    capabilities.remove(Capability::Keyboard);
                    seat.set_capabilities(capabilities);
                }).expect("Seat was destroyed")
            }
        }
    }
}
<|endoftext|>