<commit_before>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::io::Read;
use std::io::Write;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;
use storage::parser::{FileHeaderParser, Parser, ParserError};

use module::Module;
use runtime::Runtime;

pub type BackendOperationResult = Result<(), StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
}

impl StorageBackend {

    pub fn new(basepath: String) -> StorageBackend {
        StorageBackend {
            basepath: basepath,
        }
    }

    fn build<M: Module>(rt: &Runtime, m: &M) -> StorageBackend {
        let path = rt.get_rtp() + m.name() + "/store";
        StorageBackend::new(path)
    }

    fn get_file_ids(&self) -> Option<Vec<FileID>> {
        let list = glob(&self.basepath[..]);

        if let Ok(globlist) = list {
            let mut v = vec![];
            for entry in globlist {
                if let Ok(path) = entry {
                    v.push(from_pathbuf(&path));
                } else {
                    // Entry is not a path
                }
            }

            Some(v)
        } else {
            None
        }
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file<'a, HP>(&self, f: File, p: &Parser<HP>) ->
        Result<BackendOperationResult, ParserError>
        where HP: FileHeaderParser<'a>
    {
        let written = p.write(f.contents());
        if let Ok(string) = written {
            let path = self.build_filepath(&f);
            debug!("Writing file: {}", path);
            Ok(Ok(()))
        } else {
            Err(written.err().unwrap())
        }
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file<'a, HP>(&self, f: File, p: &Parser<HP>)
        -> Result<BackendOperationResult, ParserError>
        where HP: FileHeaderParser<'a>
    {
        let contents = p.write(f.contents());

        if contents.is_err() {
            return Err(contents.err().unwrap());
        }

        let content = contents.unwrap();

        let path = self.build_filepath(&f);
        if let Err(_) = FSFile::open(path) {
            return Ok(Err(StorageBackendError::new(
                "File::open()",
                &format!("Tried to open '{}'", path)[..],
                "Tried to update contents of this file, though file doesn't exist",
                None)))
        }

        if let Ok(mut file) = FSFile::create(path) {
            if let Err(writeerr) = file.write_all(&content.into_bytes()) {
                return Ok(Err(StorageBackendError::new(
                    "File::write()",
                    &format!("Tried to write '{}'", path)[..],
                    "Tried to write contents of this file, though operation did not succeed",
                    Some(content))))
            }
        }

        Ok(Ok(()))
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id<'a, HP>(&self, id: FileID, p: &Parser<HP>) -> Option<File>
        where HP: FileHeaderParser<'a>
    {
        let path = self.build_filepath_with_id(id);
        if let Ok(file) = FSFile::open(path) {
            let mut s = String::new();
            file.read_to_string(&mut s);
            let parser_out = p.read(s);
            if let Ok((header, data)) = parser_out {
                Some(File::from_parser_result(id, header, data))
            } else {
                info!("Cannot build File from ID '{}'. Parser Error:\n{}",
                      id, parser_out.err().unwrap());
                None
            }
        } else {
            None
        }
    }

    fn build_filepath(&self, f: &File) -> String {
        self.build_filepath_with_id(f.id())
    }

    fn build_filepath_with_id(&self, id: FileID) -> String {
        self.basepath + &id[..]
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub explanation: String,        // A long, user friendly description
    pub dataDump: Option<String>    // Data dump, if any
}

impl StorageBackendError {
    fn new(action: &'static str,
           desc  : &'static str,
           explan: &'static str,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         String::from(action),
            desc:           String::from(desc),
            explanation:    String::from(explan),
            dataDump:       data,
        }
    }
}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}\n\n{}",
               self.action, self.desc, self.explanation)
    }
}

<commit_msg>Refactor get_file_by_id() into smaller functions<commit_after>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::io::Read;
use std::io::Write;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;
use storage::parser::{FileHeaderParser, Parser, ParserError};

use module::Module;
use runtime::Runtime;

pub type BackendOperationResult = Result<(), StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
}

impl StorageBackend {

    pub fn new(basepath: String) -> StorageBackend {
        StorageBackend {
            basepath: basepath,
        }
    }

    fn build<M: Module>(rt: &Runtime, m: &M) -> StorageBackend {
        let path = rt.get_rtp() + m.name() + "/store";
        StorageBackend::new(path)
    }

    fn get_file_ids(&self) -> Option<Vec<FileID>> {
        let list = glob(&self.basepath[..]);

        if let Ok(globlist) = list {
            let mut v = vec![];
            for entry in globlist {
                if let Ok(path) = entry {
                    v.push(from_pathbuf(&path));
                } else {
                    // Entry is not a path
                }
            }

            Some(v)
        } else {
            None
        }
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file<'a, HP>(&self, f: File, p: &Parser<HP>) ->
        Result<BackendOperationResult, ParserError>
        where HP: FileHeaderParser<'a>
    {
        let written = p.write(f.contents());
        if let Ok(string) = written {
            let path = self.build_filepath(&f);
            debug!("Writing file: {}", path);
            Ok(Ok(()))
        } else {
            Err(written.err().unwrap())
        }
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file<'a, HP>(&self, f: File, p: &Parser<HP>)
        -> Result<BackendOperationResult, ParserError>
        where HP: FileHeaderParser<'a>
    {
        let contents = p.write(f.contents());

        if contents.is_err() {
            return Err(contents.err().unwrap());
        }

        let content = contents.unwrap();

        let path = self.build_filepath(&f);
        if let Err(_) = FSFile::open(path) {
            return Ok(Err(StorageBackendError::new(
                "File::open()",
                &format!("Tried to open '{}'", path)[..],
                "Tried to update contents of this file, though file doesn't exist",
                None)))
        }

        if let Ok(mut file) = FSFile::create(path) {
            if let Err(writeerr) = file.write_all(&content.into_bytes()) {
                return Ok(Err(StorageBackendError::new(
                    "File::write()",
                    &format!("Tried to write '{}'", path)[..],
                    "Tried to write contents of this file, though operation did not succeed",
                    Some(content))))
            }
        }

        Ok(Ok(()))
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id<'a, HP>(&self, id: FileID, p: &Parser<HP>) -> Option<File>
        where HP: FileHeaderParser<'a>
    {
        if let Ok(fs) = FSFile::open(self.build_filepath_with_id(id)) {
            let mut s = String::new();
            fs.read_to_string(&mut s);
            p.read(s).and_then(|(h, d)| Ok(File::from_parser_result(id, h, d))).ok()
        } else {
            None
        }
    }

    fn build_filepath(&self, f: &File) -> String {
        self.build_filepath_with_id(f.id())
    }

    fn build_filepath_with_id(&self, id: FileID) -> String {
        self.basepath + &id[..]
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub explanation: String,        // A long, user friendly description
    pub dataDump: Option<String>    // Data dump, if any
}

impl StorageBackendError {
    fn new(action: &'static str,
           desc  : &'static str,
           explan: &'static str,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         String::from(action),
            desc:           String::from(desc),
            explanation:    String::from(explan),
            dataDump:       data,
        }
    }
}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}\n\n{}",
               self.action, self.desc, self.explanation)
    }
}

<|endoftext|>


<commit_before>//! A queue-backed exclusive data lock.
//!
//
// * It is unclear how many of the unsafe methods within need actually remain
//   unsafe.

use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::cell::UnsafeCell;
use futures::{Future, Poll, Canceled};
use futures::sync::oneshot;
use crossbeam::sync::SegQueue;

 // Allows access to the data contained within a lock just like a mutex guard.
pub struct Guard<T> {
    qutex: Qutex<T>,
}

impl<T> Guard<T> {
    /// Releases the lock held by this `Guard` and returns the original `Qutex`.
    //
    // NOTE: This increments the `Qutex` reference count before immediately
    // decrementing it. Is it worth avoiding this by wrapping it in an Option
    // or using unsafe hackery? It would make uglier code for the measly
    // savings of two atomic stores...
    pub fn unlock(self) -> Qutex<T> {
        self.qutex.clone()
    }
}

impl<T> Deref for Guard<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.qutex.inner.cell.get() }
    }
}

impl<T> DerefMut for Guard<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.qutex.inner.cell.get() }
    }
}

impl<T> Drop for Guard<T> {
    fn drop(&mut self) {
        unsafe { self.qutex.direct_unlock().expect("Error dropping Guard") };
    }
}

/// A future which resolves to a `Guard`.
pub struct FutureGuard<T> {
    qutex: Option<Qutex<T>>,
    rx: oneshot::Receiver<()>,
}

impl<T> FutureGuard<T> {
    /// Returns a new `FutureGuard`.
    fn new(qutex: Qutex<T>, rx: oneshot::Receiver<()>) -> FutureGuard<T> {
        FutureGuard {
            qutex: Some(qutex),
            rx: rx,
        }
    }

    /// Blocks the current thread until this future resolves.
    #[inline]
    pub fn wait(self) -> Result<Guard<T>, Canceled> {
        <Self as Future>::wait(self)
    }
}

impl<T> Future for FutureGuard<T> {
    type Item = Guard<T>;
    type Error = Canceled;

    #[inline]
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.qutex.is_some() {
            unsafe { self.qutex.as_ref().unwrap().process_queue()
                .expect("Error polling FutureGuard"); }

            match self.rx.poll() {
                Ok(status) => Ok(status.map(|_| {
                    Guard { qutex: self.qutex.take().unwrap() }
                })),
                Err(e) => Err(e.into()),
            }
        } else {
            panic!("FutureGuard::poll: Task already completed.");
        }
    }
}

/// A request to lock the qutex for exclusive access.
#[derive(Debug)]
pub struct Request {
    tx: oneshot::Sender<()>,
}

impl Request {
    /// Returns a new `Request`.
    pub fn new(tx: oneshot::Sender<()>) -> Request {
        Request { tx: tx }
    }
}

struct Inner<T> {
    // TODO: Convert to `AtomicBool` if no additional states are needed:
    state: AtomicUsize,
    cell: UnsafeCell<T>,
    queue: SegQueue<Request>,
}

impl<T> From<T> for Inner<T> {
    #[inline]
    fn from(val: T) -> Inner<T> {
        Inner {
            state: AtomicUsize::new(0),
            cell: UnsafeCell::new(val),
            queue: SegQueue::new(),
        }
    }
}

unsafe impl<T: Send> Send for Inner<T> {}
unsafe impl<T: Send> Sync for Inner<T> {}

/// A lock-free-queue-backed exclusive data lock.
pub struct Qutex<T> {
    inner: Arc<Inner<T>>,
}

impl<T> Qutex<T> {
    /// Creates and returns a new `Qutex`.
    #[inline]
    pub fn new(val: T) -> Qutex<T> {
        Qutex {
            inner: Arc::new(Inner::from(val)),
        }
    }

    /// Returns a new `FutureGuard` which can be used as a future and will
    /// resolve into a `Guard`.
    pub fn request_lock(self) -> FutureGuard<T> {
        let (tx, rx) = oneshot::channel();
        unsafe { self.push_request(Request::new(tx)); }
        FutureGuard::new(self, rx)
    }

    /// Pushes a lock request onto the queue.
    ///
    //
    // TODO: Evaluate unsafe-ness.
    //
    #[inline]
    pub unsafe fn push_request(&self, req: Request) {
        self.inner.queue.push(req);
    }

    /// Returns a mutable reference to the inner `Vec` if there are currently
    /// no other copies of this `Qutex`.
    ///
    /// Since this call borrows the inner lock mutably, no actual locking needs to
    /// take place---the mutable borrow statically guarantees no locks exist.
    ///
    #[inline]
    pub fn get_mut(&mut self) -> Option<&mut T> {
        Arc::get_mut(&mut self.inner).map(|inn| unsafe { &mut *inn.cell.get() })
    }

    /// Returns a reference to the inner value.
    ///
    /// This is frought with potential peril.
    ///
    #[inline]
    pub fn as_ptr(&self) -> *const T {
        self.inner.cell.get()
    }

    /// Returns a mutable reference to the inner value.
    ///
    /// Drinking water from the tap in 1850's London would be safer.
    ///
    #[inline]
    pub fn as_mut_ptr(&self) -> *mut T {
        self.inner.cell.get()
    }

    /// Pops the next lock request in the queue if this lock is unlocked.
    //
    // TODO:
    // * This is currently public due to 'derivers' (aka. sub-types). Evaluate.
    // * Consider removing unsafe qualifier.
    // * Return proper error type.
    //
    pub unsafe fn process_queue(&self) {
        match self.inner.state.compare_and_swap(0, 1, SeqCst) {
            // Unlocked:
            0 => {
                loop {
                    if let Some(req) = self.inner.queue.try_pop() {
                        // If there is a send error, a requester has dropped
                        // its receiver so just go to the next.
                        if req.tx.send(()).is_err() {
                            continue;
                        } else {
                            // return Ok(())
                        }
                    } else {
                        self.inner.state.store(0, SeqCst);
                        // return Ok(());
                    }
                }
            },
            // Already locked, leave it alone:
            // 1 => Ok(()),
            1 => (),
            // Something else:
            n => panic!("Qutex::process_queue: inner.state: {}.", n),
        }
    }

    /// Unlocks this lock and wakes up the next task in the queue.
    //
    // TODO:
    // * Evaluate unsafe-ness.
    // * Return proper error type
    pub unsafe fn direct_unlock(&self) {
        // TODO: Consider using `Ordering::Release`.
        self.inner.state.store(0, SeqCst);
        self.process_queue()
    }
}

impl<T> From<T> for Qutex<T> {
    #[inline]
    fn from(val: T) -> Qutex<T> {
        Qutex::new(val)
    }
}

// Avoids needing `T: Clone`.
impl<T> Clone for Qutex<T> {
    #[inline]
    fn clone(&self) -> Qutex<T> {
        Qutex {
            inner: self.inner.clone(),
        }
    }
}

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

    #[test]
    fn simple() {
        let val = Qutex::from(999i32);

        println!("Reading val...");
        {
            let future_guard = val.clone().request_lock();
            let guard = future_guard.wait().unwrap();
            println!("val: {}", *guard);
        }

        println!("Storing new val...");
        {
            let future_guard = val.clone().request_lock();
            let mut guard = future_guard.wait().unwrap();
            *guard = 5;
        }

        println!("Reading val...");
        {
            let future_guard = val.clone().request_lock();
            let guard = future_guard.wait().unwrap();
            println!("val: {}", *guard);
        }
    }

    #[test]
    fn concurrent() {
        use std::thread;

        let start_val = 10000i32;
        let thread_count = 50;
        let qutex = Qutex::new(start_val);
        let mut threads = Vec::with_capacity(thread_count);

        for i in 0..thread_count {
            let future_guard = qutex.clone().request_lock();

            threads.push(thread::Builder::new().name(format!("test_thread_{}", i)).spawn(|| {
                let mut guard = future_guard.wait().unwrap();
                *guard += 1
            }).unwrap())
        }

        for thread in threads {
            thread.join().unwrap();
        }

        let guard = qutex.clone().request_lock().wait().unwrap();
        assert!(*guard == start_val + thread_count as i32);
    }
}<commit_msg>Clean up.<commit_after>//! A queue-backed exclusive data lock.
//!
//
// * It is unclear how many of the unsafe methods within need actually remain
//   unsafe.

use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::cell::UnsafeCell;
use futures::{Future, Poll, Canceled};
use futures::sync::oneshot;
use crossbeam::sync::SegQueue;

 // Allows access to the data contained within a lock just like a mutex guard.
pub struct Guard<T> {
    qutex: Qutex<T>,
}

impl<T> Guard<T> {
    /// Releases the lock held by this `Guard` and returns the original `Qutex`.
    //
    // NOTE: This increments the `Qutex` reference count before immediately
    // decrementing it. Is it worth avoiding this by wrapping it in an Option
    // or using unsafe hackery? It would make uglier code for the measly
    // savings of two atomic stores...
    pub fn unlock(self) -> Qutex<T> {
        self.qutex.clone()
    }
}

impl<T> Deref for Guard<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.qutex.inner.cell.get() }
    }
}

impl<T> DerefMut for Guard<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.qutex.inner.cell.get() }
    }
}

impl<T> Drop for Guard<T> {
    fn drop(&mut self) {
        // unsafe { self.qutex.direct_unlock().expect("Error dropping Guard") };
        unsafe { self.qutex.direct_unlock() }
    }
}

/// A future which resolves to a `Guard`.
pub struct FutureGuard<T> {
    qutex: Option<Qutex<T>>,
    rx: oneshot::Receiver<()>,
}

impl<T> FutureGuard<T> {
    /// Returns a new `FutureGuard`.
    fn new(qutex: Qutex<T>, rx: oneshot::Receiver<()>) -> FutureGuard<T> {
        FutureGuard {
            qutex: Some(qutex),
            rx: rx,
        }
    }

    /// Blocks the current thread until this future resolves.
    #[inline]
    pub fn wait(self) -> Result<Guard<T>, Canceled> {
        <Self as Future>::wait(self)
    }
}

impl<T> Future for FutureGuard<T> {
    type Item = Guard<T>;
    type Error = Canceled;

    #[inline]
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.qutex.is_some() {
            unsafe {
                self.qutex.as_ref().unwrap().process_queue()
                    // .expect("Error polling FutureGuard");
            }

            match self.rx.poll() {
                Ok(status) => Ok(status.map(|_| {
                    Guard { qutex: self.qutex.take().unwrap() }
                })),
                Err(e) => Err(e.into()),
            }
        } else {
            panic!("FutureGuard::poll: Task already completed.");
        }
    }
}

/// A request to lock the qutex for exclusive access.
#[derive(Debug)]
pub struct Request {
    tx: oneshot::Sender<()>,
}

impl Request {
    /// Returns a new `Request`.
    pub fn new(tx: oneshot::Sender<()>) -> Request {
        Request { tx: tx }
    }
}

struct Inner<T> {
    // TODO: Convert to `AtomicBool` if no additional states are needed:
    state: AtomicUsize,
    cell: UnsafeCell<T>,
    queue: SegQueue<Request>,
}

impl<T> From<T> for Inner<T> {
    #[inline]
    fn from(val: T) -> Inner<T> {
        Inner {
            state: AtomicUsize::new(0),
            cell: UnsafeCell::new(val),
            queue: SegQueue::new(),
        }
    }
}

unsafe impl<T: Send> Send for Inner<T> {}
unsafe impl<T: Send> Sync for Inner<T> {}

/// A lock-free-queue-backed exclusive data lock.
pub struct Qutex<T> {
    inner: Arc<Inner<T>>,
}

impl<T> Qutex<T> {
    /// Creates and returns a new `Qutex`.
    #[inline]
    pub fn new(val: T) -> Qutex<T> {
        Qutex {
            inner: Arc::new(Inner::from(val)),
        }
    }

    /// Returns a new `FutureGuard` which can be used as a future and will
    /// resolve into a `Guard`.
    pub fn request_lock(self) -> FutureGuard<T> {
        let (tx, rx) = oneshot::channel();
        unsafe { self.push_request(Request::new(tx)); }
        FutureGuard::new(self, rx)
    }

    /// Pushes a lock request onto the queue.
    ///
    //
    // TODO: Evaluate unsafe-ness.
    //
    #[inline]
    pub unsafe fn push_request(&self, req: Request) {
        self.inner.queue.push(req);
    }

    /// Returns a mutable reference to the inner `Vec` if there are currently
    /// no other copies of this `Qutex`.
    ///
    /// Since this call borrows the inner lock mutably, no actual locking needs to
    /// take place---the mutable borrow statically guarantees no locks exist.
    ///
    #[inline]
    pub fn get_mut(&mut self) -> Option<&mut T> {
        Arc::get_mut(&mut self.inner).map(|inn| unsafe { &mut *inn.cell.get() })
    }

    /// Returns a reference to the inner value.
    ///
    /// This is frought with potential peril.
    ///
    #[inline]
    pub fn as_ptr(&self) -> *const T {
        self.inner.cell.get()
    }

    /// Returns a mutable reference to the inner value.
    ///
    /// Drinking water from the tap in 1850's London would be safer.
    ///
    #[inline]
    pub fn as_mut_ptr(&self) -> *mut T {
        self.inner.cell.get()
    }

    /// Pops the next lock request in the queue if this lock is unlocked.
    //
    // TODO:
    // * This is currently public due to 'derivers' (aka. sub-types). Evaluate.
    // * Consider removing unsafe qualifier.
    // * Return proper error type.
    //
    // pub unsafe fn process_queue(&self) -> Result<(), ()> {
    pub unsafe fn process_queue(&self) {
        match self.inner.state.compare_and_swap(0, 1, SeqCst) {
            // Unlocked:
            0 => {
                loop {
                    if let Some(req) = self.inner.queue.try_pop() {
                        // If there is a send error, a requester has dropped
                        // its receiver so just go to the next.
                        if req.tx.send(()).is_err() {
                            continue;
                        } else {
                            // return Ok(())
                            break;
                        }
                    } else {
                        self.inner.state.store(0, SeqCst);
                        // return Ok(());
                        break;
                    }
                }
            },
            // Already locked, leave it alone:
            // 1 => Ok(()),
            1 => (),
            // Something else:
            n => panic!("Qutex::process_queue: inner.state: {}.", n),
        }
    }

    /// Unlocks this lock and wakes up the next task in the queue.
    //
    // TODO:
    // * Evaluate unsafe-ness.
    // * Return proper error type
    // pub unsafe fn direct_unlock(&self) -> Result<(), ()> {
    pub unsafe fn direct_unlock(&self) {
        // TODO: Consider using `Ordering::Release`.
        self.inner.state.store(0, SeqCst);
        self.process_queue()
    }
}

impl<T> From<T> for Qutex<T> {
    #[inline]
    fn from(val: T) -> Qutex<T> {
        Qutex::new(val)
    }
}

// Avoids needing `T: Clone`.
impl<T> Clone for Qutex<T> {
    #[inline]
    fn clone(&self) -> Qutex<T> {
        Qutex {
            inner: self.inner.clone(),
        }
    }
}

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

    #[test]
    fn simple() {
        let val = Qutex::from(999i32);

        println!("Reading val...");
        {
            let future_guard = val.clone().request_lock();
            let guard = future_guard.wait().unwrap();
            println!("val: {}", *guard);
        }

        println!("Storing new val...");
        {
            let future_guard = val.clone().request_lock();
            let mut guard = future_guard.wait().unwrap();
            *guard = 5;
        }

        println!("Reading val...");
        {
            let future_guard = val.clone().request_lock();
            let guard = future_guard.wait().unwrap();
            println!("val: {}", *guard);
        }
    }

    #[test]
    fn concurrent() {
        use std::thread;

        let start_val = 10000i32;
        let thread_count = 50;
        let qutex = Qutex::new(start_val);
        let mut threads = Vec::with_capacity(thread_count);

        for i in 0..thread_count {
            let future_guard = qutex.clone().request_lock();

            threads.push(thread::Builder::new().name(format!("test_thread_{}", i)).spawn(|| {
                let mut guard = future_guard.wait().unwrap();
                *guard += 1
            }).unwrap())
        }

        for i in 0..thread_count {
            let future_guard = qutex.clone().request_lock();

            threads.push(thread::Builder::new().name(format!("test_thread_{}", i)).spawn(|| {
                let mut guard = future_guard.wait().unwrap();
                *guard -= 1
            }).unwrap())
        }

        for thread in threads {
            thread.join().unwrap();
        }

        let guard = qutex.clone().request_lock().wait().unwrap();
        assert_eq!(*guard, start_val);
    }
}<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::path::Path;
use std::vec::Vec;

use cgmath::Point3;

use glium::backend::Facade;
use glium::VertexBuffer;

use crate::aabb::AABB;
use crate::bvh::{SplitMode, BVH};
use crate::material::{GPUMaterial, Material};
use crate::mesh::{GPUMesh, Mesh};
use crate::obj_load;
use crate::stats;
use crate::triangle::{RTTriangle, RTTriangleBuilder};
use crate::vertex::Vertex;

/// Scene containing all the CPU resources
pub struct Scene {
    pub vertices: Vec<Vertex>,
    pub meshes: Vec<Mesh>,
    pub materials: Vec<Material>,
    pub triangles: Vec<RTTriangle>,
    pub lights: Vec<RTTriangle>,
    pub aabb: AABB,
    pub bvh: BVH,
}

/// Scene containing minimum resources for GPU rendering
pub struct GPUScene {
    pub meshes: Vec<GPUMesh>,
    pub materials: Vec<GPUMaterial>,
    pub vertex_buffer: VertexBuffer<Vertex>,
}

impl Scene {
    pub fn new(scene_path: &Path) -> Scene {
        let mut scene = Scene {
            vertices: Vec::new(),
            meshes: Vec::new(),
            materials: Vec::new(),
            triangles: Vec::new(),
            lights: Vec::new(),
            aabb: AABB::empty(),
            bvh: BVH::empty(),
        };
        scene.load_scene(scene_path);
        let (bvh, permutation) = BVH::build(&scene.triangles, SplitMode::SAH);
        scene.bvh = bvh;
        scene.triangles = permutation
            .iter()
            .map(|i| scene.triangles[*i].clone())
            .collect();
        scene
    }

    /// Load a scene from the given path
    fn load_scene(&mut self, scene_path: &Path) {
        let obj = obj_load::load_obj(scene_path)
            .unwrap_or_else(|err| panic!("Failed to load scene {:?}: {}", scene_path, err));

        let mut _t = stats::time("Convert scene");
        // Closure to calculate planar normal for a triangle
        let calculate_normal = |triangle: &obj_load::Triangle| -> [f32; 3] {
            let pos_i1 = triangle.index_vertices[0].pos_i;
            let pos_i2 = triangle.index_vertices[1].pos_i;
            let pos_i3 = triangle.index_vertices[2].pos_i;
            let pos_1 = obj.positions[pos_i1];
            let pos_2 = obj.positions[pos_i2];
            let pos_3 = obj.positions[pos_i3];
            let u = [
                pos_2[0] - pos_1[0],
                pos_2[1] - pos_1[1],
                pos_2[2] - pos_1[2],
            ];
            let v = [
                pos_3[0] - pos_1[0],
                pos_3[1] - pos_1[1],
                pos_3[2] - pos_1[2],
            ];
            let normal = [
                u[1] * v[2] - u[2] * v[1],
                u[2] * v[0] - u[0] * v[2],
                u[0] * v[1] - u[1] * v[0],
            ];
            let length = (normal[0].powi(2) + normal[1].powi(2) + normal[2].powi(2)).sqrt();
            [normal[0] / length, normal[1] / length, normal[2] / length]
        };

        // Group the polygons by materials for easy rendering
        let mut vertex_map = HashMap::new();
        let mut material_map = HashMap::new();
        for range in &obj.material_ranges {
            let material_i = match material_map.get(&range.name) {
                Some(&i) => i,
                None => {
                    let obj_mat = obj
                        .materials
                        .get(&range.name)
                        .unwrap_or_else(|| panic!("Couldn't find material {}!", range.name));
                    let material = Material::new(obj_mat);
                    let i = self.materials.len();
                    self.materials.push(material);
                    material_map.insert(&range.name, i);
                    i
                }
            };
            let material = &self.materials[material_i];
            let mut mesh = Mesh::new(material_i);
            for tri in &obj.triangles[range.start_i..range.end_i] {
                let mut tri_builder = RTTriangleBuilder::new();
                let default_tex_coords = [0.0; 2];
                for index_vertex in &tri.index_vertices {
                    match vertex_map.get(index_vertex) {
                        // Vertex has already been added
                        Some(&i) => {
                            mesh.indices.push(i as u32);
                            tri_builder.add_vertex(self.vertices[i]);
                        }
                        None => {
                            let pos = obj.positions[index_vertex.pos_i];
                            self.aabb.add_point(&Point3::from(pos));

                            let tex_coords = match index_vertex.tex_i {
                                Some(tex_i) => obj.tex_coords[tex_i],
                                None => default_tex_coords,
                            };
                            let normal = match index_vertex.normal_i {
                                Some(normal_i) => obj.normals[normal_i],
                                None => calculate_normal(tri),
                            };

                            mesh.indices.push(self.vertices.len() as u32);
                            vertex_map.insert(index_vertex, self.vertices.len());
                            self.vertices.push(Vertex {
                                pos,
                                normal,
                                tex_coords,
                            });
                            tri_builder.add_vertex(*self.vertices.last().unwrap());
                        }
                    }
                }
                let triangle = tri_builder.build(material_i).expect("Failed to build tri!");
                if material.emissive.is_some() {
                    self.lights.push(triangle.clone());
                }
                self.triangles.push(triangle);
            }
            if !mesh.indices.is_empty() {
                self.meshes.push(mesh);
            }
        }
    }

    /// Load the textures + vertex and index buffers to the GPU
    pub fn upload_data<F: Facade>(&self, facade: &F) -> GPUScene {
        let _t = stats::time("Upload data");
        let vertex_buffer =
            VertexBuffer::new(facade, &self.vertices).expect("Failed to create vertex buffer!");
        let mut meshes = Vec::new();
        let mut materials = Vec::new();
        for mesh in &self.meshes {
            meshes.push(mesh.upload_data(facade));
        }
        for material in &self.materials {
            materials.push(material.upload_textures(facade));
        }
        GPUScene {
            meshes,
            materials,
            vertex_buffer,
        }
    }

    /// Get the center of the scene as defined by the bounding box
    pub fn center(&self) -> Point3<f32> {
        self.aabb.center()
    }

    /// Get the approximate size of the scene
    pub fn size(&self) -> f32 {
        self.aabb.longest_edge()
    }
}
<commit_msg>Refactor scene loading<commit_after>use std::collections::HashMap;
use std::path::Path;
use std::vec::Vec;

use cgmath::Point3;

use glium::backend::Facade;
use glium::VertexBuffer;

use crate::aabb::AABB;
use crate::bvh::{SplitMode, BVH};
use crate::material::{GPUMaterial, Material};
use crate::mesh::{GPUMesh, Mesh};
use crate::obj_load;
use crate::stats;
use crate::triangle::{RTTriangle, RTTriangleBuilder};
use crate::vertex::Vertex;

/// Scene containing all the CPU resources
pub struct Scene {
    pub vertices: Vec<Vertex>,
    pub meshes: Vec<Mesh>,
    pub materials: Vec<Material>,
    pub triangles: Vec<RTTriangle>,
    pub lights: Vec<RTTriangle>,
    pub aabb: AABB,
    pub bvh: BVH,
}

/// Scene containing minimum resources for GPU rendering
pub struct GPUScene {
    pub meshes: Vec<GPUMesh>,
    pub materials: Vec<GPUMaterial>,
    pub vertex_buffer: VertexBuffer<Vertex>,
}

impl Scene {
    pub fn new(scene_path: &Path) -> Scene {
        let obj = obj_load::load_obj(scene_path)
            .unwrap_or_else(|err| panic!("Failed to load scene {:?}: {}", scene_path, err));

        let mut _t = stats::time("Convert scene");
        let mut vertices = Vec::new();
        let mut meshes = Vec::new();
        let mut materials = Vec::new();
        let mut triangles = Vec::new();
        let mut lights = Vec::new();
        let mut aabb = AABB::empty();

        // Group the polygons by materials for easy rendering
        let mut vertex_map = HashMap::new();
        let mut material_map = HashMap::new();
        for range in &obj.material_ranges {
            let material_i = match material_map.get(&range.name) {
                Some(&i) => i,
                None => {
                    let obj_mat = obj
                        .materials
                        .get(&range.name)
                        .unwrap_or_else(|| panic!("Couldn't find material {}!", range.name));
                    let material = Material::new(obj_mat);
                    let i = materials.len();
                    materials.push(material);
                    material_map.insert(&range.name, i);
                    i
                }
            };
            let material = &materials[material_i];
            let mut mesh = Mesh::new(material_i);
            for tri in &obj.triangles[range.start_i..range.end_i] {
                let mut tri_builder = RTTriangleBuilder::new();
                for index_vertex in &tri.index_vertices {
                    match vertex_map.get(index_vertex) {
                        // Vertex has already been added
                        Some(&i) => {
                            mesh.indices.push(i as u32);
                            tri_builder.add_vertex(vertices[i]);
                        }
                        None => {
                            let pos = obj.positions[index_vertex.pos_i];
                            aabb.add_point(&Point3::from(pos));

                            let tex_coords = match index_vertex.tex_i {
                                Some(tex_i) => obj.tex_coords[tex_i],
                                None => [0.0; 2],
                            };
                            let normal = match index_vertex.normal_i {
                                Some(normal_i) => obj.normals[normal_i],
                                // TODO: don't cache vertices without normals.
                                // Now the first tri defines the normal for remaining tris aswell.
                                None => calculate_normal(tri, &obj),
                            };

                            mesh.indices.push(vertices.len() as u32);
                            vertex_map.insert(index_vertex, vertices.len());
                            vertices.push(Vertex {
                                pos,
                                normal,
                                tex_coords,
                            });
                            tri_builder.add_vertex(*vertices.last().unwrap());
                        }
                    }
                }
                let triangle = tri_builder.build(material_i).expect("Failed to build tri!");
                if material.emissive.is_some() {
                    lights.push(triangle.clone());
                }
                triangles.push(triangle);
            }
            if !mesh.indices.is_empty() {
                meshes.push(mesh);
            }
        }
        let (bvh, permutation) = BVH::build(&triangles, SplitMode::SAH);
        triangles = permutation.iter().map(|i| triangles[*i].clone()).collect();
        Scene {
            vertices,
            meshes,
            materials,
            triangles,
            lights,
            aabb,
            bvh,
        }
    }

    /// Load the textures + vertex and index buffers to the GPU
    pub fn upload_data<F: Facade>(&self, facade: &F) -> GPUScene {
        let _t = stats::time("Upload data");
        let vertex_buffer =
            VertexBuffer::new(facade, &self.vertices).expect("Failed to create vertex buffer!");
        let mut meshes = Vec::new();
        let mut materials = Vec::new();
        for mesh in &self.meshes {
            meshes.push(mesh.upload_data(facade));
        }
        for material in &self.materials {
            materials.push(material.upload_textures(facade));
        }
        GPUScene {
            meshes,
            materials,
            vertex_buffer,
        }
    }

    /// Get the center of the scene as defined by the bounding box
    pub fn center(&self) -> Point3<f32> {
        self.aabb.center()
    }

    /// Get the approximate size of the scene
    pub fn size(&self) -> f32 {
        self.aabb.longest_edge()
    }
}

/// Calculate planar normal for a triangle
fn calculate_normal(triangle: &obj_load::Triangle, obj: &obj_load::Object) -> [f32; 3] {
    let pos_i1 = triangle.index_vertices[0].pos_i;
    let pos_i2 = triangle.index_vertices[1].pos_i;
    let pos_i3 = triangle.index_vertices[2].pos_i;
    let pos_1 = obj.positions[pos_i1];
    let pos_2 = obj.positions[pos_i2];
    let pos_3 = obj.positions[pos_i3];
    let u = [
        pos_2[0] - pos_1[0],
        pos_2[1] - pos_1[1],
        pos_2[2] - pos_1[2],
    ];
    let v = [
        pos_3[0] - pos_1[0],
        pos_3[1] - pos_1[1],
        pos_3[2] - pos_1[2],
    ];
    let normal = [
        u[1] * v[2] - u[2] * v[1],
        u[2] * v[0] - u[0] * v[2],
        u[0] * v[1] - u[1] * v[0],
    ];
    let length = (normal[0].powi(2) + normal[1].powi(2) + normal[2].powi(2)).sqrt();
    [normal[0] / length, normal[1] / length, normal[2] / length]
}
<|endoftext|>


<commit_before>use std::f64;
use std::f64::consts::PI;

use rand::{Rand, Rng};

use radians::Radians;
use {Distance};

/// Represents the various supported speeds that the turtle can move at
///
/// See [`Turtle::set_speed` method](struct.Turtle.html#method.set_speed) for more information.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub enum Speed {
    One,
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Instant,
}

impl Speed {
    /// Converts a speed to its value as pixels per second
    pub fn to_absolute(self) -> Distance {
        use self::Speed::*;
        // Arbitrary values that can be tweaked
        // Just make sure to keep invariants like Five > Three, etc.
        match self {
            One => 50.,
            Two => 100.,
            Three => 200.,
            Four => 300.,
            Five => 500.,
            Six => 600.,
            Seven => 700.,
            Eight => 800.,
            Nine => 900.,
            Ten => 1000.,
            Instant => f64::INFINITY,
        }
    }

    /// Converts a speed to its value as radians per second
    pub fn to_rotation(self) -> Radians {
        use self::Speed::*;
        // Arbitrary values that can be tweaked
        // Just make sure to keep invariants like Five > Three, etc.
        Radians::from_radians_value(match self {
            One => 0.7 * PI,
            Two => 0.9 * PI,
            Three => 1.1 * PI,
            Four => 1.3 * PI,
            Five =>  1.5 * PI,
            Six => 2.5 * PI,
            Seven => 3.5 * PI,
            Eight => 4.0 * PI,
            Nine => 8.0 * PI,
            Ten => 12.0 * PI,
            Instant => f64::INFINITY,
        })
    }
}

impl Rand for Speed {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        (rng.gen::<i32>() % 10).into()
    }
}

impl<'a> From<&'a str> for Speed {
    fn from(s: &'a str) -> Self {
        use Speed::*;

        match s {
            "slowest" => One,
            "slow" => Three,
            "normal" => Six,
            "fast" => Eight,
            "fastest" => Ten,
            "instant" => Instant,
            _ => panic!("Invalid speed specified, use one of the words: 'slowest', 'slow', 'normal', 'fast', 'fastest', 'instant'"),
        }
    }
}

impl From<i32> for Speed {
    fn from(n: i32) -> Self {
        use Speed::*;

        match n {
            1 => One,
            2 => Two,
            3 => Three,
            4 => Four,
            5 => Five,
            6 => Six,
            7 => Seven,
            8 => Eight,
            9 => Nine,
            10 => Ten,
            _ => Instant,
        }
    }
}
<commit_msg>Added an impl of From<f64> for Speed + tests for all impls of Speed<commit_after>use std::f64;
use std::f64::consts::PI;

use rand::{Rand, Rng};

use radians::Radians;
use {Distance};

/// Represents the various supported speeds that the turtle can move at
///
/// See [`Turtle::set_speed` method](struct.Turtle.html#method.set_speed) for more information.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub enum Speed {
    One,
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Instant,
}

impl Speed {
    /// Converts a speed to its value as pixels per second
    pub fn to_absolute(self) -> Distance {
        use self::Speed::*;
        // Arbitrary values that can be tweaked
        // Just make sure to keep invariants like Five > Three, etc.
        match self {
            One => 50.,
            Two => 100.,
            Three => 200.,
            Four => 300.,
            Five => 500.,
            Six => 600.,
            Seven => 700.,
            Eight => 800.,
            Nine => 900.,
            Ten => 1000.,
            Instant => f64::INFINITY,
        }
    }

    /// Converts a speed to its value as radians per second
    pub fn to_rotation(self) -> Radians {
        use self::Speed::*;
        // Arbitrary values that can be tweaked
        // Just make sure to keep invariants like Five > Three, etc.
        Radians::from_radians_value(match self {
            One => 0.7 * PI,
            Two => 0.9 * PI,
            Three => 1.1 * PI,
            Four => 1.3 * PI,
            Five =>  1.5 * PI,
            Six => 2.5 * PI,
            Seven => 3.5 * PI,
            Eight => 4.0 * PI,
            Nine => 8.0 * PI,
            Ten => 12.0 * PI,
            Instant => f64::INFINITY,
        })
    }
}

impl Rand for Speed {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        (rng.gen::<i32>() % 10).into()
    }
}

impl<'a> From<&'a str> for Speed {
    fn from(s: &'a str) -> Self {
        use Speed::*;

        match s {
            "slowest" => One,
            "slow" => Three,
            "normal" => Six,
            "fast" => Eight,
            "fastest" => Ten,
            "instant" => Instant,
            _ => panic!("Invalid speed specified, use one of the words: 'slowest', 'slow', 'normal', 'fast', 'fastest', 'instant'"),
        }
    }
}

impl From<i32> for Speed {
    fn from(n: i32) -> Self {
        use Speed::*;

        match n {
            1 => One,
            2 => Two,
            3 => Three,
            4 => Four,
            5 => Five,
            6 => Six,
            7 => Seven,
            8 => Eight,
            9 => Nine,
            10 => Ten,
            _ => Instant,
        }
    }
}

// We include this implementation because we use f64 in the rest of the library.
// It makes sense to implement this so that they don't get messed up if they accidentally use a
// floating point literal with set_speed.
impl From<f64> for Speed {
    fn from(n: f64) -> Self {
        (n.round() as i32).into()
    }
}

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

    #[test]
    fn speed_names() {
        let mut turtle = Turtle::new();
        turtle.set_speed("slowest");
        assert_eq!(turtle.speed(), Speed::One);
        turtle.set_speed("slow");
        assert_eq!(turtle.speed(), Speed::Three);
        turtle.set_speed("normal");
        assert_eq!(turtle.speed(), Speed::Six);
        turtle.set_speed("fast");
        assert_eq!(turtle.speed(), Speed::Eight);
        turtle.set_speed("fastest");
        assert_eq!(turtle.speed(), Speed::Ten);
        turtle.set_speed("instant");
        assert_eq!(turtle.speed(), Speed::Instant);
    }

    #[test]
    #[should_panic(expected = "Invalid speed specified, use one of the words: 'slowest', 'slow', 'normal', 'fast', 'fastest', 'instant'")]
    fn invalid_speed() {
        let mut turtle = Turtle::new();
        turtle.set_speed("wrong");
    }

    #[test]
    fn speed_values() {
        let mut turtle = Turtle::new();
        turtle.set_speed(0);
        assert_eq!(turtle.speed(), Speed::Instant);
        turtle.set_speed(1);
        assert_eq!(turtle.speed(), Speed::One);
        turtle.set_speed(2);
        assert_eq!(turtle.speed(), Speed::Two);
        turtle.set_speed(3);
        assert_eq!(turtle.speed(), Speed::Three);
        turtle.set_speed(4);
        assert_eq!(turtle.speed(), Speed::Four);
        turtle.set_speed(5);
        assert_eq!(turtle.speed(), Speed::Five);
        turtle.set_speed(6);
        assert_eq!(turtle.speed(), Speed::Six);
        turtle.set_speed(7);
        assert_eq!(turtle.speed(), Speed::Seven);
        turtle.set_speed(8);
        assert_eq!(turtle.speed(), Speed::Eight);
        turtle.set_speed(9);
        assert_eq!(turtle.speed(), Speed::Nine);
        turtle.set_speed(10);
        assert_eq!(turtle.speed(), Speed::Ten);
        turtle.set_speed(11);
        assert_eq!(turtle.speed(), Speed::Instant);
        turtle.set_speed(20394);
        assert_eq!(turtle.speed(), Speed::Instant);
    }

    #[test]
    fn speed_values_f64() {
        let mut turtle = Turtle::new();
        turtle.set_speed(0.4);
        assert_eq!(turtle.speed(), Speed::Instant);
        turtle.set_speed(1.4);
        assert_eq!(turtle.speed(), Speed::One);
        turtle.set_speed(2.4);
        assert_eq!(turtle.speed(), Speed::Two);
        turtle.set_speed(3.4);
        assert_eq!(turtle.speed(), Speed::Three);
        turtle.set_speed(4.4);
        assert_eq!(turtle.speed(), Speed::Four);
        turtle.set_speed(5.4);
        assert_eq!(turtle.speed(), Speed::Five);
        turtle.set_speed(6.4);
        assert_eq!(turtle.speed(), Speed::Six);
        turtle.set_speed(7.4);
        assert_eq!(turtle.speed(), Speed::Seven);
        turtle.set_speed(8.4);
        assert_eq!(turtle.speed(), Speed::Eight);
        turtle.set_speed(9.4);
        assert_eq!(turtle.speed(), Speed::Nine);
        turtle.set_speed(10.4);
        assert_eq!(turtle.speed(), Speed::Ten);
        turtle.set_speed(11.4);
        assert_eq!(turtle.speed(), Speed::Instant);
        turtle.set_speed(20394.4);
        assert_eq!(turtle.speed(), Speed::Instant);
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "display")]
use std::fmt::{self, Display, Formatter};
use {Command, Error, Merger};

/// The command stack.
///
/// The stack is the simplest data structure and works by pushing and
/// popping off commands that modifies the `receiver`.
///
/// # Examples
/// ```
/// # use std::error::Error;
/// # use undo::*;
/// #[derive(Debug)]
/// struct Add(char);
///
/// impl Command<String> for Add {
///     fn exec(&mut self, s: &mut String) -> Result<(), Box<Error>> {
///         s.push(self.0);
///         Ok(())
///     }
///
///     fn undo(&mut self, s: &mut String) -> Result<(), Box<Error>> {
///         self.0 = s.pop().ok_or("`String` is unexpectedly empty")?;
///         Ok(())
///     }
/// }
///
/// fn foo() -> Result<(), Box<Error>> {
///     let mut stack = Stack::default();
///
///     stack.push(Add('a'))?;
///     stack.push(Add('b'))?;
///     stack.push(Add('c'))?;
///
///     assert_eq!(stack.as_receiver(), "abc");
///
///     let c = stack.pop().unwrap()?;
///     let b = stack.pop().unwrap()?;
///     let a = stack.pop().unwrap()?;
///
///     assert_eq!(stack.as_receiver(), "");
///
///     stack.push(a)?;
///     stack.push(b)?;
///     stack.push(c)?;
///
///     assert_eq!(stack.into_receiver(), "abc");
///
///     Ok(())
/// }
/// # foo().unwrap();
/// ```
#[derive(Debug, Default)]
pub struct Stack<R> {
    commands: Vec<Box<Command<R>>>,
    receiver: R,
}

impl<R> Stack<R> {
    /// Creates a new stack.
    #[inline]
    pub fn new<T: Into<R>>(receiver: T) -> Stack<R> {
        Stack {
            commands: Vec::new(),
            receiver: receiver.into(),
        }
    }

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

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

    /// Removes all commands from the stack without undoing them.
    ///
    /// This resets the stack back to its initial state while leaving the receiver unmodified.
    #[inline]
    pub fn clear(&mut self) {
        self.commands.clear();
    }

    /// Pushes the command on the stack and executes its [`exec`] method.
    /// The command is merged with the previous top command if their [`id`] is equal.
    ///
    /// # Errors
    /// If an error occur when executing [`exec`], the error is returned together with the command.
    ///
    /// [`exec`]: trait.Command.html#tymethod.exec
    /// [`id`]: trait.Command.html#method.id
    #[inline]
    pub fn push<C>(&mut self, mut cmd: C) -> Result<(), Error<R>>
    where
        C: Command<R> + 'static,
        R: 'static,
    {
        match cmd.exec(&mut self.receiver) {
            Ok(_) => {
                match (cmd.id(), self.commands.last().and_then(|last| last.id())) {
                    (Some(id1), Some(id2)) if id1 == id2 => {
                        // Merge the command with the one on the top of the stack.
                        let cmd = Merger {
                            cmd1: self.commands.pop().unwrap(),
                            cmd2: Box::new(cmd),
                        };
                        self.commands.push(Box::new(cmd));
                    }
                    _ => self.commands.push(Box::new(cmd)),
                }
                Ok(())
            }
            Err(e) => Err(Error(Box::new(cmd), e)),
        }
    }

    /// Calls the top commands [`undo`] method and pops it off the stack.
    /// Returns `None` if the stack is empty.
    ///
    /// # Errors
    /// If an error occur when executing [`undo`] the error is returned together with the command.
    ///
    /// [`undo`]: trait.Command.html#tymethod.undo
    #[inline]
    pub fn pop(&mut self) -> Option<Result<Box<Command<R>>, Error<R>>> {
        self.commands
            .pop()
            .map(|mut cmd| match cmd.undo(&mut self.receiver) {
                Ok(_) => Ok(cmd),
                Err(e) => Err(Error(cmd, e)),
            })
    }

    /// Returns a reference to the `receiver`.
    #[inline]
    pub fn as_receiver(&self) -> &R {
        &self.receiver
    }

    /// Consumes the stack, returning the `receiver`.
    #[inline]
    pub fn into_receiver(self) -> R {
        self.receiver
    }
}

impl<R> AsRef<R> for Stack<R> {
    #[inline]
    fn as_ref(&self) -> &R {
        self.as_receiver()
    }
}

impl<R> From<R> for Stack<R> {
    #[inline]
    fn from(receiver: R) -> Self {
        Stack::new(receiver)
    }
}

#[cfg(feature = "display")]
impl<R> Display for Stack<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        if let Some(cmd) = self.commands.last() {
            writeln!(f, "* {}", cmd)?;
            for cmd in self.commands.iter().rev().skip(1) {
                writeln!(f, "  {}", cmd)?;
            }
        }
        Ok(())
    }
}
<commit_msg>Use split_last() instead of last()<commit_after>#[cfg(feature = "display")]
use std::fmt::{self, Display, Formatter};
use {Command, Error, Merger};

/// The command stack.
///
/// The stack is the simplest data structure and works by pushing and
/// popping off commands that modifies the `receiver`.
///
/// # Examples
/// ```
/// # use std::error::Error;
/// # use undo::*;
/// #[derive(Debug)]
/// struct Add(char);
///
/// impl Command<String> for Add {
///     fn exec(&mut self, s: &mut String) -> Result<(), Box<Error>> {
///         s.push(self.0);
///         Ok(())
///     }
///
///     fn undo(&mut self, s: &mut String) -> Result<(), Box<Error>> {
///         self.0 = s.pop().ok_or("`String` is unexpectedly empty")?;
///         Ok(())
///     }
/// }
///
/// fn foo() -> Result<(), Box<Error>> {
///     let mut stack = Stack::default();
///
///     stack.push(Add('a'))?;
///     stack.push(Add('b'))?;
///     stack.push(Add('c'))?;
///
///     assert_eq!(stack.as_receiver(), "abc");
///
///     let c = stack.pop().unwrap()?;
///     let b = stack.pop().unwrap()?;
///     let a = stack.pop().unwrap()?;
///
///     assert_eq!(stack.as_receiver(), "");
///
///     stack.push(a)?;
///     stack.push(b)?;
///     stack.push(c)?;
///
///     assert_eq!(stack.into_receiver(), "abc");
///
///     Ok(())
/// }
/// # foo().unwrap();
/// ```
#[derive(Debug, Default)]
pub struct Stack<R> {
    commands: Vec<Box<Command<R>>>,
    receiver: R,
}

impl<R> Stack<R> {
    /// Creates a new stack.
    #[inline]
    pub fn new<T: Into<R>>(receiver: T) -> Stack<R> {
        Stack {
            commands: Vec::new(),
            receiver: receiver.into(),
        }
    }

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

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

    /// Removes all commands from the stack without undoing them.
    ///
    /// This resets the stack back to its initial state while leaving the receiver unmodified.
    #[inline]
    pub fn clear(&mut self) {
        self.commands.clear();
    }

    /// Pushes the command on the stack and executes its [`exec`] method.
    /// The command is merged with the previous top command if their [`id`] is equal.
    ///
    /// # Errors
    /// If an error occur when executing [`exec`], the error is returned together with the command.
    ///
    /// [`exec`]: trait.Command.html#tymethod.exec
    /// [`id`]: trait.Command.html#method.id
    #[inline]
    pub fn push<C>(&mut self, mut cmd: C) -> Result<(), Error<R>>
    where
        C: Command<R> + 'static,
        R: 'static,
    {
        match cmd.exec(&mut self.receiver) {
            Ok(_) => {
                match (cmd.id(), self.commands.last().and_then(|last| last.id())) {
                    (Some(id1), Some(id2)) if id1 == id2 => {
                        // Merge the command with the one on the top of the stack.
                        let cmd = Merger {
                            cmd1: self.commands.pop().unwrap(),
                            cmd2: Box::new(cmd),
                        };
                        self.commands.push(Box::new(cmd));
                    }
                    _ => self.commands.push(Box::new(cmd)),
                }
                Ok(())
            }
            Err(e) => Err(Error(Box::new(cmd), e)),
        }
    }

    /// Calls the top commands [`undo`] method and pops it off the stack.
    /// Returns `None` if the stack is empty.
    ///
    /// # Errors
    /// If an error occur when executing [`undo`] the error is returned together with the command.
    ///
    /// [`undo`]: trait.Command.html#tymethod.undo
    #[inline]
    pub fn pop(&mut self) -> Option<Result<Box<Command<R>>, Error<R>>> {
        self.commands
            .pop()
            .map(|mut cmd| match cmd.undo(&mut self.receiver) {
                Ok(_) => Ok(cmd),
                Err(e) => Err(Error(cmd, e)),
            })
    }

    /// Returns a reference to the `receiver`.
    #[inline]
    pub fn as_receiver(&self) -> &R {
        &self.receiver
    }

    /// Consumes the stack, returning the `receiver`.
    #[inline]
    pub fn into_receiver(self) -> R {
        self.receiver
    }
}

impl<R> AsRef<R> for Stack<R> {
    #[inline]
    fn as_ref(&self) -> &R {
        self.as_receiver()
    }
}

impl<R> From<R> for Stack<R> {
    #[inline]
    fn from(receiver: R) -> Self {
        Stack::new(receiver)
    }
}

#[cfg(feature = "display")]
impl<R> Display for Stack<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        if let Some((last, commands)) = self.commands.split_last() {
            writeln!(f, "* {}", last)?;
            for cmd in commands.iter().rev() {
                writeln!(f, "  {}", cmd)?;
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use common::{prepend, move_to_front};
use op::{NormalOp, InsertOp};
use ordered_vec_map::{InsertionResult, OrderedVecMap};
use std::cmp::Ord;
use std::cmp::Ordering::{Less, Equal, Greater};
use std::collections::VecDeque;

/// By convention:
/// * K is a map's key type, implementing `Copy` and `Ord`.
/// * T is an arbitrary type, typically stored as a value in a map.
/// * Op is an arbitrary operation type (typically a mode-specific enum).

pub enum OpErr {
    EmptyKey,
    NotEnoughArgs(usize),
}

pub enum RemapErr {
    EmptyKey,
}

pub struct ModeMap<K, Op>
where
    K: Ord,
    K: Copy,
{
    // TODO Handle noremap (key,value) by surrounding value with non-input-able
    // keys, so if it gets put in the typeahead, it cannot possibly be remapped.
    // This would also mean such values would be ignored by the op-map.
    key_map: OrderedVecMap<Vec<K>, Vec<K>>,
    op_map: OrderedVecMap<Vec<K>, Op>,
}

pub struct State<K>
where
    K: Ord,
    K: Copy,
{
    pub typeahead: VecDeque<K>,
    pub normal_mode_map: ModeMap<K, NormalOp>,
    pub insert_mode_map: ModeMap<K, InsertOp>,
}

enum Match<T> {
    FullMatch(T),
    PartialMatch,
    NoMatch,
}

/// Matches a sequence `Vec<K>` using Vi's mapping rules:
/// * First check for partial matches such that `query` is shorter than the key.
///   In this case, return `Match::PartialMatch`.
/// * If no partial match is found, check for a full match. In this
///   case, return the value it maps to in a `Match::FullMatch` variant.
/// * If no partial or full match is found, return `Match::NoMatch`.
fn find_match<'a, K, T>(
    map: &'a OrderedVecMap<Vec<K>, T>,
    query: &Vec<K>,
) -> Match<&'a T>
where
    K: Ord,
{
    if query.is_empty() {
        return Match::NoMatch;
    }

    let partial_matcher = |probe: &(Vec<K>, T)| match probe.0.cmp(query) {
        Less => Less,
        Equal => Less, // When searching for partial matches, ignore equal.
        Greater => {
            return if probe.0.len() > query.len() &&
                probe.0.starts_with(query)
            {
                Equal
            } else {
                Greater
            };
        }
    };

    let full_matcher = |probe: &(Vec<K>, T)| match probe.0.cmp(query) {
        Less => {
            return if probe.0.len() <= query.len() &&
                query.starts_with(&probe.0)
            {
                Equal
            } else {
                Less
            };
        }
        Equal => Equal,
        Greater => Greater,
    };

    map.find_by(partial_matcher).map_or(
        map.find_by(full_matcher).map_or(
            Match::NoMatch, // No partial or full match found.
            |full| {
                Match::FullMatch(full)
            }, // No partial match, found full.
        ),
        |_| Match::PartialMatch, // Found a partial match.
    )
}

/// If `query` is a full match to a key found in `map`, the
/// corresponding map value is prepended to the typeahead buffer.
/// Returns `true` if a full or partial match is found. Otherwise, `false`.
fn remap<K>(
    map: &OrderedVecMap<Vec<K>, Vec<K>>,
    query: &mut Vec<K>,
    typeahead: &mut VecDeque<K>,
) -> bool
where
    K: Ord,
    K: Copy,
{
    match find_match(map, query) {
        Match::FullMatch(mapped_keys) => {
            // Put mapped keys in front of the typeahead buffer.
            for key in mapped_keys.iter().rev() {
                typeahead.push_front(*key);
            }
            // Clear query (ergo, we'll skip matching noremap and op until next
            // iteration).
            query.clear();
            true
        }
        Match::PartialMatch => {
            // Keep searching.
            true
        }
        Match::NoMatch => {
            // We're done searching this map.
            false
        }
    }
}

impl<K, Op> ModeMap<K, Op>
where
    K: Ord,
    K: Copy,
    Op: Copy,
{
    pub fn new() -> Self {
        ModeMap {
            key_map: OrderedVecMap::<Vec<K>, Vec<K>>::new(),
            op_map: OrderedVecMap::<Vec<K>, Op>::new(),
        }
    }

    // Loop until a partly matching mapping is found or all (local) mappings
    // have been checked.  The longest full match is remembered in "mp_match".
    // A full match is only accepted if there is no partly match, so "aa" and
    // "aaa" can both be mapped.
    // https://github.com/vim/vim/blob/master/src/getchar.c#L2140-L2146
    pub fn process(&self, mut typeahead: &mut VecDeque<K>) -> Option<Op> {
        // Grab incrementally more keys from the front of the queue, looking for
        // matches.
        let mut query = Vec::<K>::with_capacity(typeahead.len());
        let mut mapping = true;
        let mut opping = true;
        // TODO no longer need to incrementally add elements to the query.
        while !typeahead.is_empty() && (mapping || opping) {
            query.push(typeahead.pop_front().unwrap());
            mapping = mapping &&
                remap(&self.key_map, &mut query, &mut typeahead);
            match find_match(&self.op_map, &mut query) {
                Match::FullMatch(op) => {
                    return Some(*op);
                }
                Match::NoMatch => {
                    opping = false;
                }
                Match::PartialMatch => {}
            }
        }
        // Put whatever is left back in the typeahead buffer.
        move_to_front(&mut query, typeahead);
        None
    }

    pub fn insert_op(
        &mut self,
        key: Vec<K>,
        value: Op,
    ) -> Result<InsertionResult, OpErr> {
        // Disallow empty keys, as they would full-match against an empty
        // typeahead buffer.
        if key.is_empty() {
            return Err(OpErr::EmptyKey);
        }
        return Ok(self.op_map.insert((key, value)));
    }

    pub fn insert_remap(
        &mut self,
        key: Vec<K>,
        value: Vec<K>,
    ) -> Result<InsertionResult, RemapErr> {
        // Disallow empty keys, as they would full-match against an empty
        // typeahead buffer.
        if key.is_empty() {
            return Err(RemapErr::EmptyKey);
        }
        return Ok(self.key_map.insert((key, value)));
    }
}

impl<K> State<K>
where
    K: Ord,
    K: Copy,
{
    pub fn new() -> Self {
        State {
            typeahead: VecDeque::<K>::new(),
            normal_mode_map: ModeMap::<K, NormalOp>::new(),
            insert_mode_map: ModeMap::<K, InsertOp>::new(),
        }
    }
}

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

    #[test]
    fn no_match() {
        let mut map = OrderedVecMap::<Vec<u8>, Vec<u8>>::new();
        map.insert((vec![2u8, 3u8], vec![6u8]));
        let mut query = vec![1u8, 2u8, 3u8];
        let mut typeahead = VecDeque::<u8>::new();
        assert_eq!(false, remap(&map, &mut query, &mut typeahead));
        assert!(typeahead.is_empty());
    }

    #[test]
    fn partial_match() {
        let mut map = OrderedVecMap::<Vec<u8>, Vec<u8>>::new();
        map.insert((vec![1u8, 2u8, 3u8, 4u8], vec![6u8]));
        let mut query = vec![1u8, 2u8, 3u8];
        let mut typeahead = VecDeque::<u8>::new();
        assert_eq!(true, remap(&map, &mut query, &mut typeahead));
        assert!(typeahead.is_empty());
    }

    #[test]
    fn full_match() {
        let mut map = OrderedVecMap::<Vec<u8>, Vec<u8>>::new();
        map.insert((vec![1u8, 2u8, 3u8], vec![6u8]));
        let mut query = vec![1u8, 2u8, 3u8];
        let mut typeahead = VecDeque::<u8>::new();
        assert_eq!(true, remap(&map, &mut query, &mut typeahead));
        assert_eq!(VecDeque::from(vec![6u8]), typeahead);
    }
}

#[cfg(test)]
mod find_match {
    use super::*;
    use std::fmt::Debug;

    fn assert_partial_match<T>(m: Match<T>) {
        match m {
            Match::PartialMatch => {
                assert!(true);
            }
            _ => {
                assert!(false);
            }
        }
    }

    fn assert_full_match<T>(expected: T, m: Match<T>)
    where
        T: PartialEq,
        T: Debug,
    {
        match m {
            Match::FullMatch(x) => {
                assert_eq!(expected, x);
            }
            _ => {
                assert!(false);
            }
        }
    }

    fn assert_no_match<T>(m: Match<T>) {
        match m {
            Match::NoMatch => {
                assert!(true);
            }
            _ => {
                assert!(false);
            }
        }
    }

    #[test]
    fn partial_match() {
        let mut map = OrderedVecMap::<Vec<u8>, u8>::new();
        map.insert((vec![1u8, 2u8, 3u8, 4u8], 6u8));
        let query = vec![1u8, 2u8, 3u8];
        assert_partial_match(find_match(&map, &query))
    }

    #[test]
    fn full_match() {
        let mut map = OrderedVecMap::<Vec<u8>, u8>::new();
        map.insert((vec![1u8, 2u8, 3u8], 6u8));
        let query = vec![1u8, 2u8, 3u8];
        assert_full_match(&6u8, find_match(&map, &query))
    }

    #[test]
    fn no_match() {
        let mut map = OrderedVecMap::<Vec<u8>, u8>::new();
        map.insert((vec![1u8, 2u8, 3u8, 4u8], 6u8));
        let query = vec![2u8, 3u8];
        assert_no_match(find_match(&map, &query))
    }

    #[test]
    fn no_query() {
        let mut map = OrderedVecMap::<Vec<u8>, u8>::new();
        map.insert((vec![1u8, 2u8, 3u8, 4u8], 6u8));
        let query = vec![];
        assert_no_match(find_match(&map, &query))
    }
}
<commit_msg>revert bad optimization<commit_after>use common::{prepend, move_to_front};
use op::{NormalOp, InsertOp};
use ordered_vec_map::{InsertionResult, OrderedVecMap};
use std::cmp::Ord;
use std::cmp::Ordering::{Less, Equal, Greater};
use std::collections::VecDeque;

/// By convention:
/// * K is a map's key type, implementing `Copy` and `Ord`.
/// * T is an arbitrary type, typically stored as a value in a map.
/// * Op is an arbitrary operation type (typically a mode-specific enum).

pub enum OpErr {
    EmptyKey,
    NotEnoughArgs(usize),
}

pub enum RemapErr {
    EmptyKey,
}

pub struct ModeMap<K, Op>
where
    K: Ord,
    K: Copy,
{
    // TODO Handle noremap (key,value) by surrounding value with non-input-able
    // keys, so if it gets put in the typeahead, it cannot possibly be remapped.
    // This would also mean such values would be ignored by the op-map.
    key_map: OrderedVecMap<Vec<K>, Vec<K>>,
    op_map: OrderedVecMap<Vec<K>, Op>,
}

pub struct State<K>
where
    K: Ord,
    K: Copy,
{
    pub typeahead: VecDeque<K>,
    pub normal_mode_map: ModeMap<K, NormalOp>,
    pub insert_mode_map: ModeMap<K, InsertOp>,
}

enum Match<T> {
    FullMatch(T),
    PartialMatch,
    NoMatch,
}

/// Matches a sequence `Vec<K>` using Vi's mapping rules:
/// * First check for partial matches such that `query` is shorter than the key.
///   In this case, return `Match::PartialMatch`.
/// * If no partial match is found, check for a full match. In this
///   case, return the value it maps to in a `Match::FullMatch` variant.
/// * If no partial or full match is found, return `Match::NoMatch`.
fn find_match<'a, K, T>(
    map: &'a OrderedVecMap<Vec<K>, T>,
    query: &Vec<K>,
) -> Match<&'a T>
where
    K: Ord,
{
    if query.is_empty() {
        return Match::NoMatch;
    }

    let partial_matcher = |probe: &(Vec<K>, T)| match probe.0.cmp(query) {
        Less => Less,
        Equal => Less, // When searching for partial matches, ignore equal.
        Greater => {
            return if probe.0.len() > query.len() &&
                probe.0.starts_with(query)
            {
                Equal
            } else {
                Greater
            };
        }
    };

    map.find_by(partial_matcher).map_or(
        map.find(query).map_or(
            Match::NoMatch, // No partial or full match found.
            |full| Match::FullMatch(full), // No partial match, found full.
        ),
        |_| Match::PartialMatch, // Found a partial match.
    )
}

/// If `query` is a full match to a key found in `map`, the
/// corresponding map value is prepended to the typeahead buffer.
/// Returns `true` if a full or partial match is found. Otherwise, `false`.
fn remap<K>(
    map: &OrderedVecMap<Vec<K>, Vec<K>>,
    query: &mut Vec<K>,
    typeahead: &mut VecDeque<K>,
) -> bool
where
    K: Ord,
    K: Copy,
{
    match find_match(map, query) {
        Match::FullMatch(mapped_keys) => {
            // Put mapped keys in front of the typeahead buffer.
            for key in mapped_keys.iter().rev() {
                typeahead.push_front(*key);
            }
            // Clear query (ergo, we'll skip matching noremap and op until next
            // iteration).
            query.clear();
            true
        }
        Match::PartialMatch => {
            // Keep searching.
            true
        }
        Match::NoMatch => {
            // We're done searching this map.
            false
        }
    }
}

impl<K, Op> ModeMap<K, Op>
where
    K: Ord,
    K: Copy,
    Op: Copy,
{
    pub fn new() -> Self {
        ModeMap {
            key_map: OrderedVecMap::<Vec<K>, Vec<K>>::new(),
            op_map: OrderedVecMap::<Vec<K>, Op>::new(),
        }
    }

    // Loop until a partly matching mapping is found or all (local) mappings
    // have been checked.  The longest full match is remembered in "mp_match".
    // A full match is only accepted if there is no partly match, so "aa" and
    // "aaa" can both be mapped.
    // https://github.com/vim/vim/blob/master/src/getchar.c#L2140-L2146
    pub fn process(&self, mut typeahead: &mut VecDeque<K>) -> Option<Op> {
        // Grab incrementally more keys from the front of the queue, looking for
        // matches.
        let mut query = Vec::<K>::with_capacity(typeahead.len());
        let mut mapping = true;
        let mut opping = true;
        // TODO no longer need to incrementally add elements to the query.
        while !typeahead.is_empty() && (mapping || opping) {
            query.push(typeahead.pop_front().unwrap());
            mapping = mapping &&
                remap(&self.key_map, &mut query, &mut typeahead);
            match find_match(&self.op_map, &mut query) {
                Match::FullMatch(op) => {
                    return Some(*op);
                }
                Match::NoMatch => {
                    opping = false;
                }
                Match::PartialMatch => {}
            }
        }
        // Put whatever is left back in the typeahead buffer.
        move_to_front(&mut query, typeahead);
        None
    }

    pub fn insert_op(
        &mut self,
        key: Vec<K>,
        value: Op,
    ) -> Result<InsertionResult, OpErr> {
        // Disallow empty keys, as they would full-match against an empty
        // typeahead buffer.
        if key.is_empty() {
            return Err(OpErr::EmptyKey);
        }
        return Ok(self.op_map.insert((key, value)));
    }

    pub fn insert_remap(
        &mut self,
        key: Vec<K>,
        value: Vec<K>,
    ) -> Result<InsertionResult, RemapErr> {
        // Disallow empty keys, as they would full-match against an empty
        // typeahead buffer.
        if key.is_empty() {
            return Err(RemapErr::EmptyKey);
        }
        return Ok(self.key_map.insert((key, value)));
    }
}

impl<K> State<K>
where
    K: Ord,
    K: Copy,
{
    pub fn new() -> Self {
        State {
            typeahead: VecDeque::<K>::new(),
            normal_mode_map: ModeMap::<K, NormalOp>::new(),
            insert_mode_map: ModeMap::<K, InsertOp>::new(),
        }
    }
}

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

    #[test]
    fn no_match() {
        let mut map = OrderedVecMap::<Vec<u8>, Vec<u8>>::new();
        map.insert((vec![2u8, 3u8], vec![6u8]));
        let mut query = vec![1u8, 2u8, 3u8];
        let mut typeahead = VecDeque::<u8>::new();
        assert_eq!(false, remap(&map, &mut query, &mut typeahead));
        assert!(typeahead.is_empty());
    }

    #[test]
    fn partial_match() {
        let mut map = OrderedVecMap::<Vec<u8>, Vec<u8>>::new();
        map.insert((vec![1u8, 2u8, 3u8, 4u8], vec![6u8]));
        let mut query = vec![1u8, 2u8, 3u8];
        let mut typeahead = VecDeque::<u8>::new();
        assert_eq!(true, remap(&map, &mut query, &mut typeahead));
        assert!(typeahead.is_empty());
    }

    #[test]
    fn full_match() {
        let mut map = OrderedVecMap::<Vec<u8>, Vec<u8>>::new();
        map.insert((vec![1u8, 2u8, 3u8], vec![6u8]));
        let mut query = vec![1u8, 2u8, 3u8];
        let mut typeahead = VecDeque::<u8>::new();
        assert_eq!(true, remap(&map, &mut query, &mut typeahead));
        assert_eq!(VecDeque::from(vec![6u8]), typeahead);
    }
}

#[cfg(test)]
mod find_match {
    use super::*;
    use std::fmt::Debug;

    fn assert_partial_match<T>(m: Match<T>) {
        match m {
            Match::PartialMatch => {
                assert!(true);
            }
            _ => {
                assert!(false);
            }
        }
    }

    fn assert_full_match<T>(expected: T, m: Match<T>)
    where
        T: PartialEq,
        T: Debug,
    {
        match m {
            Match::FullMatch(x) => {
                assert_eq!(expected, x);
            }
            _ => {
                assert!(false);
            }
        }
    }

    fn assert_no_match<T>(m: Match<T>) {
        match m {
            Match::NoMatch => {
                assert!(true);
            }
            _ => {
                assert!(false);
            }
        }
    }

    #[test]
    fn partial_match() {
        let mut map = OrderedVecMap::<Vec<u8>, u8>::new();
        map.insert((vec![1u8, 2u8, 3u8, 4u8], 6u8));
        let query = vec![1u8, 2u8, 3u8];
        assert_partial_match(find_match(&map, &query))
    }

    #[test]
    fn full_match() {
        let mut map = OrderedVecMap::<Vec<u8>, u8>::new();
        map.insert((vec![1u8, 2u8, 3u8], 6u8));
        let query = vec![1u8, 2u8, 3u8];
        assert_full_match(&6u8, find_match(&map, &query))
    }

    #[test]
    fn best_full_match() {
        let mut map = OrderedVecMap::<Vec<u8>, u8>::new();
        map.insert((vec![1u8], 4u8));
        map.insert((vec![1u8, 2u8], 5u8));
        map.insert((vec![1u8, 2u8, 3u8], 6u8));
        let query = vec![1u8, 2u8, 3u8];
        assert_full_match(&6u8, find_match(&map, &query))
    }

    #[test]
    fn no_match() {
        let mut map = OrderedVecMap::<Vec<u8>, u8>::new();
        map.insert((vec![1u8, 2u8, 3u8, 4u8], 6u8));
        let query = vec![2u8, 3u8];
        assert_no_match(find_match(&map, &query))
    }

    #[test]
    fn no_query() {
        let mut map = OrderedVecMap::<Vec<u8>, u8>::new();
        map.insert((vec![1u8, 2u8, 3u8, 4u8], 6u8));
        let query = vec![];
        assert_no_match(find_match(&map, &query))
    }
}
<|endoftext|>