<commit_before>use crate::{Command, Entry, History, Queue, Record, Result, Timeline};
use std::collections::VecDeque;

/// A checkpoint wrapper.
///
/// Wraps a record or history and gives it checkpoint functionality.
/// This allows the record or history to cancel all changes made since creating the checkpoint.
///
/// # Examples
/// ```
/// # use undo::*;
/// # struct Add(char);
/// # impl Command<String> for Add {
/// #     fn apply(&mut self, s: &mut String) -> undo::Result {
/// #         s.push(self.0);
/// #         Ok(())
/// #     }
/// #     fn undo(&mut self, s: &mut String) -> undo::Result {
/// #         self.0 = s.pop().ok_or("`s` is empty")?;
/// #         Ok(())
/// #     }
/// # }
/// # fn main() -> undo::Result {
/// let mut record = Record::default();
/// let mut cp = record.checkpoint();
/// cp.apply(Add('a'))?;
/// cp.apply(Add('b'))?;
/// cp.apply(Add('c'))?;
/// assert_eq!(cp.target(), "abc");
/// cp.cancel()?;
/// assert_eq!(record.target(), "");
/// # Ok(())
/// # }
/// ```
#[cfg_attr(feature = "display", derive(Debug))]
pub struct Checkpoint<'a, T: Timeline> {
    inner: &'a mut T,
    stack: Vec<Action<T::Target>>,
}

impl<'a, T: Timeline> Checkpoint<'a, T> {
    /// Returns a checkpoint.
    #[inline]
    pub fn new(inner: &'a mut T) -> Checkpoint<'a, T> {
        Checkpoint {
            inner,
            stack: Vec::new(),
        }
    }

    /// Reserves capacity for at least `additional` more commands in the checkpoint.
    ///
    /// # Panics
    /// Panics if the new capacity overflows usize.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        self.stack.reserve(additional);
    }

    /// Returns the capacity of the checkpoint.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.stack.capacity()
    }

    /// Shrinks the capacity of the checkpoint as much as possible.
    #[inline]
    pub fn shrink_to_fit(&mut self) {
        self.stack.shrink_to_fit();
    }

    /// Returns the number of commands in the checkpoint.
    #[inline]
    pub fn len(&self) -> usize {
        self.stack.len()
    }

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

    /// Calls the `undo` method.
    #[inline]
    pub fn undo(&mut self) -> Option<Result> {
        let undo = self.inner.undo();
        if let Some(Ok(_)) = undo {
            self.stack.push(Action::Undo);
        }
        undo
    }

    /// Calls the `redo` method.
    #[inline]
    pub fn redo(&mut self) -> Option<Result> {
        let redo = self.inner.redo();
        if let Some(Ok(_)) = redo {
            self.stack.push(Action::Redo);
        }
        redo
    }

    /// Commits the changes and consumes the checkpoint.
    #[inline]
    pub fn commit(self) {}
}

impl<T> Checkpoint<'_, Record<T>> {
    /// Calls the [`apply`] method.
    ///
    /// [`apply`]: struct.Record.html#method.apply
    #[inline]
    pub fn apply(&mut self, command: impl Command<T>) -> Result {
        let saved = self.inner.saved;
        let (_, v) = self.inner.__apply(Entry::new(command))?;
        self.stack.push(Action::Apply(saved, v));
        Ok(())
    }

    /// Calls the [`go_to`] method.
    ///
    /// [`go_to`]: struct.Record.html#method.go_to
    #[inline]
    pub fn go_to(&mut self, current: usize) -> Option<Result> {
        let old = self.inner.current();
        let go_to = self.inner.go_to(current);
        if let Some(Ok(_)) = go_to {
            self.stack.push(Action::GoTo(0, old));
        }
        go_to
    }

    /// Calls the [`extend`] method.
    ///
    /// [`extend`]: struct.Record.html#method.extend
    #[inline]
    pub fn extend<C: Command<T>>(&mut self, commands: impl IntoIterator<Item = C>) -> Result {
        for command in commands {
            self.apply(command)?;
        }
        Ok(())
    }

    /// Cancels the changes and consumes the checkpoint.
    ///
    /// # Errors
    /// If an error occur when canceling the changes, the error is returned
    /// and the remaining commands are not canceled.
    #[inline]
    pub fn cancel(self) -> Result {
        for action in self.stack.into_iter().rev() {
            match action {
                Action::Apply(saved, mut v) => {
                    if let Some(Err(error)) = self.inner.undo() {
                        return Err(error);
                    }
                    let current = self.inner.current();
                    self.inner.commands.truncate(current);
                    self.inner.commands.append(&mut v);
                    self.inner.saved = saved;
                }
                Action::Undo => {
                    if let Some(Err(error)) = self.inner.redo() {
                        return Err(error);
                    }
                }
                Action::Redo => {
                    if let Some(Err(error)) = self.inner.undo() {
                        return Err(error);
                    }
                }
                Action::GoTo(_, current) => {
                    if let Some(Err(error)) = self.inner.go_to(current) {
                        return Err(error);
                    }
                }
            }
        }
        Ok(())
    }

    /// Returns a queue.
    #[inline]
    pub fn queue(&mut self) -> Queue<Record<T>> {
        self.inner.queue()
    }

    /// Returns a checkpoint.
    #[inline]
    pub fn checkpoint(&mut self) -> Checkpoint<Record<T>> {
        self.inner.checkpoint()
    }

    /// Returns a reference to the `target`.
    #[inline]
    pub fn target(&self) -> &T {
        self.inner.target()
    }

    /// Returns a mutable reference to the `target`.
    ///
    /// This method should **only** be used when doing changes that should not be able to be undone.
    #[inline]
    pub fn target_mut(&mut self) -> &mut T {
        self.inner.target_mut()
    }
}

impl<T> Checkpoint<'_, History<T>> {
    /// Calls the [`apply`] method.
    ///
    /// [`apply`]: struct.History.html#method.apply
    #[inline]
    pub fn apply(&mut self, command: impl Command<T>) -> Result {
        let root = self.inner.branch();
        let old = self.inner.current();
        self.inner.apply(command)?;
        self.stack.push(Action::GoTo(root, old));
        Ok(())
    }

    /// Calls the [`go_to`] method.
    ///
    /// [`go_to`]: struct.History.html#method.go_to
    #[inline]
    pub fn go_to(&mut self, branch: usize, current: usize) -> Option<Result> {
        let root = self.inner.branch();
        let old = self.inner.current();
        let go_to = self.inner.go_to(branch, current);
        if let Some(Ok(_)) = go_to {
            self.stack.push(Action::GoTo(root, old));
        }
        go_to
    }

    /// Calls the [`extend`] method.
    ///
    /// [`extend`]: struct.History.html#method.extend
    #[inline]
    pub fn extend<C: Command<T>>(&mut self, commands: impl IntoIterator<Item = C>) -> Result {
        for command in commands {
            self.apply(command)?;
        }
        Ok(())
    }

    /// Cancels the changes and consumes the checkpoint.
    ///
    /// # Errors
    /// If an error occur when canceling the changes, the error is returned
    /// and the remaining commands are not canceled.
    #[inline]
    pub fn cancel(self) -> Result {
        for action in self.stack.into_iter().rev() {
            match action {
                Action::Apply(_, _) => unreachable!(),
                Action::Undo => {
                    if let Some(Err(error)) = self.inner.redo() {
                        return Err(error);
                    }
                }
                Action::Redo => {
                    if let Some(Err(error)) = self.inner.undo() {
                        return Err(error);
                    }
                }
                Action::GoTo(branch, current) => {
                    if let Some(Err(error)) = self.inner.go_to(branch, current) {
                        return Err(error);
                    }
                }
            }
        }
        Ok(())
    }

    /// Returns a queue.
    #[inline]
    pub fn queue(&mut self) -> Queue<History<T>> {
        self.inner.queue()
    }

    /// Returns a checkpoint.
    #[inline]
    pub fn checkpoint(&mut self) -> Checkpoint<History<T>> {
        self.inner.checkpoint()
    }

    /// Returns a reference to the `target`.
    #[inline]
    pub fn target(&self) -> &T {
        self.inner.target()
    }

    /// Returns a mutable reference to the `target`.
    ///
    /// This method should **only** be used when doing changes that should not be able to be undone.
    #[inline]
    pub fn target_mut(&mut self) -> &mut T {
        self.inner.target_mut()
    }
}

impl<T> Timeline for Checkpoint<'_, Record<T>> {
    type Target = T;

    #[inline]
    fn apply(&mut self, command: impl Command<T>) -> Result {
        self.apply(command)
    }

    #[inline]
    fn undo(&mut self) -> Option<Result> {
        self.undo()
    }

    #[inline]
    fn redo(&mut self) -> Option<Result> {
        self.redo()
    }
}

impl<T> Timeline for Checkpoint<'_, History<T>> {
    type Target = T;

    #[inline]
    fn apply(&mut self, command: impl Command<T>) -> Result {
        self.apply(command)
    }

    #[inline]
    fn undo(&mut self) -> Option<Result> {
        self.undo()
    }

    #[inline]
    fn redo(&mut self) -> Option<Result> {
        self.redo()
    }
}

impl<'a, T: Timeline> From<&'a mut T> for Checkpoint<'a, T> {
    #[inline]
    fn from(inner: &'a mut T) -> Self {
        Checkpoint::new(inner)
    }
}

/// An action that can be applied to a Record or History.
#[cfg_attr(feature = "display", derive(Debug))]
enum Action<T> {
    Apply(Option<usize>, VecDeque<Entry<T>>),
    Undo,
    Redo,
    GoTo(usize, usize),
}

#[cfg(all(test, not(feature = "display")))]
mod tests {
    use crate::*;

    struct Add(char);

    impl Command<String> for Add {
        fn apply(&mut self, s: &mut String) -> Result {
            s.push(self.0);
            Ok(())
        }

        fn undo(&mut self, s: &mut String) -> Result {
            self.0 = s.pop().ok_or("`s` is empty")?;
            Ok(())
        }
    }

    #[test]
    fn commit() {
        let mut record = Record::default();
        let mut cp1 = record.checkpoint();
        cp1.apply(Add('a')).unwrap();
        cp1.apply(Add('b')).unwrap();
        cp1.apply(Add('c')).unwrap();
        assert_eq!(cp1.target(), "abc");
        let mut cp2 = cp1.checkpoint();
        cp2.apply(Add('d')).unwrap();
        cp2.apply(Add('e')).unwrap();
        cp2.apply(Add('f')).unwrap();
        assert_eq!(cp2.target(), "abcdef");
        let mut cp3 = cp2.checkpoint();
        cp3.apply(Add('g')).unwrap();
        cp3.apply(Add('h')).unwrap();
        cp3.apply(Add('i')).unwrap();
        assert_eq!(cp3.target(), "abcdefghi");
        cp3.commit();
        cp2.commit();
        cp1.commit();
        assert_eq!(record.target(), "abcdefghi");
    }

    #[test]
    fn cancel() {
        let mut record = Record::default();
        let mut cp1 = record.checkpoint();
        cp1.apply(Add('a')).unwrap();
        cp1.apply(Add('b')).unwrap();
        cp1.apply(Add('c')).unwrap();
        let mut cp2 = cp1.checkpoint();
        cp2.apply(Add('d')).unwrap();
        cp2.apply(Add('e')).unwrap();
        cp2.apply(Add('f')).unwrap();
        let mut cp3 = cp2.checkpoint();
        cp3.apply(Add('g')).unwrap();
        cp3.apply(Add('h')).unwrap();
        cp3.apply(Add('i')).unwrap();
        assert_eq!(cp3.target(), "abcdefghi");
        cp3.cancel().unwrap();
        assert_eq!(cp2.target(), "abcdef");
        cp2.cancel().unwrap();
        assert_eq!(cp1.target(), "abc");
        cp1.cancel().unwrap();
        assert_eq!(record.target(), "");
    }

    #[test]
    fn saved() {
        let mut record = Record::default();
        record.apply(Add('a')).unwrap();
        record.apply(Add('b')).unwrap();
        record.apply(Add('c')).unwrap();
        record.set_saved(true);
        record.undo().unwrap().unwrap();
        record.undo().unwrap().unwrap();
        record.undo().unwrap().unwrap();
        let mut cp = record.checkpoint();
        cp.apply(Add('d')).unwrap();
        cp.apply(Add('e')).unwrap();
        cp.apply(Add('f')).unwrap();
        assert_eq!(cp.target(), "def");
        cp.cancel().unwrap();
        assert_eq!(record.target(), "");
        record.redo().unwrap().unwrap();
        record.redo().unwrap().unwrap();
        record.redo().unwrap().unwrap();
        assert!(record.is_saved());
        assert_eq!(record.target(), "abc");
    }
}
<commit_msg>Restore history state when cancelling checkpoint<commit_after>use crate::{Command, Entry, History, Queue, Record, Result, Timeline};
use std::collections::VecDeque;

/// A checkpoint wrapper.
///
/// Wraps a record or history and gives it checkpoint functionality.
/// This allows the record or history to cancel all changes made since creating the checkpoint.
///
/// # Examples
/// ```
/// # use undo::*;
/// # struct Add(char);
/// # impl Command<String> for Add {
/// #     fn apply(&mut self, s: &mut String) -> undo::Result {
/// #         s.push(self.0);
/// #         Ok(())
/// #     }
/// #     fn undo(&mut self, s: &mut String) -> undo::Result {
/// #         self.0 = s.pop().ok_or("`s` is empty")?;
/// #         Ok(())
/// #     }
/// # }
/// # fn main() -> undo::Result {
/// let mut record = Record::default();
/// let mut cp = record.checkpoint();
/// cp.apply(Add('a'))?;
/// cp.apply(Add('b'))?;
/// cp.apply(Add('c'))?;
/// assert_eq!(cp.target(), "abc");
/// cp.cancel()?;
/// assert_eq!(record.target(), "");
/// # Ok(())
/// # }
/// ```
#[cfg_attr(feature = "display", derive(Debug))]
pub struct Checkpoint<'a, T: Timeline> {
    inner: &'a mut T,
    stack: Vec<Action<T::Target>>,
}

impl<'a, T: Timeline> Checkpoint<'a, T> {
    /// Returns a checkpoint.
    #[inline]
    pub fn new(inner: &'a mut T) -> Checkpoint<'a, T> {
        Checkpoint {
            inner,
            stack: Vec::new(),
        }
    }

    /// Reserves capacity for at least `additional` more commands in the checkpoint.
    ///
    /// # Panics
    /// Panics if the new capacity overflows usize.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        self.stack.reserve(additional);
    }

    /// Returns the capacity of the checkpoint.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.stack.capacity()
    }

    /// Shrinks the capacity of the checkpoint as much as possible.
    #[inline]
    pub fn shrink_to_fit(&mut self) {
        self.stack.shrink_to_fit();
    }

    /// Returns the number of commands in the checkpoint.
    #[inline]
    pub fn len(&self) -> usize {
        self.stack.len()
    }

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

    /// Calls the `undo` method.
    #[inline]
    pub fn undo(&mut self) -> Option<Result> {
        let undo = self.inner.undo();
        if let Some(Ok(_)) = undo {
            self.stack.push(Action::Undo);
        }
        undo
    }

    /// Calls the `redo` method.
    #[inline]
    pub fn redo(&mut self) -> Option<Result> {
        let redo = self.inner.redo();
        if let Some(Ok(_)) = redo {
            self.stack.push(Action::Redo);
        }
        redo
    }

    /// Commits the changes and consumes the checkpoint.
    #[inline]
    pub fn commit(self) {}
}

impl<T> Checkpoint<'_, Record<T>> {
    /// Calls the [`apply`] method.
    ///
    /// [`apply`]: struct.Record.html#method.apply
    #[inline]
    pub fn apply(&mut self, command: impl Command<T>) -> Result {
        let saved = self.inner.saved;
        let (_, commands) = self.inner.__apply(Entry::new(command))?;
        self.stack.push(Action::Apply(saved, commands));
        Ok(())
    }

    /// Calls the [`go_to`] method.
    ///
    /// [`go_to`]: struct.Record.html#method.go_to
    #[inline]
    pub fn go_to(&mut self, current: usize) -> Option<Result> {
        let old = self.inner.current();
        let go_to = self.inner.go_to(current);
        if let Some(Ok(_)) = go_to {
            self.stack.push(Action::GoTo(0, old));
        }
        go_to
    }

    /// Calls the [`extend`] method.
    ///
    /// [`extend`]: struct.Record.html#method.extend
    #[inline]
    pub fn extend<C: Command<T>>(&mut self, commands: impl IntoIterator<Item = C>) -> Result {
        for command in commands {
            self.apply(command)?;
        }
        Ok(())
    }

    /// Cancels the changes and consumes the checkpoint.
    ///
    /// # Errors
    /// If an error occur when canceling the changes, the error is returned
    /// and the remaining commands are not canceled.
    #[inline]
    pub fn cancel(self) -> Result {
        for action in self.stack.into_iter().rev() {
            match action {
                Action::Apply(saved, mut commands) => {
                    self.inner.undo().unwrap()?;
                    self.inner.commands.pop_back();
                    self.inner.commands.append(&mut commands);
                    self.inner.saved = saved;
                }
                Action::Branch(_, _) => unreachable!(),
                Action::Undo => self.inner.redo().unwrap()?,
                Action::Redo => self.inner.undo().unwrap()?,
                Action::GoTo(_, current) => self.inner.go_to(current).unwrap()?,
            }
        }
        Ok(())
    }

    /// Returns a queue.
    #[inline]
    pub fn queue(&mut self) -> Queue<Record<T>> {
        self.inner.queue()
    }

    /// Returns a checkpoint.
    #[inline]
    pub fn checkpoint(&mut self) -> Checkpoint<Record<T>> {
        self.inner.checkpoint()
    }

    /// Returns a reference to the `target`.
    #[inline]
    pub fn target(&self) -> &T {
        self.inner.target()
    }

    /// Returns a mutable reference to the `target`.
    ///
    /// This method should **only** be used when doing changes that should not be able to be undone.
    #[inline]
    pub fn target_mut(&mut self) -> &mut T {
        self.inner.target_mut()
    }
}

impl<T> Checkpoint<'_, History<T>> {
    /// Calls the [`apply`] method.
    ///
    /// [`apply`]: struct.History.html#method.apply
    #[inline]
    pub fn apply(&mut self, command: impl Command<T>) -> Result {
        let branch = self.inner.branch();
        let current = self.inner.current();
        self.inner.apply(command)?;
        self.stack.push(Action::Branch(branch, current));
        Ok(())
    }

    /// Calls the [`go_to`] method.
    ///
    /// [`go_to`]: struct.History.html#method.go_to
    #[inline]
    pub fn go_to(&mut self, branch: usize, current: usize) -> Option<Result> {
        let root = self.inner.branch();
        let old = self.inner.current();
        let go_to = self.inner.go_to(branch, current);
        if let Some(Ok(_)) = go_to {
            self.stack.push(Action::GoTo(root, old));
        }
        go_to
    }

    /// Calls the [`extend`] method.
    ///
    /// [`extend`]: struct.History.html#method.extend
    #[inline]
    pub fn extend<C: Command<T>>(&mut self, commands: impl IntoIterator<Item = C>) -> Result {
        for command in commands {
            self.apply(command)?;
        }
        Ok(())
    }

    /// Cancels the changes and consumes the checkpoint.
    ///
    /// # Errors
    /// If an error occur when canceling the changes, the error is returned
    /// and the remaining commands are not canceled.
    #[inline]
    pub fn cancel(self) -> Result {
        for action in self.stack.into_iter().rev() {
            match action {
                Action::Apply(_, _) => unreachable!(),
                Action::Branch(branch, current) => {
                    let root = self.inner.branch();
                    self.inner.go_to(branch, current).unwrap()?;
                    if root == branch {
                        self.inner.record.commands.pop_back();
                    } else {
                        self.inner.branches.remove(&root).unwrap();
                    }
                }
                Action::Undo => self.inner.redo().unwrap()?,
                Action::Redo => self.inner.undo().unwrap()?,
                Action::GoTo(branch, current) => self.inner.go_to(branch, current).unwrap()?,
            }
        }
        Ok(())
    }

    /// Returns a queue.
    #[inline]
    pub fn queue(&mut self) -> Queue<History<T>> {
        self.inner.queue()
    }

    /// Returns a checkpoint.
    #[inline]
    pub fn checkpoint(&mut self) -> Checkpoint<History<T>> {
        self.inner.checkpoint()
    }

    /// Returns a reference to the `target`.
    #[inline]
    pub fn target(&self) -> &T {
        self.inner.target()
    }

    /// Returns a mutable reference to the `target`.
    ///
    /// This method should **only** be used when doing changes that should not be able to be undone.
    #[inline]
    pub fn target_mut(&mut self) -> &mut T {
        self.inner.target_mut()
    }
}

impl<T> Timeline for Checkpoint<'_, Record<T>> {
    type Target = T;

    #[inline]
    fn apply(&mut self, command: impl Command<T>) -> Result {
        self.apply(command)
    }

    #[inline]
    fn undo(&mut self) -> Option<Result> {
        self.undo()
    }

    #[inline]
    fn redo(&mut self) -> Option<Result> {
        self.redo()
    }
}

impl<T> Timeline for Checkpoint<'_, History<T>> {
    type Target = T;

    #[inline]
    fn apply(&mut self, command: impl Command<T>) -> Result {
        self.apply(command)
    }

    #[inline]
    fn undo(&mut self) -> Option<Result> {
        self.undo()
    }

    #[inline]
    fn redo(&mut self) -> Option<Result> {
        self.redo()
    }
}

impl<'a, T: Timeline> From<&'a mut T> for Checkpoint<'a, T> {
    #[inline]
    fn from(inner: &'a mut T) -> Self {
        Checkpoint::new(inner)
    }
}

/// An action that can be applied to a Record or History.
#[cfg_attr(feature = "display", derive(Debug))]
enum Action<T> {
    Apply(Option<usize>, VecDeque<Entry<T>>),
    Branch(usize, usize),
    Undo,
    Redo,
    GoTo(usize, usize),
}

#[cfg(all(test, not(feature = "display")))]
mod tests {
    use crate::*;

    struct Add(char);

    impl Command<String> for Add {
        fn apply(&mut self, s: &mut String) -> Result {
            s.push(self.0);
            Ok(())
        }

        fn undo(&mut self, s: &mut String) -> Result {
            self.0 = s.pop().ok_or("`s` is empty")?;
            Ok(())
        }
    }

    #[test]
    fn commit() {
        let mut record = Record::default();
        let mut cp1 = record.checkpoint();
        cp1.apply(Add('a')).unwrap();
        cp1.apply(Add('b')).unwrap();
        cp1.apply(Add('c')).unwrap();
        assert_eq!(cp1.target(), "abc");
        let mut cp2 = cp1.checkpoint();
        cp2.apply(Add('d')).unwrap();
        cp2.apply(Add('e')).unwrap();
        cp2.apply(Add('f')).unwrap();
        assert_eq!(cp2.target(), "abcdef");
        let mut cp3 = cp2.checkpoint();
        cp3.apply(Add('g')).unwrap();
        cp3.apply(Add('h')).unwrap();
        cp3.apply(Add('i')).unwrap();
        assert_eq!(cp3.target(), "abcdefghi");
        cp3.commit();
        cp2.commit();
        cp1.commit();
        assert_eq!(record.target(), "abcdefghi");
    }

    #[test]
    fn cancel() {
        let mut record = Record::default();
        let mut cp1 = record.checkpoint();
        cp1.apply(Add('a')).unwrap();
        cp1.apply(Add('b')).unwrap();
        cp1.apply(Add('c')).unwrap();
        let mut cp2 = cp1.checkpoint();
        cp2.apply(Add('d')).unwrap();
        cp2.apply(Add('e')).unwrap();
        cp2.apply(Add('f')).unwrap();
        let mut cp3 = cp2.checkpoint();
        cp3.apply(Add('g')).unwrap();
        cp3.apply(Add('h')).unwrap();
        cp3.apply(Add('i')).unwrap();
        assert_eq!(cp3.target(), "abcdefghi");
        cp3.cancel().unwrap();
        assert_eq!(cp2.target(), "abcdef");
        cp2.cancel().unwrap();
        assert_eq!(cp1.target(), "abc");
        cp1.cancel().unwrap();
        assert_eq!(record.target(), "");
    }

    #[test]
    fn saved() {
        let mut record = Record::default();
        record.apply(Add('a')).unwrap();
        record.apply(Add('b')).unwrap();
        record.apply(Add('c')).unwrap();
        record.set_saved(true);
        record.undo().unwrap().unwrap();
        record.undo().unwrap().unwrap();
        record.undo().unwrap().unwrap();
        let mut cp = record.checkpoint();
        cp.apply(Add('d')).unwrap();
        cp.apply(Add('e')).unwrap();
        cp.apply(Add('f')).unwrap();
        assert_eq!(cp.target(), "def");
        cp.cancel().unwrap();
        assert_eq!(record.target(), "");
        record.redo().unwrap().unwrap();
        record.redo().unwrap().unwrap();
        record.redo().unwrap().unwrap();
        assert!(record.is_saved());
        assert_eq!(record.target(), "abc");
    }
}
<|endoftext|>


<commit_before>fn generate_expression(size: &i32) -> Vec<char> {
    vec!['[', ']', ']', '[']
}

fn well_formed(expr: &Vec<char>) -> bool {
    let mut count = 0;

    for b in expr {
        if count < 0 {
            break;
        }

        match *b {
            '[' => count += 1,
            _ => count -= 1,
        }
    }

    count == 0
}

fn main() {
    for n in (1..10) {
        let expr = generate_expression(&n);
        let wf = well_formed(&expr);
        let wf_str: String = expr.into_iter().collect();

        println!("'{}' is {}",
                 wf_str,
                 if wf {"well formed"} else {"NOT well formed"});
    }
}
<commit_msg>Generating vec of brackets<commit_after>use std::iter::repeat;

fn generate_expression(size: &usize) -> Vec<char> {
    let opens = repeat('[').take(*size);
    let closes = repeat(']').take(*size);
    let expr = opens.chain(&closes).collect();

    expr
}

fn well_formed(expr: &Vec<char>) -> bool {
    let mut count = 0;

    for b in expr {
        if count < 0 {
            break;
        }

        match *b {
            '[' => count += 1,
            _ => count -= 1,
        }
    }

    count == 0
}

fn main() {
    for n in (1..10) {
        let expr = generate_expression(&n);
        let wf = well_formed(&expr);
        let wf_str: String = expr.into_iter().collect();

        println!("'{}' is {}",
                 wf_str,
                 if wf {"well formed"} else {"NOT well formed"});
    }
}
<|endoftext|>


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

use ::engine::config;
use ::engine::backend;
use ::util::Logger;

use std::cell::RefCell;
use std::rc::Rc;
use std::boxed::Box;
use std::process;

/*===============================================================================================*/
/*------STATIC VARIABLES-------------------------------------------------------------------------*/
/*===============================================================================================*/

static mut APP_POINTER: Option <*mut App> = None;

/*===============================================================================================*/
/*------APP STRUCT-------------------------------------------------------------------------------*/
/*===============================================================================================*/

/// The app
///
/// This is the main control center of ionCore.
/// It is in charge of initialization, updating, and shutdown of all modules,
/// as well as the handing of any inter-module communication.
#[derive (Clone)]
pub struct App {

    // Public
    /// The backend manager.
    pub backend_mgr: Rc<RefCell<backend::Manager>>,
    /// The config manager.
    pub config_mgr: Rc<RefCell<config::Manager>>,
}

/*===============================================================================================*/
/*------APPVERSION PUBLIC STATIC METHODS---------------------------------------------------------*/
/*===============================================================================================*/

impl App {

    /// Initializes the app
    pub fn init () {

        // Check if not already initialized
        if !App::is_initialized () {

            Logger::init ("./ionCore.log", true).unwrap ();
            info! ("Initializing ionCore | Version: {}", env! ("CARGO_PKG_VERSION"));

            let ab = Box::new (App {

                config_mgr: Rc::new (RefCell::new (config::Manager::new ())),
                backend_mgr: Rc::new (RefCell::new (backend::Manager::new ())),
            });

            unsafe {APP_POINTER = Some (Box::into_raw (ab))};
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Load the config files for all modules.
    pub fn load_config () {

        // Query the config directory
        let cfg_mgr = App::get_config_manager ().unwrap ();
        cfg_mgr.borrow_mut ().query_config_dir ();

        // Load config files
        let backend_mgr = App::get_backend_manager ().unwrap ();
        backend_mgr.borrow_mut ().load_config ();
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Checks if the app has been initialized.
    ///
    /// # Return value
    /// A bool returning whether the app has been initialized.
    pub fn is_initialized () -> bool {

        unsafe {

            match APP_POINTER {

                Some (pointer) => !pointer.is_null (),
                None => false
            }
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Returns a pointer to the backend manager instance.
    ///
    /// # Examples
    /// ```
    /// # use ion_core::engine::App;
    /// # App::init ();
    /// let backend_mgr = App::get_backend_manager ().unwrap ();
    /// println! ("{}", backend_mgr.borrow ().default_audio_backend);
    pub fn get_backend_manager () -> Result<Rc<RefCell<backend::Manager>>, ()> {

        // Check if app is initialized
        if App::is_initialized () {
            return Ok (unsafe {&*APP_POINTER.unwrap ()}.backend_mgr.clone ());
        }

        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Returns a pointer to the config manager instance.
    ///
    /// # Examples
    /// ```
    /// # use ion_core::engine::App;
    /// #
    /// # App::init ();
    /// let cfg = App::get_config_manager ().unwrap ();
    /// println! ("{}", cfg.borrow ().config_dir);
    pub fn get_config_manager () -> Result<Rc<RefCell<config::Manager>>, ()> {

        // Check if app is initialized
        if App::is_initialized () {
            return Ok (unsafe {&*APP_POINTER.unwrap ()}.config_mgr.clone ());
        }

        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Releases the app instance.
    ///
    /// After this point, any app commands will be ignored.
    pub fn release () {

        // Check if app is initialized
        if App::is_initialized () {

            info! ("Shutting down ion Core.");

            unsafe {

                drop (Box::from_raw (APP_POINTER.unwrap ()));
                APP_POINTER = None;
            };

            // Shut down the application
            info! ("Terminating the application.");
            process::exit (0);
        }
    }
}
<commit_msg>Renamed 'release' method to 'exit'<commit_after>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*===============================================================================================*/

use ::engine::config;
use ::engine::backend;
use ::util::Logger;

use std::cell::RefCell;
use std::rc::Rc;
use std::boxed::Box;
use std::process;

/*===============================================================================================*/
/*------STATIC VARIABLES-------------------------------------------------------------------------*/
/*===============================================================================================*/

static mut APP_POINTER: Option <*mut App> = None;

/*===============================================================================================*/
/*------APP STRUCT-------------------------------------------------------------------------------*/
/*===============================================================================================*/

/// The app
///
/// This is the main control center of ionCore.
/// It is in charge of initialization, updating, and shutdown of all modules,
/// as well as the handing of any inter-module communication.
#[derive (Clone)]
pub struct App {

    // Public
    /// The backend manager.
    pub backend_mgr: Rc<RefCell<backend::Manager>>,
    /// The config manager.
    pub config_mgr: Rc<RefCell<config::Manager>>,
}

/*===============================================================================================*/
/*------APPVERSION PUBLIC STATIC METHODS---------------------------------------------------------*/
/*===============================================================================================*/

impl App {

    /// Initializes the app
    pub fn init () {

        // Check if not already initialized
        if !App::is_initialized () {

            Logger::init ("./ionCore.log", true).unwrap ();
            info! ("Initializing ionCore | Version: {}", env! ("CARGO_PKG_VERSION"));

            let ab = Box::new (App {

                config_mgr: Rc::new (RefCell::new (config::Manager::new ())),
                backend_mgr: Rc::new (RefCell::new (backend::Manager::new ())),
            });

            unsafe {APP_POINTER = Some (Box::into_raw (ab))};
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Load the config files for all modules.
    pub fn load_config () {

        // Query the config directory
        let cfg_mgr = App::get_config_manager ().unwrap ();
        cfg_mgr.borrow_mut ().query_config_dir ();

        // Load config files
        let backend_mgr = App::get_backend_manager ().unwrap ();
        backend_mgr.borrow_mut ().load_config ();
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Checks if the app has been initialized.
    ///
    /// # Return value
    /// A bool returning whether the app has been initialized.
    pub fn is_initialized () -> bool {

        unsafe {

            match APP_POINTER {

                Some (pointer) => !pointer.is_null (),
                None => false
            }
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Returns a pointer to the backend manager instance.
    ///
    /// # Examples
    /// ```
    /// # use ion_core::engine::App;
    /// # App::init ();
    /// let backend_mgr = App::get_backend_manager ().unwrap ();
    /// println! ("{}", backend_mgr.borrow ().default_audio_backend);
    pub fn get_backend_manager () -> Result<Rc<RefCell<backend::Manager>>, ()> {

        // Check if app is initialized
        if App::is_initialized () {
            return Ok (unsafe {&*APP_POINTER.unwrap ()}.backend_mgr.clone ());
        }

        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Returns a pointer to the config manager instance.
    ///
    /// # Examples
    /// ```
    /// # use ion_core::engine::App;
    /// #
    /// # App::init ();
    /// let cfg = App::get_config_manager ().unwrap ();
    /// println! ("{}", cfg.borrow ().config_dir);
    pub fn get_config_manager () -> Result<Rc<RefCell<config::Manager>>, ()> {

        // Check if app is initialized
        if App::is_initialized () {
            return Ok (unsafe {&*APP_POINTER.unwrap ()}.config_mgr.clone ());
        }

        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Releases all resources, and exits the application.
    pub fn exit () {

        // Check if app is initialized
        if App::is_initialized () {

            info! ("Shutting down ion Core.");

            unsafe {

                drop (Box::from_raw (APP_POINTER.unwrap ()));
                APP_POINTER = None;
            };

            // Shut down the application
            info! ("Terminating the application.");
            process::exit (0);
        }
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;

use sdl2::event::{Event,WindowEvent};
use sdl2::keyboard::Keycode;
use sdl2::render::{TextureCreator, Texture};
use sdl2::surface::{Surface};

use std::collections::HashMap;
use std::path::Path;

pub mod input;
pub mod graphics;

pub struct Game<'t> {
    pub renderer: sdl2::render::WindowCanvas,
    pub events: sdl2::EventPump,
    pub screen: graphics::screen::Screen,
    textures: HashMap<&'static str, Texture<'t>>
}

impl<'t> Game<'t> {
    pub fn start(&mut self) {
        // loop until we receive a QuitEvent
        'event : loop {
            // poll_event returns the most recent event or NoEvent if nothing has happened
            for event in self.events.poll_iter() {
                match event {
                    Event::Quit{..} => break 'event,
                    Event::Window {win_event, ..} => {
                        match win_event {
                            // refresh our window, for example if it is no longer
                            // covered by other windows
                            WindowEvent::Exposed => self.renderer.present(),
                            _                      => (),
                        }
                    }
                    Event::KeyDown {keycode: Some(keycode), ..} => {
                        match keycode {
                            Keycode::Escape => break 'event,
                            _               => (), // TODO: Update current keyboard state
                        }
                    }
                    _               => continue
                }
            }
            self.screen.update();
            self.screen.draw();
        }
    }

    pub fn set_screen(&mut self, new_screen: graphics::screen::Screen) {
        self.screen = new_screen;
    }

    pub fn load_texture(&mut self, texture_creator: &mut TextureCreator<sdl2::video::WindowContext>, name: &'static str, path: &'static str) -> Texture {
        // Load a surface.
        // Surfaces live in system RAM, so they aren't ideal for performance.
        let surface = match Surface::load_bmp(&Path::new(path)) {
            Ok(surface) => surface,
            Err(err)    => panic!("failed to load surface: {}", err)
        };

        // Convert a surface to a texture.
        // Textures can be used more efficiently by the GPU. (If one is available.)
        let texture = match texture_creator.create_texture_from_surface(&surface) {
            Ok(texture) => texture,
            Err(err)    => panic!("failed to convert surface: {:?}", err)
        };

        self.textures.insert(name, texture);
        return texture;
    }
}

pub fn new(title:&str) -> Game {
    // start sdl2
    let ctx = sdl2::init().unwrap();
    let video_ctx = ctx.video().unwrap();

    // Get the display mode
    let disp = match video_ctx.current_display_mode(0) {
        Ok(disp) => disp,
        Err(err) => panic!("failed to get display mode: {}", err)
    };

    // Create a window
    let mut window = match video_ctx.window(title, disp.w as u32, disp.h as u32).position_centered().opengl().build() {
        Ok(window) => window,
        Err(err)   => panic!("failed to create window: {}", err)
    };

    let _ = window.set_bordered(false);

    // Create a rendering context
    let renderer = match window.into_canvas().build() {
        Ok(renderer) => renderer,
        Err(err)     => panic!("failed to create renderer: {}", err)
    };

    let events = ctx.event_pump().unwrap();

    return Game {
        renderer: renderer,
        events: events,
        screen: graphics::screen::Screen { components: Vec::new() },
        textures: HashMap::new()
    };
}
<commit_msg>Solve Texture lifetime issue<commit_after>extern crate sdl2;

use sdl2::event::{Event,WindowEvent};
use sdl2::keyboard::Keycode;
use sdl2::render::{TextureCreator, Texture};
use sdl2::surface::{Surface};

use std::collections::HashMap;
use std::path::Path;

pub mod input;
pub mod graphics;

pub struct Game<'t> {
    pub renderer: sdl2::render::WindowCanvas,
    pub events: sdl2::EventPump,
    pub screen: graphics::screen::Screen,
    textures: HashMap<&'static str, Texture<'t>>
}

impl<'t> Game<'t> {
    pub fn start(&mut self) {
        // loop until we receive a QuitEvent
        'event : loop {
            // poll_event returns the most recent event or NoEvent if nothing has happened
            for event in self.events.poll_iter() {
                match event {
                    Event::Quit{..} => break 'event,
                    Event::Window {win_event, ..} => {
                        match win_event {
                            // refresh our window, for example if it is no longer
                            // covered by other windows
                            WindowEvent::Exposed => self.renderer.present(),
                            _                      => (),
                        }
                    }
                    Event::KeyDown {keycode: Some(keycode), ..} => {
                        match keycode {
                            Keycode::Escape => break 'event,
                            _               => (), // TODO: Update current keyboard state
                        }
                    }
                    _               => continue
                }
            }
            self.screen.update();
            self.screen.draw();
        }
    }

    pub fn set_screen(&mut self, new_screen: graphics::screen::Screen) {
        self.screen = new_screen;
    }

    pub fn load_texture(&mut self, texture_creator: &'t mut TextureCreator<sdl2::video::WindowContext>, name: &'static str, path: &'static str) {
        // Load a surface.
        // Surfaces live in system RAM, so they aren't ideal for performance.
        let surface = match Surface::load_bmp(&Path::new(path)) {
            Ok(surface) => surface,
            Err(err)    => panic!("failed to load surface: {}", err)
        };

        // Convert a surface to a texture.
        // Textures can be used more efficiently by the GPU. (If one is available.)
        let texture = match texture_creator.create_texture_from_surface(&surface) {
            Ok(texture) => texture,
            Err(err)    => panic!("failed to convert surface: {:?}", err)
        };

        self.textures.insert(name, texture);
    }
}

pub fn new(title:&str) -> Game {
    // start sdl2
    let ctx = sdl2::init().unwrap();
    let video_ctx = ctx.video().unwrap();

    // Get the display mode
    let disp = match video_ctx.current_display_mode(0) {
        Ok(disp) => disp,
        Err(err) => panic!("failed to get display mode: {}", err)
    };

    // Create a window
    let mut window = match video_ctx.window(title, disp.w as u32, disp.h as u32).position_centered().opengl().build() {
        Ok(window) => window,
        Err(err)   => panic!("failed to create window: {}", err)
    };

    let _ = window.set_bordered(false);

    // Create a rendering context
    let renderer = match window.into_canvas().build() {
        Ok(renderer) => renderer,
        Err(err)     => panic!("failed to create renderer: {}", err)
    };

    let events = ctx.event_pump().unwrap();

    return Game {
        renderer: renderer,
        events: events,
        screen: graphics::screen::Screen { components: Vec::new() },
        textures: HashMap::new()
    };
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

//! The Aptos API response / error handling philosophy.
//!
//! The return type for every endpoint should be a
//! poem::Result<MyResponse<T>, MyError> where MyResponse is an instance of
//! ApiResponse that contains only the status codes that it can actually
//! return. This will manifest in the OpenAPI spec, making it clear to users
//! what the API can actually return. The error should operate the same way,
//! where it only describes error codes that it can actually return.
//!
//! Every endpoint should be able to return data as JSON or BCS, depending on
//! the Accept header given by the client. If none is given, default to JSON.
//!
//! The client should be able to provide data to POST endpoints as either JSON
//! or BCS, given they provide the appropriate Content-Type header.
//!
//! Where possible, if the API is returning data as BCS, it should pull the
//! bytes directly from the DB where possible without further processing.
//!
//! Internally, there are many functions that can return errors. The context
//! for what type of error those functions return is lost if we return an
//! opaque error type like anyhow::Error. As such, it is important that each
//! function return error types that capture the intended status code. This
//! module defines traits to help with this, ensuring that the error types
//! returned by each function and its callers is enforced at compile time.
//! See generate_error_traits and its invocations for more on this topic.

// TODO: https://github.com/aptos-labs/aptos-core/issues/2279

use std::fmt::Display;

use super::accept_type::AcceptType;
use aptos_api_types::{AptosError, AptosErrorCode};
use poem_openapi::{payload::Json, types::ToJSON, ResponseContent};

use super::bcs_payload::Bcs;

#[derive(ResponseContent)]
pub enum AptosResponseContent<T: ToJSON + Send + Sync> {
    // When returning data as JSON, we take in T and then serialize to JSON as
    // part of the response.
    Json(Json<T>),

    // Return the data as BCS, which is just Vec<u8>. This data could have come
    // from either an internal Rust type being serialized into bytes, or just
    // the bytes directly from storage.
    Bcs(Bcs),
}

/// This trait defines common functions that all error responses should impl.
/// As a user you shouldn't worry about this, the generate_error_response macro
/// takes care of it for you. Mostly these are helpers to allow callers holding
/// an error response to manipulate the AptosError inside it.
pub trait AptosErrorResponse {
    fn inner_mut(&mut self) -> &mut AptosError;

    fn error_code(mut self, error_code: AptosErrorCode) -> Self
    where
        Self: Sized,
    {
        self.inner_mut().error_code = Some(error_code);
        self
    }

    fn aptos_ledger_version(mut self, aptos_ledger_version: u64) -> Self
    where
        Self: Sized,
    {
        self.inner_mut().aptos_ledger_version = Some(aptos_ledger_version.into());
        self
    }
}

/// This macro defines traits for all of the given status codes. In eahc trait
/// there is a function that defines a helper for building an instance of the
/// error type using that code. These traits are helpful for defining what
/// error types an internal function can return. For example, the failpoint
/// function can return an internal error, so its signature would look like:
/// fn fail_point_poem<E: InternalError>(name: &str) -> anyhow::Result<(), E>
/// This should be invoked just once, taking in every status that we use
/// throughout the entire API. Every one of these traits requires that the
/// implementor also implements AptosErrorResponse, which saves functions from
/// having to add that bound to errors themselves.
#[macro_export]
macro_rules! generate_error_traits {
    ($($trait_name:ident),*) => {
        paste::paste! {
        $(
        pub trait [<$trait_name Error>]: AptosErrorResponse {
            fn [<$trait_name:snake>](error: anyhow::Error) -> Self where Self: Sized;
            fn [<$trait_name:snake _str>](error_str: &str) -> Self where Self: Sized;
        }
        )*
        }
    };
}

/// This macro helps generate types, From impls, etc. for an error
/// response from a Poem endpoint. It generates a response type that only has
/// the specified response codes, which is then reflected in the OpenAPI spec.
/// For each status code given to a particular invocation of this macro, we
/// implement the relevant trait from generate_error_traits.
/// See the comments in the macro for an explanation of what is happening.
#[macro_export]
macro_rules! generate_error_response {
    ($enum_name:ident, $(($status:literal, $name:ident)),*) => {
        // We use the paste crate to allows us to generate the name of the code
        // enum, more on that in the comment above that enum.
        paste::paste! {

        // Generate an enum with name `enum_name`. Iterate through each of the
        // response codes, generating a variant for each with the given name
        // and status code. We always generate a variant for 500.
        #[derive(Debug, poem_openapi::ApiResponse)]
        pub enum $enum_name {
            $(
            #[oai(status = $status)]
            $name(poem_openapi::payload::Json<aptos_api_types::AptosError>),
            )*
        }

        // For each status, implement the relevant error trait. This means if
        // the macro invocation specifies Internal and BadRequest, the
        // functions internal(anyhow::Error) and bad_request(anyhow::Error)
        // will be generated. There are also variants for taking in strs.
        $(
        impl $crate::response::[<$name Error>] for $enum_name {
            fn [<$name:snake>](error: anyhow::Error) -> Self where Self: Sized {
                let error = aptos_api_types::AptosError::from(error);
                let payload = poem_openapi::payload::Json(error);
                Self::from($enum_name::$name(payload))
            }

            fn [<$name:snake _str>](error_str: &str) -> Self where Self: Sized {
                let error = aptos_api_types::AptosError::new(error_str.to_string());
                let payload = poem_openapi::payload::Json(error);
                Self::from($enum_name::$name(payload))
            }
        }
        )*
        }

        // Generate a function that helps get the AptosError within.
        impl $crate::response::AptosErrorResponse for $enum_name {
            fn inner_mut(&mut self) -> &mut aptos_api_types::AptosError {
                match self {
                    $(
                    $enum_name::$name(poem_openapi::payload::Json(inner)) => inner,
                    )*
                }
            }
        }

        impl std::error::Error for $enum_name {}

        impl std::fmt::Display for $enum_name {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{:?}", self)
            }
        }
    };
}

/// This macro helps generate types, From impls, etc. for a successful response
/// from a Poem endpoint. It generates a response type that only has the
/// specified response codes, which is then reflected in the OpenAPI spec.
/// See the comments in the macro for an explanation of what is happening.
#[macro_export]
macro_rules! generate_success_response {
    ($enum_name:ident, $(($status:literal, $name:ident)),*) => {
        // We use the paste crate to allows us to generate the name of the code
        // enum, more on that in the comment above that enum.
        paste::paste! {

        // Generate an enum with name `enum_name`. Iterate through each of the
        // response codes, generating a variant for each with the given name
        // and status code.
        #[derive(poem_openapi::ApiResponse)]
        pub enum $enum_name<T: poem_openapi::types::ToJSON + Send + Sync> {
            $(
            #[oai(status = $status)]
            $name(
                $crate::response::AptosResponseContent<T>,
                #[oai(header = "X-Aptos-Chain-Id")] u16,
                // We use just regular u64 here instead of U64 since all header
                // values are implicitly strings anyway.
                #[oai(header = "X-Aptos-Ledger-Version")] u64,
                #[oai(header = "X-Aptos-Ledger-Oldest-Version")] u64,
                #[oai(header = "X-Aptos-Ledger-TimestampUsec")] u64,
                #[oai(header = "X-Aptos-Epoch")] u64,
                #[oai(header = "X-Aptos-Block-Height")] u64,
                #[oai(header = "X-Aptos-Oldest-Block-Height")] u64,
            ),
            )*
        }

        // Generate an enum that captures all the different status codes that
        // this response type supports. To explain this funky syntax, if you
        // named the main enum MyResponse, this would become MyResponseCode.
        pub enum [<$enum_name Status>] {
            $(
            $name,
            )*
        }

        // Generate a From impl that builds a response from AptosResponseContent.
        // Each variant in the main enum takes in the same argument, so the macro
        // is really just helping us enumerate and build each variant. We use this
        // in the other From impls.
        impl <T: poem_openapi::types::ToJSON + Send + Sync> From<($crate::response::AptosResponseContent<T>, &aptos_api_types::LedgerInfo, [<$enum_name Status>])>
            for $enum_name<T>
        {
            fn from(
                (value, ledger_info, status): (
                    $crate::response::AptosResponseContent<T>,
                    &aptos_api_types::LedgerInfo,
                    [<$enum_name Status>]
                ),
            ) -> Self {
                match status {
                    $(
                    [<$enum_name Status>]::$name => {
                        $enum_name::$name(
                            value,
                            ledger_info.chain_id as u16,
                            ledger_info.ledger_version.into(),
                            ledger_info.oldest_ledger_version.into(),
                            ledger_info.ledger_timestamp.into(),
                            ledger_info.epoch.into(),
                            ledger_info.block_height.into(),
                            ledger_info.oldest_block_height.into(),
                        )
                    },
                    )*
                }
            }
        }

        // Generate a From impl that builds a response from a Json<T> and friends.
        impl<T: poem_openapi::types::ToJSON + Send + Sync> From<(poem_openapi::payload::Json<T>, &aptos_api_types::LedgerInfo, [<$enum_name Status>])>
            for $enum_name<T>
        {
            fn from(
                (value, ledger_info, status): (poem_openapi::payload::Json<T>, &aptos_api_types::LedgerInfo, [<$enum_name Status>]),
            ) -> Self {
                let content = $crate::response::AptosResponseContent::Json(value);
                Self::from((content, ledger_info, status))
            }
        }

        // Generate a From impl that builds a response from a Bcs<Vec<u8>> and friends.
        impl<T: poem_openapi::types::ToJSON + Send + Sync> From<($crate::bcs_payload::Bcs, &aptos_api_types::LedgerInfo, [<$enum_name Status>])>
            for $enum_name<T>
        {
            fn from(
                (value, ledger_info, status): (
                    $crate::bcs_payload::Bcs,
                    &aptos_api_types::LedgerInfo,
                    [<$enum_name Status>]
                ),
            ) -> Self {
                let content = $crate::response::AptosResponseContent::Bcs(value);
                Self::from((content, ledger_info, status))
            }
        }

        // Generate a TryFrom impl that builds a response from a T, an AcceptType,
        // and all the other usual suspects. It expects to be called with a generic
        // parameter E: InternalError, with which we can build an internal error
        // response in case the BCS serialization fails.
        impl<T: poem_openapi::types::ToJSON + Send + Sync + serde::Serialize> $enum_name<T> {
            pub fn try_from_rust_value<E: InternalError>(
                (value, ledger_info, status, accept_type): (
                    T,
                    &aptos_api_types::LedgerInfo,
                    [<$enum_name Status>],
                    &$crate::accept_type::AcceptType
                ),
            ) -> Result<Self, E> {
                match accept_type {
                    AcceptType::Bcs => Ok(Self::from((
                        $crate::bcs_payload::Bcs(
                            bcs::to_bytes(&value)
                                .map_err(|e| E::internal(e.into()).error_code(aptos_api_types::AptosErrorCode::BcsSerializationError))?
                        ),
                        ledger_info,
                        status
                    ))),
                    AcceptType::Json => Ok(Self::from((
                        poem_openapi::payload::Json(value),
                        ledger_info,
                        status
                    ))),
                }
            }
        }
        }
    };
}

// Generate a success response that only has an option for 200.
generate_success_response!(BasicResponse, (200, Ok));

// Generate traits defining a "from" function for each of these status types.
// The error response then impls these traits for each status type they mention.
generate_error_traits!(
    BadRequest,
    NotFound,
    PayloadTooLarge,
    Internal,
    InsufficientStorage
);

// Generate an error response that only has options for 400 and 500.
generate_error_response!(BasicError, (400, BadRequest), (500, Internal));

// This type just simplifies using BasicResponse and BasicError together.
pub type BasicResult<T> = poem::Result<BasicResponse<T>, BasicError>;

// As above but with 404.
generate_error_response!(
    BasicErrorWith404,
    (400, BadRequest),
    (404, NotFound),
    (500, Internal)
);
pub type BasicResultWith404<T> = poem::Result<BasicResponse<T>, BasicErrorWith404>;

// Just this one helper for a specific kind of 404.
pub fn build_not_found<S: Display, E: NotFoundError>(
    resource: &str,
    identifier: S,
    ledger_version: u64,
) -> E {
    E::not_found_str(&format!("{} not found by {}", resource, identifier))
        .aptos_ledger_version(ledger_version)
}
<commit_msg>[api] Allow for separation of BCS and JSON in types<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

//! The Aptos API response / error handling philosophy.
//!
//! The return type for every endpoint should be a
//! poem::Result<MyResponse<T>, MyError> where MyResponse is an instance of
//! ApiResponse that contains only the status codes that it can actually
//! return. This will manifest in the OpenAPI spec, making it clear to users
//! what the API can actually return. The error should operate the same way,
//! where it only describes error codes that it can actually return.
//!
//! Every endpoint should be able to return data as JSON or BCS, depending on
//! the Accept header given by the client. If none is given, default to JSON.
//!
//! The client should be able to provide data to POST endpoints as either JSON
//! or BCS, given they provide the appropriate Content-Type header.
//!
//! Where possible, if the API is returning data as BCS, it should pull the
//! bytes directly from the DB where possible without further processing.
//!
//! Internally, there are many functions that can return errors. The context
//! for what type of error those functions return is lost if we return an
//! opaque error type like anyhow::Error. As such, it is important that each
//! function return error types that capture the intended status code. This
//! module defines traits to help with this, ensuring that the error types
//! returned by each function and its callers is enforced at compile time.
//! See generate_error_traits and its invocations for more on this topic.

// TODO: https://github.com/aptos-labs/aptos-core/issues/2279

use std::fmt::Display;

use super::accept_type::AcceptType;
use aptos_api_types::{AptosError, AptosErrorCode};
use poem_openapi::{payload::Json, types::ToJSON, ResponseContent};

use super::bcs_payload::Bcs;

#[derive(ResponseContent)]
pub enum AptosResponseContent<T: ToJSON + Send + Sync> {
    // When returning data as JSON, we take in T and then serialize to JSON as
    // part of the response.
    Json(Json<T>),

    // Return the data as BCS, which is just Vec<u8>. This data could have come
    // from either an internal Rust type being serialized into bytes, or just
    // the bytes directly from storage.
    Bcs(Bcs),
}

/// This trait defines common functions that all error responses should impl.
/// As a user you shouldn't worry about this, the generate_error_response macro
/// takes care of it for you. Mostly these are helpers to allow callers holding
/// an error response to manipulate the AptosError inside it.
pub trait AptosErrorResponse {
    fn inner_mut(&mut self) -> &mut AptosError;

    fn error_code(mut self, error_code: AptosErrorCode) -> Self
    where
        Self: Sized,
    {
        self.inner_mut().error_code = Some(error_code);
        self
    }

    fn aptos_ledger_version(mut self, aptos_ledger_version: u64) -> Self
    where
        Self: Sized,
    {
        self.inner_mut().aptos_ledger_version = Some(aptos_ledger_version.into());
        self
    }
}

/// This macro defines traits for all of the given status codes. In eahc trait
/// there is a function that defines a helper for building an instance of the
/// error type using that code. These traits are helpful for defining what
/// error types an internal function can return. For example, the failpoint
/// function can return an internal error, so its signature would look like:
/// fn fail_point_poem<E: InternalError>(name: &str) -> anyhow::Result<(), E>
/// This should be invoked just once, taking in every status that we use
/// throughout the entire API. Every one of these traits requires that the
/// implementor also implements AptosErrorResponse, which saves functions from
/// having to add that bound to errors themselves.
#[macro_export]
macro_rules! generate_error_traits {
    ($($trait_name:ident),*) => {
        paste::paste! {
        $(
        pub trait [<$trait_name Error>]: AptosErrorResponse {
            fn [<$trait_name:snake>](error: anyhow::Error) -> Self where Self: Sized;
            fn [<$trait_name:snake _str>](error_str: &str) -> Self where Self: Sized;
        }
        )*
        }
    };
}

/// This macro helps generate types, From impls, etc. for an error
/// response from a Poem endpoint. It generates a response type that only has
/// the specified response codes, which is then reflected in the OpenAPI spec.
/// For each status code given to a particular invocation of this macro, we
/// implement the relevant trait from generate_error_traits.
/// See the comments in the macro for an explanation of what is happening.
#[macro_export]
macro_rules! generate_error_response {
    ($enum_name:ident, $(($status:literal, $name:ident)),*) => {
        // We use the paste crate to allows us to generate the name of the code
        // enum, more on that in the comment above that enum.
        paste::paste! {

        // Generate an enum with name `enum_name`. Iterate through each of the
        // response codes, generating a variant for each with the given name
        // and status code. We always generate a variant for 500.
        #[derive(Debug, poem_openapi::ApiResponse)]
        pub enum $enum_name {
            $(
            #[oai(status = $status)]
            $name(poem_openapi::payload::Json<aptos_api_types::AptosError>),
            )*
        }

        // For each status, implement the relevant error trait. This means if
        // the macro invocation specifies Internal and BadRequest, the
        // functions internal(anyhow::Error) and bad_request(anyhow::Error)
        // will be generated. There are also variants for taking in strs.
        $(
        impl $crate::response::[<$name Error>] for $enum_name {
            fn [<$name:snake>](error: anyhow::Error) -> Self where Self: Sized {
                let error = aptos_api_types::AptosError::from(error);
                let payload = poem_openapi::payload::Json(error);
                Self::from($enum_name::$name(payload))
            }

            fn [<$name:snake _str>](error_str: &str) -> Self where Self: Sized {
                let error = aptos_api_types::AptosError::new(error_str.to_string());
                let payload = poem_openapi::payload::Json(error);
                Self::from($enum_name::$name(payload))
            }
        }
        )*
        }

        // Generate a function that helps get the AptosError within.
        impl $crate::response::AptosErrorResponse for $enum_name {
            fn inner_mut(&mut self) -> &mut aptos_api_types::AptosError {
                match self {
                    $(
                    $enum_name::$name(poem_openapi::payload::Json(inner)) => inner,
                    )*
                }
            }
        }

        impl std::error::Error for $enum_name {}

        impl std::fmt::Display for $enum_name {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{:?}", self)
            }
        }
    };
}

/// This macro helps generate types, From impls, etc. for a successful response
/// from a Poem endpoint. It generates a response type that only has the
/// specified response codes, which is then reflected in the OpenAPI spec.
/// See the comments in the macro for an explanation of what is happening.
#[macro_export]
macro_rules! generate_success_response {
    ($enum_name:ident, $(($status:literal, $name:ident)),*) => {
        // We use the paste crate to allows us to generate the name of the code
        // enum, more on that in the comment above that enum.
        paste::paste! {

        // Generate an enum with name `enum_name`. Iterate through each of the
        // response codes, generating a variant for each with the given name
        // and status code.
        #[derive(poem_openapi::ApiResponse)]
        pub enum $enum_name<T: poem_openapi::types::ToJSON + Send + Sync> {
            $(
            #[oai(status = $status)]
            $name(
                $crate::response::AptosResponseContent<T>,
                #[oai(header = "X-Aptos-Chain-Id")] u16,
                // We use just regular u64 here instead of U64 since all header
                // values are implicitly strings anyway.
                #[oai(header = "X-Aptos-Ledger-Version")] u64,
                #[oai(header = "X-Aptos-Ledger-Oldest-Version")] u64,
                #[oai(header = "X-Aptos-Ledger-TimestampUsec")] u64,
                #[oai(header = "X-Aptos-Epoch")] u64,
                #[oai(header = "X-Aptos-Block-Height")] u64,
                #[oai(header = "X-Aptos-Oldest-Block-Height")] u64,
            ),
            )*
        }

        // Generate an enum that captures all the different status codes that
        // this response type supports. To explain this funky syntax, if you
        // named the main enum MyResponse, this would become MyResponseCode.
        pub enum [<$enum_name Status>] {
            $(
            $name,
            )*
        }

        // Generate a From impl that builds a response from AptosResponseContent.
        // Each variant in the main enum takes in the same argument, so the macro
        // is really just helping us enumerate and build each variant. We use this
        // in the other From impls.
        impl <T: poem_openapi::types::ToJSON + Send + Sync> From<($crate::response::AptosResponseContent<T>, &aptos_api_types::LedgerInfo, [<$enum_name Status>])>
            for $enum_name<T>
        {
            fn from(
                (value, ledger_info, status): (
                    $crate::response::AptosResponseContent<T>,
                    &aptos_api_types::LedgerInfo,
                    [<$enum_name Status>]
                ),
            ) -> Self {
                match status {
                    $(
                    [<$enum_name Status>]::$name => {
                        $enum_name::$name(
                            value,
                            ledger_info.chain_id as u16,
                            ledger_info.ledger_version.into(),
                            ledger_info.oldest_ledger_version.into(),
                            ledger_info.ledger_timestamp.into(),
                            ledger_info.epoch.into(),
                            ledger_info.block_height.into(),
                            ledger_info.oldest_block_height.into(),
                        )
                    },
                    )*
                }
            }
        }

        // Generate a From impl that builds a response from a Json<T> and friends.
        impl<T: poem_openapi::types::ToJSON + Send + Sync> From<(poem_openapi::payload::Json<T>, &aptos_api_types::LedgerInfo, [<$enum_name Status>])>
            for $enum_name<T>
        {
            fn from(
                (value, ledger_info, status): (poem_openapi::payload::Json<T>, &aptos_api_types::LedgerInfo, [<$enum_name Status>]),
            ) -> Self {
                let content = $crate::response::AptosResponseContent::Json(value);
                Self::from((content, ledger_info, status))
            }
        }

        // Generate a From impl that builds a response from a Bcs<Vec<u8>> and friends.
        impl<T: poem_openapi::types::ToJSON + Send + Sync> From<($crate::bcs_payload::Bcs, &aptos_api_types::LedgerInfo, [<$enum_name Status>])>
            for $enum_name<T>
        {
            fn from(
                (value, ledger_info, status): (
                    $crate::bcs_payload::Bcs,
                    &aptos_api_types::LedgerInfo,
                    [<$enum_name Status>]
                ),
            ) -> Self {
                let content = $crate::response::AptosResponseContent::Bcs(value);
                Self::from((content, ledger_info, status))
            }
        }

        // Generate a TryFrom impl that builds a response from a T, an AcceptType,
        // and all the other usual suspects. It expects to be called with a generic
        // parameter E: InternalError, with which we can build an internal error
        // response in case the BCS serialization fails.
        impl<T: poem_openapi::types::ToJSON + Send + Sync + serde::Serialize> $enum_name<T> {
            pub fn try_from_rust_value<E: InternalError>(
                (value, ledger_info, status, accept_type): (
                    T,
                    &aptos_api_types::LedgerInfo,
                    [<$enum_name Status>],
                    &$crate::accept_type::AcceptType
                ),
            ) -> Result<Self, E> {
                match accept_type {
                    AcceptType::Bcs => Ok(Self::from((
                        $crate::bcs_payload::Bcs(
                            bcs::to_bytes(&value)
                                .map_err(|e| E::internal(e.into()).error_code(aptos_api_types::AptosErrorCode::BcsSerializationError))?
                        ),
                        ledger_info,
                        status
                    ))),
                    AcceptType::Json => Ok(Self::from((
                        poem_openapi::payload::Json(value),
                        ledger_info,
                        status
                    ))),
                }
            }

           pub fn try_from_json<E: InternalError>(
                (value, ledger_info, status): (
                    T,
                    &aptos_api_types::LedgerInfo,
                    [<$enum_name Status>],
                ),
            ) -> Result<Self, E> {
               Ok(Self::from((
                    poem_openapi::payload::Json(value),
                    ledger_info,
                    status
               )))
            }

            pub fn try_from_bcs<B: serde::Serialize, E: InternalError>(
                (value, ledger_info, status): (
                    B,
                    &aptos_api_types::LedgerInfo,
                    [<$enum_name Status>],
                ),
            ) -> Result<Self, E> {
               Ok(Self::from((
                    $crate::bcs_payload::Bcs(
                        bcs::to_bytes(&value)
                            .map_err(|e| E::internal(e.into()).error_code(aptos_api_types::AptosErrorCode::BcsSerializationError))?
                    ),
                    ledger_info,
                    status
               )))
            }

            pub fn try_from_encoded<E: InternalError>(
                (value, ledger_info, status): (
                    Vec<u8>,
                    &aptos_api_types::LedgerInfo,
                    [<$enum_name Status>],
                ),
            ) -> Result<Self, E> {
               Ok(Self::from((
                    $crate::bcs_payload::Bcs(
                        value
                    ),
                    ledger_info,
                    status
               )))
            }
        }
        }
    };
}

// Generate a success response that only has an option for 200.
generate_success_response!(BasicResponse, (200, Ok));

// Generate traits defining a "from" function for each of these status types.
// The error response then impls these traits for each status type they mention.
generate_error_traits!(
    BadRequest,
    NotFound,
    PayloadTooLarge,
    Internal,
    InsufficientStorage
);

// Generate an error response that only has options for 400 and 500.
generate_error_response!(BasicError, (400, BadRequest), (500, Internal));

// This type just simplifies using BasicResponse and BasicError together.
pub type BasicResult<T> = poem::Result<BasicResponse<T>, BasicError>;

// As above but with 404.
generate_error_response!(
    BasicErrorWith404,
    (400, BadRequest),
    (404, NotFound),
    (500, Internal)
);
pub type BasicResultWith404<T> = poem::Result<BasicResponse<T>, BasicErrorWith404>;

// Just this one helper for a specific kind of 404.
pub fn build_not_found<S: Display, E: NotFoundError>(
    resource: &str,
    identifier: S,
    ledger_version: u64,
) -> E {
    E::not_found_str(&format!("{} not found by {}", resource, identifier))
        .aptos_ledger_version(ledger_version)
}
<|endoftext|>


<commit_before>use super::moves::Plies;
use super::pos::Position;
use super::fen;
use super::legal;
use super::make_move::make_move;
use super::mate;

#[test]
fn perf_init_pos_3_plies() {
    //perf_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
    //         &[1, 20, 400, 8902, 197281, 4865609]);
    perf_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
             &[1, 20, 400]);
}

fn perf_fen(fen_str: &str, res: &[u64]) {
    let p = fen::fen_to_position(fen_str).unwrap();
    perf_pos(&p, res);
}

fn perf_pos(p: &Position, res: &[u64]) {
    for (num_plies, expect_num_from_pos) in res.iter().enumerate() {
        assert_eq!(*expect_num_from_pos, num_from_pos(p, Plies(num_plies as u8)));
    }
}

fn num_from_pos(p: &Position, plies: Plies) -> u64 {
    if plies == Plies(0) {
        return 1;
    }
    if !mate::has_legal_moves(p.clone()) {
        return 0;
    }
    let next_plies = Plies(plies.0 - 1);
    let mut ans = 0;
    for m in legal::receive_legal(p.clone()).iter() {
        let new_pos = make_move(p.clone(), &m);
        ans += num_from_pos(&new_pos, next_plies);
    }
    ans
}
<commit_msg>Add more tests.<commit_after>use super::moves::Plies;
use super::pos::Position;
use super::fen;
use super::legal;
use super::make_move::make_move;
use super::mate;

#[test]
fn perf_init_pos_3_plies() {
    perf_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
             &[1, 20, 400, 8902]);
}

#[test]
fn perf_kiwipete_2_plies() {
    perf_fen("r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1",
             &[1, 48, 2039]);
}

fn perf_fen(fen_str: &str, res: &[u64]) {
    let p = fen::fen_to_position(fen_str).unwrap();
    perf_pos(&p, res);
}

fn perf_pos(p: &Position, res: &[u64]) {
    for (num_plies, expect_num_from_pos) in res.iter().enumerate() {
        assert_eq!(*expect_num_from_pos, num_from_pos(p, Plies(num_plies as u8)));
    }
}

fn num_from_pos(p: &Position, plies: Plies) -> u64 {
    if plies == Plies(0) {
        return 1;
    }
    if !mate::has_legal_moves(p.clone()) {
        return 0;
    }
    let next_plies = Plies(plies.0 - 1);
    let mut ans = 0;
    for m in legal::receive_legal(p.clone()).iter() {
        let new_pos = make_move(p.clone(), &m);
        ans += num_from_pos(&new_pos, next_plies);
    }
    ans
}
<|endoftext|>


<commit_before>pub struct CompareAndDeleteConditions<'a> {
    pub modified_index: Option<u64>,
    pub value: Option<&'a str>,
}

impl<'a> CompareAndDeleteConditions<'a> {
    pub fn is_empty(&self) -> bool {
        self.modified_index.is_none() && self.value.is_none()
    }
}

impl<'a> Clone for CompareAndDeleteConditions<'a> {
    fn clone(&self) -> CompareAndDeleteConditions<'a> {
        CompareAndDeleteConditions {
            modified_index: self.modified_index.clone(),
            value: self.value.clone(),
        }
    }
}
<commit_msg>CompareAndDeleteConditions no longer needs to impl Clone.<commit_after>pub struct CompareAndDeleteConditions<'a> {
    pub modified_index: Option<u64>,
    pub value: Option<&'a str>,
}

impl<'a> CompareAndDeleteConditions<'a> {
    pub fn is_empty(&self) -> bool {
        self.modified_index.is_none() && self.value.is_none()
    }
}
<|endoftext|>


<commit_before>use dns_parser::Packet as DnsPacket;
use serde_json::{Value, Map, Number};

pub struct DnsHeader {
	id: Number,
	total_questions: Number,
	total_answer_rrs: Number,
	total_authority_rrs: Number,
	total_additional_rrs: Number,
}

impl DnsHeader {
	pub fn new(p: &DnsPacket) -> DnsHeader {
		DnsHeader {
			id: Number::from(p.header.id),
			total_questions: Number::from(p.header.questions),
			total_answer_rrs: Number::from(p.header.answers),
			total_authority_rrs: Number::from(p.header.nameservers),
			total_additional_rrs: Number::from(p.header.additional),
		}
	}

	pub fn to_json_map(&self) -> Map<String, Value> {
		let mut header = Map::new();

		header.insert("id".to_string(), Value::Number(self.id.clone()));
		header.insert("total_questions".to_string(), Value::Number(self.total_questions.clone()));
		header.insert("total_answer_rrs".to_string(), Value::Number(self.total_answer_rrs.clone()));
		header.insert("total_authority_rrs".to_string(), Value::Number(self.total_authority_rrs.clone()));
		header.insert("total_additional_rrs".to_string(), Value::Number(self.total_additional_rrs.clone()));

		header
	}
}<commit_msg>Parse DNS opcode<commit_after>use dns_parser::Packet as DnsPacket;
use dns_parser::Opcode;
use serde_json::{Value, Map, Number};

pub struct DnsHeader {
	id: Number,
	opcode: String,
	total_questions: Number,
	total_answer_rrs: Number,
	total_authority_rrs: Number,
	total_additional_rrs: Number,
}

impl DnsHeader {
	pub fn new(p: &DnsPacket) -> DnsHeader {
		let opcode_number = p.header.opcode;
		let opcode_string = match opcode_number {
			Opcode::StandardQuery => "QUERY",
			Opcode::InverseQuery => "IQUERY",
			Opcode::ServerStatusRequest => "STATUS",
			_ => "UNKNOWN",
		};

		DnsHeader {
			id: Number::from(p.header.id),
			opcode: opcode_string.to_string(),
			total_questions: Number::from(p.header.questions),
			total_answer_rrs: Number::from(p.header.answers),
			total_authority_rrs: Number::from(p.header.nameservers),
			total_additional_rrs: Number::from(p.header.additional),
		}
	}

	pub fn to_json_map(&self) -> Map<String, Value> {
		let mut header = Map::new();

		header.insert("id".to_string(), Value::Number(self.id.clone()));
		header.insert("opcode".to_string(), Value::String(self.opcode.clone()));
		header.insert("total_questions".to_string(), Value::Number(self.total_questions.clone()));
		header.insert("total_answer_rrs".to_string(), Value::Number(self.total_answer_rrs.clone()));
		header.insert("total_authority_rrs".to_string(), Value::Number(self.total_authority_rrs.clone()));
		header.insert("total_additional_rrs".to_string(), Value::Number(self.total_additional_rrs.clone()));

		header
	}
}<|endoftext|>


<commit_before>extern crate alloc;

use thread_comm::ThreadInfo;
use self::alloc::heap;
use matrix::{Scalar,Mat};

use core::mem;
use core::ptr::{self};

pub struct Matrix<T: Scalar> {
    //Height and width for iteration space
    iter_h: usize,
    iter_w: usize,

    //Padding to iteration h and w
    h_padding: usize,
    w_padding: usize,

    //This Matrix may be a submatrix within a larger one
    off_y: usize,
    off_x: usize,

    //Strides and buffer
    row_stride: usize,
    column_stride: usize,
    buffer: *mut T,
    capacity: usize,
    is_alias: bool,
}
impl<T: Scalar> Matrix<T> {
    pub fn new( h: usize, w: usize ) -> Matrix<T> {
        assert!(mem::size_of::<T>() != 0, "Matrix can't handle ZSTs");
        unsafe {
            let buf = heap::allocate( (h * w + 256) * mem::size_of::<T>(), 4096 );

            Matrix{ iter_h: h, iter_w: w,
                    h_padding: 0, w_padding: 0,
                    off_y: 0, off_x: 0,
                    row_stride: 1, column_stride: h,
                    buffer: buf as *mut _,
                    capacity: h * w,
                    is_alias: false }
        }
    }

    #[inline(always)] pub fn get_row_stride( &self ) -> usize { self.row_stride }
    #[inline(always)] pub fn get_column_stride( &self ) -> usize { self.column_stride }

    #[inline(always)]
    pub unsafe fn get_buffer( &self ) -> *const T {
        self.buffer.offset((self.off_y*self.row_stride + self.off_x*self.column_stride) as isize)
    }

    #[inline(always)]
    pub unsafe fn get_mut_buffer( &mut self ) -> *mut T {
        self.buffer.offset((self.off_y*self.row_stride + self.off_x*self.column_stride) as isize)
    }
}
impl<T: Scalar> Mat<T> for Matrix<T> {
    #[inline(always)]
    fn get( &self, y: usize, x: usize) -> T {
        let y_coord = (y + self.off_y) * self.row_stride;
        let x_coord = (x + self.off_x) * self.column_stride;
        unsafe{
            ptr::read( self.buffer.offset((y_coord + x_coord) as isize) )
        }
    }
    #[inline(always)]
    fn set( &mut self, y: usize, x: usize, alpha: T) {
        let y_coord = (y + self.off_y) * self.row_stride;
        let x_coord = (x + self.off_x) * self.column_stride;
        unsafe{
            ptr::write( self.buffer.offset((y_coord + x_coord) as isize), alpha );
        }
    }
    #[inline(always)]
    fn off_y( &self ) -> usize { self.off_y }
    #[inline(always)]
    fn off_x( &self ) -> usize { self.off_x }
/*    #[inline(always)]
    fn set_height( &mut self, h: usize ) { self.h = h; }
    #[inline(always)]
    fn set_width( &mut self, w: usize ) { self.w = w; }*/
    #[inline(always)]
    fn set_off_y( &mut self, off_y: usize ) { self.off_y = off_y }
    #[inline(always)]
    fn set_off_x( &mut self, off_x: usize ) { self.off_x = off_x }

    #[inline(always)]
    fn iter_height( &self ) -> usize { self.iter_h }
    #[inline(always)]
    fn iter_width( &self ) -> usize { self.iter_w }
    #[inline(always)]
    fn set_iter_height( &mut self, iter_h: usize ) { self.iter_h = iter_h; }
    #[inline(always)]
    fn set_iter_width( &mut self, iter_w: usize ) { self.iter_w = iter_w; }

    #[inline(always)]
    fn set_logical_h_padding( &mut self, h_pad: usize ) { self.h_padding = h_pad }
    #[inline(always)]
    fn logical_h_padding( &self ) -> usize { self.h_padding }
    #[inline(always)]
    fn set_logical_w_padding( &mut self, w_pad: usize ) { self.w_padding = w_pad }
    #[inline(always)]
    fn logical_w_padding( &self ) -> usize { self.w_padding }

    #[inline(always)]
    unsafe fn make_alias( &self ) -> Self {
        Matrix{ iter_h: self.iter_h, iter_w: self.iter_w,
                h_padding: self.h_padding, w_padding: self.w_padding,
                off_y: self.off_y, off_x: self.off_x,
                row_stride: self.row_stride, column_stride: self.column_stride,
                buffer: self.buffer,
                capacity: self.capacity,
                is_alias: true }
    }

    #[inline(always)]
    unsafe fn send_alias( &mut self, thr: &ThreadInfo<T> ) {
        let buf = thr.broadcast( self.buffer );
        self.is_alias = true;
        self.buffer = buf;
    }
}
impl<T:Scalar> Drop for Matrix<T> {
    fn drop(&mut self) {
        unsafe {
            if !self.is_alias {
                heap::deallocate(self.buffer as *mut _, mem::size_of::<T>() * self.capacity, 4096);
            }
        }
    }
}
unsafe impl<T:Scalar> Send for Matrix<T> {}
<commit_msg>Added stack of views for general strided matrices<commit_after>extern crate alloc;

use thread_comm::ThreadInfo;
use self::alloc::heap;
use matrix::{Scalar,Mat};

use core::mem;
use core::ptr::{self};

pub struct MatrixView {
    offset: usize,
    padding: usize,
    iter_size: usize,
}

pub struct Matrix<T: Scalar> {
    //Stack of views of the matrix
    y_views: Vec<MatrixView>,
    x_views: Vec<MatrixView>,

    //Strides and buffer
    row_stride: usize,
    column_stride: usize,
    buffer: *mut T,
    capacity: usize,
    is_alias: bool,
}
impl<T: Scalar> Matrix<T> {
    pub fn new( h: usize, w: usize ) -> Matrix<T> {
        assert!(mem::size_of::<T>() != 0, "Matrix can't handle ZSTs");
        unsafe {
            let buf = heap::allocate( (h * w + 256) * mem::size_of::<T>(), 4096 );

            let mut y_views : Vec<MatrixView> = Vec::with_capacity( 16 );
            let mut x_views : Vec<MatrixView> = Vec::with_capacity( 16 );
            y_views.push(MatrixView{ offset: 0, padding: 0, iter_size: h });
            x_views.push(MatrixView{ offset: 0, padding: 0, iter_size: w });

            Matrix{ y_views: y_views,
                    x_views: x_views,
                    row_stride: 1, column_stride: h,
                    buffer: buf as *mut _,
                    capacity: h * w,
                    is_alias: false }
        }
    }

    #[inline(always)] pub fn get_row_stride( &self ) -> usize { self.row_stride }
    #[inline(always)] pub fn get_column_stride( &self ) -> usize { self.column_stride }

    #[inline(always)]
    pub unsafe fn get_buffer( &self ) -> *const T {
        let y_view = self.y_views.last().unwrap();
        let x_view = self.x_views.last().unwrap();

        self.buffer.offset((y_view.offset*self.row_stride + x_view.offset*self.column_stride) as isize)
    }

    #[inline(always)]
    pub unsafe fn get_mut_buffer( &mut self ) -> *mut T {
        let y_view = self.y_views.last().unwrap();
        let x_view = self.x_views.last().unwrap();

        self.buffer.offset((y_view.offset*self.row_stride + x_view.offset*self.column_stride) as isize)
    }
}
impl<T: Scalar> Mat<T> for Matrix<T> {
    #[inline(always)]
    fn get( &self, y: usize, x: usize) -> T {
        let y_view = self.y_views.last().unwrap();
        let x_view = self.x_views.last().unwrap();

        let y_coord = (y + y_view.offset) * self.row_stride;
        let x_coord = (x + x_view.offset) * self.column_stride;
        unsafe{
            ptr::read( self.buffer.offset((y_coord + x_coord) as isize) )
        }
    }
    #[inline(always)]
    fn set( &mut self, y: usize, x: usize, alpha: T) {
        let y_view = self.y_views.last().unwrap();
        let x_view = self.x_views.last().unwrap();

        let y_coord = (y + y_view.offset) * self.row_stride;
        let x_coord = (x + x_view.offset) * self.column_stride;
        unsafe{
            ptr::write( self.buffer.offset((y_coord + x_coord) as isize), alpha );
        }
    }
    #[inline(always)]
    fn off_y( &self ) -> usize {
        self.y_views.last().unwrap().offset
    }
    #[inline(always)]
    fn off_x( &self ) -> usize {
        self.x_views.last().unwrap().offset
    }

    //Still need these for parallel range but it should go away
    #[inline(always)]
    fn set_off_y( &mut self, off_y: usize ) {
        let mut y_view = self.y_views.last_mut().unwrap();
        y_view.offset = off_y;
    }
    #[inline(always)]
    fn set_off_x( &mut self, off_x: usize ) {
        let mut x_view = self.x_views.last_mut().unwrap();
        x_view.offset = off_x;
    }

    #[inline(always)]
    fn iter_height( &self ) -> usize {
        self.y_views.last().unwrap().iter_size
    }
    #[inline(always)]
    fn iter_width( &self ) -> usize {
        self.x_views.last().unwrap().iter_size
    }
    #[inline(always)]
    fn set_iter_height( &mut self, iter_h: usize ) {
        let mut y_view = self.y_views.last_mut().unwrap();
        y_view.iter_size = iter_h;
    }
    #[inline(always)]
    fn set_iter_width( &mut self, iter_w: usize ) {
        let mut x_view = self.x_views.last_mut().unwrap();
        x_view.iter_size = iter_w;
    }

    #[inline(always)]
    fn logical_h_padding( &self ) -> usize {
        self.y_views.last().unwrap().padding
    }
    #[inline(always)]
    fn logical_w_padding( &self ) -> usize {
        self.x_views.last().unwrap().padding
    }
    #[inline(always)]
    fn set_logical_h_padding( &mut self, h_pad: usize ) {
        let mut y_view = self.y_views.last_mut().unwrap();
        y_view.padding = h_pad
    }
    #[inline(always)]
    fn set_logical_w_padding( &mut self, w_pad: usize ) {
        let mut x_view = self.x_views.last_mut().unwrap();
        x_view.padding = w_pad
    }
/*
    #[inline(always)]
    fn push_x_view( &mut self );
    #[inline(always)]
    fn push_y_view( &mut self );
    #[inline(always)]
    fn pop_x_view( &mut self );
    #[inline(always)]
    fn pop_y_view( &mut self );
 */
    #[inline(always)]
    unsafe fn make_alias( &self ) -> Self {
       let x_view = self.x_views.last().unwrap();
       let y_view = self.y_views.last().unwrap();

       let mut x_views_alias : Vec<MatrixView> = Vec::with_capacity( 16 );
       let mut y_views_alias : Vec<MatrixView> = Vec::with_capacity( 16 );
       x_views_alias.push(MatrixView{ offset: x_view.offset, padding: x_view.offset, iter_size: x_view.iter_size });
       y_views_alias.push(MatrixView{ offset: y_view.offset, padding: y_view.offset, iter_size: y_view.iter_size });

        Matrix{ x_views: x_views_alias, y_views: y_views_alias,
                row_stride: self.row_stride, column_stride: self.column_stride,
                buffer: self.buffer,
                capacity: self.capacity,
                is_alias: true }
    }

    #[inline(always)]
    unsafe fn send_alias( &mut self, thr: &ThreadInfo<T> ) {
        let buf = thr.broadcast( self.buffer );
        self.is_alias = true;
        self.buffer = buf;
    }
}
impl<T:Scalar> Drop for Matrix<T> {
    fn drop(&mut self) {
        unsafe {
            if !self.is_alias {
                heap::deallocate(self.buffer as *mut _, mem::size_of::<T>() * self.capacity, 4096);
            }
        }
    }
}
unsafe impl<T:Scalar> Send for Matrix<T> {}
<|endoftext|>