<commit_before>use rand::{StdRng, Rng};
use game_state::*;
use settings::*;

pub struct GameLogic {
    game_state: GameState,
    settings: Settings,
    rng: StdRng
}

impl GameLogic {
    pub fn new() -> GameLogic {
        GameLogic{ game_state: GameState::new(), settings: Settings::new(), rng: StdRng::new().unwrap() }
    }

    pub fn process_input(&mut self, line: &str) {
        let parts: Vec<&str> = line.split_whitespace().collect();
        match parts[0] {
            "settings" => self.settings.update(parts[1], parts[2]),
            "action" => self.make_move(parts[2]),
            "update" => self.game_state.update(parts[1], parts[2], parts[3]),
            _ => {}
        }
    }

    fn make_move(&mut self, _time: &str) {
        //TODO:: Change out the random moves for something cooler
        let xpos = self.rng.gen::<u32>() % self.settings.field_width;
        let ypos = self.rng.gen::<u32>() % self.settings.field_height;

        if self.validate_move(xpos, ypos) {
            println!("place_move {} {}", xpos, ypos);
        } else {
            println!("pass");
        }
    }

    fn validate_move(&self, xpos: u32, ypos: u32) -> bool {
        //Note:: This will also handle the KO rule
        let is_empty = self.get_point(xpos, ypos) == Point::Empty;
        if !is_empty { return false; }

        //one side must be empty (e.g. a new peice at this position must have at least one liberty)
        let is_suicide = (xpos == 0                              || self.get_point(xpos - 1, ypos)     != Point::Empty) &&
                         (xpos + 1 >= self.settings.field_width  || self.get_point(xpos + 1, ypos)     != Point::Empty) &&
                         (ypos == 0                              || self.get_point(xpos,     ypos - 1) != Point::Empty) &&
                         (ypos + 1 >= self.settings.field_height || self.get_point(xpos,     ypos + 1) != Point::Empty);
        !is_suicide
    }

    fn get_point(&self, xpos: u32, ypos: u32) -> Point {
        let index = GameLogic::coods_to_index(xpos, ypos, self.settings.field_width) as usize;
        self.game_state.field[index]
    }

    fn coods_to_index(xpos: u32, ypos: u32, width: u32) -> u32 {
        width * ypos + xpos
    }
}<commit_msg>Update game_logic.rs<commit_after>use rand::{StdRng, Rng};
use game_state::*;
use settings::*;

pub struct GameLogic {
    game_state: GameState,
    settings: Settings,
    rng: StdRng
}

impl GameLogic {
    pub fn new() -> GameLogic {
        GameLogic{ game_state: GameState::new(), settings: Settings::new(), rng: StdRng::new().unwrap() }
    }

    pub fn process_input(&mut self, line: &str) {
        let parts: Vec<&str> = line.split_whitespace().collect();
        match parts[0] {
            "settings" => self.settings.update(parts[1], parts[2]),
            "action" => self.make_move(parts[2]),
            "update" => self.game_state.update(parts[1], parts[2], parts[3]),
            _ => {}
        }
    }

    fn make_move(&mut self, _time: &str) {
        //TODO:: Change out the random moves for something cooler
        let xpos = self.rng.gen::<u32>() % self.settings.field_width;
        let ypos = self.rng.gen::<u32>() % self.settings.field_height;

        if self.is_move_valid(xpos, ypos) {
            println!("place_move {} {}", xpos, ypos);
        } else {
            println!("pass");
        }
    }

    fn is_move_valid(&self, xpos: u32, ypos: u32) -> bool {
        //Note:: This will also handle the KO rule
        let is_empty = self.get_point(xpos, ypos) == Point::Empty;
        if !is_empty { return false; }

        //one side must be empty (e.g. a new peice at this position must have at least one liberty)
        let is_suicide = (xpos == 0                              || self.get_point(xpos - 1, ypos)     != Point::Empty) &&
                         (xpos + 1 >= self.settings.field_width  || self.get_point(xpos + 1, ypos)     != Point::Empty) &&
                         (ypos == 0                              || self.get_point(xpos,     ypos - 1) != Point::Empty) &&
                         (ypos + 1 >= self.settings.field_height || self.get_point(xpos,     ypos + 1) != Point::Empty);
        !is_suicide
    }

    fn get_point(&self, xpos: u32, ypos: u32) -> Point {
        let index = GameLogic::coods_to_index(xpos, ypos, self.settings.field_width) as usize;
        self.game_state.field[index]
    }

    fn coods_to_index(xpos: u32, ypos: u32, width: u32) -> u32 {
        width * ypos + xpos
    }
}
<|endoftext|>


<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 std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use smallvec::SmallVec;

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!()
            }
        }
    }

    /// Waits for multiple fences at once.
    ///
    /// # Panic
    ///
    /// Panicks if not all fences belong to the same device.
    pub fn multi_wait<'a, I>(iter: I, timeout_ns: u64) -> Result<(), OomError>      // FIXME: wrong error
        where I: IntoIterator<Item = &'a Fence>
    {
        let mut device = None;

        let fences: SmallVec<[vk::Fence; 8]> = iter.into_iter().filter_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 wait for  multiple fences that didn't belong to the same device"),
            };

            if fence.signaled.load(Ordering::Relaxed) {
                None
            } else {
                Some(fence.fence)
            }
        }).collect();

        let r = if let Some(device) = device {
            unsafe {
                let vk = device.pointers();
                try!(check_errors(vk.WaitForFences(device.internal_object(), fences.len() as u32,
                                                   fences.as_ptr(), vk::TRUE, timeout_ns)))
            }
        } else {
            return Ok(());
        };

        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);
            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;

        let fences: SmallVec<[vk::Fence; 8]> = 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();
    }
}
<commit_msg>Add FenceWaitError<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::error;
use std::fmt;
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 smallvec::SmallVec;

use device::Device;
use device::Queue;
use Error;
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<(), FenceWaitError> {
        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 => {
                    Err(FenceWaitError::Timeout)
                },
                _ => unreachable!()
            }
        }
    }

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

        let fences: SmallVec<[vk::Fence; 8]> = iter.into_iter().filter_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 wait for  multiple fences that didn't belong to the same device"),
            };

            if fence.signaled.load(Ordering::Relaxed) {
                None
            } else {
                Some(fence.fence)
            }
        }).collect();

        let r = if let Some(device) = device {
            unsafe {
                let vk = device.pointers();
                try!(check_errors(vk.WaitForFences(device.internal_object(), fences.len() as u32,
                                                   fences.as_ptr(), vk::TRUE, timeout_ns)))
            }
        } else {
            return Ok(());
        };

        match r {
            Success::Success => Ok(()),
            Success::Timeout => Err(FenceWaitError::Timeout),
            _ => 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;

        let fences: SmallVec<[vk::Fence; 8]> = 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());
        }
    }
}

/// Error that can be returned when waiting on a fence.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum FenceWaitError {
    /// Not enough memory to complete the wait.
    OomError(OomError),

    /// The specified timeout wasn't long enough.
    Timeout,

    /// The device has been lost.
    DeviceLostError,
}

impl error::Error for FenceWaitError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            FenceWaitError::OomError(_) => "no memory available",
            FenceWaitError::Timeout => "the timeout has been reached",
            FenceWaitError::DeviceLostError => "the device was lost",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            FenceWaitError::OomError(ref err) => Some(err),
            _ => None
        }
    }
}

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

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

/// 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>use super::SplitPanelResult;
use crate::series::config::SeriesConfig;
use crate::series::{SeriesParams, SeriesPath};
use crate::try_opt_ret;
use crate::tui::component::input::{Input, NameInput, ParsedValue, ValidatedInput};
use crate::tui::component::{Component, Draw};
use crate::tui::widget_util::{block, text};
use crate::tui::UIState;
use anime::local::EpisodeParser;
use anime::remote::SeriesInfo as RemoteInfo;
use anyhow::Result;
use termion::event::Key;
use tui::backend::Backend;
use tui::layout::{Alignment, Constraint, Direction, Layout, Rect};
use tui::style::Color;
use tui::terminal::Frame;
use tui::widgets::Paragraph;

pub struct AddPanel {
    name_input: NameInput,
    data: Option<PartialData>,
}

impl AddPanel {
    pub fn new(info: RemoteInfo, path: SeriesPath) -> Self {
        Self {
            name_input: NameInput::new(true),
            data: Some(PartialData::new(info, path)),
        }
    }
}

impl Component for AddPanel {
    type State = UIState;
    type KeyResult = Result<SplitPanelResult>;

    fn process_key(&mut self, key: Key, state: &mut Self::State) -> Self::KeyResult {
        match key {
            Key::Esc => Ok(SplitPanelResult::Reset),
            Key::Char('\n') => {
                self.name_input.validate();

                if self.name_input.has_error() {
                    return Ok(SplitPanelResult::Ok);
                }

                let data = match self.data.take() {
                    Some(data) => data,
                    None => return Ok(SplitPanelResult::Reset),
                };

                let name = self.name_input.parsed_value();
                let params = SeriesParams::new(name, data.path, EpisodeParser::Default);
                let sconfig = SeriesConfig::new(data.info.id as i32, params, &state.db)?;

                Ok(SplitPanelResult::add_series(data.info, sconfig))
            }
            key => {
                self.name_input.input_mut().process_key(key);
                self.name_input.validate();
                Ok(SplitPanelResult::Ok)
            }
        }
    }
}

impl<B> Draw<B> for AddPanel
where
    B: Backend,
{
    type State = ();

    fn draw(&mut self, _: &Self::State, rect: Rect, frame: &mut Frame<B>) {
        let data = try_opt_ret!(&self.data);

        let outline = block::with_borders("Enter Name For Series");
        frame.render_widget(outline, rect);

        let vert_split = Layout::default()
            .direction(Direction::Vertical)
            .constraints(
                [
                    Constraint::Ratio(1, 3),
                    Input::DRAW_WITH_LABEL_CONSTRAINT,
                    Constraint::Min(1),
                    Constraint::Length(1),
                ]
                .as_ref(),
            )
            .horizontal_margin(2)
            .vertical_margin(3)
            .split(rect);

        let title_text = [text::bold(&data.info.title.preferred)];
        let title_widget = Paragraph::new(title_text.iter())
            .wrap(false)
            .alignment(Alignment::Center);
        frame.render_widget(title_widget, vert_split[0]);

        let name_layout = Layout::default()
            .direction(Direction::Horizontal)
            .constraints(
                [
                    Constraint::Percentage(20),
                    Constraint::Percentage(60),
                    Constraint::Percentage(20),
                ]
                .as_ref(),
            )
            .split(vert_split[1]);

        self.name_input.draw(&(), name_layout[1], frame);

        if let Some(error) = self.name_input.error() {
            let error_text = [text::bold_with(error, |s| s.fg(Color::Red))];
            let error_widget = Paragraph::new(error_text.iter())
                .alignment(Alignment::Center)
                .wrap(false);
            frame.render_widget(error_widget, vert_split[3]);
        }
    }
}

struct PartialData {
    info: RemoteInfo,
    path: SeriesPath,
}

impl PartialData {
    #[inline(always)]
    fn new(info: RemoteInfo, path: SeriesPath) -> Self {
        Self { info, path }
    }
}
<commit_msg>anup: Autofill name input when adding a series that has been split<commit_after>use super::SplitPanelResult;
use crate::series::config::SeriesConfig;
use crate::series::{SeriesParams, SeriesPath};
use crate::try_opt_ret;
use crate::tui::component::input::{Input, NameInput, ParsedValue, ValidatedInput};
use crate::tui::component::{Component, Draw};
use crate::tui::widget_util::{block, text};
use crate::tui::UIState;
use anime::local::EpisodeParser;
use anime::remote::SeriesInfo as RemoteInfo;
use anyhow::Result;
use termion::event::Key;
use tui::backend::Backend;
use tui::layout::{Alignment, Constraint, Direction, Layout, Rect};
use tui::style::Color;
use tui::terminal::Frame;
use tui::widgets::Paragraph;

pub struct AddPanel {
    name_input: NameInput,
    data: Option<PartialData>,
}

impl AddPanel {
    pub fn new(info: RemoteInfo, path: SeriesPath) -> Self {
        use anime::local::detect::dir as anime_dir;

        let name_input = anime_dir::generate_nickname(&info.title.preferred)
            .map(|nickname| NameInput::with_placeholder(true, nickname))
            .unwrap_or_else(|| NameInput::new(true));

        Self {
            name_input,
            data: Some(PartialData::new(info, path)),
        }
    }
}

impl Component for AddPanel {
    type State = UIState;
    type KeyResult = Result<SplitPanelResult>;

    fn process_key(&mut self, key: Key, state: &mut Self::State) -> Self::KeyResult {
        match key {
            Key::Esc => Ok(SplitPanelResult::Reset),
            Key::Char('\n') => {
                self.name_input.validate();

                if self.name_input.has_error() {
                    return Ok(SplitPanelResult::Ok);
                }

                let data = match self.data.take() {
                    Some(data) => data,
                    None => return Ok(SplitPanelResult::Reset),
                };

                let name = self.name_input.parsed_value();
                let params = SeriesParams::new(name, data.path, EpisodeParser::Default);
                let sconfig = SeriesConfig::new(data.info.id as i32, params, &state.db)?;

                Ok(SplitPanelResult::add_series(data.info, sconfig))
            }
            key => {
                self.name_input.input_mut().process_key(key);
                self.name_input.validate();
                Ok(SplitPanelResult::Ok)
            }
        }
    }
}

impl<B> Draw<B> for AddPanel
where
    B: Backend,
{
    type State = ();

    fn draw(&mut self, _: &Self::State, rect: Rect, frame: &mut Frame<B>) {
        let data = try_opt_ret!(&self.data);

        let outline = block::with_borders("Enter Name For Series");
        frame.render_widget(outline, rect);

        let vert_split = Layout::default()
            .direction(Direction::Vertical)
            .constraints(
                [
                    Constraint::Ratio(1, 3),
                    Input::DRAW_WITH_LABEL_CONSTRAINT,
                    Constraint::Min(1),
                    Constraint::Length(1),
                ]
                .as_ref(),
            )
            .horizontal_margin(2)
            .vertical_margin(3)
            .split(rect);

        let title_text = [text::bold(&data.info.title.preferred)];
        let title_widget = Paragraph::new(title_text.iter())
            .wrap(false)
            .alignment(Alignment::Center);
        frame.render_widget(title_widget, vert_split[0]);

        let name_layout = Layout::default()
            .direction(Direction::Horizontal)
            .constraints(
                [
                    Constraint::Percentage(20),
                    Constraint::Percentage(60),
                    Constraint::Percentage(20),
                ]
                .as_ref(),
            )
            .split(vert_split[1]);

        self.name_input.draw(&(), name_layout[1], frame);

        if let Some(error) = self.name_input.error() {
            let error_text = [text::bold_with(error, |s| s.fg(Color::Red))];
            let error_widget = Paragraph::new(error_text.iter())
                .alignment(Alignment::Center)
                .wrap(false);
            frame.render_widget(error_widget, vert_split[3]);
        }
    }
}

struct PartialData {
    info: RemoteInfo,
    path: SeriesPath,
}

impl PartialData {
    #[inline(always)]
    fn new(info: RemoteInfo, path: SeriesPath) -> Self {
        Self { info, path }
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::collections::VecDeque;
use secp256k1::key::PublicKey;
use vec_map::VecMap;
use bit_set::BitSet;

use messages::*;
use super::*;
use self::history::*;
use self::peer::Peer;

mod history;
pub mod peer;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum DcPhase {
    Exponential,
    Main,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum RunState {
    DcProcess(DcPhase),
    DcReveal(DcPhase),
    Blame,
    Confirm,
}

impl PartialOrd for RunState {
    fn partial_cmp(&self, other: &RunState) -> Option<Ordering> {
        // This is ugly but not uglier than using std::intrinsics::discriminant_value,
        // which does guarantee a proper ordering and would force us to use debug assertions
        // anyway. Note that std::mem::Discriminant<T> does not implement PartialOrd either,
        // because it relies on std::intrinsics::discriminant_value.
        // If this changes in the future, we can replace this function.
        #[inline]
        fn discriminant(x: &RunState) -> u32 {
            match *x {
                RunState::DcProcess(DcPhase::Exponential) => 0,
                RunState::DcReveal(DcPhase::Exponential) => 1,
                RunState::DcProcess(DcPhase::Main) => 2,
                RunState::DcReveal(DcPhase::Main) => 3,
                RunState::Blame => 4,
                RunState::Confirm => 5,
            }
        }

        match (*self, *other) {
            (RunState::Blame, RunState::Confirm) => None,
            (RunState::Confirm, RunState::Blame) => None,
            _ => discriminant(self).partial_cmp(&discriminant(other)),
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
struct RunStateMachine {
    run: RunCounter,
    state: RunState,
    kepks: VecMap<PublicKey>,
    received: BitSet,
    otvk_hashes: Option<Vec<[u8; 32]>>,
    peers_before_dc_exponential: Option<BitSet>,
    peers_before_dc_main: Option<BitSet>,
}

impl RunStateMachine {
    fn new(&mut self, run: RunCounter, kepks: VecMap<PublicKey>) -> Self {
        let num_peers = kepks.len();
        let new = Self {
            run: 0,
            state: RunState::DcProcess(DcPhase::Exponential),
            kepks: kepks,
            received: BitSet::with_capacity(num_peers),
            otvk_hashes: None,
            peers_before_dc_exponential: None,
            peers_before_dc_main: None,
        };
        debug_assert!(new.consistent());
        new
    }

    #[inline]
    fn num_peers(&self) -> usize {
        self.kepks.len()
    }

    #[inline]
    fn set_state(&mut self, state: RunState) {
        assert!(self.state < state);
        self.state = state;
    }

    #[inline]
    fn consistent(&self) -> bool {
        // TODO check also the state ...
        match (self.peers_before_dc_exponential.is_some(),
               self.otvk_hashes.is_some(),
               self.peers_before_dc_main.is_some()) {
            (false, false, false) => true,
            (false, _, _) => false,
            (true, x, y) => x == y,
        }
    }

    fn process_message(&mut self, msg: Message) -> Option<Payload> {
        // TODO Reject messages with wrong session id
        // TODO Reject messages with wrong sequence number
        // TODO Reject messages with invalid signature

        // The message has a correct signature and is intended for this state of this session.
        // So we can record it.
        let first_from_peer = self.received.insert(msg.header.peer_index as usize);

        // Reject the message if we have recorded a message from this peer already.
        if !first_from_peer {
            return None;
        }
        self.process_payload(msg.payload)
    }

    fn process_payload(&self, payload: Payload) -> Option<Payload> {
        match(self.state, payload) {
            (RunState::DcProcess(DcPhase::Exponential), Payload::DcExponential(msg)) => {
                unimplemented!()
            },
            (RunState::DcProcess(DcPhase::Main), Payload::DcMain(msg)) => {
                unimplemented!()
            },
            (RunState::DcReveal(phase), Payload::Reveal(msg)) => {
                unimplemented!()
            },
            (RunState::Blame, Payload::Blame(msg)) => {
                unimplemented!()
            },
            (RunState::Confirm, Payload::Confirm(msg)) => {
                unimplemented!()
            },
            _ => {
                // TODO Kick the peer out
                unimplemented!()
            }
        }
        assert!(self.consistent());
    }
}

<commit_msg>Remove solved TODOs<commit_after>use std::cmp::Ordering;
use std::collections::VecDeque;
use secp256k1::key::PublicKey;
use vec_map::VecMap;
use bit_set::BitSet;

use messages::*;
use super::*;
use self::history::*;
use self::peer::Peer;

mod history;
pub mod peer;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum DcPhase {
    Exponential,
    Main,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum RunState {
    DcProcess(DcPhase),
    DcReveal(DcPhase),
    Blame,
    Confirm,
}

impl PartialOrd for RunState {
    fn partial_cmp(&self, other: &RunState) -> Option<Ordering> {
        // This is ugly but not uglier than using std::intrinsics::discriminant_value,
        // which does guarantee a proper ordering and would force us to use debug assertions
        // anyway. Note that std::mem::Discriminant<T> does not implement PartialOrd either,
        // because it relies on std::intrinsics::discriminant_value.
        // If this changes in the future, we can replace this function.
        #[inline]
        fn discriminant(x: &RunState) -> u32 {
            match *x {
                RunState::DcProcess(DcPhase::Exponential) => 0,
                RunState::DcReveal(DcPhase::Exponential) => 1,
                RunState::DcProcess(DcPhase::Main) => 2,
                RunState::DcReveal(DcPhase::Main) => 3,
                RunState::Blame => 4,
                RunState::Confirm => 5,
            }
        }

        match (*self, *other) {
            (RunState::Blame, RunState::Confirm) => None,
            (RunState::Confirm, RunState::Blame) => None,
            _ => discriminant(self).partial_cmp(&discriminant(other)),
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
struct RunStateMachine {
    run: RunCounter,
    state: RunState,
    kepks: VecMap<PublicKey>,
    received: BitSet,
    otvk_hashes: Option<Vec<[u8; 32]>>,
    peers_before_dc_exponential: Option<BitSet>,
    peers_before_dc_main: Option<BitSet>,
}

impl RunStateMachine {
    fn new(&mut self, run: RunCounter, kepks: VecMap<PublicKey>) -> Self {
        let num_peers = kepks.len();
        let new = Self {
            run: 0,
            state: RunState::DcProcess(DcPhase::Exponential),
            kepks: kepks,
            received: BitSet::with_capacity(num_peers),
            otvk_hashes: None,
            peers_before_dc_exponential: None,
            peers_before_dc_main: None,
        };
        debug_assert!(new.consistent());
        new
    }

    #[inline]
    fn num_peers(&self) -> usize {
        self.kepks.len()
    }

    #[inline]
    fn set_state(&mut self, state: RunState) {
        assert!(self.state < state);
        self.state = state;
    }

    #[inline]
    fn consistent(&self) -> bool {
        // TODO check also the state ...
        match (self.peers_before_dc_exponential.is_some(),
               self.otvk_hashes.is_some(),
               self.peers_before_dc_main.is_some()) {
            (false, false, false) => true,
            (false, _, _) => false,
            (true, x, y) => x == y,
        }
    }

    fn process_message(&mut self, msg: Message) -> Option<Payload> {
        // The message has a correct signature and is intended for this state of this session.
        // So we can record it.
        let first_from_peer = self.received.insert(msg.header.peer_index as usize);

        // Reject the message if we have recorded a message from this peer already.
        if !first_from_peer {
            return None;
        }
        self.process_payload(msg.payload)
    }

    fn process_payload(&self, payload: Payload) -> Option<Payload> {
        match(self.state, payload) {
            (RunState::DcProcess(DcPhase::Exponential), Payload::DcExponential(msg)) => {
                unimplemented!()
            },
            (RunState::DcProcess(DcPhase::Main), Payload::DcMain(msg)) => {
                unimplemented!()
            },
            (RunState::DcReveal(phase), Payload::Reveal(msg)) => {
                unimplemented!()
            },
            (RunState::Blame, Payload::Blame(msg)) => {
                unimplemented!()
            },
            (RunState::Confirm, Payload::Confirm(msg)) => {
                unimplemented!()
            },
            _ => {
                // TODO Kick the peer out
                unimplemented!()
            }
        }
        assert!(self.consistent());
    }
}

<|endoftext|>


<commit_before>//! The `html_parse` module parses a string of html into dom node datastructures.

use dom::{AttrMap, ElementData, Node, NodeType};

use std::iter::Peekable;
use std::str::Chars;

pub struct HtmlParser<'a> {
    chars: Peekable<Chars<'a>>,
}

impl<'a> HtmlParser<'a> {
    /// Constructs a new HtmlParser.
    ///
    /// full_html: the complete html to parse.
    pub fn new(full_html: &str) -> HtmlParser {
        HtmlParser { chars: full_html.chars().peekable() }
    }

    /// Entry point to parsing html, recursively parses html nodes.
    /// TODO check tags match, deal with self closing tags
    pub fn parse_nodes(&mut self) -> Vec<Node> {
        let mut nodes = Vec::new();

        while self.chars.peek().is_some() {
            self.consume_while(char::is_whitespace);
            if self.chars.peek().map_or(false, |c| *c == '<') {
                self.chars.next();
                if self.chars.peek().map_or(false, |c| *c == '/') {
                    self.consume_while(|x| x != '>');
                    self.chars.next();
                    break;
                } else if self.chars.peek().map_or(false, |c| *c == '!') {
                    self.chars.next();
                    nodes.push(self.parse_comment_node());
                } else {
                    nodes.push(self.parse_node());
                }
            } else {
                nodes.push(self.parse_text_node());
            }
        }
        nodes
    }

    /// Parse a single html node and recursively call parse_nodes on children.
    fn parse_node(&mut self) -> Node {
        // is an valid tagname
        let tagname = self.consume_while(|x| x.is_digit(36));
        let attributes = self.parse_attributes();

        let elem = ElementData::new(tagname, attributes);
        let children = self.parse_nodes();
        Node::new(NodeType::Element(elem), children)
    }

    /// Consume the text between '>' and '<' to produce a text node.
    /// TODO deal with control characters and U+0000
    fn parse_text_node(&mut self) -> Node {
        let mut text_content = String::new();

        while self.chars.peek().map_or(false, |c| *c != '<') {
            let whitespace = self.consume_while(char::is_whitespace);
            if whitespace.len() > 0 {
                text_content.push(' ');
            }
            let text_part = self.consume_while(|x| !x.is_whitespace() && x != '<');
            text_content.push_str(&text_part);
        }
        Node::new(NodeType::Text(text_content), Vec::new())
    }

    /// Consume text between "" to produce a comment node.
    fn parse_comment_node(&mut self) -> Node {
        let mut comment_content = String::new();

        if self.chars.peek().map_or(false, |c| *c == '-') {
            self.chars.next();
            if self.chars.peek().map_or(false, |c| *c == '-') {
                self.chars.next();
                if self.chars.peek().map_or(false, |c| *c == '>') {
                    // invalid comment format
                    self.chars.next();
                    return Node::new(NodeType::Comment(comment_content), Vec::new());
                } else if self.chars.peek().map_or(false, |c| *c == '-') {
                    self.chars.next();
                    if self.chars.peek().map_or(false, |c| *c == '>') {
                        // invalid comment format
                        self.chars.next();
                        return Node::new(NodeType::Comment(comment_content), Vec::new());
                    } else {
                        comment_content.push('-');
                    }
                }
                while self.chars.peek().is_some() {
                    comment_content.push_str(&self.consume_while(|x| x != '-'));
                    if self.chars.peek().map_or(false, |c| *c == '-') {
                        self.chars.next();
                        if self.chars.peek().map_or(false, |c| *c == '-') {
                            self.consume_while(|x| x != '>');
                            self.chars.next();
                            break;
                        } else {
                            comment_content.push('-')
                        }
                    }
                }
            }
        }
        Node::new(NodeType::Comment(comment_content), Vec::new())
    }

    /// Consume characters after a tagname until '>' and return a map.
    fn parse_attributes(&mut self) -> AttrMap {
        let mut attributes = AttrMap::new();

        while self.chars.peek().map_or(false, |c| *c != '>') {
            self.consume_while(char::is_whitespace);
            let name = self.consume_while(|c| is_valid_attr_name(c)).to_lowercase();
            self.consume_while(char::is_whitespace);

            let value = if self.chars.peek().map_or(false, |c| *c == '=') {
                self.chars.next(); // consume the '='
                self.consume_while(char::is_whitespace);
                let s = self.parse_attr_value();
                // cleans up aftere any invalid characters
                self.consume_while(|c| !c.is_whitespace() && c != '>');
                self.consume_while(char::is_whitespace);
                s
            } else {
                "".to_string()
            };
            attributes.insert(name, value);
        }
        self.chars.next(); // consume the '>' if it exists.

        attributes
    }

    /// Consume an attribute value and return it.
    fn parse_attr_value(&mut self) -> String {
        self.consume_while(char::is_whitespace);

        let result = match self.chars.peek() {
            Some(&c) if c == '"' || c == '\'' => {
                self.chars.next();
                let ret = self.consume_while(|x| x != c);
                self.chars.next(); // consume the quote
                ret
            },
            _ => self.consume_while(is_valid_attr_value),
        };

        result
    }

    /// Consumes characters until condition is false or there are no more chars left.
    /// Returns a string of the consumed characters.
    fn consume_while<F>(&mut self, condition: F) -> String where F : Fn(char) -> bool {
        let mut result = String::new();
        while self.chars.peek().map_or(false, |c| condition(*c)) {
            // the check above guarentees there is a value to be consumed
            result.push(self.chars.next().unwrap());
        }

        result
    }
}

/// Utility to check if a character can be used for an attribute name.
fn is_valid_attr_name(c: char) -> bool {
    !is_excluded_name(c) && !is_control(c)
}

fn is_control(ch: char) -> bool {
    match ch {
        '\u{007F}' => true,
        c if c >= '\u{0000}' && c <= '\u{001F}' => true,
        c if c >= '\u{0080}' && c <= '\u{009F}' => true,
        _ => false,
    }

}

fn is_excluded_name(c: char) -> bool {
    match c {
        ' '|'"'|'\''|'>'|'/'|'=' => true,
        _ => false,
    }
}

/// Utility to check if a character can be used for an attribute value.
/// TODO no ambiguous ampersand
fn is_valid_attr_value(c: char) -> bool {
    match c {
        ' '|'"'|'\''|'='|'<'|'>'|'`' => false,
        _ => true
    }
}

//TODO
//  -check and consume function that takes a condition
//  -script tags/link tags
//  -parse character references

/// Tests ----------------------------------------------------------------------
#[cfg(test)]
mod tests {
    use super::*;
    use super::is_control;
    use dom::AttrMap;

    use std::iter::Peekable;
    use std::str::Chars;

    /// Test a parser is constructed correctly.
    #[test]
    fn new_parser() {
        let (parser, mut expected_chars) = test_parser("
lel
");

        for character in parser.chars {
            assert_eq!(character, expected_chars.next().unwrap());
        }

        assert_eq!(None, expected_chars.peek());
    }

    /// Test an empty attr value is parsed correctly.
    #[test]
    fn attr_value_empty() {
        let (mut parser, _) = test_parser("");
        assert_eq!("", parser.parse_attr_value());
    }

    /// Test an empty attr value is parsed correctly.
    #[test]
    fn attr_value_end() {
        let (mut parser, _) = test_parser(">");
        assert_eq!("", parser.parse_attr_value());
    }

    /// Test an regular attr value is parsed correctly.
    #[test]
    fn attr_value_reg() {
        let (mut parser, _) = test_parser("regularValue");
        assert_eq!("regularValue", parser.parse_attr_value());

        let (mut parser, _) = test_parser("regularValue>");
        assert_eq!("regularValue", parser.parse_attr_value());

        let (mut parser, _) = test_parser("regularValue ");
        assert_eq!("regularValue", parser.parse_attr_value());

        let (mut parser, _) = test_parser("regular<Value");
        assert_eq!("regular", parser.parse_attr_value());

        let (mut parser, _) = test_parser("regular'Value");
        assert_eq!("regular", parser.parse_attr_value());
    }

    /// Test an quoted attr value is parsed correctly.
    #[test]
    fn attr_value_quote() {
        let (mut parser, _) = test_parser("'regularValue'");
        assert_eq!("regularValue", parser.parse_attr_value());

        let (mut parser, _) = test_parser("\"regular'>< -_=Value\"");
        assert_eq!("regular'>< -_=Value", parser.parse_attr_value());

        let (mut parser, _) = test_parser("'regular\">< -_=Value'");
        assert_eq!("regular\">< -_=Value", parser.parse_attr_value());

        let (mut parser, _) = test_parser("\"regular\">< -_=Value\"");
        assert_eq!("regular", parser.parse_attr_value());

        let (mut parser, _) = test_parser("'regular'>< -_=Value'");
        assert_eq!("regular", parser.parse_attr_value());
    }

    /// Test empty attributes are parsed correctly.
    #[test]
    fn attrs_empty() {
        let (mut parser, _) = test_parser("");
        assert_eq!(AttrMap::new(), parser.parse_attributes());
    }

    /// Test end attributes are parsed correctly.
    #[test]
    fn attrs_end() {
        let (mut parser, _) = test_parser(">");
        assert_eq!(AttrMap::new(), parser.parse_attributes());
    }

    /// Test regular well formed attributes are parsed correctly.
    #[test]
    fn attrs_regular() {
        let (mut parser, _) = test_parser("name0 name1=value1 kek name2  ='value2' name3  = \"value3\"  ");
        let mut expected = AttrMap::new();
        expected.insert("name0".to_string(), "".to_string());
        expected.insert("kek".to_string(), "".to_string());
        expected.insert("name1".to_string(), "value1".to_string());
        expected.insert("name2".to_string(), "value2".to_string());
        expected.insert("name3".to_string(), "value3".to_string());

        assert_eq!(expected, parser.parse_attributes());
    }

    /// Test an invalid attribute.
    #[test]
    fn attrs_invalid() {
        let (mut parser, _) = test_parser("name0 name1=val'ue1 name2='va l ue2'");
        let mut expected = AttrMap::new();
        expected.insert("name0".to_string(), "".to_string());
        expected.insert("name1".to_string(), "val".to_string());
        expected.insert("name2".to_string(), "va l ue2".to_string());

        assert_eq!(expected, parser.parse_attributes());
    }

    /// Test case insensitivity for attr names and case sensitivity for attr values.
    #[test]
    fn attrs_case() {
        let (mut parser, _) = test_parser("NameZero NAMEone=VALUEone NAMETWO='VALUETWO' namethree=valuethree");
        let mut expected = AttrMap::new();
        expected.insert("namezero".to_string(), "".to_string());
        expected.insert("nameone".to_string(), "VALUEone".to_string());
        expected.insert("nametwo".to_string(), "VALUETWO".to_string());
        expected.insert("namethree".to_string(), "valuethree".to_string());

        assert_eq!(expected, parser.parse_attributes());
    }

    /// Test empty comment node.
    #[test]
    fn comment_empty() {

    }

    /// Test end comment node.
    #[test]
    fn comment_end() {

    }

    /// Test regular comment node.
    #[test]
    fn comment_regular() {

    }

    /// Test if a character is a control character
    #[test]
    fn control_characters() {
        assert!(is_control('\u{0001}'));
        assert!(is_control('\u{007F}'));
        assert!(is_control('\u{0081}'));
        assert!(!is_control(' '));
    }

    /// Utility to return a parser for tests.
    fn test_parser<'a>(mock_html: &'a str) -> (HtmlParser, Peekable<Chars<'a>>) {
        let parser = HtmlParser::new(mock_html);
        let expected_chars = mock_html.chars().peekable();
        (parser, expected_chars)
    }
}
<commit_msg>finish comment node tests and rewriting parse_comment_node<commit_after>//! The `html_parse` module parses a string of html into dom node datastructures.

use dom::{AttrMap, ElementData, Node, NodeType};

use std::iter::Peekable;
use std::str::Chars;

pub struct HtmlParser<'a> {
    chars: Peekable<Chars<'a>>,
}

impl<'a> HtmlParser<'a> {
    /// Constructs a new HtmlParser.
    ///
    /// full_html: the complete html to parse.
    pub fn new(full_html: &str) -> HtmlParser {
        HtmlParser { chars: full_html.chars().peekable() }
    }

    /// Entry point to parsing html, recursively parses html nodes.
    /// TODO check tags match, deal with self closing tags
    pub fn parse_nodes(&mut self) -> Vec<Node> {
        let mut nodes = Vec::new();

        while self.chars.peek().is_some() {
            self.consume_while(char::is_whitespace);
            if self.chars.peek().map_or(false, |c| *c == '<') {
                self.chars.next();
                if self.chars.peek().map_or(false, |c| *c == '/') {
                    self.consume_while(|x| x != '>');
                    self.chars.next();
                    break;
                } else if self.chars.peek().map_or(false, |c| *c == '!') {
                    self.chars.next();
                    nodes.push(self.parse_comment_node());
                } else {
                    nodes.push(self.parse_node());
                }
            } else {
                nodes.push(self.parse_text_node());
            }
        }
        nodes
    }

    /// Parse a single html node and recursively call parse_nodes on children.
    fn parse_node(&mut self) -> Node {
        // is an valid tagname
        let tagname = self.consume_while(|x| x.is_digit(36));
        let attributes = self.parse_attributes();

        let elem = ElementData::new(tagname, attributes);
        let children = self.parse_nodes();
        Node::new(NodeType::Element(elem), children)
    }

    /// Consume the text between '>' and '<' to produce a text node.
    /// TODO deal with control characters and U+0000
    fn parse_text_node(&mut self) -> Node {
        let mut text_content = String::new();

        while self.chars.peek().map_or(false, |c| *c != '<') {
            let whitespace = self.consume_while(char::is_whitespace);
            if whitespace.len() > 0 {
                text_content.push(' ');
            }
            let text_part = self.consume_while(|x| !x.is_whitespace() && x != '<');
            text_content.push_str(&text_part);
        }
        Node::new(NodeType::Text(text_content), Vec::new())
    }

    /// Consume text between "" to produce a comment node.
    fn parse_comment_node(&mut self) -> Node {
        let mut comment_content = String::new();

        // ensure comment begins with  is an invalid sequence to end a comment
                    } else if self.chars.peek().map_or(false, |c| *c == ' ') {
                        self.chars.next();
                        if self.chars.peek().map_or(false, |c| *c == '-') {
                            self.chars.next();
                            if self.chars.peek().map_or(false, |c| *c == '-') {
                                self.chars.next();
                                if self.chars.peek().map_or(false, |c| *c == '-') {
                                    self.chars.next();
                                    if self.chars.peek().map_or(false, |c| *c == '>') {
                                        self.chars.next();
                                        return Node::new(NodeType::Comment(String::from("")), Vec::new());
                                    } else {
                                        comment_content.push_str("<! --");
                                    }
                                } else {
                                    comment_content.push_str("<! -");
                                }
                            } else {
                                comment_content.push_str("<! ");
                            }
                        }
                    } else {
                        comment_content.push_str("<!");
                    }
                } else {
                    comment_content.push('<');
                }
            } else if self.chars.peek().map_or(false, |c| *c == '-') {
                self.chars.next();
                if self.chars.peek().map_or(false, |c| *c == '-') {
                    self.chars.next();
                    if self.chars.peek().map_or(false, |c| *c == '>') {
                        self.chars.next();
                        break;
                    } else {
                        comment_content.push_str("--");
                    }
                } else {
                    comment_content.push('-');
                }
            }
        }

        Node::new(NodeType::Comment(comment_content), Vec::new())
    }

    /// Consume characters after a tagname until '>' and return a map.
    fn parse_attributes(&mut self) -> AttrMap {
        let mut attributes = AttrMap::new();

        while self.chars.peek().map_or(false, |c| *c != '>') {
            self.consume_while(char::is_whitespace);
            let name = self.consume_while(|c| is_valid_attr_name(c)).to_lowercase();
            self.consume_while(char::is_whitespace);

            let value = if self.chars.peek().map_or(false, |c| *c == '=') {
                self.chars.next(); // consume the '='
                self.consume_while(char::is_whitespace);
                let s = self.parse_attr_value();
                // cleans up aftere any invalid characters
                self.consume_while(|c| !c.is_whitespace() && c != '>');
                self.consume_while(char::is_whitespace);
                s
            } else {
                "".to_string()
            };
            attributes.insert(name, value);
        }
        self.chars.next(); // consume the '>' if it exists.

        attributes
    }

    /// Consume an attribute value and return it.
    fn parse_attr_value(&mut self) -> String {
        self.consume_while(char::is_whitespace);

        let result = match self.chars.peek() {
            Some(&c) if c == '"' || c == '\'' => {
                self.chars.next();
                let ret = self.consume_while(|x| x != c);
                self.chars.next(); // consume the quote
                ret
            },
            _ => self.consume_while(is_valid_attr_value),
        };

        result
    }

    /// Consumes characters until condition is false or there are no more chars left.
    /// Returns a string of the consumed characters.
    fn consume_while<F>(&mut self, condition: F) -> String where F : Fn(char) -> bool {
        let mut result = String::new();
        while self.chars.peek().map_or(false, |c| condition(*c)) {
            // the check above guarentees there is a value to be consumed
            result.push(self.chars.next().unwrap());
        }

        result
    }
}

/// Utility to check if a character can be used for an attribute name.
fn is_valid_attr_name(c: char) -> bool {
    !is_excluded_name(c) && !is_control(c)
}

fn is_control(ch: char) -> bool {
    match ch {
        '\u{007F}' => true,
        c if c >= '\u{0000}' && c <= '\u{001F}' => true,
        c if c >= '\u{0080}' && c <= '\u{009F}' => true,
        _ => false,
    }

}

fn is_excluded_name(c: char) -> bool {
    match c {
        ' '|'"'|'\''|'>'|'/'|'=' => true,
        _ => false,
    }
}

/// Utility to check if a character can be used for an attribute value.
/// TODO no ambiguous ampersand
fn is_valid_attr_value(c: char) -> bool {
    match c {
        ' '|'"'|'\''|'='|'<'|'>'|'`' => false,
        _ => true
    }
}

//TODO
//  -check and consume function that takes a condition
//  -script tags/link tags
//  -parse character references

/// Tests ----------------------------------------------------------------------
#[cfg(test)]
mod tests {
    use super::*;
    use super::is_control;
    use dom::{AttrMap, Node, NodeType};

    use std::iter::Peekable;
    use std::str::Chars;

    /// Test a parser is constructed correctly.
    #[test]
    fn new_parser() {
        let (parser, mut expected_chars) = test_parser("
lel
");

        for character in parser.chars {
            assert_eq!(character, expected_chars.next().unwrap());
        }

        assert_eq!(None, expected_chars.peek());
    }

    /// Test an empty attr value is parsed correctly.
    #[test]
    fn attr_value_empty() {
        let (mut parser, _) = test_parser("");
        assert_eq!("", parser.parse_attr_value());
    }

    /// Test an empty attr value is parsed correctly.
    #[test]
    fn attr_value_end() {
        let (mut parser, _) = test_parser(">");
        assert_eq!("", parser.parse_attr_value());
    }

    /// Test an regular attr value is parsed correctly.
    #[test]
    fn attr_value_reg() {
        let (mut parser, _) = test_parser("regularValue");
        assert_eq!("regularValue", parser.parse_attr_value());

        let (mut parser, _) = test_parser("regularValue>");
        assert_eq!("regularValue", parser.parse_attr_value());

        let (mut parser, _) = test_parser("regularValue ");
        assert_eq!("regularValue", parser.parse_attr_value());

        let (mut parser, _) = test_parser("regular<Value");
        assert_eq!("regular", parser.parse_attr_value());

        let (mut parser, _) = test_parser("regular'Value");
        assert_eq!("regular", parser.parse_attr_value());
    }

    /// Test an quoted attr value is parsed correctly.
    #[test]
    fn attr_value_quote() {
        let (mut parser, _) = test_parser("'regularValue'");
        assert_eq!("regularValue", parser.parse_attr_value());

        let (mut parser, _) = test_parser("\"regular'>< -_=Value\"");
        assert_eq!("regular'>< -_=Value", parser.parse_attr_value());

        let (mut parser, _) = test_parser("'regular\">< -_=Value'");
        assert_eq!("regular\">< -_=Value", parser.parse_attr_value());

        let (mut parser, _) = test_parser("\"regular\">< -_=Value\"");
        assert_eq!("regular", parser.parse_attr_value());

        let (mut parser, _) = test_parser("'regular'>< -_=Value'");
        assert_eq!("regular", parser.parse_attr_value());
    }

    /// Test empty attributes are parsed correctly.
    #[test]
    fn attrs_empty() {
        let (mut parser, _) = test_parser("");
        assert_eq!(AttrMap::new(), parser.parse_attributes());
    }

    /// Test end attributes are parsed correctly.
    #[test]
    fn attrs_end() {
        let (mut parser, _) = test_parser(">");
        assert_eq!(AttrMap::new(), parser.parse_attributes());
    }

    /// Test regular well formed attributes are parsed correctly.
    #[test]
    fn attrs_regular() {
        let (mut parser, _) = test_parser("name0 name1=value1 kek name2  ='value2' name3  = \"value3\"  ");
        let mut expected = AttrMap::new();
        expected.insert("name0".to_string(), "".to_string());
        expected.insert("kek".to_string(), "".to_string());
        expected.insert("name1".to_string(), "value1".to_string());
        expected.insert("name2".to_string(), "value2".to_string());
        expected.insert("name3".to_string(), "value3".to_string());

        assert_eq!(expected, parser.parse_attributes());
    }

    /// Test an invalid attribute.
    #[test]
    fn attrs_invalid() {
        let (mut parser, _) = test_parser("name0 name1=val'ue1 name2='va l ue2'");
        let mut expected = AttrMap::new();
        expected.insert("name0".to_string(), "".to_string());
        expected.insert("name1".to_string(), "val".to_string());
        expected.insert("name2".to_string(), "va l ue2".to_string());

        assert_eq!(expected, parser.parse_attributes());
    }

    /// Test case insensitivity for attr names and case sensitivity for attr values.
    #[test]
    fn attrs_case() {
        let (mut parser, _) = test_parser("NameZero NAMEone=VALUEone NAMETWO='VALUETWO' namethree=valuethree");
        let mut expected = AttrMap::new();
        expected.insert("namezero".to_string(), "".to_string());
        expected.insert("nameone".to_string(), "VALUEone".to_string());
        expected.insert("nametwo".to_string(), "VALUETWO".to_string());
        expected.insert("namethree".to_string(), "valuethree".to_string());

        assert_eq!(expected, parser.parse_attributes());
    }

    /// Test empty comment node.
    #[test]
    fn comment_empty() {
        let (mut parser, _) = test_parser("");
        let expected = Node::new(NodeType::Comment(String::from("")), Vec::new());

        assert_eq!(expected, parser.parse_comment_node());
    }

    /// Test end comment node.
    #[test]
    fn comment_end() {
        let (mut parser, _) = test_parser("-->");
        let expected = Node::new(NodeType::Comment(String::from("")), Vec::new());

        assert_eq!(expected, parser.parse_comment_node());
    }

    /// Test regular comment node.
    #[test]
    fn comment_regular() {
        let (mut parser, _) = test_parser("--Here is a comment \n '\"<>XD\"'-->");
        let comment_content = String::from("Here is a comment \n '\"<>XD\"'");
        let expected = Node::new(NodeType::Comment(comment_content), Vec::new());

        assert_eq!(expected, parser.parse_comment_node());
    }

    /// Test comment node that begins with >.
    #[test]
    fn comment_invalid1() {
        let (mut parser, _) = test_parser("-->Here is a comment \n '\"<>XD\"'-->");
        let expected = Node::new(NodeType::Comment(String::from("")), Vec::new());

        assert_eq!(expected, parser.parse_comment_node());
    }

    /// Test comment node that begins with ->.
    #[test]
    fn comment_invalid2() {
        let (mut parser, _) = test_parser("--->Here is a comment \n '\"<>XD\"'-->");
        let expected = Node::new(NodeType::Comment(String::from("")), Vec::new());

        assert_eq!(expected, parser.parse_comment_node());
    }

    /// Test comment node that conains ");
        let expected = Node::new(NodeType::Comment(String::from("")), Vec::new());

        assert_eq!(expected, parser.parse_comment_node());
    }

    /// Test comment node that ends with <! -.
    #[test]
    fn comment_invalid4() {
        let (mut parser, _) = test_parser("--Here is a comment \n '\"<>XD\"'<! --->");
        let expected = Node::new(NodeType::Comment(String::from("")), Vec::new());

        assert_eq!(expected, parser.parse_comment_node());
    }

    /// Test if a character is a control character
    #[test]
    fn control_characters() {
        assert!(is_control('\u{0001}'));
        assert!(is_control('\u{007F}'));
        assert!(is_control('\u{0081}'));
        assert!(!is_control(' '));
    }

    /// Utility to return a parser for tests.
    fn test_parser<'a>(mock_html: &'a str) -> (HtmlParser, Peekable<Chars<'a>>) {
        let parser = HtmlParser::new(mock_html);
        let expected_chars = mock_html.chars().peekable();
        (parser, expected_chars)
    }
}
<|endoftext|>


<commit_before>//! Provide helpers for making ioctl system calls
//!
//! # Overview of IOCTLs
//!
//! The `ioctl` system call is a widely support system
//! call on *nix systems providing access to functions
//! and data that do not fit nicely into the standard
//! read and write operations on a file itself.  It is
//! common to see ioctls used for the following purposes:
//!
//! * Provide read/write access to out-of-band data related
//!   to a device such as configuration (for instance, setting
//!   serial port options)
//! * Provide a mechanism for performing full-duplex data
//!   transfers (for instance, xfer on SPI devices).
//! * Provide access to control functions on a device (for example,
//!   on Linux you can send commands like pause, resume, and eject
//!   to the CDROM device.
//! * Do whatever else the device driver creator thought made most sense.
//!
//! Ioctls are synchronous system calls and are similar to read and
//! write calls in that regard.
//!
//! The prototype for the ioctl system call in libc is as follows:
//!
//! ```c
//! int ioctl(int fd, unsigned long request, ...);
//! ```
//!
//! Typically, an ioctl takes 3 parameters as arguments:
//!
//! 1. An open file descriptor, `fd`.
//! 2. An device-dependennt request code or operation.  This request
//!    code is referred to as `op` in this module.
//! 3. Either a pointer to a location in memory or an integer.  This
//!    number of pointer may either be used by the kernel or written
//!    to by the kernel depending on how the operation is documented
//!    to work.
//!
//! The `op` request code is essentially an arbitrary integer having
//! a device-driver specific meaning.  Over time, it proved difficult
//! for various driver implementors to use this field sanely, so a
//! convention with macros was introduced to the Linux Kernel that
//! is used by most newer drivers.  See
//! https://github.com/torvalds/linux/blob/master/Documentation/ioctl/ioctl-number.txt
//! for additional details.  The macros exposed by the kernel for
//! consumers are implemented in this module and may be used to
//! instead of calls like `_IOC`, `_IO`, `_IOR`, and `_IOW`.
//!
//! # Interface Overview
//!
//! This ioctl module seeks to tame the ioctl beast by providing
//! a set of safer (although not safe) functions
//! implementing the most common ioctl access patterns.
//!
//! The most common access patterns for ioctls are as follows:
//!
//! 1. `read`: A pointer is provided to the kernel which is populated
//!    with a value containing the "result" of the operation.  The
//!    result may be an integer or structure.  The kernel may also
//!    read values from the provided pointer (usually a structure).
//! 2. `write`: A pointer is provided to the kernel containing values
//!    that the kernel will read in order to perform the operation.
//! 3. `execute`: The operation is passed to the kernel but no
//!    additional pointer is passed.  The operation is enough
//!    and it either succeeds or results in an error.
//!
//! Where appropriate, versions of these interface function are provided
//! taking either refernces or pointers.  The pointer versions are
//! necessary for cases (notably slices) where a reference cannot
//! be generically cast to a pointer.

use {Error, Result, errno};
use libc::{c_int, c_ulong};
use libc::funcs::bsd44::ioctl as libc_ioctl;
use std::mem;
use std::os::unix::io::RawFd;

pub type ioctl_op_t = c_ulong;

// the libc definiton of the 'op' type is platform dependent
#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "openbsd",
          target_os = "dragonfly"))]
type os_ioctl_op_t = c_ulong;

#[cfg(any(target_os = "linux", target_os = "android"))]
type os_ioctl_op_t = c_int;

// low-level ioctl functions and definitions matching the
// macros provided in ioctl.h from the kernel
const IOC_NRBITS: u32 = 8;
const IOC_TYPEBITS: u32 = 8;
const IOC_SIZEBITS: u32 = 14;
// const IOC_DIRBITS: u32 = 2;

const IOC_NRSHIFT: u32 = 0;
const IOC_TYPESHIFT: u32 = IOC_NRSHIFT + IOC_NRBITS;
const IOC_SIZESHIFT: u32 = IOC_TYPESHIFT + IOC_TYPEBITS;
const IOC_DIRSHIFT: u32 = IOC_SIZESHIFT + IOC_SIZEBITS;

/// Flags indicating the direction of the ioctl operation
/// for ioctls using modern operation conventions
bitflags! {
    flags IoctlDirFlags: u8 {
        /// Indicates that the ioctl data pointer is not used
        const IOC_NONE  = 0x00,
        /// Indicates that the ioctl data pointer contains data that
        /// will be consumed by the operating system
        const IOC_WRITE = 0x01,
        /// Indicates tha the ioctl data pointer contains data that
        /// will be populated by the operating system to be consumed
        /// by userspace
        const IOC_READ  = 0x02,
    }
}

/// Build an ioctl op with the provide parameters.  This is a helper
/// function for IOCTLs in the Linux kernel using the newer conventions
/// for IOCTLs operations.  Many ioctls do not use this newer convention
/// and the constants for those should just be used as-is.
///
/// This provides the same functionality as the Linux `_IOC` macro.
pub fn op(dir: IoctlDirFlags, ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    // actual number will always fit in 32 bits, but ioctl() expects
    // an unsigned long for the op
    let size_to_use: u32 = if size < (1 << IOC_SIZEBITS) { size as u32 } else { 0 };
    (((dir.bits as u32) << IOC_DIRSHIFT) |
     ((ioctl_type as u32) << IOC_TYPESHIFT) |
     ((nr as u32) << IOC_NRSHIFT) |
     ((size_to_use) << IOC_SIZESHIFT)) as ioctl_op_t
}

/// Build an op indicating that the data pointer is not used.
/// That is, the command itself is sufficient.
///
/// This provides the same functionality the Linux `_IO` macro.
pub fn op_none(ioctl_type: u8, nr: u8) -> ioctl_op_t {
    op(IOC_NONE, ioctl_type, nr, 0)
}

/// Build an op indicating that the data pointer will be populated
/// with data from the kernel
///
/// This provides the same functionality as the Linux `_IOR` macro.
pub fn op_read(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_READ, ioctl_type, nr, size)
}

/// Build an op indicating that the data pointer contains data
/// to be consumed by the kernel (and not written to).
///
/// This provides the same functionality as the Linux `_IOW` macro.
pub fn op_write(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_WRITE, ioctl_type, nr, size)
}

/// Build an op indicating that the data pointer both contains
/// data to be consumed by the kernel and contains fields that
/// will be populated by the kernel.
///
/// This provides the same functionality as the Linux `_IOWR` macro.
pub fn op_read_write(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_WRITE | IOC_READ, ioctl_type, nr, size)
}

fn convert_ioctl_res(res: c_int) -> Result<c_int> {
    if res < 0 {
        return Err(Error::Sys(errno::Errno::last()))
    }
    Ok(res) // res may length or similar useful to caller
}

/// Ioctl call that is expected to return a result
/// but which does not take any additional arguments on the input side
///
/// This function will allocate allocate space for and returned an owned
/// reference to the result.
pub unsafe fn read<T>(fd: RawFd, op: ioctl_op_t) -> Result<T> {
    // allocate memory for the result (should get a value from kernel)
    let mut dst: T = mem::zeroed();
    let dst_ptr: *mut T = &mut dst;
    try!(read_into_ptr(fd, op, dst_ptr));
    Ok(dst)
}

/// Ioctl where the result from the kernel will be written to the
/// provided reference
///
/// The refernced data may also contain information that will be consumed
/// by the kernel.
pub unsafe fn read_into<T>(fd: RawFd, op: ioctl_op_t, data: &mut T) -> Result<c_int> {
    read_into_ptr(fd, op, data as *mut T)
}

/// Ioctl where the result from the kernel will be written to the
/// provided pointer
///
/// The refernced data may also contain information that will be consumed
/// by the kernel.
pub unsafe fn read_into_ptr<T>(fd: RawFd, op: ioctl_op_t, data_ptr: *mut T) -> Result<c_int> {
    convert_ioctl_res(libc_ioctl(fd, op as os_ioctl_op_t, data_ptr))
}

/// Ioctl call that sends a value to the kernel but
/// does not return anything (pure side effect).
pub unsafe fn write<T>(fd: RawFd, op: ioctl_op_t, data: &T) -> Result<c_int> {
    write_ptr(fd, op, data as *const T)
}

/// Ioctl call that sends a value to the kernel but
/// does not return anything (pure side effect).
pub unsafe fn write_ptr<T>(fd: RawFd, op: ioctl_op_t, data: *const T) -> Result<c_int> {
    convert_ioctl_res(libc_ioctl(fd, op as os_ioctl_op_t, data as *const T))
}

/// Ioctl call for which no data pointer is provided to the kernel.
/// That is, the kernel has sufficient information about what to
/// do based on the op alone.
pub fn execute(fd: RawFd, op: ioctl_op_t) -> Result<c_int> {
    convert_ioctl_res(unsafe { libc_ioctl(fd, op as os_ioctl_op_t) })
}
<commit_msg>update ioctl for latest libc definition<commit_after>//! Provide helpers for making ioctl system calls
//!
//! # Overview of IOCTLs
//!
//! The `ioctl` system call is a widely support system
//! call on *nix systems providing access to functions
//! and data that do not fit nicely into the standard
//! read and write operations on a file itself.  It is
//! common to see ioctls used for the following purposes:
//!
//! * Provide read/write access to out-of-band data related
//!   to a device such as configuration (for instance, setting
//!   serial port options)
//! * Provide a mechanism for performing full-duplex data
//!   transfers (for instance, xfer on SPI devices).
//! * Provide access to control functions on a device (for example,
//!   on Linux you can send commands like pause, resume, and eject
//!   to the CDROM device.
//! * Do whatever else the device driver creator thought made most sense.
//!
//! Ioctls are synchronous system calls and are similar to read and
//! write calls in that regard.
//!
//! The prototype for the ioctl system call in libc is as follows:
//!
//! ```c
//! int ioctl(int fd, unsigned long request, ...);
//! ```
//!
//! Typically, an ioctl takes 3 parameters as arguments:
//!
//! 1. An open file descriptor, `fd`.
//! 2. An device-dependennt request code or operation.  This request
//!    code is referred to as `op` in this module.
//! 3. Either a pointer to a location in memory or an integer.  This
//!    number of pointer may either be used by the kernel or written
//!    to by the kernel depending on how the operation is documented
//!    to work.
//!
//! The `op` request code is essentially an arbitrary integer having
//! a device-driver specific meaning.  Over time, it proved difficult
//! for various driver implementors to use this field sanely, so a
//! convention with macros was introduced to the Linux Kernel that
//! is used by most newer drivers.  See
//! https://github.com/torvalds/linux/blob/master/Documentation/ioctl/ioctl-number.txt
//! for additional details.  The macros exposed by the kernel for
//! consumers are implemented in this module and may be used to
//! instead of calls like `_IOC`, `_IO`, `_IOR`, and `_IOW`.
//!
//! # Interface Overview
//!
//! This ioctl module seeks to tame the ioctl beast by providing
//! a set of safer (although not safe) functions
//! implementing the most common ioctl access patterns.
//!
//! The most common access patterns for ioctls are as follows:
//!
//! 1. `read`: A pointer is provided to the kernel which is populated
//!    with a value containing the "result" of the operation.  The
//!    result may be an integer or structure.  The kernel may also
//!    read values from the provided pointer (usually a structure).
//! 2. `write`: A pointer is provided to the kernel containing values
//!    that the kernel will read in order to perform the operation.
//! 3. `execute`: The operation is passed to the kernel but no
//!    additional pointer is passed.  The operation is enough
//!    and it either succeeds or results in an error.
//!
//! Where appropriate, versions of these interface function are provided
//! taking either refernces or pointers.  The pointer versions are
//! necessary for cases (notably slices) where a reference cannot
//! be generically cast to a pointer.

use {Error, Result, errno};
use libc::{c_int, c_ulong};
use libc::funcs::bsd44::ioctl as libc_ioctl;
use std::mem;
use std::os::unix::io::RawFd;

pub type ioctl_op_t = c_ulong;

// low-level ioctl functions and definitions matching the
// macros provided in ioctl.h from the kernel
const IOC_NRBITS: u32 = 8;
const IOC_TYPEBITS: u32 = 8;
const IOC_SIZEBITS: u32 = 14;
// const IOC_DIRBITS: u32 = 2;

const IOC_NRSHIFT: u32 = 0;
const IOC_TYPESHIFT: u32 = IOC_NRSHIFT + IOC_NRBITS;
const IOC_SIZESHIFT: u32 = IOC_TYPESHIFT + IOC_TYPEBITS;
const IOC_DIRSHIFT: u32 = IOC_SIZESHIFT + IOC_SIZEBITS;

/// Flags indicating the direction of the ioctl operation
/// for ioctls using modern operation conventions
bitflags! {
    flags IoctlDirFlags: u8 {
        /// Indicates that the ioctl data pointer is not used
        const IOC_NONE  = 0x00,
        /// Indicates that the ioctl data pointer contains data that
        /// will be consumed by the operating system
        const IOC_WRITE = 0x01,
        /// Indicates tha the ioctl data pointer contains data that
        /// will be populated by the operating system to be consumed
        /// by userspace
        const IOC_READ  = 0x02,
    }
}

/// Build an ioctl op with the provide parameters.  This is a helper
/// function for IOCTLs in the Linux kernel using the newer conventions
/// for IOCTLs operations.  Many ioctls do not use this newer convention
/// and the constants for those should just be used as-is.
///
/// This provides the same functionality as the Linux `_IOC` macro.
pub fn op(dir: IoctlDirFlags, ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    // actual number will always fit in 32 bits, but ioctl() expects
    // an unsigned long for the op
    let size_to_use: u32 = if size < (1 << IOC_SIZEBITS) { size as u32 } else { 0 };
    (((dir.bits as u32) << IOC_DIRSHIFT) |
     ((ioctl_type as u32) << IOC_TYPESHIFT) |
     ((nr as u32) << IOC_NRSHIFT) |
     ((size_to_use) << IOC_SIZESHIFT)) as ioctl_op_t
}

/// Build an op indicating that the data pointer is not used.
/// That is, the command itself is sufficient.
///
/// This provides the same functionality the Linux `_IO` macro.
pub fn op_none(ioctl_type: u8, nr: u8) -> ioctl_op_t {
    op(IOC_NONE, ioctl_type, nr, 0)
}

/// Build an op indicating that the data pointer will be populated
/// with data from the kernel
///
/// This provides the same functionality as the Linux `_IOR` macro.
pub fn op_read(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_READ, ioctl_type, nr, size)
}

/// Build an op indicating that the data pointer contains data
/// to be consumed by the kernel (and not written to).
///
/// This provides the same functionality as the Linux `_IOW` macro.
pub fn op_write(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_WRITE, ioctl_type, nr, size)
}

/// Build an op indicating that the data pointer both contains
/// data to be consumed by the kernel and contains fields that
/// will be populated by the kernel.
///
/// This provides the same functionality as the Linux `_IOWR` macro.
pub fn op_read_write(ioctl_type: u8, nr: u8, size: usize) -> ioctl_op_t {
    op(IOC_WRITE | IOC_READ, ioctl_type, nr, size)
}

fn convert_ioctl_res(res: c_int) -> Result<c_int> {
    if res < 0 {
        return Err(Error::Sys(errno::Errno::last()))
    }
    Ok(res) // res may length or similar useful to caller
}

/// Ioctl call that is expected to return a result
/// but which does not take any additional arguments on the input side
///
/// This function will allocate allocate space for and returned an owned
/// reference to the result.
pub unsafe fn read<T>(fd: RawFd, op: ioctl_op_t) -> Result<T> {
    // allocate memory for the result (should get a value from kernel)
    let mut dst: T = mem::zeroed();
    let dst_ptr: *mut T = &mut dst;
    try!(read_into_ptr(fd, op, dst_ptr));
    Ok(dst)
}

/// Ioctl where the result from the kernel will be written to the
/// provided reference
///
/// The refernced data may also contain information that will be consumed
/// by the kernel.
pub unsafe fn read_into<T>(fd: RawFd, op: ioctl_op_t, data: &mut T) -> Result<c_int> {
    read_into_ptr(fd, op, data as *mut T)
}

/// Ioctl where the result from the kernel will be written to the
/// provided pointer
///
/// The refernced data may also contain information that will be consumed
/// by the kernel.
pub unsafe fn read_into_ptr<T>(fd: RawFd, op: ioctl_op_t, data_ptr: *mut T) -> Result<c_int> {
    convert_ioctl_res(libc_ioctl(fd, op, data_ptr))
}

/// Ioctl call that sends a value to the kernel but
/// does not return anything (pure side effect).
pub unsafe fn write<T>(fd: RawFd, op: ioctl_op_t, data: &T) -> Result<c_int> {
    write_ptr(fd, op, data as *const T)
}

/// Ioctl call that sends a value to the kernel but
/// does not return anything (pure side effect).
pub unsafe fn write_ptr<T>(fd: RawFd, op: ioctl_op_t, data: *const T) -> Result<c_int> {
    convert_ioctl_res(libc_ioctl(fd, op, data as *const T))
}

/// Ioctl call for which no data pointer is provided to the kernel.
/// That is, the kernel has sufficient information about what to
/// do based on the op alone.
pub fn execute(fd: RawFd, op: ioctl_op_t) -> Result<c_int> {
    convert_ioctl_res(unsafe { libc_ioctl(fd, op) })
}
<|endoftext|>