<commit_before>//! GPU-visible memory allocation and management.
//!
//! When you create a buffer or a texture with Vulkan, you have to bind it to a chunk of allocated
//! memory. To do so, you have to pass a type that implements the `MemorySource` trait.
//!
//! There are several implementations of the trait, ie. several things that you can pass to the
//! constructors of buffers and textures:
//!
//! - `&Arc<Device>`, which will simply allocate a new chunk of memory every time (easy but not
//!   very efficient).
//! - `MemorySource`, which is the same as `&Arc<Device>` except that it will use the
//!   already-allocated block.
//! - ... needs more ...
//!
//! # Synchronization
//!
//! In Vulkan, it's the job of the programmer to enforce memory safety. In other words, the
//! programmer must take care that two chunks of memory are not read and written simultaneously.
//!
//! In this library, this is enforced by the implementation of `MemorySource` or
//! `MemorySourceChunk`.
//!
//! There are two mechanisms in Vulkan that can provide synchronization: fences and semaphores.
//! Fences provide synchronization between the CPU and the GPU, and semaphores provide
//! synchronization between multiple queues of the GPU. See the `sync` module for more info.
//!
//! # Sparse resources
//!
//! **Not yet implemented**.
//!
//! Instead of creating a buffer or an image with a single chunk of memory, you also have the
//! possibility to create resources with *sparse memory*.
//!
//! For example you can bind the first half of the buffer to a memory chunk, and the second half of
//! the buffer to another memory chunk.
//!
//! There is a hierarchy of three features related to sparse resources:
//!
//!  - The `sparseBinding` feature allows you to use sparse resources.
//!  - The `sparseResidency` feature is a superset of `sparseBinding` and allows you to leave some
//!    parts of the resource unbinded before using it.
//!  - The `sparseResidencyAliased` feature is a superset of `sparseResidency` and allows you to
//!    bind the same memory chunk to multiple different resources at once.
//!
use std::mem;
use std::ops::Deref;
use std::ops::DerefMut;
use std::os::raw::c_void;
use std::slice;
use std::sync::Arc;

use sync::Fence;
use sync::Semaphore;

use device::Device;
use device::Queue;

use OomError;

pub use self::device_memory::DeviceMemory;
pub use self::device_memory::MappedDeviceMemory;
pub use self::single::DeviceLocal;
pub use self::single::DeviceLocalChunk;
pub use self::single::HostVisible;
pub use self::single::HostVisibleChunk;

mod device_memory;
mod single;

/// Trait for memory objects that can be accessed from the CPU.
pub unsafe trait CpuAccessible<'a, T: ?Sized> {
    /// The object that provides the access.
    type Read: Deref<Target = T>;

    /// Gives a read access to the content of the buffer.
    ///
    /// If the buffer is in use by the GPU, blocks until it is available.
    // TODO: what happens if timeout is reached? a panic?
    fn read(&'a self, timeout_ns: u64) -> Self::Read;

    /// Tries to give a read access to the content of the buffer.
    ///
    /// If the buffer is in use by the GPU, returns `None`.
    fn try_read(&'a self) -> Option<Self::Read>;
}

/// Trait for memory objects that can be mutably accessed from the CPU.
pub unsafe trait CpuWriteAccessible<'a, T: ?Sized>: CpuAccessible<'a, T> {
    /// The object that provides the access.
    type Write: DerefMut<Target = T>;

    /// Gives a write access to the content of the buffer.
    ///
    /// If the buffer is in use by the GPU, blocks until it is available.
    // TODO: what happens if timeout is reached? a panic?
    fn write(&'a self, timeout_ns: u64) -> Self::Write;

    /// Tries to give a write access to the content of the buffer.
    ///
    /// If the buffer is in use by the GPU, returns `None`.
    fn try_write(&'a self) -> Option<Self::Write>;
}

/// Trait for objects that can be used to fill the memory requirements of a buffer or an image.
pub unsafe trait MemorySource {
    /// An object that represents one block of allocation. Returned by `allocate`.
    type Chunk: MemorySourceChunk;

    /// Returns true if the chunks allocated by this source will use sparse memory.
    // TODO: should return the level of the required sparse feature
    fn is_sparse(&self) -> bool;

    /// Allocates a block of memory to be used.
    ///
    /// `memory_type_bits` is a bitsfield which indicates from which memory type the memory can
    /// be allocated. For example if the bit 2 is set (`memory_type_bits & (1 << 2) != 0`), that
    /// means that the memory type whose ID is 2 can be used.
    ///
    /// The implementation is allowed to return a chunk with a larger size or alignment.
    fn allocate(self, &Arc<Device>, size: usize, alignment: usize, memory_type_bits: u32)
                -> Result<Self::Chunk, OomError>;
}

/// A chunk of GPU-visible memory.
pub unsafe trait MemorySourceChunk {
    /// Returns the properties of this chunk.
    fn properties(&self) -> ChunkProperties;

    /// Returns true if the `gpu_access` function should be passed a fence.
    #[inline]
    fn requires_fence(&self) -> bool {
        true
    }

    /// Returns true if the `gpu_access` function should be passed a semaphore.
    #[inline]
    fn requires_semaphore(&self) -> bool {
        true
    }

    /// Instructs the manager that a part of this chunk of memory is going to be used by the
    /// GPU soon in the future. The function should block if the memory is currently being
    /// accessed by the CPU.
    ///
    /// `write` indicates whether the GPU will write to the memory. If `false`, then it will only
    /// be written.
    ///
    /// `range` indicates the part of the chunk that is concerned.
    ///
    /// `queue` is the queue where the command buffer that accesses the memory will be submitted.
    /// If the `gpu_access` function submits something to that queue, it will thus be submitted
    /// beforehand. This behavior can be used for example to submit sparse binding commands.
    ///
    /// `fence` is a fence that will be signaled when this GPU access will stop. It should be
    /// waited upon whenever the user wants to read this memory from the CPU. If `requires_fence`
    /// returned false, then this value will be `None`.
    ///
    /// `semaphore` is a semaphore that will be signaled when this GPU access will stop. This value
    /// is intended to be returned later, in a follow-up call to `gpu_access`. If
    /// `requires_semaphore` returned false, then this value will be `None`.
    ///
    /// The manager must track whether this chunk of memory is being accessed by the CPU/GPU and
    /// return a semaphore that must be waited upon by the GPU before the access can start. The
    /// semaphore being returned is usually one that has been previously passed to this function,
    /// but it doesn't need to be the case.
    unsafe fn gpu_access(&self, write: bool, range: ChunkRange, queue: &Arc<Queue>,
                         fence: Option<Arc<Fence>>, semaphore: Option<Arc<Semaphore>>)
                         -> Option<Arc<Semaphore>>;

    /// Returns true if this chunk of memory may be used, now or in the future, by multiple buffers
    /// or images (or a combination of both) simultaneously. If you're not sure, it's safer to
    /// return true.
    ///
    /// If this value is true, then the Vulkan implementation must be more conservative about
    /// reordering subpasses in a renderpass.
    fn may_alias(&self) -> bool;
}

/// Describes a range in a memory chunk.
pub enum ChunkRange {
    /// The whole chunk.
    All,

    /// A subpart of the chunk.
    Range {
        /// Number of bytes between the start of the chunk and the part we want.
        offset: usize,
        /// Size in bytes of the part we want.
        size: usize,
    }
}

pub enum ChunkProperties<'a> {
    Regular {
        memory: &'a DeviceMemory,
        offset: usize,
        size: usize,
    },

    Sparse,     // TODO: unimplemented
}

/// Trait for types of data that can be mapped.
pub unsafe trait Content {
    /// Builds a pointer to this type from a raw pointer.
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut Self>;

    /// Returns true if the size is suitable to store a type like this.
    fn is_size_suitable(usize) -> bool;
}

unsafe impl<T> Content for T {
    #[inline]
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut T> {
        if size != mem::size_of::<T>() {
            return None;
        }

        Some(ptr as *mut T)
    }

    #[inline]
    fn is_size_suitable(size: usize) -> bool {
        size == mem::size_of::<T>()
    }
}

unsafe impl<T> Content for [T] {
    #[inline]
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut [T]> {
        if size % mem::size_of::<T>() != 0 {
            return None;
        }

        let ptr = ptr as *mut T;
        let size = size / mem::size_of::<T>();
        Some(unsafe { slice::from_raw_parts_mut(&mut *ptr, size) as *mut [T] })
    }

    #[inline]
    fn is_size_suitable(size: usize) -> bool {
        size % mem::size_of::<T>() == 0
    }
}

/*
TODO: do this when it's possible
unsafe impl Content for .. {}
impl<'a, T> !Content for &'a T {}
impl<'a, T> !Content for &'a mut T {}
impl<T> !Content for *const T {}
impl<T> !Content for *mut T {}
impl<T> !Content for Box<T> {}
impl<T> !Content for UnsafeCell<T> {}

*/
<commit_msg>Be more relaxed in Content::ref_from_ptr<commit_after>//! GPU-visible memory allocation and management.
//!
//! When you create a buffer or a texture with Vulkan, you have to bind it to a chunk of allocated
//! memory. To do so, you have to pass a type that implements the `MemorySource` trait.
//!
//! There are several implementations of the trait, ie. several things that you can pass to the
//! constructors of buffers and textures:
//!
//! - `&Arc<Device>`, which will simply allocate a new chunk of memory every time (easy but not
//!   very efficient).
//! - `MemorySource`, which is the same as `&Arc<Device>` except that it will use the
//!   already-allocated block.
//! - ... needs more ...
//!
//! # Synchronization
//!
//! In Vulkan, it's the job of the programmer to enforce memory safety. In other words, the
//! programmer must take care that two chunks of memory are not read and written simultaneously.
//!
//! In this library, this is enforced by the implementation of `MemorySource` or
//! `MemorySourceChunk`.
//!
//! There are two mechanisms in Vulkan that can provide synchronization: fences and semaphores.
//! Fences provide synchronization between the CPU and the GPU, and semaphores provide
//! synchronization between multiple queues of the GPU. See the `sync` module for more info.
//!
//! # Sparse resources
//!
//! **Not yet implemented**.
//!
//! Instead of creating a buffer or an image with a single chunk of memory, you also have the
//! possibility to create resources with *sparse memory*.
//!
//! For example you can bind the first half of the buffer to a memory chunk, and the second half of
//! the buffer to another memory chunk.
//!
//! There is a hierarchy of three features related to sparse resources:
//!
//!  - The `sparseBinding` feature allows you to use sparse resources.
//!  - The `sparseResidency` feature is a superset of `sparseBinding` and allows you to leave some
//!    parts of the resource unbinded before using it.
//!  - The `sparseResidencyAliased` feature is a superset of `sparseResidency` and allows you to
//!    bind the same memory chunk to multiple different resources at once.
//!
use std::mem;
use std::ops::Deref;
use std::ops::DerefMut;
use std::os::raw::c_void;
use std::slice;
use std::sync::Arc;

use sync::Fence;
use sync::Semaphore;

use device::Device;
use device::Queue;

use OomError;

pub use self::device_memory::DeviceMemory;
pub use self::device_memory::MappedDeviceMemory;
pub use self::single::DeviceLocal;
pub use self::single::DeviceLocalChunk;
pub use self::single::HostVisible;
pub use self::single::HostVisibleChunk;

mod device_memory;
mod single;

/// Trait for memory objects that can be accessed from the CPU.
pub unsafe trait CpuAccessible<'a, T: ?Sized> {
    /// The object that provides the access.
    type Read: Deref<Target = T>;

    /// Gives a read access to the content of the buffer.
    ///
    /// If the buffer is in use by the GPU, blocks until it is available.
    // TODO: what happens if timeout is reached? a panic?
    fn read(&'a self, timeout_ns: u64) -> Self::Read;

    /// Tries to give a read access to the content of the buffer.
    ///
    /// If the buffer is in use by the GPU, returns `None`.
    fn try_read(&'a self) -> Option<Self::Read>;
}

/// Trait for memory objects that can be mutably accessed from the CPU.
pub unsafe trait CpuWriteAccessible<'a, T: ?Sized>: CpuAccessible<'a, T> {
    /// The object that provides the access.
    type Write: DerefMut<Target = T>;

    /// Gives a write access to the content of the buffer.
    ///
    /// If the buffer is in use by the GPU, blocks until it is available.
    // TODO: what happens if timeout is reached? a panic?
    fn write(&'a self, timeout_ns: u64) -> Self::Write;

    /// Tries to give a write access to the content of the buffer.
    ///
    /// If the buffer is in use by the GPU, returns `None`.
    fn try_write(&'a self) -> Option<Self::Write>;
}

/// Trait for objects that can be used to fill the memory requirements of a buffer or an image.
pub unsafe trait MemorySource {
    /// An object that represents one block of allocation. Returned by `allocate`.
    type Chunk: MemorySourceChunk;

    /// Returns true if the chunks allocated by this source will use sparse memory.
    // TODO: should return the level of the required sparse feature
    fn is_sparse(&self) -> bool;

    /// Allocates a block of memory to be used.
    ///
    /// `memory_type_bits` is a bitsfield which indicates from which memory type the memory can
    /// be allocated. For example if the bit 2 is set (`memory_type_bits & (1 << 2) != 0`), that
    /// means that the memory type whose ID is 2 can be used.
    ///
    /// The implementation is allowed to return a chunk with a larger size or alignment.
    fn allocate(self, &Arc<Device>, size: usize, alignment: usize, memory_type_bits: u32)
                -> Result<Self::Chunk, OomError>;
}

/// A chunk of GPU-visible memory.
pub unsafe trait MemorySourceChunk {
    /// Returns the properties of this chunk.
    fn properties(&self) -> ChunkProperties;

    /// Returns true if the `gpu_access` function should be passed a fence.
    #[inline]
    fn requires_fence(&self) -> bool {
        true
    }

    /// Returns true if the `gpu_access` function should be passed a semaphore.
    #[inline]
    fn requires_semaphore(&self) -> bool {
        true
    }

    /// Instructs the manager that a part of this chunk of memory is going to be used by the
    /// GPU soon in the future. The function should block if the memory is currently being
    /// accessed by the CPU.
    ///
    /// `write` indicates whether the GPU will write to the memory. If `false`, then it will only
    /// be written.
    ///
    /// `range` indicates the part of the chunk that is concerned.
    ///
    /// `queue` is the queue where the command buffer that accesses the memory will be submitted.
    /// If the `gpu_access` function submits something to that queue, it will thus be submitted
    /// beforehand. This behavior can be used for example to submit sparse binding commands.
    ///
    /// `fence` is a fence that will be signaled when this GPU access will stop. It should be
    /// waited upon whenever the user wants to read this memory from the CPU. If `requires_fence`
    /// returned false, then this value will be `None`.
    ///
    /// `semaphore` is a semaphore that will be signaled when this GPU access will stop. This value
    /// is intended to be returned later, in a follow-up call to `gpu_access`. If
    /// `requires_semaphore` returned false, then this value will be `None`.
    ///
    /// The manager must track whether this chunk of memory is being accessed by the CPU/GPU and
    /// return a semaphore that must be waited upon by the GPU before the access can start. The
    /// semaphore being returned is usually one that has been previously passed to this function,
    /// but it doesn't need to be the case.
    unsafe fn gpu_access(&self, write: bool, range: ChunkRange, queue: &Arc<Queue>,
                         fence: Option<Arc<Fence>>, semaphore: Option<Arc<Semaphore>>)
                         -> Option<Arc<Semaphore>>;

    /// Returns true if this chunk of memory may be used, now or in the future, by multiple buffers
    /// or images (or a combination of both) simultaneously. If you're not sure, it's safer to
    /// return true.
    ///
    /// If this value is true, then the Vulkan implementation must be more conservative about
    /// reordering subpasses in a renderpass.
    fn may_alias(&self) -> bool;
}

/// Describes a range in a memory chunk.
pub enum ChunkRange {
    /// The whole chunk.
    All,

    /// A subpart of the chunk.
    Range {
        /// Number of bytes between the start of the chunk and the part we want.
        offset: usize,
        /// Size in bytes of the part we want.
        size: usize,
    }
}

pub enum ChunkProperties<'a> {
    Regular {
        memory: &'a DeviceMemory,
        offset: usize,
        size: usize,
    },

    Sparse,     // TODO: unimplemented
}

/// Trait for types of data that can be mapped.
pub unsafe trait Content {
    /// Builds a pointer to this type from a raw pointer.
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut Self>;

    /// Returns true if the size is suitable to store a type like this.
    fn is_size_suitable(usize) -> bool;
}

unsafe impl<T> Content for T {
    #[inline]
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut T> {
        if size < mem::size_of::<T>() {
            return None;
        }

        Some(ptr as *mut T)
    }

    #[inline]
    fn is_size_suitable(size: usize) -> bool {
        size == mem::size_of::<T>()
    }
}

unsafe impl<T> Content for [T] {
    #[inline]
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut [T]> {
        let ptr = ptr as *mut T;
        let size = size / mem::size_of::<T>();
        Some(unsafe { slice::from_raw_parts_mut(&mut *ptr, size) as *mut [T] })
    }

    #[inline]
    fn is_size_suitable(size: usize) -> bool {
        size % mem::size_of::<T>() == 0
    }
}

/*
TODO: do this when it's possible
unsafe impl Content for .. {}
impl<'a, T> !Content for &'a T {}
impl<'a, T> !Content for &'a mut T {}
impl<T> !Content for *const T {}
impl<T> !Content for *mut T {}
impl<T> !Content for Box<T> {}
impl<T> !Content for UnsafeCell<T> {}

*/
<|endoftext|>


<commit_before><commit_msg>Rust upgrade (seems to need a Clone with a Copy).<commit_after><|endoftext|>


<commit_before>//! Connection pooling via r2d2.
//!
//! Note: This module requires enabling the `r2d2` feature

extern crate r2d2;

pub use self::r2d2::*;

/// A re-export of [`r2d2::Error`], which is only used by methods on [`r2d2::Pool`].
///
/// [`r2d2::Error`]: ../../r2d2/struct.Error.html
/// [`r2d2::Pool`]: ../../r2d2/struct.Pool.html
pub type PoolError = self::r2d2::Error;

use std::convert::Into;
use std::fmt;
use std::marker::PhantomData;

use crate::connection::{SimpleConnection, TransactionManager};
use crate::deserialize::{Queryable, QueryableByName};
use crate::prelude::*;
use crate::query_builder::{AsQuery, QueryFragment, QueryId};
use crate::sql_types::HasSqlType;

/// An r2d2 connection manager for use with Diesel.
///
/// See the [r2d2 documentation] for usage examples.
///
/// [r2d2 documentation]: ../../r2d2
#[derive(Debug, Clone)]
pub struct ConnectionManager<T> {
    database_url: String,
    _marker: PhantomData<T>,
}

unsafe impl<T: Send + 'static> Sync for ConnectionManager<T> {}

impl<T> ConnectionManager<T> {
    /// Returns a new connection manager,
    /// which establishes connections to the given database URL.
    pub fn new<S: Into<String>>(database_url: S) -> Self {
        ConnectionManager {
            database_url: database_url.into(),
            _marker: PhantomData,
        }
    }
}

/// The error used when managing connections with `r2d2`.
#[derive(Debug)]
pub enum Error {
    /// An error occurred establishing the connection
    ConnectionError(ConnectionError),

    /// An error occurred pinging the database
    QueryError(crate::result::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::ConnectionError(ref e) => e.fmt(f),
            Error::QueryError(ref e) => e.fmt(f),
        }
    }
}

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

/// A trait indicating a connection could be used inside a r2d2 pool
pub trait R2D2Connection: Connection {
    /// Check if a connection is still valid
    fn ping(&self) -> QueryResult<()>;
}

#[cfg(feature = "postgres")]
impl R2D2Connection for crate::pg::PgConnection {
    fn ping(&self) -> QueryResult<()> {
        self.execute("SELECT 1").map(|_| ())
    }
}

#[cfg(feature = "mysql")]
impl R2D2Connection for crate::mysql::MysqlConnection {
    fn ping(&self) -> QueryResult<()> {
        self.execute("SELECT 1").map(|_| ())
    }
}

#[cfg(feature = "sqlite")]
impl R2D2Connection for crate::sqlite::SqliteConnection {
    fn ping(&self) -> QueryResult<()> {
        self.execute("SELECT 1").map(|_| ())
    }
}

impl<T> ManageConnection for ConnectionManager<T>
where
    T: R2D2Connection + Send + 'static,
{
    type Connection = T;
    type Error = Error;

    fn connect(&self) -> Result<T, Error> {
        T::establish(&self.database_url).map_err(Error::ConnectionError)
    }

    fn is_valid(&self, conn: &mut T) -> Result<(), Error> {
        conn.ping().map_err(Error::QueryError)
    }

    fn has_broken(&self, _conn: &mut T) -> bool {
        false
    }
}

impl<M> SimpleConnection for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: R2D2Connection + Send + 'static,
{
    fn batch_execute(&self, query: &str) -> QueryResult<()> {
        (&**self).batch_execute(query)
    }
}

impl<M> Connection for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: Connection + R2D2Connection + Send + 'static,
{
    type Backend = <M::Connection as Connection>::Backend;
    type TransactionManager = PooledConnectionTransactionManager<M>;

    fn establish(_: &str) -> ConnectionResult<Self> {
        Err(ConnectionError::BadConnection(String::from(
            "Cannot directly establish a pooled connection",
        )))
    }

    fn execute(&self, query: &str) -> QueryResult<usize> {
        (&**self).execute(query)
    }

    fn query_by_index<T, U>(&self, source: T) -> QueryResult<Vec<U>>
    where
        T: AsQuery,
        T::Query: QueryFragment<Self::Backend> + QueryId,
        Self::Backend: HasSqlType<T::SqlType>,
        U: Queryable<T::SqlType, Self::Backend>,
    {
        (&**self).query_by_index(source)
    }

    fn query_by_name<T, U>(&self, source: &T) -> QueryResult<Vec<U>>
    where
        T: QueryFragment<Self::Backend> + QueryId,
        U: QueryableByName<Self::Backend>,
    {
        (&**self).query_by_name(source)
    }

    fn execute_returning_count<T>(&self, source: &T) -> QueryResult<usize>
    where
        T: QueryFragment<Self::Backend> + QueryId,
    {
        (&**self).execute_returning_count(source)
    }

    fn transaction_manager(&self) -> &Self::TransactionManager {
        // This is actually fine because we have an #[repr(transparent)]
        // on LoggingTransactionManager, which means the layout is the same
        // as the inner type
        // See the ref-cast crate for a longer version: https://github.com/dtolnay/ref-cast
        unsafe {
            &*((&**self).transaction_manager() as *const _ as *const Self::TransactionManager)
        }
    }
}

#[doc(hidden)]
#[repr(transparent)]
#[allow(missing_debug_implementations)]
pub struct PooledConnectionTransactionManager<M>
where
    M: ManageConnection,
    M::Connection: Connection,
{
    inner: <M::Connection as Connection>::TransactionManager,
}

impl<M> TransactionManager<PooledConnection<M>> for PooledConnectionTransactionManager<M>
where
    M: ManageConnection,
    PooledConnection<M>: Connection,
    M::Connection: Connection,
{
    fn begin_transaction(&self, conn: &PooledConnection<M>) -> QueryResult<()> {
        self.inner.begin_transaction(&**conn)
    }

    fn rollback_transaction(&self, conn: &PooledConnection<M>) -> QueryResult<()> {
        self.inner.rollback_transaction(&**conn)
    }

    fn commit_transaction(&self, conn: &PooledConnection<M>) -> QueryResult<()> {
        self.inner.commit_transaction(&**conn)
    }

    fn get_transaction_depth(&self) -> u32 {
        self.inner.get_transaction_depth()
    }
}

#[cfg(test)]
mod tests {
    use std::sync::mpsc;
    use std::sync::Arc;
    use std::thread;

    use crate::r2d2::*;
    use crate::test_helpers::*;

    #[test]
    fn establish_basic_connection() {
        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Arc::new(Pool::builder().max_size(2).build(manager).unwrap());

        let (s1, r1) = mpsc::channel();
        let (s2, r2) = mpsc::channel();

        let pool1 = Arc::clone(&pool);
        let t1 = thread::spawn(move || {
            let conn = pool1.get().unwrap();
            s1.send(()).unwrap();
            r2.recv().unwrap();
            drop(conn);
        });

        let pool2 = Arc::clone(&pool);
        let t2 = thread::spawn(move || {
            let conn = pool2.get().unwrap();
            s2.send(()).unwrap();
            r1.recv().unwrap();
            drop(conn);
        });

        t1.join().unwrap();
        t2.join().unwrap();

        pool.get().unwrap();
    }

    #[test]
    fn is_valid() {
        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Pool::builder()
            .max_size(1)
            .test_on_check_out(true)
            .build(manager)
            .unwrap();

        pool.get().unwrap();
    }

    #[test]
    fn pooled_connection_impls_connection() {
        use crate::select;
        use crate::sql_types::Text;

        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Pool::builder()
            .max_size(1)
            .test_on_check_out(true)
            .build(manager)
            .unwrap();
        let conn = pool.get().unwrap();

        let query = select("foo".into_sql::<Text>());
        assert_eq!("foo", query.get_result::<String>(&conn).unwrap());
    }
}
<commit_msg>Implement a few more traits for `PooledConnection<M>`<commit_after>//! Connection pooling via r2d2.
//!
//! Note: This module requires enabling the `r2d2` feature

extern crate r2d2;

pub use self::r2d2::*;

/// A re-export of [`r2d2::Error`], which is only used by methods on [`r2d2::Pool`].
///
/// [`r2d2::Error`]: ../../r2d2/struct.Error.html
/// [`r2d2::Pool`]: ../../r2d2/struct.Pool.html
pub type PoolError = self::r2d2::Error;

use std::convert::Into;
use std::fmt;
use std::marker::PhantomData;

use crate::connection::{SimpleConnection, TransactionManager};
use crate::deserialize::{Queryable, QueryableByName};
use crate::prelude::*;
use crate::query_builder::{AsQuery, QueryFragment, QueryId};
use crate::sql_types::HasSqlType;

/// An r2d2 connection manager for use with Diesel.
///
/// See the [r2d2 documentation] for usage examples.
///
/// [r2d2 documentation]: ../../r2d2
#[derive(Debug, Clone)]
pub struct ConnectionManager<T> {
    database_url: String,
    _marker: PhantomData<T>,
}

unsafe impl<T: Send + 'static> Sync for ConnectionManager<T> {}

impl<T> ConnectionManager<T> {
    /// Returns a new connection manager,
    /// which establishes connections to the given database URL.
    pub fn new<S: Into<String>>(database_url: S) -> Self {
        ConnectionManager {
            database_url: database_url.into(),
            _marker: PhantomData,
        }
    }
}

/// The error used when managing connections with `r2d2`.
#[derive(Debug)]
pub enum Error {
    /// An error occurred establishing the connection
    ConnectionError(ConnectionError),

    /// An error occurred pinging the database
    QueryError(crate::result::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::ConnectionError(ref e) => e.fmt(f),
            Error::QueryError(ref e) => e.fmt(f),
        }
    }
}

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

/// A trait indicating a connection could be used inside a r2d2 pool
pub trait R2D2Connection: Connection {
    /// Check if a connection is still valid
    fn ping(&self) -> QueryResult<()>;
}

#[cfg(feature = "postgres")]
impl R2D2Connection for crate::pg::PgConnection {
    fn ping(&self) -> QueryResult<()> {
        self.execute("SELECT 1").map(|_| ())
    }
}

#[cfg(feature = "mysql")]
impl R2D2Connection for crate::mysql::MysqlConnection {
    fn ping(&self) -> QueryResult<()> {
        self.execute("SELECT 1").map(|_| ())
    }
}

#[cfg(feature = "sqlite")]
impl R2D2Connection for crate::sqlite::SqliteConnection {
    fn ping(&self) -> QueryResult<()> {
        self.execute("SELECT 1").map(|_| ())
    }
}

impl<T> ManageConnection for ConnectionManager<T>
where
    T: R2D2Connection + Send + 'static,
{
    type Connection = T;
    type Error = Error;

    fn connect(&self) -> Result<T, Error> {
        T::establish(&self.database_url).map_err(Error::ConnectionError)
    }

    fn is_valid(&self, conn: &mut T) -> Result<(), Error> {
        conn.ping().map_err(Error::QueryError)
    }

    fn has_broken(&self, _conn: &mut T) -> bool {
        false
    }
}

impl<M> SimpleConnection for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: R2D2Connection + Send + 'static,
{
    fn batch_execute(&self, query: &str) -> QueryResult<()> {
        (&**self).batch_execute(query)
    }
}

impl<M> Connection for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: Connection + R2D2Connection + Send + 'static,
{
    type Backend = <M::Connection as Connection>::Backend;
    type TransactionManager = PooledConnectionTransactionManager<M>;

    fn establish(_: &str) -> ConnectionResult<Self> {
        Err(ConnectionError::BadConnection(String::from(
            "Cannot directly establish a pooled connection",
        )))
    }

    fn execute(&self, query: &str) -> QueryResult<usize> {
        (&**self).execute(query)
    }

    fn query_by_index<T, U>(&self, source: T) -> QueryResult<Vec<U>>
    where
        T: AsQuery,
        T::Query: QueryFragment<Self::Backend> + QueryId,
        Self::Backend: HasSqlType<T::SqlType>,
        U: Queryable<T::SqlType, Self::Backend>,
    {
        (&**self).query_by_index(source)
    }

    fn query_by_name<T, U>(&self, source: &T) -> QueryResult<Vec<U>>
    where
        T: QueryFragment<Self::Backend> + QueryId,
        U: QueryableByName<Self::Backend>,
    {
        (&**self).query_by_name(source)
    }

    fn execute_returning_count<T>(&self, source: &T) -> QueryResult<usize>
    where
        T: QueryFragment<Self::Backend> + QueryId,
    {
        (&**self).execute_returning_count(source)
    }

    fn transaction_manager(&self) -> &Self::TransactionManager {
        // This is actually fine because we have an #[repr(transparent)]
        // on LoggingTransactionManager, which means the layout is the same
        // as the inner type
        // See the ref-cast crate for a longer version: https://github.com/dtolnay/ref-cast
        unsafe {
            &*((&**self).transaction_manager() as *const _ as *const Self::TransactionManager)
        }
    }
}

#[doc(hidden)]
#[repr(transparent)]
#[allow(missing_debug_implementations)]
pub struct PooledConnectionTransactionManager<M>
where
    M: ManageConnection,
    M::Connection: Connection,
{
    inner: <M::Connection as Connection>::TransactionManager,
}

impl<M> TransactionManager<PooledConnection<M>> for PooledConnectionTransactionManager<M>
where
    M: ManageConnection,
    PooledConnection<M>: Connection,
    M::Connection: Connection,
{
    fn begin_transaction(&self, conn: &PooledConnection<M>) -> QueryResult<()> {
        self.inner.begin_transaction(&**conn)
    }

    fn rollback_transaction(&self, conn: &PooledConnection<M>) -> QueryResult<()> {
        self.inner.rollback_transaction(&**conn)
    }

    fn commit_transaction(&self, conn: &PooledConnection<M>) -> QueryResult<()> {
        self.inner.commit_transaction(&**conn)
    }

    fn get_transaction_depth(&self) -> u32 {
        self.inner.get_transaction_depth()
    }
}

impl<M> crate::migration::MigrationConnection for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: crate::migration::MigrationConnection,
    Self: Connection,
{
    fn setup(&self) -> QueryResult<usize> {
        (&**self).setup()
    }
}

impl<Changes, Output, M> crate::query_dsl::UpdateAndFetchResults<Changes, Output>
    for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: crate::query_dsl::UpdateAndFetchResults<Changes, Output>,
    Self: Connection,
{
    fn update_and_fetch(&self, changeset: Changes) -> QueryResult<Output> {
        (&**self).update_and_fetch(changeset)
    }
}

#[cfg(test)]
mod tests {
    use std::sync::mpsc;
    use std::sync::Arc;
    use std::thread;

    use crate::r2d2::*;
    use crate::test_helpers::*;

    #[test]
    fn establish_basic_connection() {
        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Arc::new(Pool::builder().max_size(2).build(manager).unwrap());

        let (s1, r1) = mpsc::channel();
        let (s2, r2) = mpsc::channel();

        let pool1 = Arc::clone(&pool);
        let t1 = thread::spawn(move || {
            let conn = pool1.get().unwrap();
            s1.send(()).unwrap();
            r2.recv().unwrap();
            drop(conn);
        });

        let pool2 = Arc::clone(&pool);
        let t2 = thread::spawn(move || {
            let conn = pool2.get().unwrap();
            s2.send(()).unwrap();
            r1.recv().unwrap();
            drop(conn);
        });

        t1.join().unwrap();
        t2.join().unwrap();

        pool.get().unwrap();
    }

    #[test]
    fn is_valid() {
        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Pool::builder()
            .max_size(1)
            .test_on_check_out(true)
            .build(manager)
            .unwrap();

        pool.get().unwrap();
    }

    #[test]
    fn pooled_connection_impls_connection() {
        use crate::select;
        use crate::sql_types::Text;

        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Pool::builder()
            .max_size(1)
            .test_on_check_out(true)
            .build(manager)
            .unwrap();
        let conn = pool.get().unwrap();

        let query = select("foo".into_sql::<Text>());
        assert_eq!("foo", query.get_result::<String>(&conn).unwrap());
    }
}
<|endoftext|>


<commit_before>pub use super::zfile::ArgType;

/// clears spcified window
pub fn op_erase_window(value: i8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::LargeConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x0d, args);

    // signed to unsigned value
    write_u16(value as u16, &mut bytes);
    bytes
}

/// calls a routine (the address is stored in a variable)
pub fn op_call_1n_var(variable: u8) -> Vec<u8> {
    let mut bytes = op_1(0x0f, ArgType::Variable);
    //self.add_jump(jump_to_label.to_string(), JumpType::Routine);
    bytes.push(variable);
    bytes
}

/// stores a value to an array
/// stores the value of variable to the address in: array_address + 2*index
pub fn op_storew(array_address: u16, index: u8, variable: u8, object_addr: u16) -> Vec<u8> {
    assert!(array_address > 0, "not allowed array-address, becouse in _some_ interpreters (for example zoom) it crahs. -.-");
    let args: Vec<ArgType> = vec![ArgType::LargeConst, ArgType::Variable, ArgType::Variable, ArgType::Nothing];
    let mut bytes = op_var(0x01, args);

    // array address
    write_u16(object_addr + array_address, &mut bytes);

    // array index
    bytes.push(index);

    // value
    bytes.push(variable);
    bytes
}

/// loads a word from an array in a variable
/// loadw is an 2op, BUT with 3 ops -.-
pub fn op_loadw(array_address: u16, index: u8, variable: u8, object_addr: u16) -> Vec<u8> {
    let mut bytes = op_2(0x0f, vec![ArgType::LargeConst, ArgType::Variable]);

    // array address
    write_u16(object_addr + array_address, &mut bytes);

    // array index
    bytes.push(index);

    // variable
    bytes.push(variable);
    bytes
}

/// reads keys from the keyboard and saves the asci-value in local_var_id
/// read_char is VAROP
pub fn op_read_char(local_var_id: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::SmallConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x16, args);

    // write argument value
    bytes.push(0x00);

    // write varible id
    bytes.push(local_var_id);
    bytes
}

/// set the style of the text
pub fn op_set_text_style(bold: bool, reverse: bool, monospace: bool, italic: bool) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::SmallConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x11, args);

    let mut style_byte : u8;
    style_byte = 0x00;
    if bold {
        style_byte |=0x02
    }
     if reverse {
        style_byte |=0x01
    }
     if monospace {
        style_byte |=0x08
    }
     if italic {
        style_byte |=0x04
    }
    bytes.push(style_byte);
    bytes
}

/// Prints the value of a variable (only ints a possibe)
pub fn op_print_num_var(variable: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Variable, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x06, args);
    bytes.push(variable);
    bytes
}

/// pulls an value off the stack to an variable
/// SmallConst becouse pull takes an reference to an variable
pub fn op_pull(variable: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::SmallConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x09, args);
    bytes.push(variable);
    bytes
}

/// calculates a random numer from 1 to range
pub fn op_random(range: u8, variable: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::SmallConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x07, args);
    bytes.push(range);
    bytes.push(variable);
    bytes
}

/// pushs an u16 value (for example an address) on the stack
pub fn op_push_u16(value: u16) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::LargeConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x08, args);
    write_u16(value, &mut bytes);
    bytes
}

/// sets the colors of the foreground (font) and background (but with variables
pub fn op_set_color_var(foreground: u8, background: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Variable, ArgType::Variable];
    let mut bytes = op_2(0x1b, args);
    bytes.push(foreground);
    bytes.push(background);
    bytes
}

/// sets the colors of the foreground (font) and background
pub fn op_set_color(foreground: u8, background: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::SmallConst, ArgType::SmallConst];
    let mut bytes = op_2(0x1b, args);
    bytes.push(foreground);
    bytes.push(background);
    bytes
}

/// prints string at given packet adress TODO: needs testing
pub fn op_print_paddr(address: u8) -> Vec<u8> {
   let mut bytes = op_1(0x0D, ArgType::Variable);
   bytes.push(address);
   bytes
}

/// prints string at given adress TODO: needs testing
pub fn op_print_addr(address: u8) -> Vec<u8> {
   let mut bytes = op_1(0x07, ArgType::Variable);
   bytes.push(address);
   bytes
}

/// returns a SmallConst
pub fn op_ret(value: u8) -> Vec<u8> {
    let mut bytes = op_1(0x0b, ArgType::SmallConst);
    bytes.push(value);
    bytes
}

// saves an u16 to the variable
pub fn op_store_u16(variable: u8, value: u16) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Reference, ArgType::LargeConst];
    let mut bytes = op_2(0x0d, args);
    bytes.push(variable);
    write_u16(value, &mut bytes);
    bytes
}

// saves an u8 to the variable
pub fn op_store_u8(variable: u8, value: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Reference, ArgType::SmallConst];
    let mut bytes = op_2(0x0d, args);
    bytes.push(variable);
    bytes.push(value);
    bytes
}

/// subtraktion
/// variable2 = variable1 - sub_const
pub fn op_sub(variable1: u8, sub_const: u16, variable2: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Variable, ArgType::LargeConst];
    let mut bytes = op_2(0x15, args);
    bytes.push(variable1);
	write_u16(sub_const, &mut bytes);
    bytes.push(variable2);
    bytes
}

/// addition
/// variable2 = variable1 + sub_const
pub fn op_add(variable1: u8, add_const: u16, variable2: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Variable, ArgType::LargeConst];
    let mut bytes = op_2(0x14, args);
    bytes.push(variable1);
	write_u16(add_const, &mut bytes);
    bytes.push(variable2);
    bytes
}

/// decrements the value of the variable
pub fn op_dec(variable: u8) -> Vec<u8> {
    let mut bytes = op_1(0x06, ArgType::Reference);
    bytes.push(variable);
    bytes
}

/// increments the value of the variable
pub fn op_inc( variable: u8) -> Vec<u8> {
    let mut bytes = op_1(0x05, ArgType::Reference);
    bytes.push(variable);
    bytes
}

pub fn op_newline() -> Vec<u8> {
    op_0(0x0b)
}

pub fn quit() -> Vec<u8> {
    op_0(0x0a)
}

/// op-codes with 0 operators
fn op_0(value: u8) -> Vec<u8> {
    let byte = value | 0xb0;
    vec![byte]
}

/// op-codes with variable operators (4 are possible)
fn op_var(value: u8, arg_types: Vec<ArgType>) -> Vec<u8> {
	let mut ret = Vec::new();
	ret.push(value | 0xe0);
    ret.push(encode_variable_arguments(arg_types));
    ret
}

/// op-codes with 1 operator
fn op_1( value: u8, arg_type: ArgType) -> Vec<u8> {
    let mut byte: u8 = 0x80 | value;

     match arg_type {
        ArgType::Reference  => byte |= 0x01 << 4,
        ArgType::Variable   => byte |= 0x02 << 4,
        ArgType::SmallConst => byte |= 0x00 << 4,
        _                   => panic!("no possible 1OP")
    }

    vec![byte]
}

fn op_2( value: u8, arg_types: Vec<ArgType>) -> Vec<u8> {
    let mut byte: u8 = 0x00;
    let mut is_variable: bool = false;
    let mut ret = Vec::new();
    for (i, arg_type) in arg_types.iter().enumerate() {
        let shift: u8 = 6 - i as u8;
        match arg_type {
            &ArgType::SmallConst => byte |= 0x00 << shift,
            &ArgType::Variable   => byte |= 0x01 << shift,
            &ArgType::Reference  => byte |= 0x00 << shift,
            &ArgType::LargeConst => is_variable = true,
            _                    => panic!("no possible 2OP")
        }
    }

    if is_variable {
        let mut byte: u8 = 0xc0 | value;
        byte = byte | value;
        ret.push(byte);

        let mut byte2 = encode_variable_arguments(arg_types);
        byte2 = byte2 | 0xf;
        ret.push(byte2)
    } else {
        byte = byte | value;
        ret.push(byte)
    }
    ret
}

fn encode_variable_arguments( arg_types: Vec<ArgType>) -> u8 {
        let mut byte: u8 = 0x00;
        for (i, arg_type) in arg_types.iter().enumerate() {
            let shift: u8 = 6 - 2 * i as u8;
            match arg_type {
                &ArgType::LargeConst => byte |= 0x00 << shift,
                &ArgType::SmallConst => byte |= 0x01 << shift,
                &ArgType::Variable   => byte |= 0x02 << shift,
                &ArgType::Nothing    => byte |= 0x03 << shift,
                &ArgType::Reference  => byte |= 0x01 << shift,
                //_                    => panic!("no possible varOP")
            }
        }

        byte

    }

///writes u16 to a vec<u8>
pub fn write_u16(value: u16, v: &mut Vec<u8>) {
        v.push((value >> 8) as u8);
        v.push((value & 0xff) as u8);
}
<commit_msg>minor changes<commit_after>pub use super::zfile::ArgType;
pub use super::zfile::JumpType;
pub use super::zfile::Zjump;

/// clears spcified window
pub fn op_erase_window(value: i8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::LargeConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x0d, args);

    // signed to unsigned value
    write_u16(value as u16, &mut bytes);
    bytes
}

/// calls a routine (the address is stored in a variable)
pub fn op_call_1n_var(variable: u8) -> Vec<u8> {
    let mut bytes = op_1(0x0f, ArgType::Variable);
    //self.add_jump(jump_to_label.to_string(), JumpType::Routine);
    bytes.push(variable);
    bytes
}

/// stores a value to an array
/// stores the value of variable to the address in: array_address + 2*index
pub fn op_storew(array_address: u16, index: u8, variable: u8, object_addr: u16) -> Vec<u8> {
    assert!(array_address > 0, "not allowed array-address, becouse in _some_ interpreters (for example zoom) it crahs. -.-");
    let args: Vec<ArgType> = vec![ArgType::LargeConst, ArgType::Variable, ArgType::Variable, ArgType::Nothing];
    let mut bytes = op_var(0x01, args);

    // array address
    write_u16(object_addr + array_address, &mut bytes);

    // array index
    bytes.push(index);

    // value
    bytes.push(variable);
    bytes
}

/// loads a word from an array in a variable
/// loadw is an 2op, BUT with 3 ops -.-
pub fn op_loadw(array_address: u16, index: u8, variable: u8, object_addr: u16) -> Vec<u8> {
    let mut bytes = op_2(0x0f, vec![ArgType::LargeConst, ArgType::Variable]);

    // array address
    write_u16(object_addr + array_address, &mut bytes);

    // array index
    bytes.push(index);

    // variable
    bytes.push(variable);
    bytes
}

/// reads keys from the keyboard and saves the asci-value in local_var_id
/// read_char is VAROP
pub fn op_read_char(local_var_id: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::SmallConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x16, args);

    // write argument value
    bytes.push(0x00);

    // write varible id
    bytes.push(local_var_id);
    bytes
}

/// set the style of the text
pub fn op_set_text_style(bold: bool, reverse: bool, monospace: bool, italic: bool) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::SmallConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x11, args);

    let mut style_byte : u8;
    style_byte = 0x00;
    if bold {
        style_byte |=0x02
    }
     if reverse {
        style_byte |=0x01
    }
     if monospace {
        style_byte |=0x08
    }
     if italic {
        style_byte |=0x04
    }
    bytes.push(style_byte);
    bytes
}

/// Prints the value of a variable (only ints a possibe)
pub fn op_print_num_var(variable: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Variable, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x06, args);
    bytes.push(variable);
    bytes
}

/// pulls an value off the stack to an variable
/// SmallConst becouse pull takes an reference to an variable
pub fn op_pull(variable: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::SmallConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x09, args);
    bytes.push(variable);
    bytes
}

/// calculates a random numer from 1 to range
pub fn op_random(range: u8, variable: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::SmallConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x07, args);
    bytes.push(range);
    bytes.push(variable);
    bytes
}

/// pushs an u16 value (for example an address) on the stack
pub fn op_push_u16(value: u16) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::LargeConst, ArgType::Nothing, ArgType::Nothing, ArgType::Nothing];
    let mut bytes = op_var(0x08, args);
    write_u16(value, &mut bytes);
    bytes
}

/// sets the colors of the foreground (font) and background (but with variables
pub fn op_set_color_var(foreground: u8, background: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Variable, ArgType::Variable];
    let mut bytes = op_2(0x1b, args);
    bytes.push(foreground);
    bytes.push(background);
    bytes
}

/// sets the colors of the foreground (font) and background
pub fn op_set_color(foreground: u8, background: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::SmallConst, ArgType::SmallConst];
    let mut bytes = op_2(0x1b, args);
    bytes.push(foreground);
    bytes.push(background);
    bytes
}

/// prints string at given packet adress TODO: needs testing
pub fn op_print_paddr(address: u8) -> Vec<u8> {
   let mut bytes = op_1(0x0D, ArgType::Variable);
   bytes.push(address);
   bytes
}

/// prints string at given adress TODO: needs testing
pub fn op_print_addr(address: u8) -> Vec<u8> {
   let mut bytes = op_1(0x07, ArgType::Variable);
   bytes.push(address);
   bytes
}

/// returns a SmallConst
pub fn op_ret(value: u8) -> Vec<u8> {
    let mut bytes = op_1(0x0b, ArgType::SmallConst);
    bytes.push(value);
    bytes
}

// saves an u16 to the variable
pub fn op_store_u16(variable: u8, value: u16) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Reference, ArgType::LargeConst];
    let mut bytes = op_2(0x0d, args);
    bytes.push(variable);
    write_u16(value, &mut bytes);
    bytes
}

// saves an u8 to the variable
pub fn op_store_u8(variable: u8, value: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Reference, ArgType::SmallConst];
    let mut bytes = op_2(0x0d, args);
    bytes.push(variable);
    bytes.push(value);
    bytes
}

/// subtraktion
/// variable2 = variable1 - sub_const
pub fn op_sub(variable1: u8, sub_const: u16, variable2: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Variable, ArgType::LargeConst];
    let mut bytes = op_2(0x15, args);
    bytes.push(variable1);
	write_u16(sub_const, &mut bytes);
    bytes.push(variable2);
    bytes
}

/// addition
/// variable2 = variable1 + sub_const
pub fn op_add(variable1: u8, add_const: u16, variable2: u8) -> Vec<u8> {
    let args: Vec<ArgType> = vec![ArgType::Variable, ArgType::LargeConst];
    let mut bytes = op_2(0x14, args);
    bytes.push(variable1);
	write_u16(add_const, &mut bytes);
    bytes.push(variable2);
    bytes
}

/// decrements the value of the variable
pub fn op_dec(variable: u8) -> Vec<u8> {
    let mut bytes = op_1(0x06, ArgType::Reference);
    bytes.push(variable);
    bytes
}

/// increments the value of the variable
pub fn op_inc( variable: u8) -> Vec<u8> {
    let mut bytes = op_1(0x05, ArgType::Reference);
    bytes.push(variable);
    bytes
}

pub fn op_newline() -> Vec<u8> {
    op_0(0x0b)
}

pub fn quit() -> Vec<u8> {
    op_0(0x0a)
}

/// op-codes with 0 operators
fn op_0(value: u8) -> Vec<u8> {
    let byte = value | 0xb0;
    vec![byte]
}

/// op-codes with variable operators (4 are possible)
fn op_var(value: u8, arg_types: Vec<ArgType>) -> Vec<u8> {
	let mut ret = Vec::new();
	ret.push(value | 0xe0);
    ret.push(encode_variable_arguments(arg_types));
    ret
}

/// op-codes with 1 operator
fn op_1( value: u8, arg_type: ArgType) -> Vec<u8> {
    let mut byte: u8 = 0x80 | value;

     match arg_type {
        ArgType::Reference  => byte |= 0x01 << 4,
        ArgType::Variable   => byte |= 0x02 << 4,
        ArgType::SmallConst => byte |= 0x00 << 4,
        _                   => panic!("no possible 1OP")
    }

    vec![byte]
}

fn op_2( value: u8, arg_types: Vec<ArgType>) -> Vec<u8> {
    let mut byte: u8 = 0x00;
    let mut is_variable: bool = false;
    let mut ret = Vec::new();
    for (i, arg_type) in arg_types.iter().enumerate() {
        let shift: u8 = 6 - i as u8;
        match arg_type {
            &ArgType::SmallConst => byte |= 0x00 << shift,
            &ArgType::Variable   => byte |= 0x01 << shift,
            &ArgType::Reference  => byte |= 0x00 << shift,
            &ArgType::LargeConst => is_variable = true,
            _                    => panic!("no possible 2OP")
        }
    }

    if is_variable {
        let mut byte: u8 = 0xc0 | value;
        byte = byte | value;
        ret.push(byte);

        let mut byte2 = encode_variable_arguments(arg_types);
        byte2 = byte2 | 0xf;
        ret.push(byte2)
    } else {
        byte = byte | value;
        ret.push(byte)
    }
    ret
}

fn encode_variable_arguments( arg_types: Vec<ArgType>) -> u8 {
    let mut byte: u8 = 0x00;
    for (i, arg_type) in arg_types.iter().enumerate() {
        let shift: u8 = 6 - 2 * i as u8;
        match arg_type {
            &ArgType::LargeConst => byte |= 0x00 << shift,
            &ArgType::SmallConst => byte |= 0x01 << shift,
            &ArgType::Variable   => byte |= 0x02 << shift,
            &ArgType::Nothing    => byte |= 0x03 << shift,
            &ArgType::Reference  => byte |= 0x01 << shift,
            //_                    => panic!("no possible varOP")
        }
    }

    byte
 }

///writes u16 to a vec<u8>
pub fn write_u16(value: u16, v: &mut Vec<u8>) {
        v.push((value >> 8) as u8);
        v.push((value & 0xff) as u8);
}
<|endoftext|>


<commit_before>#![feature(test)]
extern crate peel;
use peel::example::prelude::*;

extern crate test;
use test::Bencher;

#[bench]
fn tree_generation(bencher: &mut Bencher) {
    bencher.iter(|| {
        peel_example();
    });
}

#[bench]
fn tree_parsing(bencher: &mut Bencher) {
    let peel = peel_example();
    let input = b"1234";
    bencher.iter(|| {
        assert!(peel.traverse(input, vec![]).is_ok());
    });
    bencher.bytes = input.len() as u64;
}
<commit_msg>Fixed benchmark builds<commit_after>#![feature(test)]
extern crate peel;
use peel::example::prelude::*;

extern crate test;
use test::Bencher;

#[bench]
fn tree_generation(bencher: &mut Bencher) {
    bencher.iter(|| {
        peel_example();
    });
}

#[bench]
fn tree_parsing(bencher: &mut Bencher) {
    let mut peel = peel_example();
    let input = b"1234";
    bencher.iter(|| {
        assert!(peel.traverse(input, vec![]).is_ok());
    });
    bencher.bytes = input.len() as u64;
}
<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;
use sudoku::Sudoku;
use sudoku::strategy::{Strategy, StrategySolver};

fn read_sudokus(sudokus_str: &str) -> Vec<Sudoku> {
    sudokus_str
        .lines()
        .map(|line| Sudoku::from_str_line(line).unwrap_or_else(|err| panic!("{:?}", err)))
        .collect()
}

/// Set of all available strategies, for test purposes
#[allow(unused)]
const ALL_STRATEGIES: &'static [Strategy] = &[
                                // difficulty as assigned by
                                // SudokuExplainer
    Strategy::NakedSingles,     // 23
    Strategy::HiddenSingles,    // 15
    Strategy::LockedCandidates, // 28
    Strategy::NakedPairs,       // 30
    Strategy::XWing,            // 32
    Strategy::HiddenPairs,      // 34
    Strategy::NakedTriples,     // 36
    Strategy::Swordfish,        // 38
    Strategy::HiddenTriples,    // 40
    Strategy::XyWing,           // 42
    Strategy::XyzWing,          // 44
    Strategy::NakedQuads,       // 50
    Strategy::Jellyfish,        // 52
    Strategy::HiddenQuads,      // 54
    //Strategy::SinglesChain,
];

macro_rules! make_benches {
    ( $sudokus_folder:expr; $($name:ident, $f:expr, $file_name:expr);* ) => {
        $(
            #[bench]
            fn $name (b: &mut test::Bencher) {
                let sudokus = read_sudokus(
                    include_str!( concat!($sudokus_folder, $file_name) )
                );
                let mut sudokus = sudokus.iter().cloned().cycle();
                b.iter(|| {
                    for sudoku in sudokus.by_ref().take(100) {
                        $f(sudoku);
                    }
                })
            }
        )*
    };
}

make_benches!(
    "../sudokus/Lines/";
    sudoku_solve_one_1_easy,     Sudoku::solve_one, "easy_sudokus.txt";
    sudoku_solve_one_2_medium,   Sudoku::solve_one, "medium_sudokus.txt";
    sudoku_solve_one_3_hard,     Sudoku::solve_one, "hard_sudokus.txt";

    sudoku_is_solvable_1_easy,   Sudoku::is_uniquely_solvable, "easy_sudokus.txt";
    sudoku_is_solvable_2_medium, Sudoku::is_uniquely_solvable, "medium_sudokus.txt";
    sudoku_is_solvable_3_hard,   Sudoku::is_uniquely_solvable, "hard_sudokus.txt";

    // the sudokus are proper so this will exhaust the entire search tree
    // trying to find a 2nd solution
    sudoku_solve_all_1_easy,   |s: Sudoku| s.solve_at_most(2), "easy_sudokus.txt";
    sudoku_solve_all_2_medium, |s: Sudoku| s.solve_at_most(2), "medium_sudokus.txt";
    sudoku_solve_all_3_hard,   |s: Sudoku| s.solve_at_most(2), "hard_sudokus.txt"
);

#[bench]
fn generate_filled_sudoku(b: &mut test::Bencher) {
    b.iter(Sudoku::generate_filled)
}

#[bench]
fn generate_unique_sudoku(b: &mut test::Bencher) {
    b.iter(Sudoku::generate_unique)
}

// this test is probabilistic in nature
// if an error occurs, note down the sudoku that it generated
#[bench]
fn shuffle(b: &mut test::Bencher) {
    let mut sudoku = Sudoku::generate_filled();
    b.iter(|| {
        sudoku.shuffle();
        test::black_box(sudoku);
    });
}

#[bench]
fn parse_line(b: &mut test::Bencher) {
    let sudokus = (0..1000)
        .map(|_| Sudoku::generate_unique().to_str_line())
        .collect::<Vec<_>>();
    let mut sudokus = sudokus.iter().cycle();

    b.iter(|| Sudoku::from_str_line(sudokus.next().unwrap()))
}

#[bench]
fn parse_lines(b: &mut test::Bencher) {
    let sudokus = (0..1000)
        .map(|_| Sudoku::generate_unique().to_str_line())
        .collect::<Vec<_>>();
    let sudokus = sudokus.iter().map(|line| &**line).collect::<Vec<_>>();
    let sudokus = sudokus.join("\n");

    b.iter(|| {
        for line in sudokus.lines() {
            let _ = Sudoku::from_str_line(line);
        }
    })
}

#[bench]
fn is_solved_on_unsolved(b: &mut test::Bencher) {
    let sudokus = read_sudokus(include_str!("../sudokus/Lines/hard_sudokus.txt"));
    b.iter(|| {
        for sudoku in sudokus.iter().cloned() {
            sudoku.is_solved();
        }
    })
}

#[bench]
fn is_solved_on_solved(b: &mut test::Bencher) {
    let solved_sudokus = read_sudokus(include_str!("../sudokus/Lines/solved_hard_sudokus.txt"));
    b.iter(|| {
        for sudoku in solved_sudokus.iter().cloned() {
            sudoku.is_solved();
        }
    })
}

#[bench]
fn strategy_solver_1_easy_sudokus(b: &mut test::Bencher) {
    let sudokus = read_sudokus( include_str!("../sudokus/Lines/easy_sudokus.txt") );
    let sudokus_100 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();
    let strategies = ALL_STRATEGIES;
    b.iter(|| {
        for sudoku in sudokus_100.iter().cloned() {
            StrategySolver::from_sudoku(sudoku).solve(&strategies).unwrap(); //.unwrap();
        }
    })
}

#[bench]
fn strategy_solver_2_medium_sudokus(b: &mut test::Bencher) {
    let sudokus = read_sudokus( include_str!("../sudokus/Lines/medium_sudokus.txt") );
    let sudokus_100 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();
    let strategies = ALL_STRATEGIES;
    b.iter(|| {
        for sudoku in sudokus_100.iter().cloned() {
            // solution not guaranteed yet, discard error.
            let _ = StrategySolver::from_sudoku(sudoku).solve(&strategies); //.unwrap();
        }
    })
}

#[bench]
fn canonicalize(b: &mut test::Bencher) {
    let sudoku = Sudoku::generate_filled();

	b.iter(|| {
		sudoku.canonicalized();
	})
}
<commit_msg>more reliable canonicalization bench<commit_after>#![feature(test)]
extern crate test;
use sudoku::Sudoku;
use sudoku::strategy::{Strategy, StrategySolver};

fn read_sudokus(sudokus_str: &str) -> Vec<Sudoku> {
    sudokus_str
        .lines()
        .map(|line| Sudoku::from_str_line(line).unwrap_or_else(|err| panic!("{:?}", err)))
        .collect()
}

/// Set of all available strategies, for test purposes
#[allow(unused)]
const ALL_STRATEGIES: &'static [Strategy] = &[
                                // difficulty as assigned by
                                // SudokuExplainer
    Strategy::NakedSingles,     // 23
    Strategy::HiddenSingles,    // 15
    Strategy::LockedCandidates, // 28
    Strategy::NakedPairs,       // 30
    Strategy::XWing,            // 32
    Strategy::HiddenPairs,      // 34
    Strategy::NakedTriples,     // 36
    Strategy::Swordfish,        // 38
    Strategy::HiddenTriples,    // 40
    Strategy::XyWing,           // 42
    Strategy::XyzWing,          // 44
    Strategy::NakedQuads,       // 50
    Strategy::Jellyfish,        // 52
    Strategy::HiddenQuads,      // 54
    //Strategy::SinglesChain,
];

macro_rules! make_benches {
    ( $sudokus_folder:expr; $($name:ident, $f:expr, $file_name:expr);* ) => {
        $(
            #[bench]
            fn $name (b: &mut test::Bencher) {
                let sudokus = read_sudokus(
                    include_str!( concat!($sudokus_folder, $file_name) )
                );
                let mut sudokus = sudokus.iter().cloned().cycle();
                b.iter(|| {
                    for sudoku in sudokus.by_ref().take(100) {
                        $f(sudoku);
                    }
                })
            }
        )*
    };
}

make_benches!(
    "../sudokus/Lines/";
    sudoku_solve_one_1_easy,     Sudoku::solve_one, "easy_sudokus.txt";
    sudoku_solve_one_2_medium,   Sudoku::solve_one, "medium_sudokus.txt";
    sudoku_solve_one_3_hard,     Sudoku::solve_one, "hard_sudokus.txt";

    sudoku_is_solvable_1_easy,   Sudoku::is_uniquely_solvable, "easy_sudokus.txt";
    sudoku_is_solvable_2_medium, Sudoku::is_uniquely_solvable, "medium_sudokus.txt";
    sudoku_is_solvable_3_hard,   Sudoku::is_uniquely_solvable, "hard_sudokus.txt";

    // the sudokus are proper so this will exhaust the entire search tree
    // trying to find a 2nd solution
    sudoku_solve_all_1_easy,   |s: Sudoku| s.solve_at_most(2), "easy_sudokus.txt";
    sudoku_solve_all_2_medium, |s: Sudoku| s.solve_at_most(2), "medium_sudokus.txt";
    sudoku_solve_all_3_hard,   |s: Sudoku| s.solve_at_most(2), "hard_sudokus.txt"
);

#[bench]
fn generate_filled_sudoku(b: &mut test::Bencher) {
    b.iter(Sudoku::generate_filled)
}

#[bench]
fn generate_unique_sudoku(b: &mut test::Bencher) {
    b.iter(Sudoku::generate_unique)
}

// this test is probabilistic in nature
// if an error occurs, note down the sudoku that it generated
#[bench]
fn shuffle(b: &mut test::Bencher) {
    let mut sudoku = Sudoku::generate_filled();
    b.iter(|| {
        sudoku.shuffle();
        test::black_box(sudoku);
    });
}

#[bench]
fn parse_line(b: &mut test::Bencher) {
    let sudokus = (0..1000)
        .map(|_| Sudoku::generate_unique().to_str_line())
        .collect::<Vec<_>>();
    let mut sudokus = sudokus.iter().cycle();

    b.iter(|| Sudoku::from_str_line(sudokus.next().unwrap()))
}

#[bench]
fn parse_lines(b: &mut test::Bencher) {
    let sudokus = (0..1000)
        .map(|_| Sudoku::generate_unique().to_str_line())
        .collect::<Vec<_>>();
    let sudokus = sudokus.iter().map(|line| &**line).collect::<Vec<_>>();
    let sudokus = sudokus.join("\n");

    b.iter(|| {
        for line in sudokus.lines() {
            let _ = Sudoku::from_str_line(line);
        }
    })
}

#[bench]
fn is_solved_on_unsolved(b: &mut test::Bencher) {
    let sudokus = read_sudokus(include_str!("../sudokus/Lines/hard_sudokus.txt"));
    b.iter(|| {
        for sudoku in sudokus.iter().cloned() {
            sudoku.is_solved();
        }
    })
}

#[bench]
fn is_solved_on_solved(b: &mut test::Bencher) {
    let solved_sudokus = read_sudokus(include_str!("../sudokus/Lines/solved_hard_sudokus.txt"));
    b.iter(|| {
        for sudoku in solved_sudokus.iter().cloned() {
            sudoku.is_solved();
        }
    })
}

#[bench]
fn strategy_solver_1_easy_sudokus(b: &mut test::Bencher) {
    let sudokus = read_sudokus( include_str!("../sudokus/Lines/easy_sudokus.txt") );
    let sudokus_100 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();
    let strategies = ALL_STRATEGIES;
    b.iter(|| {
        for sudoku in sudokus_100.iter().cloned() {
            StrategySolver::from_sudoku(sudoku).solve(&strategies).unwrap(); //.unwrap();
        }
    })
}

#[bench]
fn strategy_solver_2_medium_sudokus(b: &mut test::Bencher) {
    let sudokus = read_sudokus( include_str!("../sudokus/Lines/medium_sudokus.txt") );
    let sudokus_100 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();
    let strategies = ALL_STRATEGIES;
    b.iter(|| {
        for sudoku in sudokus_100.iter().cloned() {
            // solution not guaranteed yet, discard error.
            let _ = StrategySolver::from_sudoku(sudoku).solve(&strategies); //.unwrap();
        }
    })
}

#[bench]
fn canonicalize(b: &mut test::Bencher) {
    let sudokus = (0..1000).map(|_| Sudoku::generate_filled()).collect::<Vec<_>>();
    let mut sudokus = sudokus.iter().cycle();

	b.iter(|| {
		sudokus.next().unwrap().canonicalized();
	})
}
<|endoftext|>


<commit_before>#![crate_name="incrust_plugin"]
#![crate_type="dylib"]
#![feature(quote, plugin_registrar, rustc_private)]

#[macro_use]
extern crate log;

extern crate syntax;
extern crate rustc;
extern crate rustc_plugin;

use rustc_plugin::Registry;

use std::fmt::Write;

use std::rc::Rc;
use std::marker::PhantomData;

use syntax::abi::Abi;
use syntax::ast::{self, DUMMY_NODE_ID};

use syntax::codemap::{Span, Spanned, dummy_spanned, respan, spanned, DUMMY_SP};
use syntax::ext::base::{DummyResult, ExtCtxt, MacEager, MacResult, SyntaxExtension, NormalTT, IdentTT, TTMacroExpander, Resolver};
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::ToTokens;
use syntax::ext::hygiene::Mark;
use syntax::print::pprust::{token_to_string, tts_to_string};
use syntax::tokenstream::TokenTree;
use syntax::util::small_vector::SmallVector;
use syntax::parse::{token, PResult};
use syntax::parse::common::SeqSep;
use syntax::parse::parser::Parser;
use syntax::ptr::P;

extern crate itertools;
use itertools::Itertools;

extern crate incrust_common;

use incrust_common::codegen;
use incrust_common::jsgen::{IntoJsFunction, IntoJsOutputCall};
use incrust_common::node::{Element, TemplateExpr, TemplateNode, parse_node, parse_contents};
use incrust_common::output_actions::{OutputAction, IntoOutputActions};
use incrust_common::view::parse_view;
use incrust_common::compiled_view::CompiledView;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("define_template"),
            syntax::ext::base::IdentTT(Box::new(expand_define_template), None, false));
}

fn define_ext<'cx>(ecx: &'cx mut ExtCtxt, name: &str, ext: Rc<SyntaxExtension>) {
    let ident = ecx.ident_of(name);
    // TODO: This is changed to add_ext in b4906a (https://github.com/rust-lang/rust/commit/b4906a93)
    // update when updating nightly
    (*ecx.resolver).add_macro(Mark::root(), ident, ext);
}

macro_rules! define_named_template {
    ($ecx: ident, $name: ident, $ty:ident, $lang: expr, $views:expr) => ({
        let name = $name.name.to_string();
        let ext_name = &format!("emit_{}_view_{}", $lang, name);
        let ext = LangSyntaxExt::<$ty>::create_template(&name, $views.clone());
        define_ext($ecx, ext_name, Rc::new(NormalTT(Box::new(ext), None, true)));
    })
}

#[derive(Debug, Clone)]
struct NamedTemplateDecl {
    name: String,
    compiled_views: Vec<CompiledView>
}

enum Rust {}
enum Js {}

trait WriteBlockFactory {
    fn create_write_block<'cx>(&self, ecx: &'cx mut ExtCtxt, w_ident: ast::Ident) -> Box<MacResult + 'cx>;
}

trait Lang {
    fn ext() -> &'static str;
}

impl <L: Lang> LangSyntaxExt<L> {
    fn create_template(name: &str, compiled_views: Vec<CompiledView>) -> LangSyntaxExt<L> {
        let ext_name = &format!("emit_{}_view_{}", L::ext(), name);
        let lang_ext = LangSyntaxExt {
            decl: NamedTemplateDecl { name: String::from(name), compiled_views: compiled_views },
            _l: PhantomData
        };

        lang_ext
    }
}

#[derive(Debug, Clone)]
struct LangSyntaxExt<L: Lang> {
    decl: NamedTemplateDecl,
    _l: PhantomData<L>
}

/// Define TTMacroExpander for the given language, used the WriteBlockFactory trait above.
macro_rules! lang_expander {
    ($lang: ty) => (
        impl TTMacroExpander for LangSyntaxExt<$lang> {
            fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt, span: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
               // self.decl.expand(ecx, span, tts)
                let mut parser = ecx.new_parser_from_tts(tts);
                let w_ident = parser.parse_ident().unwrap();
                self.create_write_block(ecx, w_ident)
            }
        }
    )
}
lang_expander!(Rust);
lang_expander!(Js);

macro_rules! lang {
    ($lang: ty, $ext: expr) => (
        impl Lang for $lang {
            fn ext() -> &'static str { $ext }
        }
    )
}
lang!(Rust, "rust");
lang!(Js, "js");

impl WriteBlockFactory for LangSyntaxExt<Rust> {
    fn create_write_block<'cx>(&self, ecx: &'cx mut ExtCtxt, w_ident: ast::Ident) -> Box<MacResult + 'cx> {
        codegen::create_template_write_block(ecx, w_ident, &self.decl.compiled_views)
    }
}

impl WriteBlockFactory for LangSyntaxExt<Js> {
    fn create_write_block<'cx>(&self, ecx: &'cx mut ExtCtxt, w_ident: ast::Ident) -> Box<MacResult + 'cx> {
        let funcs: Vec<String> = self.decl.compiled_views.iter()
            .map(|compiled_view| compiled_view.into_js_function(ecx))
            .intersperse("; ".into())
            .collect();

        codegen::create_write_statements_block(ecx, w_ident, funcs.as_slice())
    }
}

impl TTMacroExpander for NamedTemplateDecl {
    fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt, span: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
        let mut parser = ecx.new_parser_from_tts(tts);
        let w_ident = parser.parse_ident().unwrap();
        codegen::create_template_write_block(ecx, w_ident, &self.compiled_views)
    }
}

fn parse_template_into_compiled_view<'cx, 'a>(ecx: &'cx mut ExtCtxt, span: Span, parser: &mut Parser<'a>)
                                                                            -> PResult<'a, CompiledView> {
    let view = try!(parse_view(ecx, parser, span));
    let output_actions = view.into_output_actions(ecx);
    ecx.span_warn(span, &format!("output_actions: {:?}", output_actions));

    let name = String::from(view.name());
    Ok(CompiledView::from_output_actions(name, output_actions))
}

fn parse_template_into_compiled_view_result<'cx, 'a>(ecx: &'cx mut ExtCtxt, span: Span, parser: &mut Parser<'a>)
                                                                            -> PResult<'a, Box<MacResult + 'cx>> {
    let view = try!(parse_view(ecx, parser, span));
    let output_actions = view.into_output_actions(ecx);

    ecx.span_warn(span, &format!("output_actions: {:?}", output_actions));
        let s: Vec<TokenTree> = output_actions.iter()
            .map(|el| el.to_tokens(ecx))
            .intersperse(vec![TokenTree::Token(DUMMY_SP, token::Comma)])
            .flat_map(|el| el.to_tokens(ecx))
            .collect();

        let name = view.name();
        let s_name = quote_expr!(ecx, $name.to_owned());
        let stmt = quote_stmt!(ecx, {{
            extern crate incrust_common;
            use incrust_common::compiled_view::CompiledView;
            use incrust_common::output_actions::OutputAction;
            let actions = vec![$s];
            CompiledView::from_output_actions($s_name, actions)
        }}).unwrap();
        let block = ecx.block(span, vec![stmt]);
        Ok(MacEager::expr(ecx.expr_block(block)))
}

/// Macro implementation: create a set of macros of the form emit_$lang_view_$template!($output_var);
/// which will render the parsed template in the given language.
fn expand_define_template<'cx>(ecx: &'cx mut ExtCtxt, span: Span, ident: ast::Ident, tts: Vec<TokenTree>) -> Box<MacResult + 'cx> {
    let name = ident.name.to_string();
    let mut parser = ecx.new_parser_from_tts(&tts);

    match parse_template_into_compiled_view(ecx, span, &mut parser) {
        Ok(compiled_view) => {
            let compiled_views = vec![compiled_view];
            define_named_template!(ecx, ident, Rust, "rust", compiled_views);
            define_named_template!(ecx, ident, Js, "js", compiled_views);

            // Empty (but must consist of items)
            MacEager::items(SmallVector::zero())
        },

        Err(mut err) => {
            err.emit();
            DummyResult::expr(span)
        }
    }

}
<commit_msg>Cleanup unused code<commit_after>#![crate_name="incrust_plugin"]
#![crate_type="dylib"]
#![feature(quote, plugin_registrar, rustc_private)]

#[macro_use]
extern crate log;

extern crate syntax;
extern crate rustc;
extern crate rustc_plugin;

use rustc_plugin::Registry;

use std::rc::Rc;
use std::marker::PhantomData;

use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base::{DummyResult, ExtCtxt, MacEager, MacResult, SyntaxExtension, NormalTT, TTMacroExpander};
use syntax::ext::hygiene::Mark;
use syntax::tokenstream::TokenTree;
use syntax::util::small_vector::SmallVector;
use syntax::parse::{token, PResult};
use syntax::parse::parser::Parser;

extern crate itertools;
use itertools::Itertools;

extern crate incrust_common;

use incrust_common::codegen;
use incrust_common::jsgen::IntoJsFunction;
use incrust_common::output_actions::IntoOutputActions;
use incrust_common::view::parse_view;
use incrust_common::compiled_view::CompiledView;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("define_template"),
            syntax::ext::base::IdentTT(Box::new(expand_define_template), None, false));
}

fn define_ext<'cx>(ecx: &'cx mut ExtCtxt, name: &str, ext: Rc<SyntaxExtension>) {
    let ident = ecx.ident_of(name);
    // TODO: This is changed to add_ext in b4906a (https://github.com/rust-lang/rust/commit/b4906a93)
    // update when updating nightly
    (*ecx.resolver).add_macro(Mark::root(), ident, ext);
}

macro_rules! define_named_template {
    ($ecx: ident, $name: ident, $ty:ident, $lang: expr, $views:expr) => ({
        let name = $name.name.to_string();
        let ext_name = &format!("emit_{}_view_{}", $lang, name);
        let ext = LangSyntaxExt::<$ty>::create_template(&name, $views.clone());
        define_ext($ecx, ext_name, Rc::new(NormalTT(Box::new(ext), None, true)));
    })
}

#[derive(Debug, Clone)]
struct NamedTemplateDecl {
    name: String,
    compiled_views: Vec<CompiledView>
}

enum Rust {}
enum Js {}

trait WriteBlockFactory {
    fn create_write_block<'cx>(&self, ecx: &'cx mut ExtCtxt, w_ident: ast::Ident) -> Box<MacResult + 'cx>;
}

trait Lang {
    fn ext() -> &'static str;
}

impl <L: Lang> LangSyntaxExt<L> {
    fn create_template(name: &str, compiled_views: Vec<CompiledView>) -> LangSyntaxExt<L> {
        let lang_ext = LangSyntaxExt {
            decl: NamedTemplateDecl { name: String::from(name), compiled_views: compiled_views },
            _l: PhantomData
        };

        lang_ext
    }
}

#[derive(Debug, Clone)]
struct LangSyntaxExt<L: Lang> {
    decl: NamedTemplateDecl,
    _l: PhantomData<L>
}

/// Define TTMacroExpander for the given language, used the WriteBlockFactory trait above.
macro_rules! lang_expander {
    ($lang: ty) => (
        impl TTMacroExpander for LangSyntaxExt<$lang> {
            fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt, _: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
               // self.decl.expand(ecx, span, tts)
                let mut parser = ecx.new_parser_from_tts(tts);
                let w_ident = parser.parse_ident().unwrap();
                self.create_write_block(ecx, w_ident)
            }
        }
    )
}
lang_expander!(Rust);
lang_expander!(Js);

macro_rules! lang {
    ($lang: ty, $ext: expr) => (
        impl Lang for $lang {
            fn ext() -> &'static str { $ext }
        }
    )
}
lang!(Rust, "rust");
lang!(Js, "js");

impl WriteBlockFactory for LangSyntaxExt<Rust> {
    fn create_write_block<'cx>(&self, ecx: &'cx mut ExtCtxt, w_ident: ast::Ident) -> Box<MacResult + 'cx> {
        codegen::create_template_write_block(ecx, w_ident, &self.decl.compiled_views)
    }
}

impl WriteBlockFactory for LangSyntaxExt<Js> {
    fn create_write_block<'cx>(&self, ecx: &'cx mut ExtCtxt, w_ident: ast::Ident) -> Box<MacResult + 'cx> {
        let funcs: Vec<String> = self.decl.compiled_views.iter()
            .map(|compiled_view| compiled_view.into_js_function(ecx))
            .intersperse("; ".into())
            .collect();

        codegen::create_write_statements_block(ecx, w_ident, funcs.as_slice())
    }
}

impl TTMacroExpander for NamedTemplateDecl {
    fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt, _: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
        let mut parser = ecx.new_parser_from_tts(tts);
        let w_ident = parser.parse_ident().unwrap();
        codegen::create_template_write_block(ecx, w_ident, &self.compiled_views)
    }
}

fn parse_template_into_compiled_view<'cx, 'a>(ecx: &'cx mut ExtCtxt, span: Span, parser: &mut Parser<'a>)
                                                                            -> PResult<'a, CompiledView> {
    let view = try!(parse_view(ecx, parser, span));
    let output_actions = view.into_output_actions(ecx);
    ecx.span_warn(span, &format!("output_actions: {:?}", output_actions));

    let name = String::from(view.name());
    Ok(CompiledView::from_output_actions(name, output_actions))
}

/// Macro implementation: create a set of macros of the form emit_$lang_view_$template!($output_var);
/// which will render the parsed template in the given language.
fn expand_define_template<'cx>(ecx: &'cx mut ExtCtxt, span: Span, ident: ast::Ident, tts: Vec<TokenTree>) -> Box<MacResult + 'cx> {
    let mut parser = ecx.new_parser_from_tts(&tts);

    match parse_template_into_compiled_view(ecx, span, &mut parser) {
        Ok(compiled_view) => {
            let compiled_views = vec![compiled_view];
            define_named_template!(ecx, ident, Rust, "rust", compiled_views);
            define_named_template!(ecx, ident, Js, "js", compiled_views);

            // Empty (but must consist of items)
            MacEager::items(SmallVector::zero())
        },

        Err(mut err) => {
            err.emit();
            DummyResult::expr(span)
        }
    }

}
<|endoftext|>


<commit_before>#[crate_id="github.com/sfackler/rust-mphf#mphf:0.0"];
#[crate_type="lib"];
#[feature(managed_boxes, macro_registrar)];

extern mod syntax;

use syntax::ast::{Name, TokenTree, LitStr, MutImmutable, Expr, ExprTup, ExprVec, ExprLit};
use syntax::codemap::{Span, NameAndSpan, MacroBang, ExpnInfo};
use syntax::ext::base::{SyntaxExtension,
                        ExtCtxt,
                        MacResult,
                        MRExpr,
                        NormalTT,
                        SyntaxExpanderTT,
                        SyntaxExpanderTTExpanderWithoutContext};
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::{COMMA, EOF, FAT_ARROW};

pub struct MphfMap<T> {
    #[doc(hidden)]
    entries: &'static [(&'static str, T)],
}

impl<T> Container for MphfMap<T> {
    fn len(&self) -> uint {
        self.entries.len()
    }
}

impl<T> Map<&'static str, T> for MphfMap<T> {
    fn find<'a>(&'a self, key: & &'static str) -> Option<&'a T> {
        self.entries.bsearch(|&(val, _)| val.cmp(key)).map(|idx| {
            let (_, ref val) = self.entries[idx];
            val
        })
    }
}

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("mphf_map"),
             NormalTT(~SyntaxExpanderTT {
                expander: SyntaxExpanderTTExpanderWithoutContext(expand_mphf_map),
                span: None
             },
             None));
}

fn expand_mphf_map(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> MacResult {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_owned());
    let mut pairs = ~[];

    while parser.token != EOF {
        let key = parser.parse_expr();

        let key_str = match key.node {
            ExprLit(lit) => {
                match lit.node {
                    LitStr(s, _) => s,
                    _ => cx.span_fatal(key.span, "expected string literal"),
                }
            }
            _ => cx.span_fatal(key.span, "expected string literal"),
        };

        if !parser.eat(&FAT_ARROW) {
            cx.span_fatal(parser.span, "expected `=>`");
        }

        let value = parser.parse_expr();

        pairs.push((key_str, key, value));

        if !parser.eat(&COMMA) && parser.token != EOF {
            cx.span_fatal(parser.span, "expected `,`");
        }
    }

    pairs.sort_by(|&(ref a, _, _), &(ref b, _, _)| a.cmp(b));

    for window in pairs.windows(2) {
        let (ref a, ref a_expr, _) = window[0];
        let (ref b, ref b_expr, _) = window[1];
        if a == b {
            cx.span_err(sp, format!("key {:s} duplicated", *a));
            cx.span_err(a_expr.span, "one occurance here");
            cx.span_err(b_expr.span, "one occurance here");
        }
    }

    let entries = pairs.move_iter()
        .map(|(_, key, value)| @Expr {
            id: 0,
            node: ExprTup(~[key, value]),
            span: Span {
                lo: key.span.lo,
                hi: value.span.hi,
                expn_info: Some(@ExpnInfo {
                    call_site: sp,
                    callee: NameAndSpan {
                        name: @"mphf_map",
                        format: MacroBang,
                        span: None,
                    }
                })
            }
        })
        .collect();
    let entries = @Expr {
        id: 0,
        node: ExprVec(entries, MutImmutable),
        span: Span {
            lo: sp.lo,
            hi: sp.hi,
            expn_info: Some(@ExpnInfo {
                call_site: sp,
                callee: NameAndSpan {
                    name: @"mphf_map",
                    format: MacroBang,
                    span: None,
                }
            })
        },
    };

    MRExpr(quote_expr!(cx, MphfMap { entries: &'static $entries }))
}
<commit_msg>Actually abort on duplicates<commit_after>#[crate_id="github.com/sfackler/rust-mphf#mphf:0.0"];
#[crate_type="lib"];
#[feature(managed_boxes, macro_registrar)];

extern mod syntax;

use syntax::ast::{Name, TokenTree, LitStr, MutImmutable, Expr, ExprTup, ExprVec, ExprLit};
use syntax::codemap::{Span, NameAndSpan, MacroBang, ExpnInfo};
use syntax::ext::base::{SyntaxExtension,
                        ExtCtxt,
                        MacResult,
                        MRExpr,
                        NormalTT,
                        SyntaxExpanderTT,
                        SyntaxExpanderTTExpanderWithoutContext};
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::{COMMA, EOF, FAT_ARROW};

pub struct MphfMap<T> {
    #[doc(hidden)]
    entries: &'static [(&'static str, T)],
}

impl<T> Container for MphfMap<T> {
    fn len(&self) -> uint {
        self.entries.len()
    }
}

impl<T> Map<&'static str, T> for MphfMap<T> {
    fn find<'a>(&'a self, key: & &'static str) -> Option<&'a T> {
        self.entries.bsearch(|&(val, _)| val.cmp(key)).map(|idx| {
            let (_, ref val) = self.entries[idx];
            val
        })
    }
}

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("mphf_map"),
             NormalTT(~SyntaxExpanderTT {
                expander: SyntaxExpanderTTExpanderWithoutContext(expand_mphf_map),
                span: None
             },
             None));
}

fn expand_mphf_map(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> MacResult {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_owned());
    let mut pairs = ~[];

    while parser.token != EOF {
        let key = parser.parse_expr();

        let key_str = match key.node {
            ExprLit(lit) => {
                match lit.node {
                    LitStr(s, _) => s,
                    _ => cx.span_fatal(key.span, "expected string literal"),
                }
            }
            _ => cx.span_fatal(key.span, "expected string literal"),
        };

        if !parser.eat(&FAT_ARROW) {
            cx.span_fatal(parser.span, "expected `=>`");
        }

        let value = parser.parse_expr();

        pairs.push((key_str, key, value));

        if !parser.eat(&COMMA) && parser.token != EOF {
            cx.span_fatal(parser.span, "expected `,`");
        }
    }

    pairs.sort_by(|&(ref a, _, _), &(ref b, _, _)| a.cmp(b));

    for window in pairs.windows(2) {
        let (ref a, ref a_expr, _) = window[0];
        let (ref b, ref b_expr, _) = window[1];
        if a == b {
            cx.span_err(sp, format!("key {:s} duplicated", *a));
            cx.span_err(a_expr.span, "one occurance here");
            cx.span_err(b_expr.span, "one occurance here");
        }
    }
    cx.parse_sess().span_diagnostic.handler().abort_if_errors();

    let entries = pairs.move_iter()
        .map(|(_, key, value)| @Expr {
            id: 0,
            node: ExprTup(~[key, value]),
            span: Span {
                lo: key.span.lo,
                hi: value.span.hi,
                expn_info: Some(@ExpnInfo {
                    call_site: sp,
                    callee: NameAndSpan {
                        name: @"mphf_map",
                        format: MacroBang,
                        span: None,
                    }
                })
            }
        })
        .collect();
    let entries = @Expr {
        id: 0,
        node: ExprVec(entries, MutImmutable),
        span: Span {
            lo: sp.lo,
            hi: sp.hi,
            expn_info: Some(@ExpnInfo {
                call_site: sp,
                callee: NameAndSpan {
                    name: @"mphf_map",
                    format: MacroBang,
                    span: None,
                }
            })
        },
    };

    MRExpr(quote_expr!(cx, MphfMap { entries: &'static $entries }))
}
<|endoftext|>