<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Communication channel with a physical device.
//!
//! The `Device` is one of the most important objects of Vulkan. Creating a `Device` is required
//! before you can create buffers, textures, shaders, etc.
//!
use std::ffi::CString;
use std::fmt;
use std::error;
use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
use smallvec::SmallVec;

use instance::Features;
use instance::Instance;
use instance::PhysicalDevice;
use instance::QueueFamily;
use memory::pool::StdMemoryPool;
use sync::Semaphore;

use Error;
use OomError;
use SynchronizedVulkanObject;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

pub use instance::DeviceExtensions;

/// Represents a Vulkan context.
pub struct Device {
    instance: Arc<Instance>,
    physical_device: usize,
    device: vk::Device,
    vk: vk::DevicePointers,
    standard_pool: Mutex<Option<Arc<StdMemoryPool>>>,
    features: Features,
    extensions: DeviceExtensions,
}

impl Device {
    /// Builds a new Vulkan device for the given physical device.
    ///
    /// You must pass two things when creating a logical device:
    ///
    /// - A list of optional Vulkan features that must be enabled on the device. Note that if a
    ///   feature is not enabled at device creation, you can't use it later even it it's supported
    ///   by the physical device.
    ///
    /// - An iterator to a list of queues to create. Each element of the iterator must indicate
    ///   the family whose queue belongs to and a priority between 0.0 and 1.0 to assign to it.
    ///   A queue with a higher value indicates that the commands will execute faster than on a
    ///   queue with a lower value. Note however that no guarantee can be made on the way the
    ///   priority value is handled by the implementation.
    ///
    /// # Panic
    ///
    /// - Panicks if one of the requested features is not supported by the physical device.
    /// - Panicks if one of the queue families doesn't belong to the given device.
    /// - Panicks if you request more queues from a family than available.
    /// - Panicks if one of the priorities is outside of the `[0.0 ; 1.0]` range.
    ///
    // TODO: return Arc<Queue> and handle synchronization in the Queue
    pub fn new<'a, I, L>(phys: &'a PhysicalDevice, requested_features: &Features,
                         extensions: &DeviceExtensions, layers: L, queue_families: I)
                         -> Result<(Arc<Device>, Vec<Arc<Queue>>), DeviceCreationError>
        where I: IntoIterator<Item = (QueueFamily<'a>, f32)>,
              L: IntoIterator<Item = &'a &'a str>
    {
        let queue_families = queue_families.into_iter();

        assert!(phys.supported_features().superset_of(&requested_features));

        let vk_i = phys.instance().pointers();

        // this variable will contain the queue family ID and queue ID of each requested queue
        let mut output_queues: Vec<(u32, u32)> = Vec::with_capacity(queue_families.size_hint().0);

        let layers = layers.into_iter().map(|&layer| {
            // FIXME: check whether each layer is supported
            CString::new(layer).unwrap()
        }).collect::<SmallVec<[_; 8]>>();
        let layers = layers.iter().map(|layer| {
            layer.as_ptr()
        }).collect::<SmallVec<[_; 8]>>();

        let extensions_list = extensions.build_extensions_list();
        let extensions_list = extensions_list.iter().map(|extension| {
            extension.as_ptr()
        }).collect::<SmallVec<[_; 16]>>();

        // device creation
        let device = unsafe {
            // each element of `queues` is a `(queue_family, priorities)`
            // each queue family must only have one entry in `queues`
            let mut queues: Vec<(u32, Vec<f32>)> = Vec::with_capacity(phys.queue_families().len());

            for (queue_family, priority) in queue_families {
                // checking the parameters
                assert_eq!(queue_family.physical_device().internal_object(),
                           phys.internal_object());
                assert!(priority >= 0.0 && priority <= 1.0);

                // adding to `queues` and `output_queues`
                if let Some(q) = queues.iter_mut().find(|q| q.0 == queue_family.id()) {
                    output_queues.push((queue_family.id(), q.1.len() as u32));
                    q.1.push(priority);
                    assert!(q.1.len() < queue_family.queues_count());
                    continue;
                }
                queues.push((queue_family.id(), vec![priority]));
                output_queues.push((queue_family.id(), 0));
            }

            // turning `queues` into an array of `vkDeviceQueueCreateInfo` suitable for Vulkan
            let queues = queues.iter().map(|&(queue_id, ref priorities)| {
                vk::DeviceQueueCreateInfo {
                    sType: vk::STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
                    pNext: ptr::null(),
                    flags: 0,   // reserved
                    queueFamilyIndex: queue_id,
                    queueCount: priorities.len() as u32,
                    pQueuePriorities: priorities.as_ptr()
                }
            }).collect::<SmallVec<[_; 16]>>();

            // TODO: The plan regarding `robustBufferAccess` is to check the shaders' code to see
            //       if they can possibly perform out-of-bounds reads and writes. If the user tries
            //       to use a shader that can perform out-of-bounds operations without having
            //       `robustBufferAccess` enabled, an error is returned.
            //
            //       However for the moment this verification isn't performed. In order to be safe,
            //       we always enable the `robustBufferAccess` feature as it is guaranteed to be
            //       supported everywhere.
            //
            //       The only alternative (while waiting for shaders introspection to work) is to
            //       make all shaders depend on `robustBufferAccess`. But since usually the
            //       majority of shaders don't need this feature, it would be very annoying to have
            //       to enable it manually when you don't need it.
            let features = {
                let mut features: vk::PhysicalDeviceFeatures = requested_features.clone().into();
                features.robustBufferAccess = vk::TRUE;
                features
            };

            let infos = vk::DeviceCreateInfo {
                sType: vk::STRUCTURE_TYPE_DEVICE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                queueCreateInfoCount: queues.len() as u32,
                pQueueCreateInfos: queues.as_ptr(),
                enabledLayerCount: layers.len() as u32,
                ppEnabledLayerNames: layers.as_ptr(),
                enabledExtensionCount: extensions_list.len() as u32,
                ppEnabledExtensionNames: extensions_list.as_ptr(),
                pEnabledFeatures: &features,
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk_i.CreateDevice(phys.internal_object(), &infos,
                                                ptr::null(), &mut output)));
            output
        };

        // loading the function pointers of the newly-created device
        let vk = vk::DevicePointers::load(|name| {
            unsafe { vk_i.GetDeviceProcAddr(device, name.as_ptr()) as *const _ }
        });

        let device = Arc::new(Device {
            instance: phys.instance().clone(),
            physical_device: phys.index(),
            device: device,
            vk: vk,
            standard_pool: Mutex::new(None),
            features: requested_features.clone(),
            extensions: extensions.clone(),
        });

        // Creating the memory pool.
        {
            let mut pool_dest = device.standard_pool.lock().unwrap();
            *pool_dest = Some(StdMemoryPool::new(&device));
        }

        // querying the queues
        let output_queues = output_queues.into_iter().map(|(family, id)| {
            unsafe {
                let mut output = mem::uninitialized();
                device.vk.GetDeviceQueue(device.device, family, id, &mut output);
                Arc::new(Queue {
                    queue: Mutex::new(output),
                    device: device.clone(),
                    family: family,
                    id: id,
                    dedicated_semaphore: Mutex::new(None),
                })
            }
        }).collect();

        Ok((device, output_queues))
    }

    /// Waits until all work on this device has finished. You should never need to call
    /// this function, but it can be useful for debugging or benchmarking purposes.
    ///
    /// This is the Vulkan equivalent of `glFinish`.
    // FIXME: must synchronize all queuees
    #[inline]
    pub fn wait(&self) -> Result<(), OomError> {
        unsafe {
            try!(check_errors(self.vk.DeviceWaitIdle(self.device)));
            Ok(())
        }
    }

    /// Returns the instance used to create this device.
    #[inline]
    pub fn instance(&self) -> &Arc<Instance> {
        &self.instance
    }

    /// Returns the physical device that was used to create this device.
    #[inline]
    pub fn physical_device(&self) -> PhysicalDevice {
        PhysicalDevice::from_index(&self.instance, self.physical_device).unwrap()
    }

    /// Returns the features that are enabled in the device.
    #[inline]
    pub fn enabled_features(&self) -> &Features {
        &self.features
    }

    /// Returns the list of extensions that have been loaded.
    #[inline]
    pub fn loaded_extensions(&self) -> &DeviceExtensions {
        &self.extensions
    }

    /// Returns the standard memory pool used by default if you don't provide any other pool.
    #[inline]
    pub fn standard_pool(&self) -> Arc<StdMemoryPool> {
        self.standard_pool.lock().unwrap().clone().unwrap()
    }
}

impl fmt::Debug for Device {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "<Vulkan device>")
    }
}

unsafe impl VulkanObject for Device {
    type Object = vk::Device;

    #[inline]
    fn internal_object(&self) -> vk::Device {
        self.device
    }
}

impl VulkanPointers for Device {
    type Pointers = vk::DevicePointers;

    #[inline]
    fn pointers(&self) -> &vk::DevicePointers {
        &self.vk
    }
}

impl Drop for Device {
    #[inline]
    fn drop(&mut self) {
        let _ = self.standard_pool.lock().unwrap().take();

        unsafe {
            self.vk.DeviceWaitIdle(self.device);
            self.vk.DestroyDevice(self.device, ptr::null());
        }
    }
}

/// Error that can be returned when creating a device.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum DeviceCreationError {
    /// There is no memory available on the host (ie. the CPU, RAM, etc.).
    OutOfHostMemory,
    /// There is no memory available on the device (ie. video memory).
    OutOfDeviceMemory,
    // FIXME: other values
}

impl error::Error for DeviceCreationError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            DeviceCreationError::OutOfHostMemory => "no memory available on the host",
            DeviceCreationError::OutOfDeviceMemory => "no memory available on the graphical device",
        }
    }
}

impl fmt::Display for DeviceCreationError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<Error> for DeviceCreationError {
    #[inline]
    fn from(err: Error) -> DeviceCreationError {
        match err {
            Error::OutOfHostMemory => DeviceCreationError::OutOfHostMemory,
            Error::OutOfDeviceMemory => DeviceCreationError::OutOfDeviceMemory,
            _ => panic!("Unexpected error value: {}", err as i32)
        }
    }
}

/// Represents a queue where commands can be submitted.
// TODO: should use internal synchronization
#[derive(Debug)]
pub struct Queue {
    queue: Mutex<vk::Queue>,
    device: Arc<Device>,
    family: u32,
    id: u32,    // id within family

    // For safety purposes, each command buffer submitted to a queue has to both wait on and
    // signal the semaphore specified here.
    //
    // If this is `None`, then that means we haven't used the semaphore yet.
    //
    // For more infos, see TODO: see what?
    dedicated_semaphore: Mutex<Option<Arc<Semaphore>>>,
}

impl Queue {
    /// Returns the device this queue belongs to.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }

    /// Returns the family this queue belongs to.
    #[inline]
    pub fn family(&self) -> QueueFamily {
        self.device.physical_device().queue_family_by_id(self.family).unwrap()
    }

    /// Returns the index of this queue within its family.
    #[inline]
    pub fn id_within_family(&self) -> u32 {
        self.id
    }

    /// Waits until all work on this queue has finished.
    ///
    /// Just like `Device::wait()`, you shouldn't have to call this function.
    #[inline]
    pub fn wait(&self) -> Result<(), OomError> {
        unsafe {
            let vk = self.device.pointers();
            let queue = self.queue.lock().unwrap();
            try!(check_errors(vk.QueueWaitIdle(*queue)));
            Ok(())
        }
    }

    // TODO: the design of this functions depends on https://github.com/KhronosGroup/Vulkan-Docs/issues/155
    /*// TODO: document
    #[doc(hidden)]
    #[inline]
    pub unsafe fn dedicated_semaphore(&self) -> Result<(Arc<Semaphore>, bool), OomError> {
        let mut sem = self.dedicated_semaphore.lock().unwrap();

        if let Some(ref semaphore) = *sem {
            return Ok((semaphore.clone(), true));
        }

        let semaphore = try!(Semaphore::new(&self.device));
        *sem = Some(semaphore.clone());
        Ok((semaphore, false))
    }*/
    #[doc(hidden)]
    #[inline]
    pub unsafe fn dedicated_semaphore(&self, signalled: Arc<Semaphore>) -> Option<Arc<Semaphore>> {
        let mut sem = self.dedicated_semaphore.lock().unwrap();
        mem::replace(&mut *sem, Some(signalled))
    }
}

unsafe impl SynchronizedVulkanObject for Queue {
    type Object = vk::Queue;

    #[inline]
    fn internal_object_guard(&self) -> MutexGuard<vk::Queue> {
        self.queue.lock().unwrap()
    }
}

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

    #[test]
    #[ignore]   // FIXME: failing, fix me
    fn one_ref() {
        let (mut device, _) = gfx_dev_and_queue!();
        assert!(Arc::get_mut(&mut device).is_some());
    }
}
<commit_msg>optional Oomerror in Device::wait and Queue:wait<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Communication channel with a physical device.
//!
//! The `Device` is one of the most important objects of Vulkan. Creating a `Device` is required
//! before you can create buffers, textures, shaders, etc.
//!
use std::ffi::CString;
use std::fmt;
use std::error;
use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
use smallvec::SmallVec;

use instance::Features;
use instance::Instance;
use instance::PhysicalDevice;
use instance::QueueFamily;
use memory::pool::StdMemoryPool;
use sync::Semaphore;

use Error;
use OomError;
use SynchronizedVulkanObject;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

pub use instance::DeviceExtensions;

/// Represents a Vulkan context.
pub struct Device {
    instance: Arc<Instance>,
    physical_device: usize,
    device: vk::Device,
    vk: vk::DevicePointers,
    standard_pool: Mutex<Option<Arc<StdMemoryPool>>>,
    features: Features,
    extensions: DeviceExtensions,
}

impl Device {
    /// Builds a new Vulkan device for the given physical device.
    ///
    /// You must pass two things when creating a logical device:
    ///
    /// - A list of optional Vulkan features that must be enabled on the device. Note that if a
    ///   feature is not enabled at device creation, you can't use it later even it it's supported
    ///   by the physical device.
    ///
    /// - An iterator to a list of queues to create. Each element of the iterator must indicate
    ///   the family whose queue belongs to and a priority between 0.0 and 1.0 to assign to it.
    ///   A queue with a higher value indicates that the commands will execute faster than on a
    ///   queue with a lower value. Note however that no guarantee can be made on the way the
    ///   priority value is handled by the implementation.
    ///
    /// # Panic
    ///
    /// - Panicks if one of the requested features is not supported by the physical device.
    /// - Panicks if one of the queue families doesn't belong to the given device.
    /// - Panicks if you request more queues from a family than available.
    /// - Panicks if one of the priorities is outside of the `[0.0 ; 1.0]` range.
    ///
    // TODO: return Arc<Queue> and handle synchronization in the Queue
    pub fn new<'a, I, L>(phys: &'a PhysicalDevice, requested_features: &Features,
                         extensions: &DeviceExtensions, layers: L, queue_families: I)
                         -> Result<(Arc<Device>, Vec<Arc<Queue>>), DeviceCreationError>
        where I: IntoIterator<Item = (QueueFamily<'a>, f32)>,
              L: IntoIterator<Item = &'a &'a str>
    {
        let queue_families = queue_families.into_iter();

        assert!(phys.supported_features().superset_of(&requested_features));

        let vk_i = phys.instance().pointers();

        // this variable will contain the queue family ID and queue ID of each requested queue
        let mut output_queues: Vec<(u32, u32)> = Vec::with_capacity(queue_families.size_hint().0);

        let layers = layers.into_iter().map(|&layer| {
            // FIXME: check whether each layer is supported
            CString::new(layer).unwrap()
        }).collect::<SmallVec<[_; 8]>>();
        let layers = layers.iter().map(|layer| {
            layer.as_ptr()
        }).collect::<SmallVec<[_; 8]>>();

        let extensions_list = extensions.build_extensions_list();
        let extensions_list = extensions_list.iter().map(|extension| {
            extension.as_ptr()
        }).collect::<SmallVec<[_; 16]>>();

        // device creation
        let device = unsafe {
            // each element of `queues` is a `(queue_family, priorities)`
            // each queue family must only have one entry in `queues`
            let mut queues: Vec<(u32, Vec<f32>)> = Vec::with_capacity(phys.queue_families().len());

            for (queue_family, priority) in queue_families {
                // checking the parameters
                assert_eq!(queue_family.physical_device().internal_object(),
                           phys.internal_object());
                assert!(priority >= 0.0 && priority <= 1.0);

                // adding to `queues` and `output_queues`
                if let Some(q) = queues.iter_mut().find(|q| q.0 == queue_family.id()) {
                    output_queues.push((queue_family.id(), q.1.len() as u32));
                    q.1.push(priority);
                    assert!(q.1.len() < queue_family.queues_count());
                    continue;
                }
                queues.push((queue_family.id(), vec![priority]));
                output_queues.push((queue_family.id(), 0));
            }

            // turning `queues` into an array of `vkDeviceQueueCreateInfo` suitable for Vulkan
            let queues = queues.iter().map(|&(queue_id, ref priorities)| {
                vk::DeviceQueueCreateInfo {
                    sType: vk::STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
                    pNext: ptr::null(),
                    flags: 0,   // reserved
                    queueFamilyIndex: queue_id,
                    queueCount: priorities.len() as u32,
                    pQueuePriorities: priorities.as_ptr()
                }
            }).collect::<SmallVec<[_; 16]>>();

            // TODO: The plan regarding `robustBufferAccess` is to check the shaders' code to see
            //       if they can possibly perform out-of-bounds reads and writes. If the user tries
            //       to use a shader that can perform out-of-bounds operations without having
            //       `robustBufferAccess` enabled, an error is returned.
            //
            //       However for the moment this verification isn't performed. In order to be safe,
            //       we always enable the `robustBufferAccess` feature as it is guaranteed to be
            //       supported everywhere.
            //
            //       The only alternative (while waiting for shaders introspection to work) is to
            //       make all shaders depend on `robustBufferAccess`. But since usually the
            //       majority of shaders don't need this feature, it would be very annoying to have
            //       to enable it manually when you don't need it.
            let features = {
                let mut features: vk::PhysicalDeviceFeatures = requested_features.clone().into();
                features.robustBufferAccess = vk::TRUE;
                features
            };

            let infos = vk::DeviceCreateInfo {
                sType: vk::STRUCTURE_TYPE_DEVICE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                queueCreateInfoCount: queues.len() as u32,
                pQueueCreateInfos: queues.as_ptr(),
                enabledLayerCount: layers.len() as u32,
                ppEnabledLayerNames: layers.as_ptr(),
                enabledExtensionCount: extensions_list.len() as u32,
                ppEnabledExtensionNames: extensions_list.as_ptr(),
                pEnabledFeatures: &features,
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk_i.CreateDevice(phys.internal_object(), &infos,
                                                ptr::null(), &mut output)));
            output
        };

        // loading the function pointers of the newly-created device
        let vk = vk::DevicePointers::load(|name| {
            unsafe { vk_i.GetDeviceProcAddr(device, name.as_ptr()) as *const _ }
        });

        let device = Arc::new(Device {
            instance: phys.instance().clone(),
            physical_device: phys.index(),
            device: device,
            vk: vk,
            standard_pool: Mutex::new(None),
            features: requested_features.clone(),
            extensions: extensions.clone(),
        });

        // Creating the memory pool.
        {
            let mut pool_dest = device.standard_pool.lock().unwrap();
            *pool_dest = Some(StdMemoryPool::new(&device));
        }

        // querying the queues
        let output_queues = output_queues.into_iter().map(|(family, id)| {
            unsafe {
                let mut output = mem::uninitialized();
                device.vk.GetDeviceQueue(device.device, family, id, &mut output);
                Arc::new(Queue {
                    queue: Mutex::new(output),
                    device: device.clone(),
                    family: family,
                    id: id,
                    dedicated_semaphore: Mutex::new(None),
                })
            }
        }).collect();

        Ok((device, output_queues))
    }

    /// Waits until all work on this device has finished. You should never need to call
    /// this function, but it can be useful for debugging or benchmarking purposes.
    ///
    /// This is the Vulkan equivalent of `glFinish`.
    // FIXME: must synchronize all queuees
    #[inline]
    pub fn wait_raw(&self) -> Result<(), OomError> {
        unsafe {
            try!(check_errors(self.vk.DeviceWaitIdle(self.device)));
            Ok(())
        }
    }

    /// Waits until all work on this device has finished. You should never need to call
    /// this function, but it can be useful for debugging or benchmarking purposes.
    ///
    /// This is the Vulkan equivalent of `glFinish`.
    ///
    /// # Panic
    ///
    /// - Panicks if the device or host ran out of memory.
    ///
    // FIXME: must synchronize all queuees
    #[inline]
    pub fn wait(&self) {
        self.wait_raw().unwrap();
    }

    /// Returns the instance used to create this device.
    #[inline]
    pub fn instance(&self) -> &Arc<Instance> {
        &self.instance
    }

    /// Returns the physical device that was used to create this device.
    #[inline]
    pub fn physical_device(&self) -> PhysicalDevice {
        PhysicalDevice::from_index(&self.instance, self.physical_device).unwrap()
    }

    /// Returns the features that are enabled in the device.
    #[inline]
    pub fn enabled_features(&self) -> &Features {
        &self.features
    }

    /// Returns the list of extensions that have been loaded.
    #[inline]
    pub fn loaded_extensions(&self) -> &DeviceExtensions {
        &self.extensions
    }

    /// Returns the standard memory pool used by default if you don't provide any other pool.
    #[inline]
    pub fn standard_pool(&self) -> Arc<StdMemoryPool> {
        self.standard_pool.lock().unwrap().clone().unwrap()
    }
}

impl fmt::Debug for Device {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "<Vulkan device>")
    }
}

unsafe impl VulkanObject for Device {
    type Object = vk::Device;

    #[inline]
    fn internal_object(&self) -> vk::Device {
        self.device
    }
}

impl VulkanPointers for Device {
    type Pointers = vk::DevicePointers;

    #[inline]
    fn pointers(&self) -> &vk::DevicePointers {
        &self.vk
    }
}

impl Drop for Device {
    #[inline]
    fn drop(&mut self) {
        let _ = self.standard_pool.lock().unwrap().take();

        unsafe {
            self.vk.DeviceWaitIdle(self.device);
            self.vk.DestroyDevice(self.device, ptr::null());
        }
    }
}

/// Error that can be returned when creating a device.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum DeviceCreationError {
    /// There is no memory available on the host (ie. the CPU, RAM, etc.).
    OutOfHostMemory,
    /// There is no memory available on the device (ie. video memory).
    OutOfDeviceMemory,
    // FIXME: other values
}

impl error::Error for DeviceCreationError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            DeviceCreationError::OutOfHostMemory => "no memory available on the host",
            DeviceCreationError::OutOfDeviceMemory => "no memory available on the graphical device",
        }
    }
}

impl fmt::Display for DeviceCreationError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<Error> for DeviceCreationError {
    #[inline]
    fn from(err: Error) -> DeviceCreationError {
        match err {
            Error::OutOfHostMemory => DeviceCreationError::OutOfHostMemory,
            Error::OutOfDeviceMemory => DeviceCreationError::OutOfDeviceMemory,
            _ => panic!("Unexpected error value: {}", err as i32)
        }
    }
}

/// Represents a queue where commands can be submitted.
// TODO: should use internal synchronization
#[derive(Debug)]
pub struct Queue {
    queue: Mutex<vk::Queue>,
    device: Arc<Device>,
    family: u32,
    id: u32,    // id within family

    // For safety purposes, each command buffer submitted to a queue has to both wait on and
    // signal the semaphore specified here.
    //
    // If this is `None`, then that means we haven't used the semaphore yet.
    //
    // For more infos, see TODO: see what?
    dedicated_semaphore: Mutex<Option<Arc<Semaphore>>>,
}

impl Queue {
    /// Returns the device this queue belongs to.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }

    /// Returns the family this queue belongs to.
    #[inline]
    pub fn family(&self) -> QueueFamily {
        self.device.physical_device().queue_family_by_id(self.family).unwrap()
    }

    /// Returns the index of this queue within its family.
    #[inline]
    pub fn id_within_family(&self) -> u32 {
        self.id
    }

    /// Waits until all work on this queue has finished.
    ///
    /// Just like `Device::wait()`, you shouldn't have to call this function.
    #[inline]
    pub fn wait_raw(&self) -> Result<(), OomError> {
        unsafe {
            let vk = self.device.pointers();
            let queue = self.queue.lock().unwrap();
            try!(check_errors(vk.QueueWaitIdle(*queue)));
            Ok(())
        }
    }

    /// Waits until all work on this queue has finished.
    ///
    /// Just like `Device::wait()`, you shouldn't have to call this function.
    ///
    /// # Panic
    ///
    /// - Panicks if the device or host ran out of memory.
    ///
    #[inline]
    pub fn wait(&self) {
        self.wait_raw().unwrap();
    }

    // TODO: the design of this functions depends on https://github.com/KhronosGroup/Vulkan-Docs/issues/155
    /*// TODO: document
    #[doc(hidden)]
    #[inline]
    pub unsafe fn dedicated_semaphore(&self) -> Result<(Arc<Semaphore>, bool), OomError> {
        let mut sem = self.dedicated_semaphore.lock().unwrap();

        if let Some(ref semaphore) = *sem {
            return Ok((semaphore.clone(), true));
        }

        let semaphore = try!(Semaphore::new(&self.device));
        *sem = Some(semaphore.clone());
        Ok((semaphore, false))
    }*/
    #[doc(hidden)]
    #[inline]
    pub unsafe fn dedicated_semaphore(&self, signalled: Arc<Semaphore>) -> Option<Arc<Semaphore>> {
        let mut sem = self.dedicated_semaphore.lock().unwrap();
        mem::replace(&mut *sem, Some(signalled))
    }
}

unsafe impl SynchronizedVulkanObject for Queue {
    type Object = vk::Queue;

    #[inline]
    fn internal_object_guard(&self) -> MutexGuard<vk::Queue> {
        self.queue.lock().unwrap()
    }
}

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

    #[test]
    #[ignore]   // FIXME: failing, fix me
    fn one_ref() {
        let (mut device, _) = gfx_dev_and_queue!();
        assert!(Arc::get_mut(&mut device).is_some());
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::io::{BufferedReader, File};
use std::os;

static WORD_THRESHOLD: u32 = 1000;
static CLUSTER_THRESHOLD: u32 = 1000;

fn main() {
    let args = os::args();
    let inputs: Vec<Path> = args.tail().iter().map(|f| Path::new(f.as_slice())).collect();

    let mut word_freq: HashMap<u64, u32> = HashMap::new();
    for path in inputs.iter() {
        let mut file = BufferedReader::new(File::open(path));
        for l in file.lines() {
            for w in l.ok().unwrap().as_slice().words() {
                let hash = fnv1a(w);
                word_freq.insert_or_update_with(hash, 1, |_k,v| *v+=1);
            }
        }
    }

    println!("words found: {}", word_freq.len());

    let mut clusters: HashMap<String, u32> = HashMap::new();
    for path in inputs.iter() {
        let mut file = BufferedReader::new(File::open(path));
        for l in file.lines() {
            let cluster = clusterify(&word_freq, l.ok().unwrap().as_slice());
            if !cluster.is_empty() {
                clusters.insert_or_update_with(cluster, 1, |_k,v| *v+=1);
            }
        }
    }

    println!("clusters found: {}", clusters.len());

    for (k,v) in clusters.iter() {
        if *v >= CLUSTER_THRESHOLD {
            println!("{}\t{}", v, k);
        }
    }
}

fn clusterify(word_freq: &HashMap<u64, u32>, line: &str) -> String {
    let words: Vec<&str> = line.words().map({|w|
        if word_freq[fnv1a(w)] < WORD_THRESHOLD {
            "*"
        } else {
            w
        }
    }).collect();

    words.connect(" ")
}

static FNV_PRIME_64: u64 = 1099511628211;
static FNV1_OFFSET_BASIS_64: u64 = 14695981039346656037;

fn fnv1a(s: &str) -> u64 {
    let mut hash = FNV1_OFFSET_BASIS_64;
    for b in s.as_bytes().iter() {
        hash = (hash ^ *b as u64) * FNV_PRIME_64;
    }
    hash
}
<commit_msg>Word and cluster thresholds can now be passed as flags<commit_after>extern crate getopts;

use std::collections::HashMap;
use std::io::{BufferedReader, File};
use std::os;
use std::rt::heap;

use getopts::{getopts,optflag,optopt};

type Hash = uint;
type Count = u32;
type Words = HashMap<Hash, Count>;
type Clusters = HashMap<String, Count>;

fn main() {
    let opts = [
        optopt("c", "cluster-threshold", "cluster appearance threshold for diplay", "CLUSTERTHRESHOLD"),
        optflag("m", "mem-stats", "print memory allocator statistics at the end"),
        optflag("r", "rare", "display only clusters below CLUSTERTHRESHOLD"),
        optopt("w", "word-threshold", "minimum frequency of a word to be considered for a cluster", "WORDTHRESHOLD"),
    ];
    let matches = getopts(os::args().tail(), opts).unwrap_or_else(|f| fail!(f.to_string()));

    let cluster_threshold: Count = match matches.opt_str("c") {
        Some(ct) => { from_str(ct.as_slice()).unwrap() }
        None => { 1000 }
    };

    let word_threshold: Count = match matches.opt_str("w") {
        Some(wt) => { from_str(wt.as_slice()).unwrap() }
        None => { 1000 }
    };

    let show_rare = matches.opt_present("r");
    let print_mem_stats = matches.opt_present("m");

    let inputs: Vec<Path> = matches.free.iter().map(|f| Path::new(f.as_slice())).collect();

    let word_freq = calc_word_freq(&inputs);
    println!("found {} unique words", word_freq.len());

    let clusters = calc_clusters(&inputs, &word_freq, word_threshold);
    println!("found {} clusters", clusters.len());

    if print_mem_stats {
        heap::stats_print();
    }

    for (k,v) in clusters.iter() {
        if show_rare == *v < cluster_threshold {
            println!("{}\t{}", v, k);
        }
    }
}

fn calc_word_freq(paths: &Vec<Path>) -> Words {
    let mut word_freq: HashMap<Hash, Count> = HashMap::new();

    for path in paths.iter() {
        let mut file = BufferedReader::new(File::open(path));
        for l in file.lines() {
            for w in l.ok().unwrap().as_slice().words() {
                let hash = fnv1a(w);
                word_freq.insert_or_update_with(hash, 1, |_k,v| *v+=1);
            }
        }
    }

    word_freq
}

fn calc_clusters(paths: &Vec<Path>, word_freq: &Words, word_threshold: Count) -> Clusters {
    let mut clusters: HashMap<String, Count> = HashMap::new();

    for path in paths.iter() {
        let mut file = BufferedReader::new(File::open(path));
        for l in file.lines() {
            let cluster = clusterify(l.unwrap().as_slice(), word_freq, word_threshold);
            if !cluster.is_empty() {
                clusters.insert_or_update_with(cluster, 1, |_k,v| *v+=1);
            }
        }
    }

    clusters
}

fn clusterify(line: &str, word_freq: &Words, word_threshold: Count) -> String {
    let words: Vec<&str> = line.words().map({|w|
        if word_freq[fnv1a(w)] < word_threshold {
            "*"
        } else {
            w
        }
    }).collect();

    words.connect(" ")
}

static FNV_PRIME_64: Hash = 1099511628211;
static FNV1_OFFSET_BASIS_64: Hash = 14695981039346656037;

fn fnv1a(s: &str) -> Hash {
    let mut hash = FNV1_OFFSET_BASIS_64;
    for b in s.as_bytes().iter() {
        hash = (hash ^ *b as Hash) * FNV_PRIME_64;
    }
    hash
}
<|endoftext|>


<commit_before>//! Layout tree.
//!
//! The idea is to take the DOM tree and produce a layout tree with SVG concepts.

use std::rc::Rc;
use std::sync::Arc;

use crate::aspect_ratio::AspectRatio;
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::dasharray::Dasharray;
use crate::document::AcquiredNodes;
use crate::element::Element;
use crate::length::*;
use crate::node::*;
use crate::paint_server::{PaintSource, UserSpacePaintSource};
use crate::path_builder::Path;
use crate::properties::{
    ClipRule, ComputedValues, Direction, FillRule, Filter, FontFamily, FontStretch, FontStyle,
    FontVariant, FontWeight, Isolation, MixBlendMode, Opacity, Overflow, PaintOrder,
    ShapeRendering, StrokeDasharray, StrokeLinecap, StrokeLinejoin, StrokeMiterlimit,
    TextDecoration, TextRendering, UnicodeBidi, VectorEffect, XmlLang,
};
use crate::rect::Rect;
use crate::session::Session;
use crate::surface_utils::shared_surface::SharedImageSurface;
use crate::transform::Transform;
use crate::unit_interval::UnitInterval;

/// SVG Stacking context, an inner node in the layout tree.
///
/// <https://www.w3.org/TR/SVG2/render.html#EstablishingStackingContex>
///
/// This is not strictly speaking an SVG2 stacking context, but a
/// looser version of it.  For example. the SVG spec mentions that a
/// an element should establish a stacking context if the `filter`
/// property applies to the element and is not `none`.  In that case,
/// the element is rendered as an "isolated group" -
/// <https://www.w3.org/TR/2015/CR-compositing-1-20150113/#csscompositingrules_SVG>
///
/// Here we store all the parameters that may lead to the decision to actually
/// render an element as an isolated group.
pub struct StackingContext {
    pub element_name: String,
    pub transform: Transform,
    pub opacity: Opacity,
    pub filter: Filter,
    pub clip_in_user_space: Option<Node>,
    pub clip_in_object_space: Option<Node>,
    pub mask: Option<Node>,
    pub mix_blend_mode: MixBlendMode,
    pub isolation: Isolation,

    /// Target from an <a> element
    pub link_target: Option<String>,
}

/// Stroke parameters in user-space coordinates.
pub struct Stroke {
    pub width: f64,
    pub miter_limit: StrokeMiterlimit,
    pub line_cap: StrokeLinecap,
    pub line_join: StrokeLinejoin,
    pub dash_offset: f64,
    pub dashes: Box<[f64]>,
    // https://svgwg.org/svg2-draft/painting.html#non-scaling-stroke
    pub non_scaling: bool,
}

/// Paths and basic shapes resolved to a path.
///
/// Note that `stroke_paint` and `fill_paint` are not in user-space coordinates;
/// they are just resolved to a `PaintSource`.  Turning them to a `UserSpacePaintSource`
/// involves knowing the bounding box of the path.
pub struct Shape {
    pub path: Rc<Path>,
    pub extents: Option<Rect>,
    pub is_visible: bool,
    pub paint_order: PaintOrder,
    pub stroke: Stroke,
    pub stroke_paint: UserSpacePaintSource,
    pub fill_paint: UserSpacePaintSource,
    pub fill_rule: FillRule,
    pub clip_rule: ClipRule,
    pub shape_rendering: ShapeRendering,
    pub marker_start: Marker,
    pub marker_mid: Marker,
    pub marker_end: Marker,
}

pub struct Marker {
    pub node_ref: Option<Node>,
    pub context_stroke: Arc<PaintSource>,
    pub context_fill: Arc<PaintSource>,
}

/// Image in user-space coordinates.
pub struct Image {
    pub surface: SharedImageSurface,
    pub is_visible: bool,
    pub rect: Rect,
    pub aspect: AspectRatio,
    pub overflow: Overflow,
}

/// A single text span in user-space coordinates.
pub struct TextSpan {
    pub layout: pango::Layout,
    pub gravity: pango::Gravity,
    pub bbox: Option<BoundingBox>,
    pub is_visible: bool,
    pub x: f64,
    pub y: f64,
    pub paint_order: PaintOrder,
    pub stroke: Stroke,
    pub stroke_paint: UserSpacePaintSource,
    pub fill_paint: UserSpacePaintSource,
    pub text_rendering: TextRendering,
    pub link_target: Option<String>,
}

/// Fully laid-out text in user-space coordinates.
pub struct Text {
    pub spans: Vec<TextSpan>,
}

/// Font-related properties extracted from `ComputedValues`.
pub struct FontProperties {
    pub xml_lang: XmlLang,
    pub unicode_bidi: UnicodeBidi,
    pub direction: Direction,
    pub font_family: FontFamily,
    pub font_style: FontStyle,
    pub font_variant: FontVariant,
    pub font_weight: FontWeight,
    pub font_stretch: FontStretch,
    pub font_size: f64,
    pub letter_spacing: f64,
    pub text_decoration: TextDecoration,
}

impl StackingContext {
    pub fn new(
        session: &Session,
        acquired_nodes: &mut AcquiredNodes<'_>,
        element: &Element,
        transform: Transform,
        values: &ComputedValues,
    ) -> StackingContext {
        let element_name = format!("{}", element);

        let opacity;
        let filter;

        match *element {
            // "The opacity, filter and display properties do not apply to the mask element"
            // https://drafts.fxtf.org/css-masking-1/#MaskElement
            Element::Mask(_) => {
                opacity = Opacity(UnitInterval::clamp(1.0));
                filter = Filter::None;
            }

            _ => {
                opacity = values.opacity();
                filter = values.filter();
            }
        }

        let clip_path = values.clip_path();
        let clip_uri = clip_path.0.get();
        let (clip_in_user_space, clip_in_object_space) = clip_uri
            .and_then(|node_id| {
                acquired_nodes
                    .acquire(node_id)
                    .ok()
                    .filter(|a| is_element_of_type!(*a.get(), ClipPath))
            })
            .map(|acquired| {
                let clip_node = acquired.get().clone();

                let units = borrow_element_as!(clip_node, ClipPath).get_units();

                match units {
                    CoordUnits::UserSpaceOnUse => (Some(clip_node), None),
                    CoordUnits::ObjectBoundingBox => (None, Some(clip_node)),
                }
            })
            .unwrap_or((None, None));

        let mask = values.mask().0.get().and_then(|mask_id| {
            if let Ok(acquired) = acquired_nodes.acquire(mask_id) {
                let node = acquired.get();
                match *node.borrow_element() {
                    Element::Mask(_) => Some(node.clone()),

                    _ => {
                        rsvg_log!(
                            session,
                            "element {} references \"{}\" which is not a mask",
                            element,
                            mask_id
                        );

                        None
                    }
                }
            } else {
                rsvg_log!(
                    session,
                    "element {} references nonexistent mask \"{}\"",
                    element,
                    mask_id
                );

                None
            }
        });

        let mix_blend_mode = values.mix_blend_mode();
        let isolation = values.isolation();

        StackingContext {
            element_name,
            transform,
            opacity,
            filter,
            clip_in_user_space,
            clip_in_object_space,
            mask,
            mix_blend_mode,
            isolation,
            link_target: None,
        }
    }

    pub fn new_with_link(
        session: &Session,
        acquired_nodes: &mut AcquiredNodes<'_>,
        element: &Element,
        transform: Transform,
        values: &ComputedValues,
        link_target: Option<String>,
    ) -> StackingContext {
        let mut ctx = Self::new(session, acquired_nodes, element, transform, values);
        ctx.link_target = link_target;
        ctx
    }
}

impl Stroke {
    pub fn new(values: &ComputedValues, params: &NormalizeParams) -> Stroke {
        let width = values.stroke_width().0.to_user(params);
        let miter_limit = values.stroke_miterlimit();
        let line_cap = values.stroke_line_cap();
        let line_join = values.stroke_line_join();
        let dash_offset = values.stroke_dashoffset().0.to_user(params);
        let non_scaling = values.vector_effect() == VectorEffect::NonScalingStroke;

        let dashes = match values.stroke_dasharray() {
            StrokeDasharray(Dasharray::None) => Box::new([]),
            StrokeDasharray(Dasharray::Array(dashes)) => dashes
                .iter()
                .map(|l| l.to_user(params))
                .collect::<Box<[f64]>>(),
        };

        Stroke {
            width,
            miter_limit,
            line_cap,
            line_join,
            dash_offset,
            dashes,
            non_scaling,
        }
    }
}

impl FontProperties {
    /// Collects font properties from a `ComputedValues`.
    ///
    /// The `writing-mode` property is passed separately, as it must come from the `<text>` element,
    /// not the `<tspan>` whose computed values are being passed.
    pub fn new(values: &ComputedValues, params: &NormalizeParams) -> FontProperties {
        FontProperties {
            xml_lang: values.xml_lang(),
            unicode_bidi: values.unicode_bidi(),
            direction: values.direction(),
            font_family: values.font_family(),
            font_style: values.font_style(),
            font_variant: values.font_variant(),
            font_weight: values.font_weight(),
            font_stretch: values.font_stretch(),
            font_size: values.font_size().to_user(params),
            letter_spacing: values.letter_spacing().to_user(params),
            text_decoration: values.text_decoration(),
        }
    }
}
<commit_msg>Remove obsolete comment<commit_after>//! Layout tree.
//!
//! The idea is to take the DOM tree and produce a layout tree with SVG concepts.

use std::rc::Rc;
use std::sync::Arc;

use crate::aspect_ratio::AspectRatio;
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::dasharray::Dasharray;
use crate::document::AcquiredNodes;
use crate::element::Element;
use crate::length::*;
use crate::node::*;
use crate::paint_server::{PaintSource, UserSpacePaintSource};
use crate::path_builder::Path;
use crate::properties::{
    ClipRule, ComputedValues, Direction, FillRule, Filter, FontFamily, FontStretch, FontStyle,
    FontVariant, FontWeight, Isolation, MixBlendMode, Opacity, Overflow, PaintOrder,
    ShapeRendering, StrokeDasharray, StrokeLinecap, StrokeLinejoin, StrokeMiterlimit,
    TextDecoration, TextRendering, UnicodeBidi, VectorEffect, XmlLang,
};
use crate::rect::Rect;
use crate::session::Session;
use crate::surface_utils::shared_surface::SharedImageSurface;
use crate::transform::Transform;
use crate::unit_interval::UnitInterval;

/// SVG Stacking context, an inner node in the layout tree.
///
/// <https://www.w3.org/TR/SVG2/render.html#EstablishingStackingContex>
///
/// This is not strictly speaking an SVG2 stacking context, but a
/// looser version of it.  For example. the SVG spec mentions that a
/// an element should establish a stacking context if the `filter`
/// property applies to the element and is not `none`.  In that case,
/// the element is rendered as an "isolated group" -
/// <https://www.w3.org/TR/2015/CR-compositing-1-20150113/#csscompositingrules_SVG>
///
/// Here we store all the parameters that may lead to the decision to actually
/// render an element as an isolated group.
pub struct StackingContext {
    pub element_name: String,
    pub transform: Transform,
    pub opacity: Opacity,
    pub filter: Filter,
    pub clip_in_user_space: Option<Node>,
    pub clip_in_object_space: Option<Node>,
    pub mask: Option<Node>,
    pub mix_blend_mode: MixBlendMode,
    pub isolation: Isolation,

    /// Target from an <a> element
    pub link_target: Option<String>,
}

/// Stroke parameters in user-space coordinates.
pub struct Stroke {
    pub width: f64,
    pub miter_limit: StrokeMiterlimit,
    pub line_cap: StrokeLinecap,
    pub line_join: StrokeLinejoin,
    pub dash_offset: f64,
    pub dashes: Box<[f64]>,
    // https://svgwg.org/svg2-draft/painting.html#non-scaling-stroke
    pub non_scaling: bool,
}

/// Paths and basic shapes resolved to a path.
pub struct Shape {
    pub path: Rc<Path>,
    pub extents: Option<Rect>,
    pub is_visible: bool,
    pub paint_order: PaintOrder,
    pub stroke: Stroke,
    pub stroke_paint: UserSpacePaintSource,
    pub fill_paint: UserSpacePaintSource,
    pub fill_rule: FillRule,
    pub clip_rule: ClipRule,
    pub shape_rendering: ShapeRendering,
    pub marker_start: Marker,
    pub marker_mid: Marker,
    pub marker_end: Marker,
}

pub struct Marker {
    pub node_ref: Option<Node>,
    pub context_stroke: Arc<PaintSource>,
    pub context_fill: Arc<PaintSource>,
}

/// Image in user-space coordinates.
pub struct Image {
    pub surface: SharedImageSurface,
    pub is_visible: bool,
    pub rect: Rect,
    pub aspect: AspectRatio,
    pub overflow: Overflow,
}

/// A single text span in user-space coordinates.
pub struct TextSpan {
    pub layout: pango::Layout,
    pub gravity: pango::Gravity,
    pub bbox: Option<BoundingBox>,
    pub is_visible: bool,
    pub x: f64,
    pub y: f64,
    pub paint_order: PaintOrder,
    pub stroke: Stroke,
    pub stroke_paint: UserSpacePaintSource,
    pub fill_paint: UserSpacePaintSource,
    pub text_rendering: TextRendering,
    pub link_target: Option<String>,
}

/// Fully laid-out text in user-space coordinates.
pub struct Text {
    pub spans: Vec<TextSpan>,
}

/// Font-related properties extracted from `ComputedValues`.
pub struct FontProperties {
    pub xml_lang: XmlLang,
    pub unicode_bidi: UnicodeBidi,
    pub direction: Direction,
    pub font_family: FontFamily,
    pub font_style: FontStyle,
    pub font_variant: FontVariant,
    pub font_weight: FontWeight,
    pub font_stretch: FontStretch,
    pub font_size: f64,
    pub letter_spacing: f64,
    pub text_decoration: TextDecoration,
}

impl StackingContext {
    pub fn new(
        session: &Session,
        acquired_nodes: &mut AcquiredNodes<'_>,
        element: &Element,
        transform: Transform,
        values: &ComputedValues,
    ) -> StackingContext {
        let element_name = format!("{}", element);

        let opacity;
        let filter;

        match *element {
            // "The opacity, filter and display properties do not apply to the mask element"
            // https://drafts.fxtf.org/css-masking-1/#MaskElement
            Element::Mask(_) => {
                opacity = Opacity(UnitInterval::clamp(1.0));
                filter = Filter::None;
            }

            _ => {
                opacity = values.opacity();
                filter = values.filter();
            }
        }

        let clip_path = values.clip_path();
        let clip_uri = clip_path.0.get();
        let (clip_in_user_space, clip_in_object_space) = clip_uri
            .and_then(|node_id| {
                acquired_nodes
                    .acquire(node_id)
                    .ok()
                    .filter(|a| is_element_of_type!(*a.get(), ClipPath))
            })
            .map(|acquired| {
                let clip_node = acquired.get().clone();

                let units = borrow_element_as!(clip_node, ClipPath).get_units();

                match units {
                    CoordUnits::UserSpaceOnUse => (Some(clip_node), None),
                    CoordUnits::ObjectBoundingBox => (None, Some(clip_node)),
                }
            })
            .unwrap_or((None, None));

        let mask = values.mask().0.get().and_then(|mask_id| {
            if let Ok(acquired) = acquired_nodes.acquire(mask_id) {
                let node = acquired.get();
                match *node.borrow_element() {
                    Element::Mask(_) => Some(node.clone()),

                    _ => {
                        rsvg_log!(
                            session,
                            "element {} references \"{}\" which is not a mask",
                            element,
                            mask_id
                        );

                        None
                    }
                }
            } else {
                rsvg_log!(
                    session,
                    "element {} references nonexistent mask \"{}\"",
                    element,
                    mask_id
                );

                None
            }
        });

        let mix_blend_mode = values.mix_blend_mode();
        let isolation = values.isolation();

        StackingContext {
            element_name,
            transform,
            opacity,
            filter,
            clip_in_user_space,
            clip_in_object_space,
            mask,
            mix_blend_mode,
            isolation,
            link_target: None,
        }
    }

    pub fn new_with_link(
        session: &Session,
        acquired_nodes: &mut AcquiredNodes<'_>,
        element: &Element,
        transform: Transform,
        values: &ComputedValues,
        link_target: Option<String>,
    ) -> StackingContext {
        let mut ctx = Self::new(session, acquired_nodes, element, transform, values);
        ctx.link_target = link_target;
        ctx
    }
}

impl Stroke {
    pub fn new(values: &ComputedValues, params: &NormalizeParams) -> Stroke {
        let width = values.stroke_width().0.to_user(params);
        let miter_limit = values.stroke_miterlimit();
        let line_cap = values.stroke_line_cap();
        let line_join = values.stroke_line_join();
        let dash_offset = values.stroke_dashoffset().0.to_user(params);
        let non_scaling = values.vector_effect() == VectorEffect::NonScalingStroke;

        let dashes = match values.stroke_dasharray() {
            StrokeDasharray(Dasharray::None) => Box::new([]),
            StrokeDasharray(Dasharray::Array(dashes)) => dashes
                .iter()
                .map(|l| l.to_user(params))
                .collect::<Box<[f64]>>(),
        };

        Stroke {
            width,
            miter_limit,
            line_cap,
            line_join,
            dash_offset,
            dashes,
            non_scaling,
        }
    }
}

impl FontProperties {
    /// Collects font properties from a `ComputedValues`.
    ///
    /// The `writing-mode` property is passed separately, as it must come from the `<text>` element,
    /// not the `<tspan>` whose computed values are being passed.
    pub fn new(values: &ComputedValues, params: &NormalizeParams) -> FontProperties {
        FontProperties {
            xml_lang: values.xml_lang(),
            unicode_bidi: values.unicode_bidi(),
            direction: values.direction(),
            font_family: values.font_family(),
            font_style: values.font_style(),
            font_variant: values.font_variant(),
            font_weight: values.font_weight(),
            font_stretch: values.font_stretch(),
            font_size: values.font_size().to_user(params),
            letter_spacing: values.letter_spacing().to_user(params),
            text_decoration: values.text_decoration(),
        }
    }
}
<|endoftext|>


<commit_before>/// Return early with an error.
///
/// This macro is equivalent to `return Err(`[`anyhow!($args...)`][anyhow!]`)`.
///
/// The surrounding function's or closure's return value is required to be
/// `Result<_,`[`anyhow::Error`][crate::Error]`>`.
///
/// # Example
///
/// ```
/// # use anyhow::{bail, Result};
/// #
/// # fn has_permission(user: usize, resource: usize) -> bool {
/// #     true
/// # }
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #     let resource = 0;
/// #
/// if !has_permission(user, resource) {
///     bail!("permission denied for accessing {}", resource);
/// }
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{bail, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// if depth > MAX_DEPTH {
///     bail!(ScienceError::RecursionLimitExceeded);
/// }
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! bail {
    ($msg:literal $(,)?) => {
        return $crate::private::Err($crate::anyhow!($msg))
    };
    ($err:expr $(,)?) => {
        return $crate::private::Err($crate::anyhow!($err))
    };
    ($fmt:expr, $($arg:tt)*) => {
        return $crate::private::Err($crate::anyhow!($fmt, $($arg)*))
    };
}

/// Return early with an error if a condition is not satisfied.
///
/// This macro is equivalent to `if !$cond { return
/// Err(`[`anyhow!($args...)`][anyhow!]`); }`.
///
/// The surrounding function's or closure's return value is required to be
/// `Result<_,`[`anyhow::Error`][crate::Error]`>`.
///
/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
/// rather than panicking.
///
/// # Example
///
/// ```
/// # use anyhow::{ensure, Result};
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #
/// ensure!(user == 0, "only user 0 is allowed");
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{ensure, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! ensure {
    ($cond:expr $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::Error::msg(
                $crate::private::concat!("Condition failed: `", $crate::private::stringify!($cond), "`")
            ));
        }
    };
    ($cond:expr, $msg:literal $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($msg));
        }
    };
    ($cond:expr, $err:expr $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($err));
        }
    };
    ($cond:expr, $fmt:expr, $($arg:tt)*) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
        }
    };
}

/// Construct an ad-hoc error from a string or existing non-`anyhow` error
/// value.
///
/// This evaluates to an [`Error`][crate::Error]. It can take either just a
/// string, or a format string with arguments. It also can take any custom type
/// which implements `Debug` and `Display`.
///
/// If called with a single argument whose type implements `std::error::Error`
/// (in addition to `Debug` and `Display`, which are always required), then that
/// Error impl's `source` is preserved as the `source` of the resulting
/// `anyhow::Error`.
///
/// # Example
///
/// ```
/// # type V = ();
/// #
/// use anyhow::{anyhow, Result};
///
/// fn lookup(key: &str) -> Result<V> {
///     if key.len() != 16 {
///         return Err(anyhow!("key length must be 16 characters, got {:?}", key));
///     }
///
///     // ...
///     # Ok(())
/// }
/// ```
#[macro_export]
macro_rules! anyhow {
    ($msg:literal $(,)?) => {
        $crate::private::format_err($msg, $crate::private::format_args!($msg))
    };
    ($err:expr $(,)?) => ({
        use $crate::private::kind::*;
        match $err {
            error => (&error).anyhow_kind().new(error),
        }
    });
    ($fmt:expr, $($arg:tt)*) => {
        $crate::Error::msg($crate::private::format!($fmt, $($arg)*))
    };
}
<commit_msg>Scope format_args temporaries<commit_after>/// Return early with an error.
///
/// This macro is equivalent to `return Err(`[`anyhow!($args...)`][anyhow!]`)`.
///
/// The surrounding function's or closure's return value is required to be
/// `Result<_,`[`anyhow::Error`][crate::Error]`>`.
///
/// # Example
///
/// ```
/// # use anyhow::{bail, Result};
/// #
/// # fn has_permission(user: usize, resource: usize) -> bool {
/// #     true
/// # }
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #     let resource = 0;
/// #
/// if !has_permission(user, resource) {
///     bail!("permission denied for accessing {}", resource);
/// }
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{bail, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// if depth > MAX_DEPTH {
///     bail!(ScienceError::RecursionLimitExceeded);
/// }
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! bail {
    ($msg:literal $(,)?) => {
        return $crate::private::Err($crate::anyhow!($msg))
    };
    ($err:expr $(,)?) => {
        return $crate::private::Err($crate::anyhow!($err))
    };
    ($fmt:expr, $($arg:tt)*) => {
        return $crate::private::Err($crate::anyhow!($fmt, $($arg)*))
    };
}

/// Return early with an error if a condition is not satisfied.
///
/// This macro is equivalent to `if !$cond { return
/// Err(`[`anyhow!($args...)`][anyhow!]`); }`.
///
/// The surrounding function's or closure's return value is required to be
/// `Result<_,`[`anyhow::Error`][crate::Error]`>`.
///
/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
/// rather than panicking.
///
/// # Example
///
/// ```
/// # use anyhow::{ensure, Result};
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #
/// ensure!(user == 0, "only user 0 is allowed");
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{ensure, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! ensure {
    ($cond:expr $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::Error::msg(
                $crate::private::concat!("Condition failed: `", $crate::private::stringify!($cond), "`")
            ));
        }
    };
    ($cond:expr, $msg:literal $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($msg));
        }
    };
    ($cond:expr, $err:expr $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($err));
        }
    };
    ($cond:expr, $fmt:expr, $($arg:tt)*) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
        }
    };
}

/// Construct an ad-hoc error from a string or existing non-`anyhow` error
/// value.
///
/// This evaluates to an [`Error`][crate::Error]. It can take either just a
/// string, or a format string with arguments. It also can take any custom type
/// which implements `Debug` and `Display`.
///
/// If called with a single argument whose type implements `std::error::Error`
/// (in addition to `Debug` and `Display`, which are always required), then that
/// Error impl's `source` is preserved as the `source` of the resulting
/// `anyhow::Error`.
///
/// # Example
///
/// ```
/// # type V = ();
/// #
/// use anyhow::{anyhow, Result};
///
/// fn lookup(key: &str) -> Result<V> {
///     if key.len() != 16 {
///         return Err(anyhow!("key length must be 16 characters, got {:?}", key));
///     }
///
///     // ...
///     # Ok(())
/// }
/// ```
#[macro_export]
macro_rules! anyhow {
    ($msg:literal $(,)?) => ({
        let error = $crate::private::format_err($msg, $crate::private::format_args!($msg));
        error
    });
    ($err:expr $(,)?) => ({
        use $crate::private::kind::*;
        match $err {
            error => (&error).anyhow_kind().new(error),
        }
    });
    ($fmt:expr, $($arg:tt)*) => {
        $crate::Error::msg($crate::private::format!($fmt, $($arg)*))
    };
}
<|endoftext|>


<commit_before>use std::convert;
use std::ops::{Add, Sub};
use std::default::Default;

/// The class of monoids
///
/// The class of monoids (types with an accumulative binary operation that has
/// an identity).
///
/// Technically, `Add<Self, Output=Self>` is standing in for "semigroup" here,
/// while `Default` is standing in for "identity".
///
/// An instance _M_ should satisfy the following laws:
///
///  + _x_`.add(`_M_`::default())` = _x_
///  + _M_`::default().add(`_x_`)` = _x_
///  + _x_`.add(`_y_`.add(`_z_`))` = _z_`.add(`_x_`.add(`_y_`))`
///  + _M_`::accumulate(`_a_`)` = _a_`.fold(`_M_`::default,`_M_`::sum)`
///
pub trait Monoid: Add<Self, Output=Self> + Default + Sized {
    #[inline]
    fn accumulate<F>(xs: F) -> Self
    where F: Iterator<Item=Self>
        , Self: Sized {
        xs.fold(Self::default(), Self::add)
    }
}

pub trait Measured<M: Metric> {
    /// Apply `Metric` to `Self`
    ///
    /// Although we aren't currently enforcing this, `measure`ing a `Node` with
    /// two children should produce the same result as `measure`ing both
    /// children and `Monoid::sum`ming the result. That is to say, `measure`
    /// should be a [_monoid homomorphism_]
    /// (https://en.wikipedia.org/wiki/Monoid#Monoid_homomorphisms).
    fn measure(&self) -> M;

    /// Measure the `weight` of `Node` by this `metric`.
    fn measure_weight(&self) -> M;

    /// Convert the `Metric` into a byte index into the given `Node`
    ///
    /// # Returns
    /// - `Some` with the byte index of the beginning of the `n`th  element
    ///    in `node` measured by this `Metric`, if there is an `n`th element
    /// - `None` if there is no `n`th element in `node`
    fn to_byte_index(&self, index: M) -> Option<usize>;
}

/// A monoid that can be applied to a `Node` as a measurement
pub trait Metric: Monoid + Eq + Add<usize, Output=Self>
                         + Sub<usize, Output=Self>
                         + Sub<Self, Output=Self>
                         + Eq + Ord
                         + Sized {

    fn is_splittable() -> bool;

    /// Returns the byte index of the next element of this metric in `Node`
    #[inline]
    fn next<M: Measured<Self> >(self, node: &M)-> Option<usize> {
        node.to_byte_index(self + 1)
    }

    /// Returns the byte index of the previous element of this metric in `Node`
    #[inline]
    fn back<M: Measured<Self>>(self, node: &M) -> Option<usize> {
        node.to_byte_index(self - 1)
    }

    /// Returns true if index `i` in `node` is a boundary along this `Metric`
    fn is_boundary<M: Measured<Self>>(node: &M, i: usize) -> bool;
}

#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Grapheme(usize);
impl Default for Grapheme {
    #[inline] fn default() -> Self { Grapheme(0) }
}
impl convert::From<usize> for Grapheme {
    #[inline] fn from(u: usize) -> Self { Grapheme(u) }
}
impl convert::Into<usize> for Grapheme {
    #[inline] fn into(self) -> usize { self.0 }
}
impl Add<usize> for Grapheme {
    type Output = Self;
    #[inline] fn add(self, rhs: usize) -> Self { Grapheme(self.0 + rhs) }
}
impl Add<Grapheme> for Grapheme {
    type Output = Self;
    #[inline] fn add(self, rhs: Self) -> Self { Grapheme(self.0 + rhs.0) }
}
impl Monoid for Grapheme { }
impl Sub<usize> for Grapheme {
    type Output = Self;
    #[inline] fn sub(self, rhs: usize) -> Self { Grapheme(self.0 - rhs) }
}
impl Sub<Grapheme> for Grapheme {
    type Output = Self;
    #[inline] fn sub(self, rhs: Self) -> Self { Grapheme(self.0 - rhs.0) }
}

#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Line(usize);
impl Default for Line {
    #[inline] fn default() -> Self { Line(0) }
}
impl Add<Line> for Line {
    type Output = Self;
    #[inline] fn add(self, rhs: Self) -> Self { Line(self.0 + rhs.0) }
}
impl Sub<Line> for Line {
    type Output = Self;
    #[inline] fn sub(self, rhs: Self) -> Self { Line(self.0 - rhs.0) }
}
impl convert::From<usize> for Line {
    #[inline] fn from(u: usize) -> Self { Line(u) }
}
impl convert::Into<usize> for Line {
    #[inline] fn into(self) -> usize { self.0 }
}
impl Monoid for Line { }
impl Add<usize> for Line {
    type Output = Self;
    #[inline] fn add(self, rhs: usize) -> Self { Line(self.0 + rhs) }
}
impl Sub<usize> for Line {
    type Output = Self;
    #[inline] fn sub(self, rhs: usize) -> Self { Line(self.0 - rhs) }
}
<commit_msg>feat(Rope): add char metric<commit_after>use std::convert;
use std::ops::{Add, Sub};
use std::default::Default;

/// The class of monoids
///
/// The class of monoids (types with an accumulative binary operation that has
/// an identity).
///
/// Technically, `Add<Self, Output=Self>` is standing in for "semigroup" here,
/// while `Default` is standing in for "identity".
///
/// An instance _M_ should satisfy the following laws:
///
///  + _x_`.add(`_M_`::default())` = _x_
///  + _M_`::default().add(`_x_`)` = _x_
///  + _x_`.add(`_y_`.add(`_z_`))` = _z_`.add(`_x_`.add(`_y_`))`
///  + _M_`::accumulate(`_a_`)` = _a_`.fold(`_M_`::default,`_M_`::sum)`
///
pub trait Monoid: Add<Self, Output=Self> + Default + Sized {
    #[inline]
    fn accumulate<F>(xs: F) -> Self
    where F: Iterator<Item=Self>
        , Self: Sized {
        xs.fold(Self::default(), Self::add)
    }
}

pub trait Measured<M: Metric> {
    /// Apply `Metric` to `Self`
    ///
    /// Although we aren't currently enforcing this, `measure`ing a `Node` with
    /// two children should produce the same result as `measure`ing both
    /// children and `Monoid::sum`ming the result. That is to say, `measure`
    /// should be a [_monoid homomorphism_]
    /// (https://en.wikipedia.org/wiki/Monoid#Monoid_homomorphisms).
    fn measure(&self) -> M;

    /// Measure the `weight` of `Node` by this `metric`.
    fn measure_weight(&self) -> M;

    /// Convert the `Metric` into a byte index into the given `Node`
    ///
    /// # Returns
    /// - `Some` with the byte index of the beginning of the `n`th  element
    ///    in `node` measured by this `Metric`, if there is an `n`th element
    /// - `None` if there is no `n`th element in `node`
    fn to_byte_index(&self, index: M) -> Option<usize>;
}

/// A monoid that can be applied to a `Node` as a measurement
pub trait Metric: Monoid + Eq + Add<usize, Output=Self>
                         + Sub<usize, Output=Self>
                         + Sub<Self, Output=Self>
                         + Eq + Ord
                         + Sized {

    fn is_splittable() -> bool;

    /// Returns the byte index of the next element of this metric in `Node`
    #[inline]
    fn next<M: Measured<Self> >(self, node: &M)-> Option<usize> {
        node.to_byte_index(self + 1)
    }

    /// Returns the byte index of the previous element of this metric in `Node`
    #[inline]
    fn back<M: Measured<Self>>(self, node: &M) -> Option<usize> {
        node.to_byte_index(self - 1)
    }

    /// Returns true if index `i` in `node` is a boundary along this `Metric`
    fn is_boundary<M: Measured<Self>>(node: &M, i: usize) -> bool;
}

#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Grapheme(usize);
impl Default for Grapheme {
    #[inline] fn default() -> Self { Grapheme(0) }
}
impl convert::From<usize> for Grapheme {
    #[inline] fn from(u: usize) -> Self { Grapheme(u) }
}
impl convert::Into<usize> for Grapheme {
    #[inline] fn into(self) -> usize { self.0 }
}
impl Add<usize> for Grapheme {
    type Output = Self;
    #[inline] fn add(self, rhs: usize) -> Self { Grapheme(self.0 + rhs) }
}
impl Add<Grapheme> for Grapheme {
    type Output = Self;
    #[inline] fn add(self, rhs: Self) -> Self { Grapheme(self.0 + rhs.0) }
}
impl Monoid for Grapheme { }
impl Sub<usize> for Grapheme {
    type Output = Self;
    #[inline] fn sub(self, rhs: usize) -> Self { Grapheme(self.0 - rhs) }
}
impl Sub<Grapheme> for Grapheme {
    type Output = Self;
    #[inline] fn sub(self, rhs: Self) -> Self { Grapheme(self.0 - rhs.0) }
}

#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Line(usize);
impl Default for Line {
    #[inline] fn default() -> Self { Line(0) }
}
impl Add<Line> for Line {
    type Output = Self;
    #[inline] fn add(self, rhs: Self) -> Self { Line(self.0 + rhs.0) }
}
impl Sub<Line> for Line {
    type Output = Self;
    #[inline] fn sub(self, rhs: Self) -> Self { Line(self.0 - rhs.0) }
}
impl convert::From<usize> for Line {
    #[inline] fn from(u: usize) -> Self { Line(u) }
}
impl convert::Into<usize> for Line {
    #[inline] fn into(self) -> usize { self.0 }
}
impl Monoid for Line { }
impl Add<usize> for Line {
    type Output = Self;
    #[inline] fn add(self, rhs: usize) -> Self { Line(self.0 + rhs) }
}
impl Sub<usize> for Line {
    type Output = Self;
    #[inline] fn sub(self, rhs: usize) -> Self { Line(self.0 - rhs) }
}

#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Char(usize);
impl Default for Char {
    #[inline] fn default() -> Self { Char(0) }
}
impl Add<Char> for Char {
    type Output = Self;
    #[inline] fn add(self, rhs: Self) -> Self { Char(self.0 + rhs.0) }
}
impl Sub<Char> for Char {
    type Output = Self;
    #[inline] fn sub(self, rhs: Self) -> Self { Char(self.0 - rhs.0) }
}
impl convert::From<usize> for Char {
    #[inline] fn from(u: usize) -> Self { Char(u) }
}
impl convert::Into<usize> for Char {
    #[inline] fn into(self) -> usize { self.0 }
}
impl Monoid for Char { }
impl Add<usize> for Char {
    type Output = Self;
    #[inline] fn add(self, rhs: usize) -> Self { Char(self.0 + rhs) }
}
impl Sub<usize> for Char {
    type Output = Self;
    #[inline] fn sub(self, rhs: usize) -> Self { Char(self.0 - rhs) }
}
<|endoftext|>


<commit_before>use std::convert;
use std::ops::{Add, Sub};
use std::default::Default;
use internals::{Node, BranchNode};

/// The class of monoids
///
/// The class of monoids (types with an accumulative binary operation that has
/// an identity).
///
/// Technically, `Add<Self, Output=Self>` is standing in for "semigroup" here,
/// while `Default` is standing in for "identity".
///
/// An instance _M_ should satisfy the following laws:
///
///  + _x_`.add(`_M_`::default())` = _x_
///  + _M_`::default().add(`_x_`)` = _x_
///  + _x_`.add(`_y_`.add(`_z_`))` = _z_`.add(`_x_`.add(`_y_`))`
///  + _M_`::accumulate(`_a_`)` = _a_`.fold(`_M_`::default,`_M_`::sum)`
///
pub trait Monoid: Add<Self, Output=Self> + Default + Sized {
    #[inline]
    fn accumulate<F>(xs: F) -> Self
    where F: Iterator<Item=Self>
        , Self: Sized {
        xs.fold(Self::default(), Self::add)
    }
}

pub trait Measured<M: Metric> {
    /// Apply `Metric` to `Self`
    ///
    /// Although we aren't currently enforcing this, `measure`ing a `Node` with
    /// two children should produce the same result as `measure`ing both
    /// children and `Monoid::sum`ming the result. That is to say, `measure`
    /// should be a [_monoid homomorphism_]
    /// (https://en.wikipedia.org/wiki/Monoid#Monoid_homomorphisms).
    fn measure(&self) -> M;

    /// Measure the `weight` of `Node` by this `metric`.
    fn measure_weight(&self) -> M;

    /// Convert the `Metric` into a byte index into the given `Node`
    ///
    /// # Returns
    /// - `Some` with the byte index of the beginning of the `n`th  element
    ///    in `node` measured by this `Metric`, if there is an `n`th element
    /// - `None` if there is no `n`th element in `node`
    fn to_byte_index(&self, index: M) -> Option<usize>;
}

/// A monoid that can be applied to a `Node` as a measurement
pub trait Metric: Monoid + Eq + Add<usize, Output=Self>
                         + Sub<usize, Output=Self>
                         + Sub<Self, Output=Self>
                         + Eq + Ord
                         + Sized {

    fn is_splittable() -> bool;

    /// Returns the byte index of the next element of this metric in `Node`
    #[inline]
    fn next<M: Measured<Self> >(self, node: &M)-> Option<usize> {
        node.to_byte_index(self + 1)
    }

    /// Returns the byte index of the previous element of this metric in `Node`
    #[inline]
    fn back<M: Measured<Self>>(self, node: &M) -> Option<usize> {
        node.to_byte_index(self - 1)
    }

    /// Returns true if index `i` in `node` is a boundary along this `Metric`
    fn is_boundary<M: Measured<Self>>(node: &M, i: usize) -> bool;
}

#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Grapheme(usize);
impl Default for Grapheme {
    #[inline] fn default() -> Self { Grapheme(0) }
}
impl convert::From<usize> for Grapheme {
    #[inline] fn from(u: usize) -> Self { Grapheme(u) }
}
impl convert::Into<usize> for Grapheme {
    #[inline] fn into(self) -> usize { self.0 }
}
impl Add<usize> for Grapheme {
    type Output = Self;
    #[inline] fn add(self, rhs: usize) -> Self { Grapheme(self.0 + rhs) }
}
impl Add<Grapheme> for Grapheme {
    type Output = Self;
    #[inline] fn add(self, rhs: Self) -> Self { Grapheme(self.0 + rhs.0) }
}
impl Monoid for Grapheme { }
impl Sub<usize> for Grapheme {
    type Output = Self;
    #[inline] fn sub(self, rhs: usize) -> Self { Grapheme(self.0 - rhs) }
}
impl Sub<Grapheme> for Grapheme {
    type Output = Self;
    #[inline] fn sub(self, rhs: Self) -> Self { Grapheme(self.0 - rhs.0) }
}

#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Line(usize);
impl Default for Line {
    #[inline] fn default() -> Self { Line(0) }
}
impl Add<Line> for Line {
    type Output = Self;
    #[inline] fn add(self, rhs: Self) -> Self { Line(self.0 + rhs.0) }
}
impl Sub<Line> for Line {
    type Output = Self;
    #[inline] fn sub(self, rhs: Self) -> Self { Line(self.0 - rhs.0) }
}
impl convert::From<usize> for Line {
    #[inline] fn from(u: usize) -> Self { Line(u) }
}
impl convert::Into<usize> for Line {
    #[inline] fn into(self) -> usize { self.0 }
}
impl Monoid for Line { }
impl Add<usize> for Line {
    type Output = Self;
    #[inline] fn add(self, rhs: usize) -> Self { Line(self.0 + rhs) }
}
impl Sub<usize> for Line {
    type Output = Self;
    #[inline] fn sub(self, rhs: usize) -> Self { Line(self.0 - rhs) }
}
<commit_msg>refactor(rope metrics): remove unused imports<commit_after>use std::convert;
use std::ops::{Add, Sub};
use std::default::Default;

/// The class of monoids
///
/// The class of monoids (types with an accumulative binary operation that has
/// an identity).
///
/// Technically, `Add<Self, Output=Self>` is standing in for "semigroup" here,
/// while `Default` is standing in for "identity".
///
/// An instance _M_ should satisfy the following laws:
///
///  + _x_`.add(`_M_`::default())` = _x_
///  + _M_`::default().add(`_x_`)` = _x_
///  + _x_`.add(`_y_`.add(`_z_`))` = _z_`.add(`_x_`.add(`_y_`))`
///  + _M_`::accumulate(`_a_`)` = _a_`.fold(`_M_`::default,`_M_`::sum)`
///
pub trait Monoid: Add<Self, Output=Self> + Default + Sized {
    #[inline]
    fn accumulate<F>(xs: F) -> Self
    where F: Iterator<Item=Self>
        , Self: Sized {
        xs.fold(Self::default(), Self::add)
    }
}

pub trait Measured<M: Metric> {
    /// Apply `Metric` to `Self`
    ///
    /// Although we aren't currently enforcing this, `measure`ing a `Node` with
    /// two children should produce the same result as `measure`ing both
    /// children and `Monoid::sum`ming the result. That is to say, `measure`
    /// should be a [_monoid homomorphism_]
    /// (https://en.wikipedia.org/wiki/Monoid#Monoid_homomorphisms).
    fn measure(&self) -> M;

    /// Measure the `weight` of `Node` by this `metric`.
    fn measure_weight(&self) -> M;

    /// Convert the `Metric` into a byte index into the given `Node`
    ///
    /// # Returns
    /// - `Some` with the byte index of the beginning of the `n`th  element
    ///    in `node` measured by this `Metric`, if there is an `n`th element
    /// - `None` if there is no `n`th element in `node`
    fn to_byte_index(&self, index: M) -> Option<usize>;
}

/// A monoid that can be applied to a `Node` as a measurement
pub trait Metric: Monoid + Eq + Add<usize, Output=Self>
                         + Sub<usize, Output=Self>
                         + Sub<Self, Output=Self>
                         + Eq + Ord
                         + Sized {

    fn is_splittable() -> bool;

    /// Returns the byte index of the next element of this metric in `Node`
    #[inline]
    fn next<M: Measured<Self> >(self, node: &M)-> Option<usize> {
        node.to_byte_index(self + 1)
    }

    /// Returns the byte index of the previous element of this metric in `Node`
    #[inline]
    fn back<M: Measured<Self>>(self, node: &M) -> Option<usize> {
        node.to_byte_index(self - 1)
    }

    /// Returns true if index `i` in `node` is a boundary along this `Metric`
    fn is_boundary<M: Measured<Self>>(node: &M, i: usize) -> bool;
}

#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Grapheme(usize);
impl Default for Grapheme {
    #[inline] fn default() -> Self { Grapheme(0) }
}
impl convert::From<usize> for Grapheme {
    #[inline] fn from(u: usize) -> Self { Grapheme(u) }
}
impl convert::Into<usize> for Grapheme {
    #[inline] fn into(self) -> usize { self.0 }
}
impl Add<usize> for Grapheme {
    type Output = Self;
    #[inline] fn add(self, rhs: usize) -> Self { Grapheme(self.0 + rhs) }
}
impl Add<Grapheme> for Grapheme {
    type Output = Self;
    #[inline] fn add(self, rhs: Self) -> Self { Grapheme(self.0 + rhs.0) }
}
impl Monoid for Grapheme { }
impl Sub<usize> for Grapheme {
    type Output = Self;
    #[inline] fn sub(self, rhs: usize) -> Self { Grapheme(self.0 - rhs) }
}
impl Sub<Grapheme> for Grapheme {
    type Output = Self;
    #[inline] fn sub(self, rhs: Self) -> Self { Grapheme(self.0 - rhs.0) }
}

#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Line(usize);
impl Default for Line {
    #[inline] fn default() -> Self { Line(0) }
}
impl Add<Line> for Line {
    type Output = Self;
    #[inline] fn add(self, rhs: Self) -> Self { Line(self.0 + rhs.0) }
}
impl Sub<Line> for Line {
    type Output = Self;
    #[inline] fn sub(self, rhs: Self) -> Self { Line(self.0 - rhs.0) }
}
impl convert::From<usize> for Line {
    #[inline] fn from(u: usize) -> Self { Line(u) }
}
impl convert::Into<usize> for Line {
    #[inline] fn into(self) -> usize { self.0 }
}
impl Monoid for Line { }
impl Add<usize> for Line {
    type Output = Self;
    #[inline] fn add(self, rhs: usize) -> Self { Line(self.0 + rhs) }
}
impl Sub<usize> for Line {
    type Output = Self;
    #[inline] fn sub(self, rhs: usize) -> Self { Line(self.0 - rhs) }
}
<|endoftext|>


<commit_before>//! An "hello world" echo server with tokio-core
//!
//! This server will create a TCP listener, accept connections in a loop, and
//! simply write back everything that's read off of each TCP connection. Each
//! TCP connection is processed concurrently with all other TCP connections, and
//! each connection will have its own buffer that it's reading in/out of.
//!
//! To see this server in action, you can run this in one terminal:
//!
//!     cargo run --example echo
//!
//! and in another terminal you can run:
//!
//!     cargo run --example connect 127.0.0.1:8080
//!
//! Each line you type in to the `connect` terminal should be echo'd back to
//! you! If you open up multiple terminals running the `connect` example you
//! should be able to see them all make progress simultaneously.

extern crate futures;
extern crate tokio_core;

use std::env;
use std::net::SocketAddr;

use futures::Future;
use futures::stream::Stream;
use tokio_core::io::{copy, Io};
use tokio_core::net::TcpListener;
use tokio_core::reactor::Core;

fn main() {
    // Allow passing an address to listen on as the first argument of this
    // program, but otherwise we'll just set up our TCP listener on
    // 127.0.0.1:8080 for connections.
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:1337".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    // First up we'll create the event loop that's going to drive this server.
    // This is done by creating an instance of the `Core` type, tokio-core's
    // event loop. Most functions in tokio-core return an `io::Result`, and
    // `Core::new` is no exception. For this example, though, we're mostly just
    // ignoring errors, so we unwrap the return value.
    //
    // After the event loop is created we acquire a handle to it through the
    // `handle` method. With this handle we'll then later be able to create I/O
    // objects and spawn futures.
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    // Next up we create a TCP listener which will listen for incoming
    // connections. This TCP listener is bound to the address we determined
    // above and must be associated with an event loop, so we pass in a handle
    // to our event loop. After the socket's created we inform that we're ready
    // to go and start accepting connections.
    let socket = TcpListener::bind(&addr, &handle).unwrap();
    println!("Listening on: {}", addr);

    // Here we convert the `TcpListener` to a stream of incoming connections
    // with the `incoming` method. We then define how to process each element in
    // the stream with the `for_each` method.
    //
    // This combinator, defined on the `Stream` trait, will allow us to define a
    // computation to happen for all items on the stream (in this case TCP
    // connections made to the server).  The return value of the `for_each`
    // method is itself a future representing processing the entire stream of
    // connections, and ends up being our server.
    let done = socket.incoming().for_each(move |(socket, addr)| {

        // Once we're inside this closure this represents an accepted client
        // from our server. The `socket` is the client connection and `addr` is
        // the remote address of the client (similar to how the standard library
        // operates).
        //
        // We just want to copy all data read from the socket back onto the
        // socket itself (e.g. "echo"). We can use the standard `io::copy`
        // combinator in the `tokio-core` crate to do precisely this!
        //
        // The `copy` function takes two arguments, where to read from and where
        // to write to. We only have one argument, though, with `socket`.
        // Luckily there's a method, `Io::split`, which will split an Read/Write
        // stream into its two halves. This operation allows us to work with
        // each stream independently, such as pass them as two arguments to the
        // `copy` function.
        //
        // The `copy` function then returns a future, and this future will be
        // resolved when the copying operation is complete, resolving to the
        // amount of data that was copied.
        let (reader, writer) = socket.split();
        let amt = copy(reader, writer);

        // After our copy operation is complete we just print out some helpful
        // information.
        let msg = amt.then(move |result| {
            match result {
                Ok(amt) => println!("wrote {} bytes to {}", amt, addr),
                Err(e) => println!("error on {}: {}", addr, e),
            }

            Ok(())
        });

        // And this is where much of the magic of this server happens. We
        // crucially want all clients to make progress concurrently, rather than
        // blocking one on completion of another. To achieve this we use the
        // `spawn` function on `Handle` to essentially execute some work in the
        // background.
        //
        // This function will transfer ownership of the future (`msg` in this
        // case) to the event loop that `handle` points to. The event loop will
        // then drive the future to completion.
        //
        // Essentially here we're spawning a new task to run concurrently, which
        // will allow all of our clients to be processed concurrently.
        handle.spawn(msg);

        Ok(())
    });

    // And finally now that we've define what our server is, we run it! We
    // didn't actually do much I/O up to this point and this `Core::run` method
    // is responsible for driving the entire server to completion.
    //
    // The `run` method will return the result of the future that it's running,
    // but in our case the `done` future won't ever finish because a TCP
    // listener is never done accepting clients. That basically just means that
    // we're going to be running the server until it's killed (e.g. ctrl-c).
    core.run(done).unwrap();
}
<commit_msg>tried using refcell<commit_after>//! An "hello world" echo server with tokio-core
//!
//! This server will create a TCP listener, accept connections in a loop, and
//! simply write back everything that's read off of each TCP connection. Each
//! TCP connection is processed concurrently with all other TCP connections, and
//! each connection will have its own buffer that it's reading in/out of.
//!
//! To see this server in action, you can run this in one terminal:
//!
//!     cargo run --example echo
//!
//! and in another terminal you can run:
//!
//!     cargo run --example connect 127.0.0.1:8080
//!
//! Each line you type in to the `connect` terminal should be echo'd back to
//! you! If you open up multiple terminals running the `connect` example you
//! should be able to see them all make progress simultaneously.

extern crate futures;
extern crate tokio_core;

use std::env;
use std::net::SocketAddr;

use futures::Future;
use futures::stream::Stream;
use tokio_core::io::{copy, Io};
use tokio_core::net::TcpListener;
use tokio_core::reactor::Core;
use std::cell::RefCell;

type ConnectionList = RefCell<Vec<tokio_core::io::WriteHalf<tokio_core::net::TcpStream>>>;

fn main() {
    // Allow passing an address to listen on as the first argument of this
    // program, but otherwise we'll just set up our TCP listener on
    // 127.0.0.1:8080 for connections.
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:1337".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    let connection_list : ConnectionList = RefCell::new(vec![]);
    // First up we'll create the event loop that's going to drive this server.
    // This is done by creating an instance of the `Core` type, tokio-core's
    // event loop. Most functions in tokio-core return an `io::Result`, and
    // `Core::new` is no exception. For this example, though, we're mostly just
    // ignoring errors, so we unwrap the return value.
    //
    // After the event loop is created we acquire a handle to it through the
    // `handle` method. With this handle we'll then later be able to create I/O
    // objects and spawn futures.
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    // Next up we create a TCP listener which will listen for incoming
    // connections. This TCP listener is bound to the address we determined
    // above and must be associated with an event loop, so we pass in a handle
    // to our event loop. After the socket's created we inform that we're ready
    // to go and start accepting connections.
    let socket = TcpListener::bind(&addr, &handle).unwrap();
    println!("Listening on: {}", addr);

    // Here we convert the `TcpListener` to a stream of incoming connections
    // with the `incoming` method. We then define how to process each element in
    // the stream with the `for_each` method.
    //
    // This combinator, defined on the `Stream` trait, will allow us to define a
    // computation to happen for all items on the stream (in this case TCP
    // connections made to the server).  The return value of the `for_each`
    // method is itself a future representing processing the entire stream of
    // connections, and ends up being our server.
    let done = socket.incoming().for_each(move |(socket, addr)| {

        // Once we're inside this closure this represents an accepted client
        // from our server. The `socket` is the client connection and `addr` is
        // the remote address of the client (similar to how the standard library
        // operates).
        //
        // We just want to copy all data read from the socket back onto the
        // socket itself (e.g. "echo"). We can use the standard `io::copy`
        // combinator in the `tokio-core` crate to do precisely this!
        //
        // The `copy` function takes two arguments, where to read from and where
        // to write to. We only have one argument, though, with `socket`.
        // Luckily there's a method, `Io::split`, which will split an Read/Write
        // stream into its two halves. This operation allows us to work with
        // each stream independently, such as pass them as two arguments to the
        // `copy` function.
        //
        // The `copy` function then returns a future, and this future will be
        // resolved when the copying operation is complete, resolving to the
        // amount of data that was copied.
        let (reader, writer) = socket.split();

        connection_list.borrow_mut().push(writer);

        //let amt = coq(reader, writer);

        // After our copy operation is complete we just print out some helpful
        // information.
        let msg = amt.then(move |result| {
            match result {
                Ok(amt) => println!("wrote {} bytes to {}", amt, addr),
                Err(e) => println!("error on {}: {}", addr, e),
            }

            Ok(())
        });

        // And this is where much of the magic of this server happens. We
        // crucially want all clients to make progress concurrently, rather than
        // blocking one on completion of another. To achieve this we use the
        // `spawn` function on `Handle` to essentially execute some work in the
        // background.
        //
        // This function will transfer ownership of the future (`msg` in this
        // case) to the event loop that `handle` points to. The event loop will
        // then drive the future to completion.
        //
        // Essentially here we're spawning a new task to run concurrently, which
        // will allow all of our clients to be processed concurrently.
        handle.spawn(msg);

        Ok(())
    });

    // And finally now that we've define what our server is, we run it! We
    // didn't actually do much I/O up to this point and this `Core::run` method
    // is responsible for driving the entire server to completion.
    //
    // The `run` method will return the result of the future that it's running,
    // but in our case the `done` future won't ever finish because a TCP
    // listener is never done accepting clients. That basically just means that
    // we're going to be running the server until it's killed (e.g. ctrl-c).
    core.run(done).unwrap();
}
<|endoftext|>


<commit_before>extern crate yaml_rust;
extern crate tis_100_superoptimizer;

use std::env;
use std::fs::File;
use std::io::Read;
use yaml_rust::YamlLoader;

use tis_100_superoptimizer::TIS_100::Node;
use tis_100_superoptimizer::TIS_100::Ports::Port;
use tis_100_superoptimizer::optimizer::{Config, optimize};

fn to_vec(yaml_doc: Option<&Vec<yaml_rust::Yaml>>) -> Vec<i32> {
    let mut result: Vec<i32> = vec![];
    for value in yaml_doc.unwrap() {
        result.push(value.as_i64().unwrap() as i32);
    }
    result
}

fn main() {
    let arguments: Vec<String> = env::args().collect();
    if arguments.len() != 2 {
        println!("provide a file to optimize");
        return;
    }

    let mut data = String::new();
    let mut f = File::open(&arguments[1]).unwrap();
    f.read_to_string(&mut data).unwrap();

    let docs = YamlLoader::load_from_str(&data[..]).unwrap();
    let doc = &docs[0];

    let node: Node = Node::new().set_up(Port::new(to_vec(doc["input"].as_vec())));
    let expected_output: Vec<i32> = to_vec(doc["output"].as_vec());
    let config: Config = Config::new(10, 3);

    match optimize(node, expected_output, config) {
        Some(program) => println!("{:?}", program),
        _ => println!("Could not find a program within the bounds"),
    }
}
<commit_msg>Use config from yaml<commit_after>extern crate yaml_rust;
extern crate tis_100_superoptimizer;

use std::env;
use std::fs::File;
use std::io::Read;
use yaml_rust::YamlLoader;

use tis_100_superoptimizer::TIS_100::Node;
use tis_100_superoptimizer::TIS_100::Ports::Port;
use tis_100_superoptimizer::optimizer::{Config, optimize};

fn to_vec(yaml_doc: Option<&Vec<yaml_rust::Yaml>>) -> Vec<i32> {
    let mut result: Vec<i32> = vec![];
    for value in yaml_doc.unwrap() {
        result.push(value.as_i64().unwrap() as i32);
    }
    result
}

fn main() {
    let arguments: Vec<String> = env::args().collect();
    if arguments.len() != 2 {
        println!("provide a file to optimize");
        return;
    }

    let mut data = String::new();
    let mut f = File::open(&arguments[1]).unwrap();
    f.read_to_string(&mut data).unwrap();

    let docs = YamlLoader::load_from_str(&data[..]).unwrap();
    let doc = &docs[0];

    let node: Node = Node::new().set_up(Port::new(to_vec(doc["input"].as_vec())));
    let expected_output: Vec<i32> = to_vec(doc["output"].as_vec());
    let config: Config = Config::new(
        doc["maximum_cycle"].as_i64().unwrap() as u32,
        doc["maximum_program_length"].as_i64().unwrap() as usize);

    match optimize(node, expected_output, config) {
        Some(program) => println!("{:?}", program),
        _ => println!("Could not find a program within the bounds"),
    }
}
<|endoftext|>