<commit_before>//! Synchronization primitives for Vulkan objects.
//!
//! In Vulkan, you have to manually ensure two things:
//!
//! - That a buffer or an image are not read and written simultaneously (similarly to the CPU).
//! - That writes to a buffer or an image are propagated to other queues by inserting memory
//!   barriers.
//!
//! But don't worry ; this is automatically enforced by this library (as long as you don't use
//! any unsafe function). See the `memory` module for more info.
//!
use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;

use device::Device;
use device::Queue;
use OomError;
use Success;
use SynchronizedVulkanObject;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Base trait for objects that can be used as resources and must be synchronized.
pub unsafe trait Resource {
    /// Returns in which queue family or families this resource can be used.
    fn sharing_mode(&self) -> &SharingMode;

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

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

/// Declares in which queue(s) a resource can be used.
///
/// When you create a buffer or an image, you have to tell the Vulkan library in which queue
/// families it will be used. The vulkano library requires you to tell in which queue famiily
/// the resource will be used, even for exclusive mode.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SharingMode {
    /// The resource is used is only one queue family.
    Exclusive(u32),
    /// The resource is used in multiple queue families. Can be slower than `Exclusive`.
    Concurrent(Vec<u32>),       // TODO: Vec is too expensive here
}

impl<'a> From<&'a Arc<Queue>> for SharingMode {
    #[inline]
    fn from(queue: &'a Arc<Queue>) -> SharingMode {
        SharingMode::Exclusive(queue.family().id())
    }
}

impl<'a> From<&'a [&'a Arc<Queue>]> for SharingMode {
    #[inline]
    fn from(queues: &'a [&'a Arc<Queue>]) -> SharingMode {
        SharingMode::Concurrent(queues.iter().map(|queue| {
            queue.family().id()
        }).collect())
    }
}

/// A fence is used to know when a command buffer submission has finished its execution.
///
/// When a command buffer accesses a ressource, you have to ensure that the CPU doesn't access
/// the same ressource simultaneously (except for concurrent reads). Therefore in order to know
/// when the CPU can access a ressource again, a fence has to be used.
pub struct Fence {
    device: Arc<Device>,
    fence: vk::Fence,
}

impl Fence {
    /// Builds a new fence.
    #[inline]
    pub fn new(device: &Arc<Device>) -> Result<Arc<Fence>, OomError> {
        Fence::new_impl(device, false)
    }

    /// Builds a new fence already in the "signaled" state.
    #[inline]
    pub fn signaled(device: &Arc<Device>) -> Result<Arc<Fence>, OomError> {
        Fence::new_impl(device, true)
    }

    fn new_impl(device: &Arc<Device>, signaled: bool) -> Result<Arc<Fence>, OomError> {
        let vk = device.pointers();

        let fence = unsafe {
            let infos = vk::FenceCreateInfo {
                sType: vk::STRUCTURE_TYPE_FENCE_CREATE_INFO,
                pNext: ptr::null(),
                flags: if signaled { vk::FENCE_CREATE_SIGNALED_BIT } else { 0 },
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateFence(device.internal_object(), &infos, ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(Fence {
            device: device.clone(),
            fence: fence,
        }))
    }

    /// Returns true if the fence is signaled.
    #[inline]
    pub fn ready(&self) -> Result<bool, OomError> {
        unsafe {
            let vk = self.device.pointers();
            let result = try!(check_errors(vk.GetFenceStatus(self.device.internal_object(),
                                                             self.fence)));
            match result {
                Success::Success => Ok(true),
                Success::NotReady => Ok(false),
                _ => unreachable!()
            }
        }
    }

    /// Waits until the fence is signaled, or at least until the number of nanoseconds of the
    /// timeout has elapsed.
    ///
    /// Returns `Ok` if the fence is now signaled. Returns `Err` if the timeout was reached instead.
    pub fn wait(&self, timeout_ns: u64) -> Result<(), OomError> {       // FIXME: wrong error
        unsafe {
            let vk = self.device.pointers();
            let r = try!(check_errors(vk.WaitForFences(self.device.internal_object(), 1,
                                                       &self.fence, vk::TRUE, timeout_ns)));

            match r {
                Success::Success => Ok(()),
                Success::Timeout => panic!(),        // FIXME:
                _ => unreachable!()
            }
        }
    }

    /// Resets the fence.
    // FIXME: must synchronize the fence
    #[inline]
    pub fn reset(&self) {
        unsafe {
            let vk = self.device.pointers();
            vk.ResetFences(self.device.internal_object(), 1, &self.fence);
        }
    }

    /// Resets multiple fences at once.
    ///
    /// # Panic
    ///
    /// Panicks if not all fences belong to the same device.
    pub fn multi_reset<'a, I>(iter: I)
        where I: IntoIterator<Item = &'a Fence>
    {
        let mut device = None;

        // TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
        let fences: Vec<vk::Fence> = iter.into_iter().map(|fence| {
            match &mut device {
                dev @ &mut None => *dev = Some(fence.device.clone()),
                &mut Some(ref dev) if &**dev as *const Device == &*fence.device as *const Device => {},
                _ => panic!("Tried to reset multiple fences that didn't belong to the same device"),
            };

            fence.fence
        }).collect();

        if let Some(device) = device {
            unsafe {
                let vk = device.pointers();
                vk.ResetFences(device.internal_object(), fences.len() as u32, fences.as_ptr());
            }
        }
    }
}

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

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

impl Drop for Fence {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyFence(self.device.internal_object(), self.fence, ptr::null());
        }
    }
}

/// Used to provide synchronization between command buffers during their execution.
///
/// It is similar to a fence, except that it is purely on the GPU side. The CPU can't query a
/// semaphore's status or wait for it to be signaled.
pub struct Semaphore {
    device: Arc<Device>,
    semaphore: vk::Semaphore,
}

impl Semaphore {
    /// Builds a new semaphore.
    #[inline]
    pub fn new(device: &Arc<Device>) -> Result<Arc<Semaphore>, OomError> {
        let vk = device.pointers();

        let semaphore = unsafe {
            // since the creation is constant, we use a `static` instead of a struct on the stack
            static mut INFOS: vk::SemaphoreCreateInfo = vk::SemaphoreCreateInfo {
                sType: vk::STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
                pNext: 0 as *const _,   // ptr::null()
                flags: 0,   // reserved
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateSemaphore(device.internal_object(), &INFOS,
                                                 ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(Semaphore {
            device: device.clone(),
            semaphore: semaphore,
        }))
    }
}

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

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

impl Drop for Semaphore {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroySemaphore(self.device.internal_object(), self.semaphore, ptr::null());
        }
    }
}

/// Used to block the GPU execution until an event on the CPU occurs.
///
/// Note that Vulkan implementations may have limits on how long a command buffer will wait for an
/// event to be signaled, in order to avoid interfering with progress of other clients of the GPU.
/// If the event isn't signaled within these limits, results are undefined and may include
/// device loss.
pub struct Event {
    device: Arc<Device>,
    event: Mutex<vk::Event>,
}

impl Event {
    /// Builds a new event.
    #[inline]
    pub fn new(device: &Arc<Device>) -> Result<Arc<Event>, OomError> {
        let vk = device.pointers();

        let event = unsafe {
            // since the creation is constant, we use a `static` instead of a struct on the stack
            static mut INFOS: vk::EventCreateInfo = vk::EventCreateInfo {
                sType: vk::STRUCTURE_TYPE_EVENT_CREATE_INFO,
                pNext: 0 as *const _, //ptr::null(),
                flags: 0,   // reserved
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateEvent(device.internal_object(), &INFOS,
                                             ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(Event {
            device: device.clone(),
            event: Mutex::new(event),
        }))
    }

    /// Returns true if the event is signaled.
    #[inline]
    pub fn signaled(&self) -> Result<bool, OomError> {
        unsafe {
            let vk = self.device.pointers();
            let event = self.event.lock().unwrap();
            let result = try!(check_errors(vk.GetEventStatus(self.device.internal_object(),
                                                             *event)));
            match result {
                Success::EventSet => Ok(true),
                Success::EventReset => Ok(false),
                _ => unreachable!()
            }
        }
    }

    /// Changes the `Event` to the signaled state.
    ///
    /// If a command buffer is waiting on this event, it is then unblocked.
    #[inline]
    pub fn set(&self) -> Result<(), OomError> {
        unsafe {
            let vk = self.device.pointers();
            let event = self.event.lock().unwrap();
            try!(check_errors(vk.SetEvent(self.device.internal_object(), *event)).map(|_| ()));
            Ok(())
        }
    }

    /// Changes the `Event` to the unsignaled state.
    #[inline]
    pub fn reset(&self) -> Result<(), OomError> {
        unsafe {
            let vk = self.device.pointers();
            let event = self.event.lock().unwrap();
            try!(check_errors(vk.ResetEvent(self.device.internal_object(), *event)).map(|_| ()));
            Ok(())
        }
    }
}

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

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

impl Drop for Event {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            let event = self.event.lock().unwrap();
            vk.DestroyEvent(self.device.internal_object(), *event, ptr::null());
        }
    }
}

#[cfg(test)]
mod tests {
    use sync::Fence;
    use sync::Semaphore;

    #[test]
    #[ignore]       // TODO: fails on AMD + Windows
    fn fence_create() {
        let (device, _) = gfx_dev_and_queue!();

        let fence = Fence::new(&device).unwrap();
        assert!(!fence.ready().unwrap());
    }

    #[test]
    fn fence_create_signaled() {
        let (device, _) = gfx_dev_and_queue!();

        let fence = Fence::signaled(&device).unwrap();
        assert!(fence.ready().unwrap());
    }

    #[test]
    fn fence_signaled_wait() {
        let (device, _) = gfx_dev_and_queue!();

        let fence = Fence::signaled(&device).unwrap();
        fence.wait(10).unwrap();
    }

    #[test]
    #[ignore]       // TODO: fails on AMD + Windows
    fn fence_reset() {
        let (device, _) = gfx_dev_and_queue!();

        let fence = Fence::signaled(&device).unwrap();
        fence.reset();
        assert!(!fence.ready().unwrap());
    }

    #[test]
    fn semaphore_create() {
        let (device, _) = gfx_dev_and_queue!();
        let _ = Semaphore::new(&device).unwrap();
    }
}
<commit_msg>Cache the signaled state of fences<commit_after>//! Synchronization primitives for Vulkan objects.
//!
//! In Vulkan, you have to manually ensure two things:
//!
//! - That a buffer or an image are not read and written simultaneously (similarly to the CPU).
//! - That writes to a buffer or an image are propagated to other queues by inserting memory
//!   barriers.
//!
//! But don't worry ; this is automatically enforced by this library (as long as you don't use
//! any unsafe function). See the `memory` module for more info.
//!
use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;

use device::Device;
use device::Queue;
use OomError;
use Success;
use SynchronizedVulkanObject;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Base trait for objects that can be used as resources and must be synchronized.
pub unsafe trait Resource {
    /// Returns in which queue family or families this resource can be used.
    fn sharing_mode(&self) -> &SharingMode;

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

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

/// Declares in which queue(s) a resource can be used.
///
/// When you create a buffer or an image, you have to tell the Vulkan library in which queue
/// families it will be used. The vulkano library requires you to tell in which queue famiily
/// the resource will be used, even for exclusive mode.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SharingMode {
    /// The resource is used is only one queue family.
    Exclusive(u32),
    /// The resource is used in multiple queue families. Can be slower than `Exclusive`.
    Concurrent(Vec<u32>),       // TODO: Vec is too expensive here
}

impl<'a> From<&'a Arc<Queue>> for SharingMode {
    #[inline]
    fn from(queue: &'a Arc<Queue>) -> SharingMode {
        SharingMode::Exclusive(queue.family().id())
    }
}

impl<'a> From<&'a [&'a Arc<Queue>]> for SharingMode {
    #[inline]
    fn from(queues: &'a [&'a Arc<Queue>]) -> SharingMode {
        SharingMode::Concurrent(queues.iter().map(|queue| {
            queue.family().id()
        }).collect())
    }
}

/// A fence is used to know when a command buffer submission has finished its execution.
///
/// When a command buffer accesses a ressource, you have to ensure that the CPU doesn't access
/// the same ressource simultaneously (except for concurrent reads). Therefore in order to know
/// when the CPU can access a ressource again, a fence has to be used.
pub struct Fence {
    device: Arc<Device>,
    fence: vk::Fence,

    // If true, we know that the `Fence` is signaled. If false, we don't know.
    // This variable exists so that we don't need to call `vkGetFenceStatus` or `vkWaitForFences`
    // multiple times.
    signaled: AtomicBool,
}

impl Fence {
    /// Builds a new fence.
    #[inline]
    pub fn new(device: &Arc<Device>) -> Result<Arc<Fence>, OomError> {
        Fence::new_impl(device, false)
    }

    /// Builds a new fence already in the "signaled" state.
    #[inline]
    pub fn signaled(device: &Arc<Device>) -> Result<Arc<Fence>, OomError> {
        Fence::new_impl(device, true)
    }

    fn new_impl(device: &Arc<Device>, signaled: bool) -> Result<Arc<Fence>, OomError> {
        let vk = device.pointers();

        let fence = unsafe {
            let infos = vk::FenceCreateInfo {
                sType: vk::STRUCTURE_TYPE_FENCE_CREATE_INFO,
                pNext: ptr::null(),
                flags: if signaled { vk::FENCE_CREATE_SIGNALED_BIT } else { 0 },
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateFence(device.internal_object(), &infos, ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(Fence {
            device: device.clone(),
            fence: fence,
            signaled: AtomicBool::new(signaled),
        }))
    }

    /// Returns true if the fence is signaled.
    #[inline]
    pub fn ready(&self) -> Result<bool, OomError> {
        unsafe {
            if self.signaled.load(Ordering::Relaxed) { return Ok(true); }

            let vk = self.device.pointers();
            let result = try!(check_errors(vk.GetFenceStatus(self.device.internal_object(),
                                                             self.fence)));
            match result {
                Success::Success => {
                    self.signaled.store(true, Ordering::Relaxed);
                    Ok(true)
                },
                Success::NotReady => Ok(false),
                _ => unreachable!()
            }
        }
    }

    /// Waits until the fence is signaled, or at least until the number of nanoseconds of the
    /// timeout has elapsed.
    ///
    /// Returns `Ok` if the fence is now signaled. Returns `Err` if the timeout was reached instead.
    pub fn wait(&self, timeout_ns: u64) -> Result<(), OomError> {       // FIXME: wrong error
        unsafe {
            if self.signaled.load(Ordering::Relaxed) { return Ok(()); }

            let vk = self.device.pointers();
            let r = try!(check_errors(vk.WaitForFences(self.device.internal_object(), 1,
                                                       &self.fence, vk::TRUE, timeout_ns)));

            match r {
                Success::Success => {
                    self.signaled.store(true, Ordering::Relaxed);
                    Ok(())
                },
                Success::Timeout => panic!(),        // FIXME:
                _ => unreachable!()
            }
        }
    }

    /// Resets the fence.
    // FIXME: must synchronize the fence
    #[inline]
    pub fn reset(&self) {
        unsafe {
            let vk = self.device.pointers();
            vk.ResetFences(self.device.internal_object(), 1, &self.fence);
            self.signaled.store(false, Ordering::Relaxed);
        }
    }

    /// Resets multiple fences at once.
    ///
    /// # Panic
    ///
    /// Panicks if not all fences belong to the same device.
    pub fn multi_reset<'a, I>(iter: I)
        where I: IntoIterator<Item = &'a Fence>
    {
        let mut device = None;

        // TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
        let fences: Vec<vk::Fence> = iter.into_iter().map(|fence| {
            match &mut device {
                dev @ &mut None => *dev = Some(fence.device.clone()),
                &mut Some(ref dev) if &**dev as *const Device == &*fence.device as *const Device => {},
                _ => panic!("Tried to reset multiple fences that didn't belong to the same device"),
            };

            fence.signaled.store(false, Ordering::Relaxed);
            fence.fence

        }).collect();

        if let Some(device) = device {
            unsafe {
                let vk = device.pointers();
                vk.ResetFences(device.internal_object(), fences.len() as u32, fences.as_ptr());
            }
        }
    }
}

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

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

impl Drop for Fence {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyFence(self.device.internal_object(), self.fence, ptr::null());
        }
    }
}

/// Used to provide synchronization between command buffers during their execution.
///
/// It is similar to a fence, except that it is purely on the GPU side. The CPU can't query a
/// semaphore's status or wait for it to be signaled.
pub struct Semaphore {
    device: Arc<Device>,
    semaphore: vk::Semaphore,
}

impl Semaphore {
    /// Builds a new semaphore.
    #[inline]
    pub fn new(device: &Arc<Device>) -> Result<Arc<Semaphore>, OomError> {
        let vk = device.pointers();

        let semaphore = unsafe {
            // since the creation is constant, we use a `static` instead of a struct on the stack
            static mut INFOS: vk::SemaphoreCreateInfo = vk::SemaphoreCreateInfo {
                sType: vk::STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
                pNext: 0 as *const _,   // ptr::null()
                flags: 0,   // reserved
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateSemaphore(device.internal_object(), &INFOS,
                                                 ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(Semaphore {
            device: device.clone(),
            semaphore: semaphore,
        }))
    }
}

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

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

impl Drop for Semaphore {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroySemaphore(self.device.internal_object(), self.semaphore, ptr::null());
        }
    }
}

/// Used to block the GPU execution until an event on the CPU occurs.
///
/// Note that Vulkan implementations may have limits on how long a command buffer will wait for an
/// event to be signaled, in order to avoid interfering with progress of other clients of the GPU.
/// If the event isn't signaled within these limits, results are undefined and may include
/// device loss.
pub struct Event {
    device: Arc<Device>,
    event: Mutex<vk::Event>,
}

impl Event {
    /// Builds a new event.
    #[inline]
    pub fn new(device: &Arc<Device>) -> Result<Arc<Event>, OomError> {
        let vk = device.pointers();

        let event = unsafe {
            // since the creation is constant, we use a `static` instead of a struct on the stack
            static mut INFOS: vk::EventCreateInfo = vk::EventCreateInfo {
                sType: vk::STRUCTURE_TYPE_EVENT_CREATE_INFO,
                pNext: 0 as *const _, //ptr::null(),
                flags: 0,   // reserved
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateEvent(device.internal_object(), &INFOS,
                                             ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(Event {
            device: device.clone(),
            event: Mutex::new(event),
        }))
    }

    /// Returns true if the event is signaled.
    #[inline]
    pub fn signaled(&self) -> Result<bool, OomError> {
        unsafe {
            let vk = self.device.pointers();
            let event = self.event.lock().unwrap();
            let result = try!(check_errors(vk.GetEventStatus(self.device.internal_object(),
                                                             *event)));
            match result {
                Success::EventSet => Ok(true),
                Success::EventReset => Ok(false),
                _ => unreachable!()
            }
        }
    }

    /// Changes the `Event` to the signaled state.
    ///
    /// If a command buffer is waiting on this event, it is then unblocked.
    #[inline]
    pub fn set(&self) -> Result<(), OomError> {
        unsafe {
            let vk = self.device.pointers();
            let event = self.event.lock().unwrap();
            try!(check_errors(vk.SetEvent(self.device.internal_object(), *event)).map(|_| ()));
            Ok(())
        }
    }

    /// Changes the `Event` to the unsignaled state.
    #[inline]
    pub fn reset(&self) -> Result<(), OomError> {
        unsafe {
            let vk = self.device.pointers();
            let event = self.event.lock().unwrap();
            try!(check_errors(vk.ResetEvent(self.device.internal_object(), *event)).map(|_| ()));
            Ok(())
        }
    }
}

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

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

impl Drop for Event {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            let event = self.event.lock().unwrap();
            vk.DestroyEvent(self.device.internal_object(), *event, ptr::null());
        }
    }
}

#[cfg(test)]
mod tests {
    use sync::Fence;
    use sync::Semaphore;

    #[test]
    #[ignore]       // TODO: fails on AMD + Windows
    fn fence_create() {
        let (device, _) = gfx_dev_and_queue!();

        let fence = Fence::new(&device).unwrap();
        assert!(!fence.ready().unwrap());
    }

    #[test]
    fn fence_create_signaled() {
        let (device, _) = gfx_dev_and_queue!();

        let fence = Fence::signaled(&device).unwrap();
        assert!(fence.ready().unwrap());
    }

    #[test]
    fn fence_signaled_wait() {
        let (device, _) = gfx_dev_and_queue!();

        let fence = Fence::signaled(&device).unwrap();
        fence.wait(10).unwrap();
    }

    #[test]
    #[ignore]       // TODO: fails on AMD + Windows
    fn fence_reset() {
        let (device, _) = gfx_dev_and_queue!();

        let fence = Fence::signaled(&device).unwrap();
        fence.reset();
        assert!(!fence.ready().unwrap());
    }

    #[test]
    fn semaphore_create() {
        let (device, _) = gfx_dev_and_queue!();
        let _ = Semaphore::new(&device).unwrap();
    }
}
<|endoftext|>


<commit_before>#![cfg(feature = "serde")]

extern crate serde;

use EnumMap;
use Internal;

use self::serde::ser::{Serialize, Serializer, SerializeMap};
use self::serde::de::{self, Deserialize, Deserializer, Error, MapAccess};

use core::fmt;
use core::marker::PhantomData;

/// Requires crate feature `"serde"`
impl<K: Internal<V> + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (key, value) in self {
            map.serialize_entry(&key, value)?;
        }
        map.end()
    }
}

/// Requires crate feature `"serde"`
impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
where
    K: Internal<V>
        + Internal<Option<V>>
        + Deserialize<'de>,
    V: Deserialize<'de>,
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_map(Visitor(PhantomData))
    }
}

struct Visitor<K: Internal<V>, V>(PhantomData<EnumMap<K, V>>);

impl<'de, K, V> de::Visitor<'de> for Visitor<K, V>
where
    K: Internal<V>
        + Internal<Option<V>>
        + Deserialize<'de>,
    V: Deserialize<'de>,
{
    type Value = EnumMap<K, V>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "a map")
    }

    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
        let mut entries = enum_map! { _ => None };
        while let Some((key, value)) = access.next_entry()? {
            entries[key] = Some(value);
        }
        for (_, value) in &entries {
            if value.is_none() {
                return Err(M::Error::custom("key not specified"));
            }
        }
        Ok(enum_map! { key => entries[key].take().unwrap() })
    }
}
<commit_msg>Simplify Visitor struct<commit_after>#![cfg(feature = "serde")]

extern crate serde;

use EnumMap;
use Internal;

use self::serde::ser::{Serialize, Serializer, SerializeMap};
use self::serde::de::{self, Deserialize, Deserializer, Error, MapAccess};

use core::fmt;
use core::marker::PhantomData;

/// Requires crate feature `"serde"`
impl<K: Internal<V> + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (key, value) in self {
            map.serialize_entry(&key, value)?;
        }
        map.end()
    }
}

/// Requires crate feature `"serde"`
impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
where
    K: Internal<V>
        + Internal<Option<V>>
        + Deserialize<'de>,
    V: Deserialize<'de>,
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_map(Visitor(PhantomData))
    }
}

struct Visitor<K, V>(PhantomData<(K, V)>);

impl<'de, K, V> de::Visitor<'de> for Visitor<K, V>
where
    K: Internal<V>
        + Internal<Option<V>>
        + Deserialize<'de>,
    V: Deserialize<'de>,
{
    type Value = EnumMap<K, V>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "a map")
    }

    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
        let mut entries = enum_map! { _ => None };
        while let Some((key, value)) = access.next_entry()? {
            entries[key] = Some(value);
        }
        for (_, value) in &entries {
            if value.is_none() {
                return Err(M::Error::custom("key not specified"));
            }
        }
        Ok(enum_map! { key => entries[key].take().unwrap() })
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::io::Error as IoError;
use config::ConfigError;
use tera::Error as TeraError;

/// The error type used by this crate.
#[derive(Debug, Fail)]
pub enum Error {
    #[fail(display = "IO error")]
    Io(#[cause] ::std::io::Error),

    #[fail(display = "Config error")]
    Config(#[cause] ConfigError),

     #[fail(display = "Template error: {}", _0)]
     Template(String),
     // Template(#[cause] ::tera::Error),

    #[fail(display = "Fmt error")]
    Fmt(#[cause] ::std::fmt::Error),

    #[fail(display = "blog root directory `{:?}` already exists", _0)]
    RootDirExisted(PathBuf),

    #[fail(display = "blog theme `{}` not found", _0)]
    ThemeNotFound(String),

    #[fail(display = "post `{:?}` head part format error", _0)]
    PostHead(PathBuf),

    #[fail(display = "post `{:?}` has not body part", _0)]
    PostNoBody(PathBuf),
}

impl From<IoError> for Error {
     fn from(err: IoError) -> Error {
         Error::Io(err)
     }
}

impl From<ConfigError> for Error {
     fn from(err: ConfigError) -> Error {
         Error::Config(err)
     }
}

impl From<TeraError> for Error {
     fn from(err: TeraError) -> Error {
         Error::Template(err.description().to_string())
     }
}

/// A specialized `Result` type where the error is hard-wired to [`Error`].
///
/// [`Error`]: enum.Error.html
pub type Result<T> = ::std::result::Result<T, Error>;
<commit_msg>fix indent<commit_after>use std::path::PathBuf;
use std::io::Error as IoError;
use config::ConfigError;
use tera::Error as TeraError;

/// The error type used by this crate.
#[derive(Debug, Fail)]
pub enum Error {
    #[fail(display = "IO error")]
    Io(#[cause] ::std::io::Error),

    #[fail(display = "Config error")]
    Config(#[cause] ConfigError),

    #[fail(display = "Template error: {}", _0)]
    Template(String),
    // Template(#[cause] ::tera::Error),

    #[fail(display = "Fmt error")]
    Fmt(#[cause] ::std::fmt::Error),

    #[fail(display = "blog root directory `{:?}` already exists", _0)]
    RootDirExisted(PathBuf),

    #[fail(display = "blog theme `{}` not found", _0)]
    ThemeNotFound(String),

    #[fail(display = "post `{:?}` head part format error", _0)]
    PostHead(PathBuf),

    #[fail(display = "post `{:?}` has not body part", _0)]
    PostNoBody(PathBuf),
}

impl From<IoError> for Error {
     fn from(err: IoError) -> Error {
         Error::Io(err)
     }
}

impl From<ConfigError> for Error {
     fn from(err: ConfigError) -> Error {
         Error::Config(err)
     }
}

impl From<TeraError> for Error {
     fn from(err: TeraError) -> Error {
         Error::Template(err.description().to_string())
     }
}

/// A specialized `Result` type where the error is hard-wired to [`Error`].
///
/// [`Error`]: enum.Error.html
pub type Result<T> = ::std::result::Result<T, Error>;
<|endoftext|>


<commit_before>use std::io;
use std::process::Output;

error_chain! {
  foreign_links {
    io::Error, IO;
  }

  errors {
    GitConfig(output: Output) {
      description("git config error")
      display("git config error ({:?}): '{}'",
        output.status.code(),
        String::from_utf8_lossy(&output.stderr).trim(),
      )
    }
    AuthorNotFound(init: String) {
      description("author not found")
      display("author not found: '{}'", init)
    }
    InvalidAuthor(raw: String) {
      description("invalid author")
      display("invalid author: '{}'", raw)
    }
  }
}
<commit_msg>remove unused Error<commit_after>use std::io;

error_chain! {
  foreign_links {
    io::Error, IO;
  }

  errors {
    AuthorNotFound(init: String) {
      description("author not found")
      display("author not found: '{}'", init)
    }
    InvalidAuthor(raw: String) {
      description("invalid author")
      display("invalid author: '{}'", raw)
    }
  }
}
<|endoftext|>


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

//! Defines the prefix (→) operator.

use std::fmt::Debug;
use std::fmt::Display;

use auto_enums::enum_derive;

use crate::process::Afters;
use crate::process::Initials;

/// Constructs a new _prefix_ process `a → P`.  This process performs event `a` and then behaves
/// like process `P`.
pub fn prefix<E, P: From<Prefix<E, P>>>(initial: E, after: P) -> P {
    Prefix(initial, after).into()
}

/// The type of a [`prefix`] process.
///
/// [`prefix`]: fn.prefix.html
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Prefix<E, P>(E, P);

impl<E: Display, P: Display> Display for Prefix<E, P> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{} → {}", self.0, self.1)
    }
}

impl<E: Display, P: Display> Debug for Prefix<E, P> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

// Operational semantics for a → P
//
// 1) ─────────────
//     a → P -a→ P

impl<'a, E, P> Initials<'a, E> for Prefix<E, P>
where
    E: Clone + 'a,
{
    type Initials = std::iter::Once<E>;

    fn initials(&'a self) -> Self::Initials {
        // initials(a → P) = {a}
        std::iter::once(self.0.clone())
    }
}

#[doc(hidden)]
#[enum_derive(Iterator)]
pub enum PrefixAfters<Initial, NotInitial> {
    Initial(Initial),
    NotInitial(NotInitial),
}

impl<'a, E, P> Afters<'a, E, P> for Prefix<E, P>
where
    E: Eq,
    P: Clone + 'a,
{
    type Afters = PrefixAfters<std::iter::Once<P>, std::iter::Empty<P>>;

    fn afters(&'a self, initial: &E) -> Self::Afters {
        // afters(a → P, a) = P
        if *initial == self.0 {
            PrefixAfters::Initial(std::iter::once(self.1.clone()))
        } else {
            PrefixAfters::NotInitial(std::iter::empty())
        }
    }
}

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

    use maplit::hashmap;
    use proptest_attr_macro::proptest;

    use crate::csp::CSP;
    use crate::process::transitions;
    use crate::test_support::NumberedEvent;
    use crate::test_support::TestEvent;

    #[proptest]
    fn check_prefix_transitions(initial: NumberedEvent, after: CSP<TestEvent>) {
        let initial = TestEvent::from(initial);
        let process = prefix(initial.clone(), after.clone());
        let transitions = transitions(&process);
        assert_eq!(transitions, hashmap! { initial => vec![after] });
    }
}
<commit_msg>Add Process impl for Prefix<commit_after>// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2019, HST authors.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied.  See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------------------

//! Defines the prefix (→) operator.

use std::fmt::Debug;
use std::fmt::Display;

use auto_enums::enum_derive;

use crate::process::Afters;
use crate::process::Cursor;
use crate::process::Initials;
use crate::process::Process;

/// Constructs a new _prefix_ process `a → P`.  This process performs event `a` and then behaves
/// like process `P`.
pub fn prefix<E, P: From<Prefix<E, P>>>(initial: E, after: P) -> P {
    Prefix(initial, after).into()
}

/// The type of a [`prefix`] process.
///
/// [`prefix`]: fn.prefix.html
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Prefix<E, P>(E, P);

impl<E: Display, P: Display> Display for Prefix<E, P> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{} → {}", self.0, self.1)
    }
}

impl<E: Display, P: Display> Debug for Prefix<E, P> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

// Operational semantics for a → P
//
// 1) ─────────────
//     a → P -a→ P

#[doc(hidden)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct PrefixCursor<E, P> {
    state: PrefixState,
    initial: E,
    after: P,
}

#[doc(hidden)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum PrefixState {
    BeforeInitial,
    AfterInitial,
}

impl<E, P> Process<E> for Prefix<E, P>
where
    E: Clone + Display + Eq + 'static,
    P: Process<E>,
{
    type Cursor = PrefixCursor<E, P::Cursor>;

    fn root(&self) -> Self::Cursor {
        PrefixCursor {
            state: PrefixState::BeforeInitial,
            initial: self.0.clone(),
            after: self.1.root(),
        }
    }
}

impl<E, P> Cursor<E> for PrefixCursor<E, P>
where
    E: Clone + Display + Eq + 'static,
    P: Cursor<E>,
{
    fn events(&self) -> Box<dyn Iterator<Item = E>> {
        match self.state {
            PrefixState::BeforeInitial => Box::new(std::iter::once(self.initial.clone())),
            PrefixState::AfterInitial => self.after.events(),
        }
    }

    fn can_perform(&self, event: &E) -> bool {
        match self.state {
            PrefixState::BeforeInitial => *event == self.initial,
            PrefixState::AfterInitial => self.after.can_perform(event),
        }
    }

    fn perform(&mut self, event: &E) {
        if self.state == PrefixState::AfterInitial {
            self.after.perform(event);
            return;
        }
        if *event != self.initial {
            panic!("Prefix cannot perform {}", event);
        }
        self.state = PrefixState::AfterInitial;
    }
}

impl<'a, E, P> Initials<'a, E> for Prefix<E, P>
where
    E: Clone + 'a,
{
    type Initials = std::iter::Once<E>;

    fn initials(&'a self) -> Self::Initials {
        // initials(a → P) = {a}
        std::iter::once(self.0.clone())
    }
}

#[doc(hidden)]
#[enum_derive(Iterator)]
pub enum PrefixAfters<Initial, NotInitial> {
    Initial(Initial),
    NotInitial(NotInitial),
}

impl<'a, E, P> Afters<'a, E, P> for Prefix<E, P>
where
    E: Eq,
    P: Clone + 'a,
{
    type Afters = PrefixAfters<std::iter::Once<P>, std::iter::Empty<P>>;

    fn afters(&'a self, initial: &E) -> Self::Afters {
        // afters(a → P, a) = P
        if *initial == self.0 {
            PrefixAfters::Initial(std::iter::once(self.1.clone()))
        } else {
            PrefixAfters::NotInitial(std::iter::empty())
        }
    }
}

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

    use maplit::hashmap;
    use proptest_attr_macro::proptest;

    use crate::csp::CSP;
    use crate::primitives::stop;
    use crate::primitives::tau;
    use crate::primitives::Stop;
    use crate::process::satisfies_trace;
    use crate::process::transitions;
    use crate::test_support::NumberedEvent;
    use crate::test_support::TestEvent;

    #[proptest]
    fn check_prefix_events(initial: NumberedEvent) {
        let initial = TestEvent::from(initial);
        // TODO: Use CSP<TestEvent> once all operators implement Process
        let process = Prefix::<TestEvent, Stop<TestEvent>>(initial.clone(), stop());
        let mut cursor = process.root();
        assert_eq!(cursor.events().collect::<Vec<_>>(), vec![initial.clone()]);
        cursor.perform(&initial);
        assert!(cursor.events().collect::<Vec<_>>().is_empty());
    }

    #[proptest]
    fn check_prefix_traces(initial: NumberedEvent) {
        let initial = TestEvent::from(initial);
        // TODO: Use CSP<TestEvent> once all operators implement Process
        let process = Prefix::<TestEvent, Stop<TestEvent>>(initial.clone(), stop());
        let cursor = process.root();
        assert!(satisfies_trace(cursor.clone(), vec![initial.clone()]));
        assert!(!satisfies_trace(cursor.clone(), vec![tau()]));
        assert!(!satisfies_trace(
            cursor.clone(),
            vec![initial.clone(), tau()]
        ));
    }

    #[proptest]
    fn check_prefix_transitions(initial: NumberedEvent, after: CSP<TestEvent>) {
        let initial = TestEvent::from(initial);
        let process = prefix(initial.clone(), after.clone());
        let transitions = transitions(&process);
        assert_eq!(transitions, hashmap! { initial => vec![after] });
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::net::SocketAddr;

use tokio::net::TcpListener;
use tokio::net::TcpStream;

use futures::future::Future;
use futures::future::TryFutureExt;

use net2;

use crate::net::addr::AnySocketAddr;
use crate::net::connect::ToClientStream;
use crate::net::listen::SocketListener;
use crate::net::listen::ToSocketListener;
use crate::net::listen::ToTokioListener;
use crate::net::socket::SocketStream;
use crate::ServerConf;
use std::pin::Pin;
use tokio::runtime::Handle;

impl ToSocketListener for SocketAddr {
    fn to_listener(&self, conf: &ServerConf) -> io::Result<Box<dyn ToTokioListener + Send>> {
        Ok(Box::new(listener(self, conf)?))
    }

    fn cleanup(&self) {}
}

#[cfg(unix)]
fn configure_tcp(tcp: &net2::TcpBuilder, conf: &ServerConf) -> io::Result<()> {
    use net2::unix::UnixTcpBuilderExt;
    if let Some(reuse_port) = conf.reuse_port {
        tcp.reuse_port(reuse_port)?;
    }
    Ok(())
}

#[cfg(windows)]
fn configure_tcp(_tcp: &net2::TcpBuilder, conf: &ServerConf) -> io::Result<()> {
    Ok(())
}

fn listener(addr: &SocketAddr, conf: &ServerConf) -> io::Result<::std::net::TcpListener> {
    let listener = match *addr {
        SocketAddr::V4(_) => net2::TcpBuilder::new_v4()?,
        SocketAddr::V6(_) => net2::TcpBuilder::new_v6()?,
    };

    if let SocketAddr::V6(_) = *addr {
        // Assume only_v6 = false by default
        // Note: it is not default behavior for Rust
        let only_v6 = conf.only_v6.unwrap_or(false);
        listener.only_v6(only_v6)?;
    }

    configure_tcp(&listener, conf)?;
    listener.reuse_address(true)?;
    debug!("binding socket to {}", addr);
    listener.bind(addr)?;
    let backlog = conf.backlog.unwrap_or(1024);
    listener.listen(backlog)
}

impl ToTokioListener for ::std::net::TcpListener {
    fn to_tokio_listener(self: Box<Self>, handle: &Handle) -> Pin<Box<dyn SocketListener>> {
        handle.enter(|| Box::pin(TcpListener::from_std(*self).unwrap()))
    }

    fn local_addr(&self) -> io::Result<AnySocketAddr> {
        Ok(AnySocketAddr::Inet(self.local_addr().unwrap()))
    }
}

impl SocketListener for TcpListener {
    fn accept<'a>(
        self: Pin<&'a mut Self>,
    ) -> Pin<
        Box<
            dyn Future<Output = io::Result<(Pin<Box<dyn SocketStream + Send>>, AnySocketAddr)>>
                + Send
                + 'a,
        >,
    > {
        Box::pin(async move {
            let (socket, peer_addr) = TcpListener::accept(Pin::get_mut(self)).await?;
            Ok((
                Box::pin(socket) as Pin<Box<dyn SocketStream + Send>>,
                AnySocketAddr::Inet(peer_addr),
            ))
        })
    }
}

impl ToClientStream for SocketAddr {
    fn connect(
        &self,
        _handle: &Handle,
    ) -> Pin<Box<dyn Future<Output = io::Result<Pin<Box<dyn SocketStream + Send>>>> + Send>> {
        let future = TcpStream::connect(self.clone())
            .map_ok(|stream| Box::pin(stream) as Pin<Box<dyn SocketStream + Send>>);
        Box::pin(future)
    }

    fn socket_addr(&self) -> AnySocketAddr {
        AnySocketAddr::Inet(*self)
    }
}

impl SocketStream for TcpStream {
    fn is_tcp(&self) -> bool {
        true
    }

    fn set_nodelay(&self, no_delay: bool) -> io::Result<()> {
        self.set_nodelay(no_delay)
    }
}
<commit_msg>Better configure_tcp condition macro<commit_after>use std::io;
use std::net::SocketAddr;

use tokio::net::TcpListener;
use tokio::net::TcpStream;

use futures::future::Future;
use futures::future::TryFutureExt;

use net2;

use crate::net::addr::AnySocketAddr;
use crate::net::connect::ToClientStream;
use crate::net::listen::SocketListener;
use crate::net::listen::ToSocketListener;
use crate::net::listen::ToTokioListener;
use crate::net::socket::SocketStream;
use crate::ServerConf;
use std::pin::Pin;
use tokio::runtime::Handle;

impl ToSocketListener for SocketAddr {
    fn to_listener(&self, conf: &ServerConf) -> io::Result<Box<dyn ToTokioListener + Send>> {
        Ok(Box::new(listener(self, conf)?))
    }

    fn cleanup(&self) {}
}

#[cfg(not(windows))]
fn configure_tcp(tcp: &net2::TcpBuilder, conf: &ServerConf) -> io::Result<()> {
    use net2::unix::UnixTcpBuilderExt;
    if let Some(reuse_port) = conf.reuse_port {
        tcp.reuse_port(reuse_port)?;
    }
    Ok(())
}

#[cfg(windows)]
fn configure_tcp(_tcp: &net2::TcpBuilder, conf: &ServerConf) -> io::Result<()> {
    Ok(())
}

fn listener(addr: &SocketAddr, conf: &ServerConf) -> io::Result<::std::net::TcpListener> {
    let listener = match *addr {
        SocketAddr::V4(_) => net2::TcpBuilder::new_v4()?,
        SocketAddr::V6(_) => net2::TcpBuilder::new_v6()?,
    };

    if let SocketAddr::V6(_) = *addr {
        // Assume only_v6 = false by default
        // Note: it is not default behavior for Rust
        let only_v6 = conf.only_v6.unwrap_or(false);
        listener.only_v6(only_v6)?;
    }

    configure_tcp(&listener, conf)?;
    listener.reuse_address(true)?;
    debug!("binding socket to {}", addr);
    listener.bind(addr)?;
    let backlog = conf.backlog.unwrap_or(1024);
    listener.listen(backlog)
}

impl ToTokioListener for ::std::net::TcpListener {
    fn to_tokio_listener(self: Box<Self>, handle: &Handle) -> Pin<Box<dyn SocketListener>> {
        handle.enter(|| Box::pin(TcpListener::from_std(*self).unwrap()))
    }

    fn local_addr(&self) -> io::Result<AnySocketAddr> {
        Ok(AnySocketAddr::Inet(self.local_addr().unwrap()))
    }
}

impl SocketListener for TcpListener {
    fn accept<'a>(
        self: Pin<&'a mut Self>,
    ) -> Pin<
        Box<
            dyn Future<Output = io::Result<(Pin<Box<dyn SocketStream + Send>>, AnySocketAddr)>>
                + Send
                + 'a,
        >,
    > {
        Box::pin(async move {
            let (socket, peer_addr) = TcpListener::accept(Pin::get_mut(self)).await?;
            Ok((
                Box::pin(socket) as Pin<Box<dyn SocketStream + Send>>,
                AnySocketAddr::Inet(peer_addr),
            ))
        })
    }
}

impl ToClientStream for SocketAddr {
    fn connect(
        &self,
        _handle: &Handle,
    ) -> Pin<Box<dyn Future<Output = io::Result<Pin<Box<dyn SocketStream + Send>>>> + Send>> {
        let future = TcpStream::connect(self.clone())
            .map_ok(|stream| Box::pin(stream) as Pin<Box<dyn SocketStream + Send>>);
        Box::pin(future)
    }

    fn socket_addr(&self) -> AnySocketAddr {
        AnySocketAddr::Inet(*self)
    }
}

impl SocketStream for TcpStream {
    fn is_tcp(&self) -> bool {
        true
    }

    fn set_nodelay(&self, no_delay: bool) -> io::Result<()> {
        self.set_nodelay(no_delay)
    }
}
<|endoftext|>


<commit_before>use log::trace;
use amq_protocol::frame::AMQPFrame;
use parking_lot::Mutex;

use std::{
  collections::{VecDeque, HashMap},
  sync::Arc,
};

use crate::{
  channel::Reply,
  channel_status::ChannelState,
  id_sequence::IdSequence,
  wait::{Cancellable, Wait, WaitHandle},
  error::ErrorKind,
};

pub(crate) type SendId = u64;

#[derive(Clone, Debug)]
pub(crate) enum Priority {
  NORMAL,
  CRITICAL,
}

impl Default for Priority {
  fn default() -> Self {
    Priority::NORMAL
  }
}

#[derive(Clone, Debug, Default)]
pub(crate) struct Frames {
  inner: Arc<Mutex<Inner>>,
}

impl Frames {
  pub(crate) fn push(&self, channel_id: u16, priority: Priority, frame: AMQPFrame, expected_reply: Option<(Reply, Box<dyn Cancellable + Send>)>) -> Wait<()> {
    self.inner.lock().push(channel_id, priority, frame, expected_reply)
  }

  pub(crate) fn push_frames(&self, channel_id: u16, frames: Vec<(AMQPFrame, Option<AMQPFrame>)>) -> Wait<()> {
    self.inner.lock().push_frames(channel_id, frames)
  }

  pub(crate) fn retry(&self, send_id: SendId, frame: AMQPFrame) {
    self.inner.lock().retry(send_id, frame);
  }

  pub(crate) fn pop(&self, flow: bool) -> Option<(SendId, AMQPFrame)> {
    self.inner.lock().pop(flow)
  }

  pub(crate) fn next_expected_reply(&self, channel_id: u16) -> Option<Reply> {
    self.inner.lock().expected_replies.get_mut(&channel_id).and_then(|replies| replies.pop_front()).map(|t| t.0)
  }

  pub(crate) fn mark_sent(&self, send_id: SendId) {
    if let Some((_, send)) = self.inner.lock().outbox.remove(&send_id) {
      send.finish(());
    }
  }

  pub(crate) fn drop_pending(&self) {
    self.inner.lock().drop_pending();
  }

  pub(crate) fn clear_expected_replies(&self, channel_id: u16, channel_state: ChannelState) {
    self.inner.lock().clear_expected_replies(channel_id, channel_state);
  }
}

#[derive(Debug)]
struct Inner {
  next_frame:       Option<(SendId, AMQPFrame)>,
  priority_frames:  VecDeque<(SendId, AMQPFrame)>,
  frames:           VecDeque<(SendId, AMQPFrame)>,
  low_prio_frames:  VecDeque<(SendId, AMQPFrame, Option<AMQPFrame>)>,
  expected_replies: HashMap<u16, VecDeque<(Reply, Box<dyn Cancellable + Send>)>>,
  outbox:           HashMap<SendId, (u16, WaitHandle<()>)>,
  send_id:          IdSequence<SendId>,
}

impl Default for Inner {
  fn default() -> Self {
    Self {
      next_frame:       None,
      priority_frames:  VecDeque::default(),
      frames:           VecDeque::default(),
      low_prio_frames:  VecDeque::default(),
      expected_replies: HashMap::default(),
      outbox:           HashMap::default(),
      send_id:          IdSequence::new(false),
    }
  }
}

impl Inner {
  fn push(&mut self, channel_id: u16, priority: Priority, frame: AMQPFrame, expected_reply: Option<(Reply, Box<dyn Cancellable + Send>)>) -> Wait<()> {
    let send_id = if let Priority::CRITICAL = priority { 0 } else { self.send_id.next() };
    match priority {
      Priority::NORMAL   => self.frames.push_back((send_id, frame)),
      Priority::CRITICAL => self.priority_frames.push_front((send_id, frame)),
    }
    let (wait, wait_handle) = Wait::new();
    self.outbox.insert(send_id, (channel_id, wait_handle));
    if let Some(reply) = expected_reply {
      trace!("channel {} state is now waiting for {:?}", channel_id, reply);
      self.expected_replies.entry(channel_id).or_default().push_back(reply);
    }
    wait
  }

  fn push_frames(&mut self, channel_id: u16, mut frames: Vec<(AMQPFrame, Option<AMQPFrame>)>) -> Wait<()> {
    let send_id = self.send_id.next();
    let (wait, wait_handle) = Wait::new();
    let last_frame = frames.pop();

    for frame in frames {
      self.low_prio_frames.push_back((0, frame.0, frame.1));
    }
    if let Some(last_frame) = last_frame {
      self.low_prio_frames.push_back((send_id, last_frame.0, last_frame.1));
    } else {
      wait_handle.finish(());
    }

    self.outbox.insert(send_id, (channel_id, wait_handle));

    wait
  }

  fn pop(&mut self, flow: bool) -> Option<(SendId, AMQPFrame)> {
    if let Some(frame) = self.next_frame.take().or_else(|| self.priority_frames.pop_front()).or_else(|| self.frames.pop_front()) {
      return Some(frame);
    }
    if flow {
      if let Some(mut frame) = self.low_prio_frames.pop_front() {
        if let Some(next_frame) = frame.2 {
          self.next_frame = Some((frame.0, next_frame));
          frame.0 = 0;
        }
        return Some((frame.0, frame.1));
      }
    }
    None
  }

  fn retry(&mut self, send_id: SendId, frame: AMQPFrame) {
    if let AMQPFrame::Header(..) = &frame {
      self.next_frame = Some((send_id, frame));
    } else {
      self.priority_frames.push_back((send_id, frame));
    }
  }

  fn drop_pending(&mut self) {
    self.priority_frames.clear();
    self.frames.clear();
    self.low_prio_frames.clear();
    for (_, replies) in self.expected_replies.drain() {
      Self::cancel_expected_replies(replies, ChannelState::Closed);
    }
    for (_, (_, wait_handle)) in self.outbox.drain() {
      wait_handle.finish(());
    }
  }

  fn clear_expected_replies(&mut self, channel_id: u16, channel_state: ChannelState) {
    let mut outbox = HashMap::default();

    for (send_id, (chan_id, wait_handle)) in self.outbox.drain() {
      if chan_id == channel_id {
        wait_handle.error(ErrorKind::InvalidChannelState(channel_state.clone()).into())
      } else {
        outbox.insert(send_id, (chan_id, wait_handle));
      }
    }

    self.outbox = outbox;

    if let Some(replies) = self.expected_replies.remove(&channel_id) {
      Self::cancel_expected_replies(replies, channel_state);
    }
  }

  fn cancel_expected_replies(replies: VecDeque<(Reply, Box<dyn Cancellable + Send>)>, channel_state: ChannelState) {
    for (_, cancel) in replies {
      cancel.cancel(ErrorKind::InvalidChannelState(channel_state.clone()).into());
    }
  }
}
<commit_msg>properly clenaup potential pending frame on connection close<commit_after>use log::trace;
use amq_protocol::frame::AMQPFrame;
use parking_lot::Mutex;

use std::{
  collections::{VecDeque, HashMap},
  sync::Arc,
};

use crate::{
  channel::Reply,
  channel_status::ChannelState,
  id_sequence::IdSequence,
  wait::{Cancellable, Wait, WaitHandle},
  error::ErrorKind,
};

pub(crate) type SendId = u64;

#[derive(Clone, Debug)]
pub(crate) enum Priority {
  NORMAL,
  CRITICAL,
}

impl Default for Priority {
  fn default() -> Self {
    Priority::NORMAL
  }
}

#[derive(Clone, Debug, Default)]
pub(crate) struct Frames {
  inner: Arc<Mutex<Inner>>,
}

impl Frames {
  pub(crate) fn push(&self, channel_id: u16, priority: Priority, frame: AMQPFrame, expected_reply: Option<(Reply, Box<dyn Cancellable + Send>)>) -> Wait<()> {
    self.inner.lock().push(channel_id, priority, frame, expected_reply)
  }

  pub(crate) fn push_frames(&self, channel_id: u16, frames: Vec<(AMQPFrame, Option<AMQPFrame>)>) -> Wait<()> {
    self.inner.lock().push_frames(channel_id, frames)
  }

  pub(crate) fn retry(&self, send_id: SendId, frame: AMQPFrame) {
    self.inner.lock().retry(send_id, frame);
  }

  pub(crate) fn pop(&self, flow: bool) -> Option<(SendId, AMQPFrame)> {
    self.inner.lock().pop(flow)
  }

  pub(crate) fn next_expected_reply(&self, channel_id: u16) -> Option<Reply> {
    self.inner.lock().expected_replies.get_mut(&channel_id).and_then(|replies| replies.pop_front()).map(|t| t.0)
  }

  pub(crate) fn mark_sent(&self, send_id: SendId) {
    if let Some((_, send)) = self.inner.lock().outbox.remove(&send_id) {
      send.finish(());
    }
  }

  pub(crate) fn drop_pending(&self) {
    self.inner.lock().drop_pending();
  }

  pub(crate) fn clear_expected_replies(&self, channel_id: u16, channel_state: ChannelState) {
    self.inner.lock().clear_expected_replies(channel_id, channel_state);
  }
}

#[derive(Debug)]
struct Inner {
  next_frame:       Option<(SendId, AMQPFrame)>,
  priority_frames:  VecDeque<(SendId, AMQPFrame)>,
  frames:           VecDeque<(SendId, AMQPFrame)>,
  low_prio_frames:  VecDeque<(SendId, AMQPFrame, Option<AMQPFrame>)>,
  expected_replies: HashMap<u16, VecDeque<(Reply, Box<dyn Cancellable + Send>)>>,
  outbox:           HashMap<SendId, (u16, WaitHandle<()>)>,
  send_id:          IdSequence<SendId>,
}

impl Default for Inner {
  fn default() -> Self {
    Self {
      next_frame:       None,
      priority_frames:  VecDeque::default(),
      frames:           VecDeque::default(),
      low_prio_frames:  VecDeque::default(),
      expected_replies: HashMap::default(),
      outbox:           HashMap::default(),
      send_id:          IdSequence::new(false),
    }
  }
}

impl Inner {
  fn push(&mut self, channel_id: u16, priority: Priority, frame: AMQPFrame, expected_reply: Option<(Reply, Box<dyn Cancellable + Send>)>) -> Wait<()> {
    let send_id = if let Priority::CRITICAL = priority { 0 } else { self.send_id.next() };
    match priority {
      Priority::NORMAL   => self.frames.push_back((send_id, frame)),
      Priority::CRITICAL => self.priority_frames.push_front((send_id, frame)),
    }
    let (wait, wait_handle) = Wait::new();
    self.outbox.insert(send_id, (channel_id, wait_handle));
    if let Some(reply) = expected_reply {
      trace!("channel {} state is now waiting for {:?}", channel_id, reply);
      self.expected_replies.entry(channel_id).or_default().push_back(reply);
    }
    wait
  }

  fn push_frames(&mut self, channel_id: u16, mut frames: Vec<(AMQPFrame, Option<AMQPFrame>)>) -> Wait<()> {
    let send_id = self.send_id.next();
    let (wait, wait_handle) = Wait::new();
    let last_frame = frames.pop();

    for frame in frames {
      self.low_prio_frames.push_back((0, frame.0, frame.1));
    }
    if let Some(last_frame) = last_frame {
      self.low_prio_frames.push_back((send_id, last_frame.0, last_frame.1));
    } else {
      wait_handle.finish(());
    }

    self.outbox.insert(send_id, (channel_id, wait_handle));

    wait
  }

  fn pop(&mut self, flow: bool) -> Option<(SendId, AMQPFrame)> {
    if let Some(frame) = self.next_frame.take().or_else(|| self.priority_frames.pop_front()).or_else(|| self.frames.pop_front()) {
      return Some(frame);
    }
    if flow {
      if let Some(mut frame) = self.low_prio_frames.pop_front() {
        if let Some(next_frame) = frame.2 {
          self.next_frame = Some((frame.0, next_frame));
          frame.0 = 0;
        }
        return Some((frame.0, frame.1));
      }
    }
    None
  }

  fn retry(&mut self, send_id: SendId, frame: AMQPFrame) {
    if let AMQPFrame::Header(..) = &frame {
      self.next_frame = Some((send_id, frame));
    } else {
      self.priority_frames.push_back((send_id, frame));
    }
  }

  fn drop_pending(&mut self) {
    self.next_frame.take();
    self.priority_frames.clear();
    self.frames.clear();
    self.low_prio_frames.clear();
    for (_, replies) in self.expected_replies.drain() {
      Self::cancel_expected_replies(replies, ChannelState::Closed);
    }
    for (_, (_, wait_handle)) in self.outbox.drain() {
      wait_handle.finish(());
    }
  }

  fn clear_expected_replies(&mut self, channel_id: u16, channel_state: ChannelState) {
    let mut outbox = HashMap::default();

    for (send_id, (chan_id, wait_handle)) in self.outbox.drain() {
      if chan_id == channel_id {
        wait_handle.error(ErrorKind::InvalidChannelState(channel_state.clone()).into())
      } else {
        outbox.insert(send_id, (chan_id, wait_handle));
      }
    }

    self.outbox = outbox;

    if let Some(replies) = self.expected_replies.remove(&channel_id) {
      Self::cancel_expected_replies(replies, channel_state);
    }
  }

  fn cancel_expected_replies(replies: VecDeque<(Reply, Box<dyn Cancellable + Send>)>, channel_state: ChannelState) {
    for (_, cancel) in replies {
      cancel.cancel(ErrorKind::InvalidChannelState(channel_state.clone()).into());
    }
  }
}
<|endoftext|>


<commit_before>use std::process::exit;
use chrono::naive::datetime::NaiveDateTime;

use libimagdiary::diary::Diary;
use libimagdiary::diaryid::DiaryId;
use libimagdiary::error::DiaryError as DE;
use libimagdiary::error::DiaryErrorKind as DEK;
use libimagentryedit::edit::Edit;
use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error;
use libimagtimeui::datetime::DateTime;
use libimagtimeui::parse::Parse;

use util::get_diary_name;

pub fn edit(rt: &Runtime) {
    let diaryname = get_diary_name(rt);
    if diaryname.is_none() {
        warn!("No diary name");
        exit(1);
    }
    let diaryname = diaryname.unwrap();
    let diary = Diary::open(rt.store(), &diaryname[..]);

    let datetime : Option<NaiveDateTime> = rt
        .cli()
        .subcommand_matches("edit")
        .unwrap()
        .value_of("datetime")
        .and_then(DateTime::parse)
        .map(|dt| dt.into());

    let to_edit = match datetime {
        Some(dt) => Some(diary.retrieve(DiaryId::from_datetime(diaryname.clone(), dt))),
        None     => diary.get_youngest_entry(),
    };

    match to_edit {
        Some(Ok(mut e)) => e.edit_content(rt).map_err(|e| DE::new(DEK::IOError, Some(Box::new(e)))),

        Some(Err(e)) => Err(e),
        None => Err(DE::new(DEK::EntryNotInDiary, None)),
    }
    .map_err(|e| trace_error(&e)).ok();
}

<commit_msg>Simplify error handling<commit_after>use std::process::exit;
use chrono::naive::datetime::NaiveDateTime;

use libimagdiary::diary::Diary;
use libimagdiary::diaryid::DiaryId;
use libimagdiary::error::DiaryErrorKind as DEK;
use libimagdiary::error::MapErrInto;
use libimagentryedit::edit::Edit;
use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error;
use libimagerror::into::IntoError;
use libimagtimeui::datetime::DateTime;
use libimagtimeui::parse::Parse;

use util::get_diary_name;

pub fn edit(rt: &Runtime) {
    let diaryname = get_diary_name(rt);
    if diaryname.is_none() {
        warn!("No diary name");
        exit(1);
    }
    let diaryname = diaryname.unwrap();
    let diary = Diary::open(rt.store(), &diaryname[..]);

    let datetime : Option<NaiveDateTime> = rt
        .cli()
        .subcommand_matches("edit")
        .unwrap()
        .value_of("datetime")
        .and_then(DateTime::parse)
        .map(|dt| dt.into());

    let to_edit = match datetime {
        Some(dt) => Some(diary.retrieve(DiaryId::from_datetime(diaryname.clone(), dt))),
        None     => diary.get_youngest_entry(),
    };

    match to_edit {
        Some(Ok(mut e)) => e.edit_content(rt).map_err_into(DEK::IOError),

        Some(Err(e)) => Err(e),
        None => Err(DEK::EntryNotInDiary.into_error()),
    }
    .map_err(|e| trace_error(&e)).ok();
}

<|endoftext|>


<commit_before>/* Copyright (C)  2016 nokaa <nokaa@cock.li>
 * This software is licensed under the terms of the
 * GNU Affero General Public License. You should have
 * received a copy of this license with this software.
 * The license may also be found at https://gnu.org/licenses/agpl.txt
 */

use std::io::{Write, stderr};
use std::str;

use rotor::{EventSet, PollOpt, Void};
use rotor::mio::{TryRead, TryWrite};
use rotor::mio::tcp::{TcpListener, TcpStream};
use rotor::{Machine, Response, EarlyScope, Scope};

use super::util::*;

pub struct Context {
    pub root_dir: String,
}

pub enum Gopher {
    Server(TcpListener),
    Connection(TcpStream),
}

impl Gopher {
    pub fn new(sock: TcpListener, scope: &mut EarlyScope)
        -> Response<Gopher, Void>
    {
        scope.register(&sock, EventSet::readable(), PollOpt::edge())
            .unwrap();
        Response::ok(Gopher::Server(sock))
    }
    fn accept(self) -> Response<Gopher, TcpStream> {
        match self {
            Gopher::Server(sock) => {
                match sock.accept() {
                    Ok(Some((conn, _))) => {
                        Response::spawn(Gopher::Server(sock), conn)
                    }
                    Ok(None) => {
                        Response::ok(Gopher::Server(sock))
                    }
                    Err(e) => {
                        writeln!(&mut stderr(), "Error: {}", e).ok();
                        Response::ok(Gopher::Server(sock))
                    }
                }
            }
            _ => unreachable!(),
        }
    }
}

impl Machine for Gopher {
    type Context = Context;
    type Seed = TcpStream;

    fn create(conn: TcpStream, scope: &mut Scope<Context>)
        -> Response<Self, Void>
    {
        scope.register(&conn, EventSet::readable(), PollOpt::level())
            .unwrap();
        Response::ok(Gopher::Connection(conn))
    }

    fn ready(self, _events: EventSet, scope: &mut Scope<Context>)
        -> Response<Self, TcpStream>
    {
        match self {
            me @ Gopher::Server(..) => me.accept(),
            Gopher::Connection(mut sock) => {
                let mut data = [0u8; 1024];
                match sock.try_read(&mut data) {
                    Err(e) => {
                        writeln!(&mut stderr(), "read: {}", e).ok();
                        Response::done()
                    }
                    Ok(Some(0)) => {
                        Response::done()
                    }
                    Ok(Some(x)) => {
                        match local_path_for_request(&data[..x], &scope.root_dir) {
                            Some(p) => {
                                match sock.try_write(&p) {
                                    Ok(Some(x)) => {
                                        // TODO(nokaa): keep writing while x < p.len
                                        if x < p.len() {
                                            println!("not enough");
                                        }
                                        Response::done()
                                    }
                                    Ok(None) => Response::done(),
                                    Err(e) => {
                                        writeln!(&mut stderr(), "write: {}", e).ok();
                                        Response::done()
                                    }
                                }
                            }
                            None => {
                                let token = str::from_utf8(&data[..x-2]).unwrap();
                                let d = &format!("3Sorry, but the requested token '{}' could not be found.\tErr\tlocalhost\t70\r\n.", token)[..];
                                match sock.try_write(d.as_bytes()) {
                                    Ok(_) => Response::done(),
                                    Err(e) => {
                                        writeln!(&mut stderr(), "write: {}", e).ok();
                                        Response::done()
                                    }
                                }
                            }
                        }
                    }
                    Ok(None) => {
                        Response::ok(Gopher::Connection(sock))
                    }
                }
            }
        }
    }
    fn spawned(self, _scope: &mut Scope<Context>) -> Response<Self, TcpStream>
    {
        match self {
            me @ Gopher::Server(..) => me.accept(),
            _ => unreachable!(),
        }
    }
    fn timeout(self, _scope: &mut Scope<Context>)
        -> Response<Self, TcpStream>
    {
        unreachable!();
    }
    fn wakeup(self, _scope: &mut Scope<Context>)
        -> Response<Self, TcpStream>
    {
        unreachable!();
    }
}
<commit_msg>Check if all bytes were written<commit_after>/* Copyright (C)  2016 nokaa <nokaa@cock.li>
 * This software is licensed under the terms of the
 * GNU Affero General Public License. You should have
 * received a copy of this license with this software.
 * The license may also be found at https://gnu.org/licenses/agpl.txt
 */

use std::io::{Write, stderr};
use std::str;

use rotor::{EventSet, PollOpt, Void};
use rotor::mio::{TryRead, TryWrite};
use rotor::mio::tcp::{TcpListener, TcpStream};
use rotor::{Machine, Response, EarlyScope, Scope};

use super::util::*;

pub struct Context {
    pub root_dir: String,
}

pub enum Gopher {
    Server(TcpListener),
    Connection(TcpStream),
}

impl Gopher {
    pub fn new(sock: TcpListener, scope: &mut EarlyScope)
        -> Response<Gopher, Void>
    {
        scope.register(&sock, EventSet::readable(), PollOpt::edge())
            .unwrap();
        Response::ok(Gopher::Server(sock))
    }
    fn accept(self) -> Response<Gopher, TcpStream> {
        match self {
            Gopher::Server(sock) => {
                match sock.accept() {
                    Ok(Some((conn, _))) => {
                        Response::spawn(Gopher::Server(sock), conn)
                    }
                    Ok(None) => {
                        Response::ok(Gopher::Server(sock))
                    }
                    Err(e) => {
                        writeln!(&mut stderr(), "Error: {}", e).ok();
                        Response::ok(Gopher::Server(sock))
                    }
                }
            }
            _ => unreachable!(),
        }
    }
}

impl Machine for Gopher {
    type Context = Context;
    type Seed = TcpStream;

    fn create(conn: TcpStream, scope: &mut Scope<Context>)
        -> Response<Self, Void>
    {
        scope.register(&conn, EventSet::readable(), PollOpt::level())
            .unwrap();
        Response::ok(Gopher::Connection(conn))
    }

    fn ready(self, _events: EventSet, scope: &mut Scope<Context>)
        -> Response<Self, TcpStream>
    {
        match self {
            me @ Gopher::Server(..) => me.accept(),
            Gopher::Connection(mut sock) => {
                let mut data = [0u8; 1024];
                match sock.try_read(&mut data) {
                    Err(e) => {
                        writeln!(&mut stderr(), "read: {}", e).ok();
                        Response::done()
                    }
                    Ok(Some(0)) => {
                        Response::done()
                    }
                    Ok(Some(x)) => {
                        match local_path_for_request(&data[..x], &scope.root_dir) {
                            Some(p) => {
                                let mut b = 0; // The number of bytes written so far.
                                while b < p.len() {
                                    match sock.try_write(&p[b..]) {
                                        Ok(Some(x)) => {
                                            b += x
                                        }
                                        Ok(None) => {
                                            return Response::done();
                                        }
                                        Err(e) => {
                                            writeln!(&mut stderr(), "write: {}", e).ok();
                                            return Response::done();
                                        }
                                    }
                                }

                                Response::done()
                            }
                            None => {
                                let token = str::from_utf8(&data[..x-2]).unwrap();
                                let d = &format!("3Sorry, but the requested token '{}' could not be found.\tErr\tlocalhost\t70\r\n.", token)[..];
                                match sock.try_write(d.as_bytes()) {
                                    Ok(_) => Response::done(),
                                    Err(e) => {
                                        writeln!(&mut stderr(), "write: {}", e).ok();
                                        Response::done()
                                    }
                                }
                            }
                        }
                    }
                    Ok(None) => {
                        Response::ok(Gopher::Connection(sock))
                    }
                }
            }
        }
    }
    fn spawned(self, _scope: &mut Scope<Context>) -> Response<Self, TcpStream>
    {
        match self {
            me @ Gopher::Server(..) => me.accept(),
            _ => unreachable!(),
        }
    }
    fn timeout(self, _scope: &mut Scope<Context>)
        -> Response<Self, TcpStream>
    {
        unreachable!();
    }
    fn wakeup(self, _scope: &mut Scope<Context>)
        -> Response<Self, TcpStream>
    {
        unreachable!();
    }
}
<|endoftext|>


<commit_before>
use BuildQuery;
use Groups;

// https://docs.gitlab.com/ce/api/groups.html
// List groups:                 GET /groups
// List owned groups:           GET /groups/owned
// List a group's projects:     GET /groups/:id/projects
// Details of a group:          GET /groups/:id
// New group:                   POST /groups
// Transfer project to group:   POST  /groups/:id/projects/:project_id
// Update group:                PUT /groups/:id
// Remove group:                DELETE /groups/:id
// Search for group:            GET /groups?search=foobar

// https://docs.gitlab.com/ce/api/groups.html#list-groups

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsOrderBy {
    Name,
    Path,
}

// impl Default for GroupListerOptionsOrderBy {
//     fn default() -> GroupListerOptionsOrderBy { GroupListerOptionsOrderBy::Name }
// }

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsSort {
    Asc,
    Desc,
}

// impl Default for GroupListerOptionsSort {
//     fn default() -> GroupListerOptionsSort { GroupListerOptionsSort::Asc }
// }

fn append_group_lister_options_order_by(order_by: GroupListerOptionsOrderBy, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsOrderBy::Name => "name",
        GroupListerOptionsOrderBy::Path => "path",
    });
}

fn append_group_lister_options_sort(order_by: GroupListerOptionsSort, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsSort::Asc => "asc",
        GroupListerOptionsSort::Desc => "desc",
    });
}

/// https://docs.gitlab.com/ce/api/groups.html#list-groups
#[derive(Default, Debug)]
struct GroupListerOptions {
    /// Skip the group IDs passes
    pub skip_groups: Option<Vec<i64>>,
    /// Show all the groups you have access to
    pub all_available: Option<bool>,
    /// Return list of authorized groups matching the search criteria
    pub search: Option<String>,
    /// Order groups by `name` or `path`. Default is `name`
    pub order_by: Option<GroupListerOptionsOrderBy>,
    /// Order groups in `asc` or `desc` order. Default is `asc`
    pub sort: Option<GroupListerOptionsSort>,
}

#[derive(Default, Debug)]
pub struct GroupListing {
    options: GroupListerOptions,
}

impl BuildQuery for GroupListing {
    fn build_query(&self) -> String {

        let options = &self.options;

        let mut query = String::from("groups");

        // FIXME: Add skip_groups

        // Append a "?", only if one of the `Option` is `Some(_)`
        query.push_str(match (&options.skip_groups,
                              &options.all_available,
                              &options.search,
                              &options.order_by,
                              &options.sort) {
            (&None, &None, &None, &None, &None) => "",
            _ => "?",
        });

        options.all_available.map(|all_available| {
            if all_available {
                query.push_str("all_available=true")
            } else {
                query.push_str("all_available=false")
            }
        });

        options.search.as_ref().map(|search| {
            query.push_str("search=");
            query.push_str(search);
        });

        options.order_by.map(|order_by| {
            query.push_str("order_by=");
            append_group_lister_options_order_by(order_by, &mut query);
        });

        options.sort.map(|sort| {
            query.push_str("sort=");
            append_group_lister_options_sort(sort, &mut query);
        });

        query
    }
}

impl GroupListing {
    fn list(&self) -> Groups {
        let groups: Groups = vec![];

        groups
    }
}

#[test]
fn test_append_group_lister_options_order_by() {
    let expected_string = "Initialnamepathpathname";

    let mut s = String::from("Initial");

    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn test_append_group_lister_options_sort() {
    let expected_string = "Initialascdescascdesc";

    let mut s = String::from("Initial");

    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn groups_build_query_default() {
    let expected_string = "groups";
    let listing: GroupListing = Default::default();
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups";
    let listing = GroupListing { options: Default::default() };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

// FIXME: Add for 'skip_groups'

#[test]
fn groups_build_query_all_available() {
    let expected_string = "groups?all_available=true";
    let listing = GroupListing {
        options: GroupListerOptions {
            all_available: Some(true),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?all_available=false";
    let listing = GroupListing {
        options: GroupListerOptions {
            all_available: Some(false),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search() {
    let expected_string = "groups?search=SearchPattern";
    let listing = GroupListing {
        options: GroupListerOptions {
            search: Some(String::from("SearchPattern")),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_name() {
    let expected_string = "groups?order_by=name";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Name),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_path() {
    let expected_string = "groups?order_by=path";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Path),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_sort() {
    let expected_string = "groups?sort=asc";
    let listing = GroupListing {
        options: GroupListerOptions {
            sort: Some(GroupListerOptionsSort::Asc),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?sort=desc";
    let listing = GroupListing {
        options: GroupListerOptions {
            sort: Some(GroupListerOptionsSort::Desc),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search_order_by_path() {
    let expected_string = "groups?search=SearchPattern&order_by=path";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Path),
            search: Some(String::from("SearchPattern")),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}
<commit_msg>Make sure to separate options with "&"<commit_after>
use BuildQuery;
use Groups;

// https://docs.gitlab.com/ce/api/groups.html
// List groups:                 GET /groups
// List owned groups:           GET /groups/owned
// List a group's projects:     GET /groups/:id/projects
// Details of a group:          GET /groups/:id
// New group:                   POST /groups
// Transfer project to group:   POST  /groups/:id/projects/:project_id
// Update group:                PUT /groups/:id
// Remove group:                DELETE /groups/:id
// Search for group:            GET /groups?search=foobar

// https://docs.gitlab.com/ce/api/groups.html#list-groups

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsOrderBy {
    Name,
    Path,
}

// impl Default for GroupListerOptionsOrderBy {
//     fn default() -> GroupListerOptionsOrderBy { GroupListerOptionsOrderBy::Name }
// }

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsSort {
    Asc,
    Desc,
}

// impl Default for GroupListerOptionsSort {
//     fn default() -> GroupListerOptionsSort { GroupListerOptionsSort::Asc }
// }

fn append_group_lister_options_order_by(order_by: GroupListerOptionsOrderBy, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsOrderBy::Name => "name",
        GroupListerOptionsOrderBy::Path => "path",
    });
}

fn append_group_lister_options_sort(order_by: GroupListerOptionsSort, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsSort::Asc => "asc",
        GroupListerOptionsSort::Desc => "desc",
    });
}

/// https://docs.gitlab.com/ce/api/groups.html#list-groups
#[derive(Default, Debug)]
struct GroupListerOptions {
    /// Skip the group IDs passes
    pub skip_groups: Option<Vec<i64>>,
    /// Show all the groups you have access to
    pub all_available: Option<bool>,
    /// Return list of authorized groups matching the search criteria
    pub search: Option<String>,
    /// Order groups by `name` or `path`. Default is `name`
    pub order_by: Option<GroupListerOptionsOrderBy>,
    /// Order groups in `asc` or `desc` order. Default is `asc`
    pub sort: Option<GroupListerOptionsSort>,
}

#[derive(Default, Debug)]
pub struct GroupListing {
    options: GroupListerOptions,
}

impl BuildQuery for GroupListing {
    fn build_query(&self) -> String {

        let options = &self.options;

        let mut query = String::from("groups");
        let mut previous_option_present = false;

        // FIXME: Add skip_groups

        // Append a "?", only if one of the `Option` is `Some(_)`
        query.push_str(match (&options.skip_groups,
                              &options.all_available,
                              &options.search,
                              &options.order_by,
                              &options.sort) {
            (&None, &None, &None, &None, &None) => "",
            _ => "?",
        });

        options.all_available.map(|all_available| {
            if previous_option_present {
                query.push_str("&");
            }
            if all_available {
                query.push_str("all_available=true")
            } else {
                query.push_str("all_available=false")
            }
            previous_option_present = true;
        });

        options.search.as_ref().map(|search| {
            if previous_option_present {
                query.push_str("&");
            }
            query.push_str("search=");
            query.push_str(search);
            previous_option_present = true;
        });

        options.order_by.map(|order_by| {
            if previous_option_present {
                query.push_str("&");
            }
            query.push_str("order_by=");
            append_group_lister_options_order_by(order_by, &mut query);
            previous_option_present = true;
        });

        options.sort.map(|sort| {
            if previous_option_present {
                query.push_str("&");
            }
            query.push_str("sort=");
            append_group_lister_options_sort(sort, &mut query);
            previous_option_present = true;
        });

        query
    }
}

impl GroupListing {
    fn list(&self) -> Groups {
        let groups: Groups = vec![];

        groups
    }
}

#[test]
fn test_append_group_lister_options_order_by() {
    let expected_string = "Initialnamepathpathname";

    let mut s = String::from("Initial");

    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn test_append_group_lister_options_sort() {
    let expected_string = "Initialascdescascdesc";

    let mut s = String::from("Initial");

    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn groups_build_query_default() {
    let expected_string = "groups";
    let listing: GroupListing = Default::default();
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups";
    let listing = GroupListing { options: Default::default() };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

// FIXME: Add for 'skip_groups'

#[test]
fn groups_build_query_all_available() {
    let expected_string = "groups?all_available=true";
    let listing = GroupListing {
        options: GroupListerOptions {
            all_available: Some(true),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?all_available=false";
    let listing = GroupListing {
        options: GroupListerOptions {
            all_available: Some(false),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search() {
    let expected_string = "groups?search=SearchPattern";
    let listing = GroupListing {
        options: GroupListerOptions {
            search: Some(String::from("SearchPattern")),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_name() {
    let expected_string = "groups?order_by=name";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Name),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_path() {
    let expected_string = "groups?order_by=path";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Path),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_sort() {
    let expected_string = "groups?sort=asc";
    let listing = GroupListing {
        options: GroupListerOptions {
            sort: Some(GroupListerOptionsSort::Asc),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?sort=desc";
    let listing = GroupListing {
        options: GroupListerOptions {
            sort: Some(GroupListerOptionsSort::Desc),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search_order_by_path() {
    let expected_string = "groups?search=SearchPattern&order_by=path";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Path),
            search: Some(String::from("SearchPattern")),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}
<|endoftext|>