<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("InheritedBox", inherited=True, gecko_name="Visibility") %>

// TODO: collapse. Well, do tables first.
${helpers.single_keyword(
    "visibility",
    "visible hidden",
    extra_gecko_values="collapse",
    gecko_ffi_name="mVisible",
    animation_value_type="ComputedValue",
    spec="https://drafts.csswg.org/css-box/#propdef-visibility",
)}

// CSS Writing Modes Level 3
// https://drafts.csswg.org/css-writing-modes-3
${helpers.single_keyword(
    "writing-mode",
    "horizontal-tb vertical-rl vertical-lr",
    extra_gecko_values="sideways-rl sideways-lr",
    extra_gecko_aliases="lr=horizontal-tb lr-tb=horizontal-tb \
                         rl=horizontal-tb rl-tb=horizontal-tb \
                         tb=vertical-rl   tb-rl=vertical-rl",
    servo_pref="layout.writing-mode.enabled",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-writing-mode",
    servo_restyle_damage="rebuild_and_reflow",
)}

${helpers.single_keyword(
    "direction",
    "ltr rtl",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction",
    needs_conversion=True,
    servo_restyle_damage="rebuild_and_reflow",
)}

${helpers.single_keyword(
    "text-orientation",
    "mixed upright sideways",
    extra_gecko_aliases="sideways-right=sideways",
    products="gecko",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-text-orientation",
)}

// CSS Color Module Level 4
// https://drafts.csswg.org/css-color/
${helpers.single_keyword(
    "color-adjust",
    "economy exact", products="gecko",
    gecko_pref="layout.css.color-adjust.enabled",
    animation_value_type="discrete",
    spec="https://drafts.csswg.org/css-color/#propdef-color-adjust",
)}

// According to to CSS-IMAGES-3, `optimizespeed` and `optimizequality` are synonyms for `auto`
// And, firefox doesn't support `pixelated` yet (https://bugzilla.mozilla.org/show_bug.cgi?id=856337)
${helpers.single_keyword(
    "image-rendering",
    "auto crisp-edges",
    extra_gecko_values="optimizespeed optimizequality",
    extra_servo_values="pixelated",
    extra_gecko_aliases="-moz-crisp-edges=crisp-edges",
    animation_value_type="discrete",
    spec="https://drafts.csswg.org/css-images/#propdef-image-rendering",
)}

${helpers.single_keyword(
    "image-orientation",
    "none from-image",
    products="gecko",
    gecko_enum_prefix="StyleImageOrientation",
    animation_value_type="discrete",
    gecko_pref="layout.css.image-orientation.enabled",
    spec="https://drafts.csswg.org/css-images/#propdef-image-orientation",
)}
<commit_msg>style: changes to implement enum class for #define NS_STYLE_COLOR_ADJUST.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("InheritedBox", inherited=True, gecko_name="Visibility") %>

// TODO: collapse. Well, do tables first.
${helpers.single_keyword(
    "visibility",
    "visible hidden",
    extra_gecko_values="collapse",
    gecko_ffi_name="mVisible",
    animation_value_type="ComputedValue",
    spec="https://drafts.csswg.org/css-box/#propdef-visibility",
)}

// CSS Writing Modes Level 3
// https://drafts.csswg.org/css-writing-modes-3
${helpers.single_keyword(
    "writing-mode",
    "horizontal-tb vertical-rl vertical-lr",
    extra_gecko_values="sideways-rl sideways-lr",
    extra_gecko_aliases="lr=horizontal-tb lr-tb=horizontal-tb \
                         rl=horizontal-tb rl-tb=horizontal-tb \
                         tb=vertical-rl   tb-rl=vertical-rl",
    servo_pref="layout.writing-mode.enabled",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-writing-mode",
    servo_restyle_damage="rebuild_and_reflow",
)}

${helpers.single_keyword(
    "direction",
    "ltr rtl",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction",
    needs_conversion=True,
    servo_restyle_damage="rebuild_and_reflow",
)}

${helpers.single_keyword(
    "text-orientation",
    "mixed upright sideways",
    extra_gecko_aliases="sideways-right=sideways",
    products="gecko",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-text-orientation",
)}

// CSS Color Module Level 4
// https://drafts.csswg.org/css-color/
${helpers.single_keyword(
    "color-adjust",
    "economy exact", products="gecko",
    gecko_enum_prefix="StyleColorAdjust",
    gecko_pref="layout.css.color-adjust.enabled",
    animation_value_type="discrete",
    spec="https://drafts.csswg.org/css-color/#propdef-color-adjust",
)}

// According to to CSS-IMAGES-3, `optimizespeed` and `optimizequality` are synonyms for `auto`
// And, firefox doesn't support `pixelated` yet (https://bugzilla.mozilla.org/show_bug.cgi?id=856337)
${helpers.single_keyword(
    "image-rendering",
    "auto crisp-edges",
    extra_gecko_values="optimizespeed optimizequality",
    extra_servo_values="pixelated",
    extra_gecko_aliases="-moz-crisp-edges=crisp-edges",
    animation_value_type="discrete",
    spec="https://drafts.csswg.org/css-images/#propdef-image-rendering",
)}

${helpers.single_keyword(
    "image-orientation",
    "none from-image",
    products="gecko",
    gecko_enum_prefix="StyleImageOrientation",
    animation_value_type="discrete",
    gecko_pref="layout.css.image-orientation.enabled",
    spec="https://drafts.csswg.org/css-images/#propdef-image-orientation",
)}
<|endoftext|>


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

use std::error;
use std::fmt;
use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
use crossbeam::sync::MsQueue;

use device::Device;
use device::Queue;
use format::Format;
use format::FormatDesc;
use image::sys::Dimensions;
use image::sys::UnsafeImage;
use image::sys::Usage as ImageUsage;
use image::swapchain::SwapchainImage;
use swapchain::CompositeAlpha;
use swapchain::PresentMode;
use swapchain::Surface;
use swapchain::SurfaceTransform;
use sync::Semaphore;
use sync::SharingMode;

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

/// Contains the swapping system and the images that can be shown on a surface.
// TODO: #[derive(Debug)] (waiting on https://github.com/aturon/crossbeam/issues/62)
pub struct Swapchain {
    device: Arc<Device>,
    surface: Arc<Surface>,
    swapchain: vk::SwapchainKHR,

    /// Pool of semaphores from which a semaphore is retreived when acquiring an image.
    ///
    /// We need to use a queue so that we don't use the same semaphore twice in a row. The length
    /// of the queue is strictly superior to the number of images, in case the driver lets us
    /// acquire an image before it is presented.
    semaphores_pool: MsQueue<Arc<Semaphore>>,

    images_semaphores: Mutex<Vec<Option<Arc<Semaphore>>>>,
}

impl Swapchain {
    /// Builds a new swapchain. Allocates images who content can be made visible on a surface.
    ///
    /// See also the `Surface::get_capabilities` function which returns the values that are
    /// supported by the implementation. All the parameters that you pass to `Swapchain::new`
    /// must be supported.
    ///
    /// The `clipped` parameter indicates whether the implementation is allowed to discard
    /// rendering operations that affect regions of the surface which aren't visible. This is
    /// important to take into account if your fragment shader has side-effects or if you want to
    /// read back the content of the image afterwards.
    ///
    /// This function returns the swapchain plus a list of the images that belong to the
    /// swapchain. The order in which the images are returned is important for the
    /// `acquire_next_image` and `present` functions.
    ///
    /// # Panic
    ///
    /// - Panicks if the device and the surface don't belong to the same instance.
    /// - Panicks if `color_attachment` is false in `usage`.
    ///
    #[inline]
    pub fn new<F, S>(device: &Arc<Device>, surface: &Arc<Surface>, num_images: u32, format: F,
                     dimensions: [u32; 2], layers: u32, usage: &ImageUsage, sharing: S,
                     transform: SurfaceTransform, alpha: CompositeAlpha, mode: PresentMode,
                     clipped: bool) -> Result<(Arc<Swapchain>, Vec<Arc<SwapchainImage>>), OomError>
        where F: FormatDesc, S: Into<SharingMode>
    {
        Swapchain::new_inner(device, surface, num_images, format.format(), dimensions, layers,
                             usage, sharing.into(), transform, alpha, mode, clipped)
    }

    // TODO:
    //pub fn recreate() { ... }

    // TODO: images layouts should always be set to "PRESENT", since we have no way to switch the
    //       layout at present time
    fn new_inner(device: &Arc<Device>, surface: &Arc<Surface>, num_images: u32, format: Format,
                 dimensions: [u32; 2], layers: u32, usage: &ImageUsage, sharing: SharingMode,
                 transform: SurfaceTransform, alpha: CompositeAlpha, mode: PresentMode,
                 clipped: bool) -> Result<(Arc<Swapchain>, Vec<Arc<SwapchainImage>>), OomError>
    {
        // FIXME: check that the parameters are supported

        // FIXME: check that the device and the surface belong to the same instance
        let vk = device.pointers();
        assert!(device.loaded_extensions().khr_swapchain);     // TODO: return error instead

        assert!(usage.color_attachment);
        let usage = usage.to_usage_bits();

        let sharing = sharing.into();

        let swapchain = unsafe {
            let (sh_mode, sh_count, sh_indices) = match sharing {
                SharingMode::Exclusive(id) => (vk::SHARING_MODE_EXCLUSIVE, 0, ptr::null()),
                SharingMode::Concurrent(ref ids) => (vk::SHARING_MODE_CONCURRENT, ids.len() as u32,
                                                     ids.as_ptr()),
            };

            let infos = vk::SwapchainCreateInfoKHR {
                sType: vk::STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
                pNext: ptr::null(),
                flags: 0,   // reserved
                surface: surface.internal_object(),
                minImageCount: num_images,
                imageFormat: format as u32,
                imageColorSpace: vk::COLORSPACE_SRGB_NONLINEAR_KHR,     // only available value
                imageExtent: vk::Extent2D { width: dimensions[0], height: dimensions[1] },
                imageArrayLayers: layers,
                imageUsage: usage,
                imageSharingMode: sh_mode,
                queueFamilyIndexCount: sh_count,
                pQueueFamilyIndices: sh_indices,
                preTransform: transform as u32,
                compositeAlpha: alpha as u32,
                presentMode: mode as u32,
                clipped: if clipped { vk::TRUE } else { vk::FALSE },
                oldSwapchain: 0,      // TODO:
            };

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

        let swapchain = Arc::new(Swapchain {
            device: device.clone(),
            surface: surface.clone(),
            swapchain: swapchain,
            semaphores_pool: MsQueue::new(),
            images_semaphores: Mutex::new(Vec::new()),
        });

        let images = unsafe {
            let mut num = 0;
            try!(check_errors(vk.GetSwapchainImagesKHR(device.internal_object(),
                                                       swapchain.swapchain, &mut num,
                                                       ptr::null_mut())));

            let mut images = Vec::with_capacity(num as usize);
            try!(check_errors(vk.GetSwapchainImagesKHR(device.internal_object(),
                                                       swapchain.swapchain, &mut num,
                                                       images.as_mut_ptr())));
            images.set_len(num as usize);
            images
        };

        let images = images.into_iter().enumerate().map(|(id, image)| unsafe {
            let unsafe_image = UnsafeImage::from_raw(device, image, usage, format,
                                                     Dimensions::Dim2d { width: dimensions[0], height: dimensions[1] }, 1, 1);
            SwapchainImage::from_raw(unsafe_image, format, &swapchain, id as u32).unwrap()     // TODO: propagate error
        }).collect::<Vec<_>>();

        {
            let mut semaphores = swapchain.images_semaphores.lock().unwrap();
            for _ in 0 .. images.len() {
                semaphores.push(None);
            }
        }

        for _ in 0 .. images.len() + 1 {
            swapchain.semaphores_pool.push(try!(Semaphore::new(device)));
        }

        Ok((swapchain, images))
    }

    /// Tries to take ownership of an image in order to draw on it.
    ///
    /// The function returns the index of the image in the array of images that was returned
    /// when creating the swapchain.
    ///
    /// If you try to draw on an image without acquiring it first, the execution will block. (TODO
    /// behavior may change).
    pub fn acquire_next_image(&self, timeout: Duration) -> Result<usize, AcquireError> {
        let vk = self.device.pointers();

        unsafe {
            // TODO: AMD driver crashes when we use the pool
            //let semaphore = self.semaphores_pool.try_pop().expect("Failed to obtain a semaphore from \
            //                                                       the swapchain semaphores pool");
            let semaphore = Semaphore::new(&self.device).unwrap();

            let timeout_ns = timeout.as_secs().saturating_mul(1_000_000_000)
                                              .saturating_add(timeout.subsec_nanos() as u64);

            let mut out = mem::uninitialized();
            let r = try!(check_errors(vk.AcquireNextImageKHR(self.device.internal_object(),
                                                             self.swapchain, timeout_ns,
                                                             semaphore.internal_object(), 0,     // TODO: timeout
                                                             &mut out)));

            let id = match r {
                Success::Success => out as usize,
                Success::Suboptimal => out as usize,        // TODO: give that info to the user
                Success::NotReady => return Err(AcquireError::Timeout),
                Success::Timeout => return Err(AcquireError::Timeout),
                s => panic!("unexpected success value: {:?}", s)
            };

            let mut images_semaphores = self.images_semaphores.lock().unwrap();
            images_semaphores[id] = Some(semaphore);

            Ok(id)
        }
    }

    /// Presents an image on the screen.
    ///
    /// The parameter is the same index as what `acquire_next_image` returned. The image must
    /// have been acquired first.
    ///
    /// The actual behavior depends on the present mode that you passed when creating the
    /// swapchain.
    pub fn present(&self, queue: &Arc<Queue>, index: usize) -> Result<(), OomError> {     // FIXME: wrong error
        let vk = self.device.pointers();

        let wait_semaphore = {
            let mut images_semaphores = self.images_semaphores.lock().unwrap();
            images_semaphores[index].take().expect("Trying to present an image that was \
                                                    not acquired")
        };

        // FIXME: the semaphore will be destroyed ; need to return it

        unsafe {
            let mut result = mem::uninitialized();

            let queue = queue.internal_object_guard();
            let index = index as u32;

            let infos = vk::PresentInfoKHR {
                sType: vk::STRUCTURE_TYPE_PRESENT_INFO_KHR,
                pNext: ptr::null(),
                waitSemaphoreCount: 1,
                pWaitSemaphores: &wait_semaphore.internal_object(),
                swapchainCount: 1,
                pSwapchains: &self.swapchain,
                pImageIndices: &index,
                pResults: &mut result,
            };

            try!(check_errors(vk.QueuePresentKHR(*queue, &infos)));
            //try!(check_errors(result));       // TODO: AMD driver doesn't seem to write the result
        }

        //self.semaphores_pool.push(wait_semaphore);        // TODO: AMD driver crashes when we use the pool
        Ok(())
    }

    /*/// Returns the semaphore that is going to be signalled when the image is going to be ready
    /// to be drawn upon.
    ///
    /// Returns `None` if the image was not acquired first, or was already presented.
    // TODO: racy, as someone could present the image before using the semaphore
    #[inline]
    pub fn image_semaphore(&self, id: u32) -> Option<Arc<Semaphore>> {
        let semaphores = self.images_semaphores.lock().unwrap();
        semaphores[id as usize].as_ref().map(|s| s.clone())
    }*/
    // TODO: the design of this functions depends on https://github.com/KhronosGroup/Vulkan-Docs/issues/155
    #[inline]
    pub fn image_semaphore(&self, id: u32, semaphore: Arc<Semaphore>) -> Option<Arc<Semaphore>> {
        let mut semaphores = self.images_semaphores.lock().unwrap();
        mem::replace(&mut semaphores[id as usize], Some(semaphore))
    }
}

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

/// Error that can happen when calling `acquire_next_image`.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum AcquireError {
    Timeout,
    SurfaceLost,
    OutOfDate,
}

impl error::Error for AcquireError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            AcquireError::Timeout => "no image is available for acquiring yet",
            AcquireError::SurfaceLost => "the surface of this swapchain is no longer valid",
            AcquireError::OutOfDate => "the swapchain needs to be recreated",
        }
    }
}

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

impl From<Error> for AcquireError {
    #[inline]
    fn from(err: Error) -> AcquireError {
        match err {
            Error::SurfaceLost => AcquireError::SurfaceLost,
            Error::OutOfDate => AcquireError::OutOfDate,
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}
<commit_msg>Restore semaphores pool for swapchains<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::fmt;
use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
use crossbeam::sync::MsQueue;

use device::Device;
use device::Queue;
use format::Format;
use format::FormatDesc;
use image::sys::Dimensions;
use image::sys::UnsafeImage;
use image::sys::Usage as ImageUsage;
use image::swapchain::SwapchainImage;
use swapchain::CompositeAlpha;
use swapchain::PresentMode;
use swapchain::Surface;
use swapchain::SurfaceTransform;
use sync::Semaphore;
use sync::SharingMode;

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

/// Contains the swapping system and the images that can be shown on a surface.
// TODO: #[derive(Debug)] (waiting on https://github.com/aturon/crossbeam/issues/62)
pub struct Swapchain {
    device: Arc<Device>,
    surface: Arc<Surface>,
    swapchain: vk::SwapchainKHR,

    /// Pool of semaphores from which a semaphore is retreived when acquiring an image.
    ///
    /// We need to use a queue so that we don't use the same semaphore twice in a row. The length
    /// of the queue is strictly superior to the number of images, in case the driver lets us
    /// acquire an image before it is presented.
    semaphores_pool: MsQueue<Arc<Semaphore>>,

    images_semaphores: Mutex<Vec<Option<Arc<Semaphore>>>>,
}

impl Swapchain {
    /// Builds a new swapchain. Allocates images who content can be made visible on a surface.
    ///
    /// See also the `Surface::get_capabilities` function which returns the values that are
    /// supported by the implementation. All the parameters that you pass to `Swapchain::new`
    /// must be supported.
    ///
    /// The `clipped` parameter indicates whether the implementation is allowed to discard
    /// rendering operations that affect regions of the surface which aren't visible. This is
    /// important to take into account if your fragment shader has side-effects or if you want to
    /// read back the content of the image afterwards.
    ///
    /// This function returns the swapchain plus a list of the images that belong to the
    /// swapchain. The order in which the images are returned is important for the
    /// `acquire_next_image` and `present` functions.
    ///
    /// # Panic
    ///
    /// - Panicks if the device and the surface don't belong to the same instance.
    /// - Panicks if `color_attachment` is false in `usage`.
    ///
    #[inline]
    pub fn new<F, S>(device: &Arc<Device>, surface: &Arc<Surface>, num_images: u32, format: F,
                     dimensions: [u32; 2], layers: u32, usage: &ImageUsage, sharing: S,
                     transform: SurfaceTransform, alpha: CompositeAlpha, mode: PresentMode,
                     clipped: bool) -> Result<(Arc<Swapchain>, Vec<Arc<SwapchainImage>>), OomError>
        where F: FormatDesc, S: Into<SharingMode>
    {
        Swapchain::new_inner(device, surface, num_images, format.format(), dimensions, layers,
                             usage, sharing.into(), transform, alpha, mode, clipped)
    }

    // TODO:
    //pub fn recreate() { ... }

    // TODO: images layouts should always be set to "PRESENT", since we have no way to switch the
    //       layout at present time
    fn new_inner(device: &Arc<Device>, surface: &Arc<Surface>, num_images: u32, format: Format,
                 dimensions: [u32; 2], layers: u32, usage: &ImageUsage, sharing: SharingMode,
                 transform: SurfaceTransform, alpha: CompositeAlpha, mode: PresentMode,
                 clipped: bool) -> Result<(Arc<Swapchain>, Vec<Arc<SwapchainImage>>), OomError>
    {
        // FIXME: check that the parameters are supported

        // FIXME: check that the device and the surface belong to the same instance
        let vk = device.pointers();
        assert!(device.loaded_extensions().khr_swapchain);     // TODO: return error instead

        assert!(usage.color_attachment);
        let usage = usage.to_usage_bits();

        let sharing = sharing.into();

        let swapchain = unsafe {
            let (sh_mode, sh_count, sh_indices) = match sharing {
                SharingMode::Exclusive(id) => (vk::SHARING_MODE_EXCLUSIVE, 0, ptr::null()),
                SharingMode::Concurrent(ref ids) => (vk::SHARING_MODE_CONCURRENT, ids.len() as u32,
                                                     ids.as_ptr()),
            };

            let infos = vk::SwapchainCreateInfoKHR {
                sType: vk::STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
                pNext: ptr::null(),
                flags: 0,   // reserved
                surface: surface.internal_object(),
                minImageCount: num_images,
                imageFormat: format as u32,
                imageColorSpace: vk::COLORSPACE_SRGB_NONLINEAR_KHR,     // only available value
                imageExtent: vk::Extent2D { width: dimensions[0], height: dimensions[1] },
                imageArrayLayers: layers,
                imageUsage: usage,
                imageSharingMode: sh_mode,
                queueFamilyIndexCount: sh_count,
                pQueueFamilyIndices: sh_indices,
                preTransform: transform as u32,
                compositeAlpha: alpha as u32,
                presentMode: mode as u32,
                clipped: if clipped { vk::TRUE } else { vk::FALSE },
                oldSwapchain: 0,      // TODO:
            };

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

        let swapchain = Arc::new(Swapchain {
            device: device.clone(),
            surface: surface.clone(),
            swapchain: swapchain,
            semaphores_pool: MsQueue::new(),
            images_semaphores: Mutex::new(Vec::new()),
        });

        let images = unsafe {
            let mut num = 0;
            try!(check_errors(vk.GetSwapchainImagesKHR(device.internal_object(),
                                                       swapchain.swapchain, &mut num,
                                                       ptr::null_mut())));

            let mut images = Vec::with_capacity(num as usize);
            try!(check_errors(vk.GetSwapchainImagesKHR(device.internal_object(),
                                                       swapchain.swapchain, &mut num,
                                                       images.as_mut_ptr())));
            images.set_len(num as usize);
            images
        };

        let images = images.into_iter().enumerate().map(|(id, image)| unsafe {
            let unsafe_image = UnsafeImage::from_raw(device, image, usage, format,
                                                     Dimensions::Dim2d { width: dimensions[0], height: dimensions[1] }, 1, 1);
            SwapchainImage::from_raw(unsafe_image, format, &swapchain, id as u32).unwrap()     // TODO: propagate error
        }).collect::<Vec<_>>();

        {
            let mut semaphores = swapchain.images_semaphores.lock().unwrap();
            for _ in 0 .. images.len() {
                semaphores.push(None);
            }
        }

        for _ in 0 .. images.len() + 1 {
            swapchain.semaphores_pool.push(try!(Semaphore::new(device)));
        }

        Ok((swapchain, images))
    }

    /// Tries to take ownership of an image in order to draw on it.
    ///
    /// The function returns the index of the image in the array of images that was returned
    /// when creating the swapchain.
    ///
    /// If you try to draw on an image without acquiring it first, the execution will block. (TODO
    /// behavior may change).
    pub fn acquire_next_image(&self, timeout: Duration) -> Result<usize, AcquireError> {
        let vk = self.device.pointers();

        unsafe {
            let semaphore = self.semaphores_pool.try_pop().expect("Failed to obtain a semaphore \
                                                                   from the swapchain semaphores \
                                                                   pool");

            let timeout_ns = timeout.as_secs().saturating_mul(1_000_000_000)
                                              .saturating_add(timeout.subsec_nanos() as u64);

            let mut out = mem::uninitialized();
            let r = try!(check_errors(vk.AcquireNextImageKHR(self.device.internal_object(),
                                                             self.swapchain, timeout_ns,
                                                             semaphore.internal_object(), 0,     // TODO: timeout
                                                             &mut out)));

            let id = match r {
                Success::Success => out as usize,
                Success::Suboptimal => out as usize,        // TODO: give that info to the user
                Success::NotReady => return Err(AcquireError::Timeout),
                Success::Timeout => return Err(AcquireError::Timeout),
                s => panic!("unexpected success value: {:?}", s)
            };

            let mut images_semaphores = self.images_semaphores.lock().unwrap();
            images_semaphores[id] = Some(semaphore);

            Ok(id)
        }
    }

    /// Presents an image on the screen.
    ///
    /// The parameter is the same index as what `acquire_next_image` returned. The image must
    /// have been acquired first.
    ///
    /// The actual behavior depends on the present mode that you passed when creating the
    /// swapchain.
    pub fn present(&self, queue: &Arc<Queue>, index: usize) -> Result<(), OomError> {     // FIXME: wrong error
        let vk = self.device.pointers();

        let wait_semaphore = {
            let mut images_semaphores = self.images_semaphores.lock().unwrap();
            images_semaphores[index].take().expect("Trying to present an image that was \
                                                    not acquired")
        };

        // FIXME: the semaphore may be destroyed ; need to return it

        unsafe {
            let mut result = mem::uninitialized();

            let queue = queue.internal_object_guard();
            let index = index as u32;

            let infos = vk::PresentInfoKHR {
                sType: vk::STRUCTURE_TYPE_PRESENT_INFO_KHR,
                pNext: ptr::null(),
                waitSemaphoreCount: 1,
                pWaitSemaphores: &wait_semaphore.internal_object(),
                swapchainCount: 1,
                pSwapchains: &self.swapchain,
                pImageIndices: &index,
                pResults: &mut result,
            };

            try!(check_errors(vk.QueuePresentKHR(*queue, &infos)));
            //try!(check_errors(result));       // TODO: AMD driver doesn't seem to write the result
        }

        self.semaphores_pool.push(wait_semaphore);
        Ok(())
    }

    /*/// Returns the semaphore that is going to be signalled when the image is going to be ready
    /// to be drawn upon.
    ///
    /// Returns `None` if the image was not acquired first, or was already presented.
    // TODO: racy, as someone could present the image before using the semaphore
    #[inline]
    pub fn image_semaphore(&self, id: u32) -> Option<Arc<Semaphore>> {
        let semaphores = self.images_semaphores.lock().unwrap();
        semaphores[id as usize].as_ref().map(|s| s.clone())
    }*/
    // TODO: the design of this functions depends on https://github.com/KhronosGroup/Vulkan-Docs/issues/155
    #[inline]
    pub fn image_semaphore(&self, id: u32, semaphore: Arc<Semaphore>) -> Option<Arc<Semaphore>> {
        let mut semaphores = self.images_semaphores.lock().unwrap();
        mem::replace(&mut semaphores[id as usize], Some(semaphore))
    }
}

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

/// Error that can happen when calling `acquire_next_image`.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum AcquireError {
    Timeout,
    SurfaceLost,
    OutOfDate,
}

impl error::Error for AcquireError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            AcquireError::Timeout => "no image is available for acquiring yet",
            AcquireError::SurfaceLost => "the surface of this swapchain is no longer valid",
            AcquireError::OutOfDate => "the swapchain needs to be recreated",
        }
    }
}

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

impl From<Error> for AcquireError {
    #[inline]
    fn from(err: Error) -> AcquireError {
        match err {
            Error::SurfaceLost => AcquireError::SurfaceLost,
            Error::OutOfDate => AcquireError::OutOfDate,
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}
<|endoftext|>


<commit_before>use std::char;

pub enum TokenType {
    ILLEGAL,
    EOF,
    IDENT,
    INT,
    ASSIGN,
    PLUS,
    MINUS,
    COMMA,
    SEMICOLON,
    LPAREN,
    RPAREN,
    LBRACE,
    RBRACE,
    FUNCTION,
    LET,
}

pub enum Value {
    Int(String),
    Str(String),
}

pub struct Token {
    pub token_type: TokenType,
    pub value: Option<Value>,
}

impl TokenType {
    pub fn from_string(s: String) -> TokenType {
        match s.as_ref() {
            "\n" => TokenType::EOF,
            "let" => TokenType::LET,
            "+" => TokenType::PLUS,
            "-" => TokenType::MINUS,
            "," => TokenType::COMMA,
            ";" => TokenType::SEMICOLON,
            "(" => TokenType::LPAREN,
            ")" => TokenType::RPAREN,
            "{" => TokenType::LBRACE,
            "}" => TokenType::RBRACE,
            "func" => TokenType::FUNCTION,
            _ => TokenType::ILLEGAL
        }
    }
}

pub struct Parser<'a> {
    pub tokens: &'a [Token]
}

impl<'a> Parser<'a> {
    pub fn parse(&self) {
        return ();
    }
}

pub struct Lexer<'a> {
    pub input: String,
    pub position: usize,
    pub read_position: usize,
    pub ch: &'a char
}

impl<'a> Lexer<'a> {
    pub fn new(input: String, c: &'a char) -> Lexer<'a> {
        return Lexer {
            input: input,
            position: 0,
            read_position: 0,
            ch: c
        };
    }

//    pub fn read_char(&'a mut self)  {
//        if self.read_position >= self.input.len() {
//            self.ch = & '0';
//        } else {
//            self.ch = & self.input.chars().nth(self.read_position).unwrap();
//            self.position = self.read_position;
//            self.read_position += 1;
//        }
//    }

    pub fn next_token(&'a mut self) -> Token {
        let token_type = TokenType::from_string(self.ch.to_string());
//        self.read_char();
        return Token {
            token_type: token_type,
            value: Some(Value::Str(self.ch.to_string()))
        }
    }

    pub fn peek_char(&self) -> char {
        if self.read_position >= self.input.len() {
            return '0';
        } else {
            return self.input.chars().nth(self.read_position).unwrap();
        }
    }
}

#[test]
fn next_token() {
    let input = String::from("=+(){},;");
    let tests = [
        (TokenType::ASSIGN, "="),
        (TokenType::PLUS, "+"),
        (TokenType::LPAREN, "("),
        (TokenType::RPAREN, ")"),
        (TokenType::LBRACE, "{"),
        (TokenType::RBRACE, "}"),
        (TokenType::COMMA, ","),
        (TokenType::SEMICOLON, ";"),
        (TokenType::EOF, ""),
    ];
}
<commit_msg>add mutability<commit_after>use std::char;

pub enum TokenType {
    ILLEGAL,
    EOF,
    IDENT,
    INT,
    ASSIGN,
    PLUS,
    MINUS,
    COMMA,
    SEMICOLON,
    LPAREN,
    RPAREN,
    LBRACE,
    RBRACE,
    FUNCTION,
    LET,
}

pub enum Value {
    Int(String),
    Str(String),
}

pub struct Token {
    pub token_type: TokenType,
    pub value: Option<Value>,
}

impl TokenType {
    pub fn from_string(s: String) -> TokenType {
        match s.as_ref() {
            "\n" => TokenType::EOF,
            "let" => TokenType::LET,
            "+" => TokenType::PLUS,
            "-" => TokenType::MINUS,
            "," => TokenType::COMMA,
            ";" => TokenType::SEMICOLON,
            "(" => TokenType::LPAREN,
            ")" => TokenType::RPAREN,
            "{" => TokenType::LBRACE,
            "}" => TokenType::RBRACE,
            "func" => TokenType::FUNCTION,
            _ => TokenType::ILLEGAL
        }
    }
}

pub struct Parser<'a> {
    pub tokens: &'a [Token]
}

impl<'a> Parser<'a> {
    pub fn parse(&self) {
        return ();
    }
}

pub struct Lexer<'a> {
    pub input: String,
    pub position: usize,
    pub read_position: usize,
    pub ch: &'a mut char
}

impl<'a> Lexer<'a> {
    pub fn new(input: String, c: &'a mut char) -> Lexer<'a> {
        return Lexer {
            input: input,
            position: 0,
            read_position: 0,
            ch: c
        };
    }

    //    pub fn read_char(&'a mut self)  {
    //        if self.read_position >= self.input.len() {
    //            self.ch = & '0';
    //        } else {
    //            self.ch = & self.input.chars().nth(self.read_position).unwrap();
    //            self.position = self.read_position;
    //            self.read_position += 1;
    //        }
    //    }

    pub fn next_token(&'a mut self) -> Token {
        let token_type = TokenType::from_string(self.ch.to_string());
        //        self.read_char();
        return Token {
            token_type: token_type,
            value: Some(Value::Str(self.ch.to_string()))
        };
    }

    pub fn peek_char(&self) -> char {
        if self.read_position >= self.input.len() {
            return '0';
        } else {
            return self.input.chars().nth(self.read_position).unwrap();
        }
    }
}

#[test]
fn next_token() {
    let input = String::from("=+(){},;");
    let tests = [
        (TokenType::ASSIGN, "="),
        (TokenType::PLUS, "+"),
        (TokenType::LPAREN, "("),
        (TokenType::RPAREN, ")"),
        (TokenType::LBRACE, "{"),
        (TokenType::RBRACE, "}"),
        (TokenType::COMMA, ","),
        (TokenType::SEMICOLON, ";"),
        (TokenType::EOF, ""),
    ];
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(warnings)]

extern crate build_helper;
extern crate gcc;

use std::env;
use std::process::Command;
use build_helper::{run, native_lib_boilerplate};

fn main() {
    let target = env::var("TARGET").expect("TARGET was not set");
    let host = env::var("HOST").expect("HOST was not set");
    if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") &&
        !target.contains("emscripten") && !target.contains("fuchsia") && !target.contains("redox") {
        let _ = build_libbacktrace(&host, &target);
    }

    if target.contains("linux") {
        if target.contains("android") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=log");
            println!("cargo:rustc-link-lib=gcc");
        } else if !target.contains("musl") || target.contains("mips") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=rt");
            println!("cargo:rustc-link-lib=pthread");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=execinfo");
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("dragonfly") || target.contains("bitrig") ||
              target.contains("netbsd") || target.contains("openbsd") {
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("apple-darwin") {
        println!("cargo:rustc-link-lib=System");

        // res_init and friends require -lresolv on macOS/iOS.
        // See #41582 and http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("apple-ios") {
        println!("cargo:rustc-link-lib=System");
        println!("cargo:rustc-link-lib=objc");
        println!("cargo:rustc-link-lib=framework=Security");
        println!("cargo:rustc-link-lib=framework=Foundation");
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("windows") {
        println!("cargo:rustc-link-lib=advapi32");
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=userenv");
        println!("cargo:rustc-link-lib=shell32");
    } else if target.contains("fuchsia") {
        // use system-provided libbacktrace
        if cfg!(feature = "backtrace") {
            println!("cargo:rustc-link-lib=backtrace");
        }
        println!("cargo:rustc-link-lib=magenta");
        println!("cargo:rustc-link-lib=mxio");
        println!("cargo:rustc-link-lib=launchpad"); // for std::process
    }
}

fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
    let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;

    let compiler = gcc::Config::new().get_compiler();
    // only msvc returns None for ar so unwrap is okay
    let ar = build_helper::cc2ar(compiler.path(), target).unwrap();
    let mut cflags = compiler.args().iter().map(|s| s.to_str().unwrap())
                             .collect::<Vec<_>>().join(" ");
    cflags.push_str(" -fvisibility=hidden");
    run(Command::new("sh")
                .current_dir(&native.out_dir)
                .arg(native.src_dir.join("configure").to_str().unwrap()
                                   .replace("C:\\", "/c/")
                                   .replace("\\", "/"))
                .arg("--with-pic")
                .arg("--disable-multilib")
                .arg("--disable-shared")
                .arg("--disable-host-shared")
                .arg(format!("--host={}", build_helper::gnu_target(target)))
                .arg(format!("--build={}", build_helper::gnu_target(host)))
                .env("CC", compiler.path())
                .env("AR", &ar)
                .env("RANLIB", format!("{} s", ar.display()))
                .env("CFLAGS", cflags));

    run(Command::new(build_helper::make(host))
                .current_dir(&native.out_dir)
                .arg(format!("INCDIR={}", native.src_dir.display()))
                .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));
    Ok(())
}
<commit_msg>Auto merge of #43104 - nbaksalyar:rustbuild-illumos-fix, r=sanxiyn<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(warnings)]

extern crate build_helper;
extern crate gcc;

use std::env;
use std::process::Command;
use build_helper::{run, native_lib_boilerplate};

fn main() {
    let target = env::var("TARGET").expect("TARGET was not set");
    let host = env::var("HOST").expect("HOST was not set");
    if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") &&
        !target.contains("emscripten") && !target.contains("fuchsia") && !target.contains("redox") {
        let _ = build_libbacktrace(&host, &target);
    }

    if target.contains("linux") {
        if target.contains("android") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=log");
            println!("cargo:rustc-link-lib=gcc");
        } else if !target.contains("musl") || target.contains("mips") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=rt");
            println!("cargo:rustc-link-lib=pthread");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=execinfo");
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("dragonfly") || target.contains("bitrig") ||
              target.contains("netbsd") || target.contains("openbsd") {
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("solaris") {
        println!("cargo:rustc-link-lib=socket");
        println!("cargo:rustc-link-lib=posix4");
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("apple-darwin") {
        println!("cargo:rustc-link-lib=System");

        // res_init and friends require -lresolv on macOS/iOS.
        // See #41582 and http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("apple-ios") {
        println!("cargo:rustc-link-lib=System");
        println!("cargo:rustc-link-lib=objc");
        println!("cargo:rustc-link-lib=framework=Security");
        println!("cargo:rustc-link-lib=framework=Foundation");
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("windows") {
        println!("cargo:rustc-link-lib=advapi32");
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=userenv");
        println!("cargo:rustc-link-lib=shell32");
    } else if target.contains("fuchsia") {
        // use system-provided libbacktrace
        if cfg!(feature = "backtrace") {
            println!("cargo:rustc-link-lib=backtrace");
        }
        println!("cargo:rustc-link-lib=magenta");
        println!("cargo:rustc-link-lib=mxio");
        println!("cargo:rustc-link-lib=launchpad"); // for std::process
    }
}

fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
    let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;

    let compiler = gcc::Config::new().get_compiler();
    // only msvc returns None for ar so unwrap is okay
    let ar = build_helper::cc2ar(compiler.path(), target).unwrap();
    let mut cflags = compiler.args().iter().map(|s| s.to_str().unwrap())
                             .collect::<Vec<_>>().join(" ");
    cflags.push_str(" -fvisibility=hidden");
    run(Command::new("sh")
                .current_dir(&native.out_dir)
                .arg(native.src_dir.join("configure").to_str().unwrap()
                                   .replace("C:\\", "/c/")
                                   .replace("\\", "/"))
                .arg("--with-pic")
                .arg("--disable-multilib")
                .arg("--disable-shared")
                .arg("--disable-host-shared")
                .arg(format!("--host={}", build_helper::gnu_target(target)))
                .arg(format!("--build={}", build_helper::gnu_target(host)))
                .env("CC", compiler.path())
                .env("AR", &ar)
                .env("RANLIB", format!("{} s", ar.display()))
                .env("CFLAGS", cflags));

    run(Command::new(build_helper::make(host))
                .current_dir(&native.out_dir)
                .arg(format!("INCDIR={}", native.src_dir.display()))
                .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));
    Ok(())
}
<|endoftext|>


<commit_before>#![cfg(test)]
use super::*;
use crate::{test_utils::*, *};
use fixed_len_vec::typenum::*;
use serde_derive::{Deserialize, Serialize};

#[test]
fn default_values() {
    let cache = CommitteeCache::default();

    assert_eq!(cache.is_initialized_at(Epoch::new(0)), false);
    assert_eq!(cache.active_validator_indices(), &[]);
    assert_eq!(cache.get_crosslink_committee_for_shard(0), None);
    assert_eq!(cache.get_attestation_duties(0), None);
    assert_eq!(cache.active_validator_count(), 0);
    assert_eq!(cache.epoch_committee_count(), 0);
    assert_eq!(cache.epoch_start_shard(), 0);
    assert_eq!(cache.get_crosslink_committees_for_slot(Slot::new(0)), None);
    assert_eq!(cache.first_committee_at_slot(Slot::new(0)), None);
}

fn new_state<T: EthSpec>(validator_count: usize, slot: Slot) -> BeaconState<T> {
    let spec = &T::spec();

    let mut builder =
        TestingBeaconStateBuilder::from_single_keypair(validator_count, &Keypair::random(), spec);

    builder.teleport_to_slot(slot, spec);

    let (state, _keypairs) = builder.build();

    state
}

#[test]
fn fails_without_validators() {
    let state = new_state::<FewValidatorsEthSpec>(0, Slot::new(0));
    let spec = &FewValidatorsEthSpec::spec();

    assert_eq!(
        CommitteeCache::initialized(&state, state.current_epoch(), &spec),
        Err(BeaconStateError::InsufficientValidators)
    );
}

#[test]
fn initializes_with_the_right_epoch() {
    let state = new_state::<FewValidatorsEthSpec>(16, Slot::new(0));
    let spec = &FewValidatorsEthSpec::spec();

    let cache = CommitteeCache::default();
    assert_eq!(cache.initialized_epoch, None);

    let cache = CommitteeCache::initialized(&state, state.current_epoch(), &spec).unwrap();
    assert_eq!(cache.initialized_epoch, Some(state.current_epoch()));

    let cache = CommitteeCache::initialized(&state, state.previous_epoch(), &spec).unwrap();
    assert_eq!(cache.initialized_epoch, Some(state.previous_epoch()));

    let cache = CommitteeCache::initialized(&state, state.next_epoch(), &spec).unwrap();
    assert_eq!(cache.initialized_epoch, Some(state.next_epoch()));
}

#[test]
fn shuffles_for_the_right_epoch() {
    let num_validators = FewValidatorsEthSpec::minimum_validator_count() * 2;
    let epoch = Epoch::new(100_000_000);
    let slot = epoch.start_slot(FewValidatorsEthSpec::slots_per_epoch());

    let mut state = new_state::<FewValidatorsEthSpec>(num_validators, slot);
    let spec = &FewValidatorsEthSpec::spec();

    let distinct_hashes: Vec<Hash256> = (0..FewValidatorsEthSpec::latest_randao_mixes_length())
        .into_iter()
        .map(|i| Hash256::from(i as u64))
        .collect();

    state.latest_randao_mixes = FixedLenVec::from(distinct_hashes);

    let previous_seed = state.generate_seed(state.previous_epoch(), spec).unwrap();
    let current_seed = state.generate_seed(state.current_epoch(), spec).unwrap();
    let next_seed = state.generate_seed(state.next_epoch(), spec).unwrap();

    assert!((previous_seed != current_seed) && (current_seed != next_seed));

    let shuffling_with_seed = |seed: Hash256| {
        shuffle_list(
            (0..num_validators).collect(),
            spec.shuffle_round_count,
            &seed[..],
            false,
        )
        .unwrap()
    };

    let assert_shuffling_positions_accurate = |cache: &CommitteeCache| {
        for (i, v) in cache.shuffling.iter().enumerate() {
            assert_eq!(
                cache.shuffling_positions[*v].unwrap().get() - 1,
                i,
                "Shuffling position inaccurate"
            );
        }
    };

    let cache = CommitteeCache::initialized(&state, state.current_epoch(), spec).unwrap();
    assert_eq!(cache.shuffling, shuffling_with_seed(current_seed));
    assert_shuffling_positions_accurate(&cache);

    let cache = CommitteeCache::initialized(&state, state.previous_epoch(), spec).unwrap();
    assert_eq!(cache.shuffling, shuffling_with_seed(previous_seed));
    assert_shuffling_positions_accurate(&cache);

    let cache = CommitteeCache::initialized(&state, state.next_epoch(), spec).unwrap();
    assert_eq!(cache.shuffling, shuffling_with_seed(next_seed));
    assert_shuffling_positions_accurate(&cache);
}

#[test]
fn can_start_on_any_shard() {
    let num_validators = FewValidatorsEthSpec::minimum_validator_count() * 2;
    let epoch = Epoch::new(100_000_000);
    let slot = epoch.start_slot(FewValidatorsEthSpec::slots_per_epoch());

    let mut state = new_state::<FewValidatorsEthSpec>(num_validators, slot);
    let spec = &FewValidatorsEthSpec::spec();

    for i in 0..FewValidatorsEthSpec::shard_count() as u64 {
        state.latest_start_shard = i;

        let cache = CommitteeCache::initialized(&state, state.current_epoch(), spec).unwrap();
        assert_eq!(cache.shuffling_start_shard, i);

        let cache = CommitteeCache::initialized(&state, state.previous_epoch(), spec).unwrap();
        assert_eq!(cache.shuffling_start_shard, i);

        let cache = CommitteeCache::initialized(&state, state.next_epoch(), spec).unwrap();
        assert_eq!(cache.shuffling_start_shard, i);
    }
}

/// This spec has more shards than slots in an epoch, permitting epochs where not all shards are
/// included in the committee.
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct ExcessShardsEthSpec;

impl EthSpec for ExcessShardsEthSpec {
    type ShardCount = U128;
    type SlotsPerHistoricalRoot = U8192;
    type LatestRandaoMixesLength = U8192;
    type LatestActiveIndexRootsLength = U8192;
    type LatestSlashedExitLength = U8192;

    fn spec() -> ChainSpec {
        ChainSpec::few_validators()
    }
}

#[test]
fn starts_on_the_correct_shard() {
    let spec = &ExcessShardsEthSpec::spec();

    let num_validators = ExcessShardsEthSpec::shard_count();

    let epoch = Epoch::new(100_000_000);
    let slot = epoch.start_slot(ExcessShardsEthSpec::slots_per_epoch());

    let mut state = new_state::<ExcessShardsEthSpec>(num_validators, slot);

    let validator_count = state.validator_registry.len();

    let previous_epoch = state.previous_epoch();
    let current_epoch = state.current_epoch();
    let next_epoch = state.next_epoch();

    for (i, mut v) in state.validator_registry.iter_mut().enumerate() {
        let epoch = if i < validator_count / 4 {
            previous_epoch
        } else if i < validator_count / 2 {
            current_epoch
        } else {
            next_epoch
        };

        v.activation_epoch = epoch;
    }

    assert_eq!(
        get_active_validator_count(&state.validator_registry, previous_epoch),
        validator_count / 4
    );
    assert_eq!(
        get_active_validator_count(&state.validator_registry, current_epoch),
        validator_count / 2
    );
    assert_eq!(
        get_active_validator_count(&state.validator_registry, next_epoch),
        validator_count
    );

    let previous_shards = ExcessShardsEthSpec::get_epoch_committee_count(
        get_active_validator_count(&state.validator_registry, previous_epoch),
    );
    let current_shards = ExcessShardsEthSpec::get_epoch_committee_count(
        get_active_validator_count(&state.validator_registry, current_epoch),
    );
    let next_shards = ExcessShardsEthSpec::get_epoch_committee_count(get_active_validator_count(
        &state.validator_registry,
        next_epoch,
    ));

    assert_eq!(
        previous_shards as usize,
        ExcessShardsEthSpec::shard_count() / 4
    );
    assert_eq!(
        current_shards as usize,
        ExcessShardsEthSpec::shard_count() / 2
    );
    assert_eq!(next_shards as usize, ExcessShardsEthSpec::shard_count());

    let shard_count = ExcessShardsEthSpec::shard_count();
    for i in 0..ExcessShardsEthSpec::shard_count() {
        state.latest_start_shard = i as u64;

        let cache = CommitteeCache::initialized(&state, state.current_epoch(), spec).unwrap();
        assert_eq!(cache.shuffling_start_shard as usize, i);

        let cache = CommitteeCache::initialized(&state, state.previous_epoch(), spec).unwrap();
        assert_eq!(
            cache.shuffling_start_shard as usize,
            (i + shard_count - previous_shards) % shard_count
        );

        let cache = CommitteeCache::initialized(&state, state.next_epoch(), spec).unwrap();
        assert_eq!(
            cache.shuffling_start_shard as usize,
            (i + current_shards) % shard_count
        );
    }
}
<commit_msg>committee cache: fix a test for shard delta changes<commit_after>#![cfg(test)]
use super::*;
use crate::{test_utils::*, *};
use fixed_len_vec::typenum::*;
use serde_derive::{Deserialize, Serialize};

#[test]
fn default_values() {
    let cache = CommitteeCache::default();

    assert_eq!(cache.is_initialized_at(Epoch::new(0)), false);
    assert_eq!(cache.active_validator_indices(), &[]);
    assert_eq!(cache.get_crosslink_committee_for_shard(0), None);
    assert_eq!(cache.get_attestation_duties(0), None);
    assert_eq!(cache.active_validator_count(), 0);
    assert_eq!(cache.epoch_committee_count(), 0);
    assert_eq!(cache.epoch_start_shard(), 0);
    assert_eq!(cache.get_crosslink_committees_for_slot(Slot::new(0)), None);
    assert_eq!(cache.first_committee_at_slot(Slot::new(0)), None);
}

fn new_state<T: EthSpec>(validator_count: usize, slot: Slot) -> BeaconState<T> {
    let spec = &T::spec();

    let mut builder =
        TestingBeaconStateBuilder::from_single_keypair(validator_count, &Keypair::random(), spec);

    builder.teleport_to_slot(slot, spec);

    let (state, _keypairs) = builder.build();

    state
}

#[test]
fn fails_without_validators() {
    let state = new_state::<FewValidatorsEthSpec>(0, Slot::new(0));
    let spec = &FewValidatorsEthSpec::spec();

    assert_eq!(
        CommitteeCache::initialized(&state, state.current_epoch(), &spec),
        Err(BeaconStateError::InsufficientValidators)
    );
}

#[test]
fn initializes_with_the_right_epoch() {
    let state = new_state::<FewValidatorsEthSpec>(16, Slot::new(0));
    let spec = &FewValidatorsEthSpec::spec();

    let cache = CommitteeCache::default();
    assert_eq!(cache.initialized_epoch, None);

    let cache = CommitteeCache::initialized(&state, state.current_epoch(), &spec).unwrap();
    assert_eq!(cache.initialized_epoch, Some(state.current_epoch()));

    let cache = CommitteeCache::initialized(&state, state.previous_epoch(), &spec).unwrap();
    assert_eq!(cache.initialized_epoch, Some(state.previous_epoch()));

    let cache = CommitteeCache::initialized(&state, state.next_epoch(), &spec).unwrap();
    assert_eq!(cache.initialized_epoch, Some(state.next_epoch()));
}

#[test]
fn shuffles_for_the_right_epoch() {
    let num_validators = FewValidatorsEthSpec::minimum_validator_count() * 2;
    let epoch = Epoch::new(100_000_000);
    let slot = epoch.start_slot(FewValidatorsEthSpec::slots_per_epoch());

    let mut state = new_state::<FewValidatorsEthSpec>(num_validators, slot);
    let spec = &FewValidatorsEthSpec::spec();

    let distinct_hashes: Vec<Hash256> = (0..FewValidatorsEthSpec::latest_randao_mixes_length())
        .into_iter()
        .map(|i| Hash256::from(i as u64))
        .collect();

    state.latest_randao_mixes = FixedLenVec::from(distinct_hashes);

    let previous_seed = state.generate_seed(state.previous_epoch(), spec).unwrap();
    let current_seed = state.generate_seed(state.current_epoch(), spec).unwrap();
    let next_seed = state.generate_seed(state.next_epoch(), spec).unwrap();

    assert!((previous_seed != current_seed) && (current_seed != next_seed));

    let shuffling_with_seed = |seed: Hash256| {
        shuffle_list(
            (0..num_validators).collect(),
            spec.shuffle_round_count,
            &seed[..],
            false,
        )
        .unwrap()
    };

    let assert_shuffling_positions_accurate = |cache: &CommitteeCache| {
        for (i, v) in cache.shuffling.iter().enumerate() {
            assert_eq!(
                cache.shuffling_positions[*v].unwrap().get() - 1,
                i,
                "Shuffling position inaccurate"
            );
        }
    };

    let cache = CommitteeCache::initialized(&state, state.current_epoch(), spec).unwrap();
    assert_eq!(cache.shuffling, shuffling_with_seed(current_seed));
    assert_shuffling_positions_accurate(&cache);

    let cache = CommitteeCache::initialized(&state, state.previous_epoch(), spec).unwrap();
    assert_eq!(cache.shuffling, shuffling_with_seed(previous_seed));
    assert_shuffling_positions_accurate(&cache);

    let cache = CommitteeCache::initialized(&state, state.next_epoch(), spec).unwrap();
    assert_eq!(cache.shuffling, shuffling_with_seed(next_seed));
    assert_shuffling_positions_accurate(&cache);
}

#[test]
fn can_start_on_any_shard() {
    let num_validators = FewValidatorsEthSpec::minimum_validator_count() * 2;
    let epoch = Epoch::new(100_000_000);
    let slot = epoch.start_slot(FewValidatorsEthSpec::slots_per_epoch());

    let mut state = new_state::<FewValidatorsEthSpec>(num_validators, slot);
    let spec = &FewValidatorsEthSpec::spec();

    let shard_delta = FewValidatorsEthSpec::get_shard_delta(num_validators);
    let shard_count = FewValidatorsEthSpec::shard_count() as u64;

    for i in 0..FewValidatorsEthSpec::shard_count() as u64 {
        state.latest_start_shard = i;

        let cache = CommitteeCache::initialized(&state, state.current_epoch(), spec).unwrap();
        assert_eq!(cache.shuffling_start_shard, i);

        let cache = CommitteeCache::initialized(&state, state.previous_epoch(), spec).unwrap();
        assert_eq!(
            cache.shuffling_start_shard,
            (i + shard_count - shard_delta) % shard_count
        );

        let cache = CommitteeCache::initialized(&state, state.next_epoch(), spec).unwrap();
        assert_eq!(cache.shuffling_start_shard, (i + shard_delta) % shard_count);
    }
}

/// This spec has more shards than slots in an epoch, permitting epochs where not all shards are
/// included in the committee.
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct ExcessShardsEthSpec;

impl EthSpec for ExcessShardsEthSpec {
    type ShardCount = U128;
    type SlotsPerHistoricalRoot = U8192;
    type LatestRandaoMixesLength = U8192;
    type LatestActiveIndexRootsLength = U8192;
    type LatestSlashedExitLength = U8192;

    fn spec() -> ChainSpec {
        ChainSpec::few_validators()
    }
}

#[test]
fn starts_on_the_correct_shard() {
    let spec = &ExcessShardsEthSpec::spec();

    let num_validators = ExcessShardsEthSpec::shard_count();

    let epoch = Epoch::new(100_000_000);
    let slot = epoch.start_slot(ExcessShardsEthSpec::slots_per_epoch());

    let mut state = new_state::<ExcessShardsEthSpec>(num_validators, slot);

    let validator_count = state.validator_registry.len();

    let previous_epoch = state.previous_epoch();
    let current_epoch = state.current_epoch();
    let next_epoch = state.next_epoch();

    for (i, mut v) in state.validator_registry.iter_mut().enumerate() {
        let epoch = if i < validator_count / 4 {
            previous_epoch
        } else if i < validator_count / 2 {
            current_epoch
        } else {
            next_epoch
        };

        v.activation_epoch = epoch;
    }

    assert_eq!(
        get_active_validator_count(&state.validator_registry, previous_epoch),
        validator_count / 4
    );
    assert_eq!(
        get_active_validator_count(&state.validator_registry, current_epoch),
        validator_count / 2
    );
    assert_eq!(
        get_active_validator_count(&state.validator_registry, next_epoch),
        validator_count
    );

    let previous_shards = ExcessShardsEthSpec::get_epoch_committee_count(
        get_active_validator_count(&state.validator_registry, previous_epoch),
    );
    let current_shards = ExcessShardsEthSpec::get_epoch_committee_count(
        get_active_validator_count(&state.validator_registry, current_epoch),
    );
    let next_shards = ExcessShardsEthSpec::get_epoch_committee_count(get_active_validator_count(
        &state.validator_registry,
        next_epoch,
    ));

    assert_eq!(
        previous_shards as usize,
        ExcessShardsEthSpec::shard_count() / 4
    );
    assert_eq!(
        current_shards as usize,
        ExcessShardsEthSpec::shard_count() / 2
    );
    assert_eq!(next_shards as usize, ExcessShardsEthSpec::shard_count());

    let shard_count = ExcessShardsEthSpec::shard_count();
    for i in 0..ExcessShardsEthSpec::shard_count() {
        state.latest_start_shard = i as u64;

        let cache = CommitteeCache::initialized(&state, state.current_epoch(), spec).unwrap();
        assert_eq!(cache.shuffling_start_shard as usize, i);

        let cache = CommitteeCache::initialized(&state, state.previous_epoch(), spec).unwrap();
        assert_eq!(
            cache.shuffling_start_shard as usize,
            (i + shard_count - previous_shards) % shard_count
        );

        let cache = CommitteeCache::initialized(&state, state.next_epoch(), spec).unwrap();
        assert_eq!(
            cache.shuffling_start_shard as usize,
            (i + current_shards) % shard_count
        );
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use self::libc::{c_char, c_uchar};

/// Create keys (both primary and revocation) for the given schema and stores the keys in a secure wallet.
/// A signing type can be set (curently only CL signature type is supported).
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// schema_json: schema as a json
/// sign_type: signature type (optional). Currently only CL is supported.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Created public keys as a json.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_issuer_create_and_store_keys(client_id: i32, command_id: i32,
                                             schema_json: *const c_char,
                                             sign_type: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                             public_key_json: *const c_char)) {
    unimplemented!();
}

/// Create a new revocation registry for the given public key.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// public_key_id: ID of a public key
/// max_claim_num: maximum number of claims the new registry can process.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Created revocation registry as a jsons.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_issuer_create_and_store_revoc_reg(client_id: i32, command_id: i32,
                                             public_key_id: *const c_char,
                                             max_claim_num: i32,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                       revoc_reg_json: *const c_char)) {
    unimplemented!();
}

/// Signs a given claim for the given user by a given key (that is create a credential).
/// The corresponding keys and revocation registry must be already created an stored into the wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// claim_req_json: a claim request with a blinded secret from the user (returned by anoncreds_prover_create_and_store_claim_req)
/// claim_json: a claim containing attribute values for each of requested attribute names.
///     Example:
///     {
///      "attr1" : "value1",
///      "attr2" : "valkue2"
///     }
/// public_key_id: ID of a public key
/// revoc_reg_id: ID of a revocation registry to use
//  user_revoc_id: ID of a new user in the revocation registry (optional; default one is used if not provided)
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Credential json containing issued credential, and public_key_id and revoc_reg_id used for issuance
///     {
///         "cred": string,
///         "schema_id": string,
///         "public_key_id", string,
///         "revoc_reg_id", string
///     }
/// Updated revoc_reg as json
///
/// #Errors
/// RevocRegistryFull
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_issuer_sign_claim(client_id: i32, command_id: i32,
                                             claim_req_json: *const c_char,
                                             claim_json: *const c_char,
                                             public_key_id: *const c_char,
                                             revoc_reg_id: *const c_char,
                                             user_revoc_id: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                       credential_json: *const c_char,
                                                       revoc_reg_update_json: *const c_char)) {
    unimplemented!();
}

/// Revokes a user identified by a revoc_id in a given revoc-registry.
/// The corresponding keys and revocation registry must be already created an stored into the wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// revoc_reg_id: ID of a revocation registry to use
//  user_revoc_id: ID of the user in the revocation registry
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Updated revoc_reg as json
///
/// #Errors
/// NotIssued
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_issuer_revoke_claim(client_id: i32, command_id: i32,
                                             revoc_reg_id: *const c_char,
                                             user_revoc_id: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32
                                                       revoc_reg_update_json: *const c_char)) {
    unimplemented!();
}

/// Creates a clam request json for the given claim offer and and stores it in a secure wallet.
/// The claim offer contains the information about Issuer (DID, public_key_id), and the schema (schema_id).
/// The method gets public key and schema from the ledger, stores them in a wallet, and creates a blinded master secret
/// which is a prt of the claim request.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// claim_offer_json: claim offer as a json containing information about the issuer and a claim:
///        {
///            "issuer_did": string,
///            "schema_id": string,
///            "public_key_id": string
///        }
/// master_secret: (optional) If not provided, then a new one will be generated.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Claim request json.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_prover_create_and_store_claim_req(client_id: i32, command_id: i32,
                                             claim_offer_json: *const c_char,
                                             master_secret: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                           claim_req_json: *const c_char)) {
    unimplemented!();
}

/// Updates the credential by a master secret and store in a secure wallet.
/// The credential contains the information about schema_id, public_key_id revoc_reg_id (see anoncreds_issuer_sign_claim).
/// The method loads a blinded secret for this key from the wallet, updates the credential and stores it in a wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// credentials_json: credentials json:
///     {
///         "cred": string,
///         "schema_id": string,
///         "public_key_id", string,
///         "revoc_reg_id", string
///     }
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// None
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_prover_store_credential(client_id: i32, command_id: i32,
                                             credentials_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32)) {
    unimplemented!();
}

/// Parses the given proof_request json and creates a proof.
/// A proof request may request multiple claims from different schemas and different issuers.
/// The method gets from the Ledger all required data (public keys, etc.), and prepares a proof (of multiple claim).
/// The proof request also contains nonce.
/// The proof contains proofs for each schema with corresponding public_key_id, revoc_reg_id
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// proof_request_json: proof request as a json
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Proof json
/// {
///    "proofs":[
///        {
///            "proof": string,
///            "schema_id": string,
///            "public_key_id": string,
///            "revoc_reg_id": string,
///            "revealed_attr_values": array,
///        }],
///    "aggregated_proof": object
/// }
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_prover_create_proof(client_id: i32, command_id: i32,
                                             proof_request_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                proof_json: *const c_char)) {
    unimplemented!();
}

/// Parses the given proof_request json and creates a proof.
/// A proof request may request multiple claims from different schemas and different issuers.
/// The method gets all required data (public keys, etc.) from the Ledger, and verifies a proof (of multiple claim).
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// proof_request_initial_json: initial proof request as sent by the verifier
/// proof_request_disclosed_json: an updated by the prover proof_request if the prover doesn't want to disclose all the information from the
///                             initial proof_request. disclosed pool request contains information participating in the proof only.
/// proof_json: proof as a json
/// {
///    "proofs":[
///        {
///            "proof": string,
///            "schema_id": string,
///            "public_key_id": string,
///            "revoc_reg_id": string,
///            "revealed_attr_values": array,
///        }],
///    "aggregated_proof": object
/// }
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// None
///
/// #Errors
/// VerificationError.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_verifier_verify_proof(client_id: i32, command_id: i32,
                                             proof_request_initial_json: *const c_char,
                                             proof_request_disclosed_json: *const c_char,
                                             proof_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32)) {
    unimplemented!();
}

<commit_msg>API proposal<commit_after>extern crate libc;

use self::libc::{c_char, c_uchar};

/// Create keys (both primary and revocation) for the given schema and stores the keys in a secure wallet.
/// A signing type can be set (curently only CL signature type is supported).
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// schema_json: schema as a json
/// sign_type: signature type (optional). Currently only CL is supported.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Created public keys as a json.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_issuer_create_and_store_keys(client_id: i32, command_id: i32,
                                             schema_json: *const c_char,
                                             sign_type: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                             public_key_json: *const c_char)) {
    unimplemented!();
}

/// Create a new revocation registry for the given public key.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// public_key_id: ID of a public key
/// max_claim_num: maximum number of claims the new registry can process.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Created revocation registry as a jsons.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_issuer_create_and_store_revoc_reg(client_id: i32, command_id: i32,
                                             public_key_id: *const c_char,
                                             max_claim_num: i32,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                       revoc_reg_json: *const c_char)) {
    unimplemented!();
}

/// Signs a given claim for the given user by a given key (that is create a credential).
/// The corresponding keys and revocation registry must be already created an stored into the wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// claim_req_json: a claim request with a blinded secret from the user (returned by anoncreds_prover_create_and_store_claim_req)
/// claim_json: a claim containing attribute values for each of requested attribute names.
///     Example:
///     {
///      "attr1" : "value1",
///      "attr2" : "valkue2"
///     }
/// public_key_id: ID of a public key
/// revoc_reg_id: ID of a revocation registry to use
//  user_revoc_id: ID of a new user in the revocation registry (optional; default one is used if not provided)
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Credential json containing issued credential, and public_key_id and revoc_reg_id used for issuance
///     {
///         "cred": string,
///         "schema_id": string,
///         "public_key_id", string,
///         "revoc_reg_id", string
///     }
/// Updated revoc_reg as json
///
/// #Errors
/// RevocRegistryFull
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_issuer_create_credential(client_id: i32, command_id: i32,
                                             claim_req_json: *const c_char,
                                             claim_json: *const c_char,
                                             public_key_id: *const c_char,
                                             revoc_reg_id: *const c_char,
                                             user_revoc_id: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                       credential_json: *const c_char,
                                                       revoc_reg_update_json: *const c_char)) {
    unimplemented!();
}

/// Revokes a user identified by a revoc_id in a given revoc-registry.
/// The corresponding keys and revocation registry must be already created an stored into the wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// revoc_reg_id: ID of a revocation registry to use
//  user_revoc_id: ID of the user in the revocation registry
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Updated revoc_reg as json
///
/// #Errors
/// NotIssued
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_issuer_revoke_claim(client_id: i32, command_id: i32,
                                             revoc_reg_id: *const c_char,
                                             user_revoc_id: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32
                                                       revoc_reg_update_json: *const c_char)) {
    unimplemented!();
}

/// Creates a clam request json for the given claim offer and and stores it in a secure wallet.
/// The claim offer contains the information about Issuer (DID, public_key_id), and the schema (schema_id).
/// The method gets public key and schema from the ledger, stores them in a wallet, and creates a blinded master secret
/// which is a prt of the claim request.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// claim_offer_json: claim offer as a json containing information about the issuer and a claim:
///        {
///            "issuer_did": string,
///            "schema_id": string,
///            "public_key_id": string
///        }
/// master_secret: (optional) If not provided, then a new one will be generated.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Claim request json.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_prover_create_and_store_claim_req(client_id: i32, command_id: i32,
                                             claim_offer_json: *const c_char,
                                             master_secret: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                           claim_req_json: *const c_char)) {
    unimplemented!();
}

/// Updates the credential by a master secret and store in a secure wallet.
/// The credential contains the information about schema_id, public_key_id revoc_reg_id (see anoncreds_issuer_sign_claim).
/// The method loads a blinded secret for this key from the wallet, updates the credential and stores it in a wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// credentials_json: credentials json:
///     {
///         "cred": string,
///         "schema_id": string,
///         "public_key_id", string,
///         "revoc_reg_id", string
///     }
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// None
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_prover_store_credential(client_id: i32, command_id: i32,
                                             credentials_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32)) {
    unimplemented!();
}

/// Parses the given proof_request json and creates a proof.
/// A proof request may request multiple claims from different schemas and different issuers.
/// The method gets from the Ledger all required data (public keys, etc.), and prepares a proof (of multiple claim).
/// The proof request also contains nonce.
/// The proof contains proofs for each schema with corresponding public_key_id, revoc_reg_id
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// proof_request_json: proof request as a json
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Proof json
/// {
///    "proofs":[
///        {
///            "proof": string,
///            "schema_id": string,
///            "public_key_id": string,
///            "revoc_reg_id": string,
///            "revealed_attr_values": array,
///        }],
///    "aggregated_proof": object
/// }
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_prover_create_proof(client_id: i32, command_id: i32,
                                             proof_request_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                proof_json: *const c_char)) {
    unimplemented!();
}

/// Parses the given proof_request json and creates a proof.
/// A proof request may request multiple claims from different schemas and different issuers.
/// The method gets all required data (public keys, etc.) from the Ledger, and verifies a proof (of multiple claim).
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// proof_request_initial_json: initial proof request as sent by the verifier
/// proof_request_disclosed_json: an updated by the prover proof_request if the prover doesn't want to disclose all the information from the
///                             initial proof_request. disclosed pool request contains information participating in the proof only.
/// proof_json: proof as a json
/// {
///    "proofs":[
///        {
///            "proof": string,
///            "schema_id": string,
///            "public_key_id": string,
///            "revoc_reg_id": string,
///            "revealed_attr_values": array,
///        }],
///    "aggregated_proof": object
/// }
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// None
///
/// #Errors
/// VerificationError.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn anoncreds_verifier_verify_proof(client_id: i32, command_id: i32,
                                             proof_request_initial_json: *const c_char,
                                             proof_request_disclosed_json: *const c_char,
                                             proof_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32)) {
    unimplemented!();
}

<|endoftext|>


<commit_before>extern crate diesel;

use self::diesel::prelude::*;
use data::model::quiz::category::*;
use data::model::quiz::player::*;
use data::establish_connection;
use data::schema;
use self::diesel::result::{Error, DatabaseErrorKind};

type Result<T> = self::diesel::QueryResult<T>;

pub fn create_player(name: &str) -> Result<Player> {
    if name.is_empty() {
        return Err(Error::DatabaseError(DatabaseErrorKind::__Unknown,
                                             Box::new("Name cannot be empty".to_owned())));
    }
    use self::schema::player;
    let new_player = NewPlayer { name };
    let conn = establish_connection();
    diesel::insert(&new_player).into(player::table).get_result(&conn)
}

pub fn create_category(text: &str) -> Result<Category> {
    use self::schema::category;
    let new_category = NewCategory { text };
    let conn = establish_connection();
    diesel::insert(&new_category).into(category::table).get_result(&conn)
}

pub fn get_categories() -> Result<Vec<Category>> {
    use self::schema::category::dsl::*;
    let conn = establish_connection();
    category.filter(is_active.eq(true)).load::<Category>(&conn)
}
<commit_msg>Run rustfmt<commit_after>extern crate diesel;

use self::diesel::prelude::*;
use data::model::quiz::category::*;
use data::model::quiz::player::*;
use data::establish_connection;
use data::schema;
use self::diesel::result::{Error, DatabaseErrorKind};

type Result<T> = self::diesel::QueryResult<T>;

pub fn create_player(name: &str) -> Result<Player> {
    if name.is_empty() {
        return Err(Error::DatabaseError(DatabaseErrorKind::__Unknown,
                                        Box::new("Name cannot be empty".to_owned())));
    }
    use self::schema::player;
    let new_player = NewPlayer { name };
    let conn = establish_connection();
    diesel::insert(&new_player).into(player::table).get_result(&conn)
}

pub fn create_category(text: &str) -> Result<Category> {
    use self::schema::category;
    let new_category = NewCategory { text };
    let conn = establish_connection();
    diesel::insert(&new_category).into(category::table).get_result(&conn)
}

pub fn get_categories() -> Result<Vec<Category>> {
    use self::schema::category::dsl::*;
    let conn = establish_connection();
    category.filter(is_active.eq(true)).load::<Category>(&conn)
}
<|endoftext|>