<commit_before>//! Support for sending and receiving data link layer packets using libpcap.
//! Also has support for reading pcap files.

extern crate pcap;

use std::io;
use std::marker::{Send, Sync};
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::time::Duration;

use self::pcap::{Activated, Active};

use Channel::Ethernet;
use {DataLinkReceiver, DataLinkSender, NetworkInterface};

/// Configuration for the pcap datalink backend.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Config {
    /// The size of buffer to use when reading packets. Must be at least
    /// 65516 with pcap.
    pub read_buffer_size: usize,

    /// The read timeout. Defaults to None.
    pub read_timeout: Option<Duration>,
}

impl<'a> From<&'a super::Config> for Config {
    fn from(config: &super::Config) -> Config {
        let mut c = Config {
            read_buffer_size: config.read_buffer_size,
            read_timeout: config.read_timeout,
        };
        // pcap is unique in that the buffer size must be greater or equal to
        // MAXIMUM_SNAPLEN, which is currently hard-coded to 65536
        // So, just reset it to the default.
        if c.read_buffer_size < 65536 {
            c.read_buffer_size = Config::default().read_buffer_size;
        }
        c
    }
}

impl Default for Config {
    fn default() -> Config {
        Config {
            // Just let pcap pick the default size
            read_buffer_size: 0,
            read_timeout: None,
        }
    }
}

/// Create a datalink channel from the provided pcap device.
#[inline]
pub fn channel(network_interface: &NetworkInterface, config: Config) -> io::Result<super::Channel> {
    let cap = match pcap::Capture::from_device(&*network_interface.name) {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    }
    .buffer_size(config.read_buffer_size as i32);
    let cap = match config.read_timeout {
        Some(to) => cap.timeout((to.as_secs() * 1000 + (to.subsec_nanos() / 1000) as u64) as i32),
        None => cap,
    };
    // Enable promiscuous capture
    let cap = cap.promisc(true);
    let cap = match cap.open() {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    };
    let cap = Arc::new(Mutex::new(cap));
    Ok(Ethernet(
        Box::new(DataLinkSenderImpl {
            capture: cap.clone(),
        }),
        Box::new(DataLinkReceiverImpl {
            capture: cap.clone(),
            read_buffer: vec![0; config.read_buffer_size],
        }),
    ))
}

/// Create a datalink channel from a pcap file.
#[inline]
pub fn from_file<P: AsRef<Path>>(path: P, config: Config) -> io::Result<super::Channel> {
    let cap = match pcap::Capture::from_file(path) {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    };
    let cap = Arc::new(Mutex::new(cap));
    Ok(Ethernet(
        Box::new(InvalidDataLinkSenderImpl {}),
        Box::new(DataLinkReceiverImpl {
            capture: cap.clone(),
            read_buffer: vec![0; config.read_buffer_size],
        }),
    ))
}

struct DataLinkSenderImpl {
    capture: Arc<Mutex<pcap::Capture<Active>>>,
}

impl DataLinkSender for DataLinkSenderImpl {
    #[inline]
    fn build_and_send(
        &mut self,
        num_packets: usize,
        packet_size: usize,
        func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>> {
        for _ in 0..num_packets {
            let mut data = vec![0; packet_size];
            func(&mut data);
            let mut cap = self.capture.lock().unwrap();
            if let Err(e) = cap.sendpacket(data) {
                return Some(Err(io::Error::new(io::ErrorKind::Other, e)));
            }
        }
        Some(Ok(()))
    }

    #[inline]
    fn send_to(&mut self, packet: &[u8], _dst: Option<NetworkInterface>) -> Option<io::Result<()>> {
        let mut cap = self.capture.lock().unwrap();
        Some(match cap.sendpacket(packet) {
            Ok(()) => Ok(()),
            Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
        })
    }
}

struct InvalidDataLinkSenderImpl {}

impl DataLinkSender for InvalidDataLinkSenderImpl {
    #[inline]
    fn build_and_send(
        &mut self,
        _num_packets: usize,
        _packet_size: usize,
        _func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>> {
        None
    }

    #[inline]
    fn send_to(
        &mut self,
        _packet: &[u8],
        _dst: Option<NetworkInterface>,
    ) -> Option<io::Result<()>> {
        None
    }
}

struct DataLinkReceiverImpl<T: Activated + Send + Sync> {
    capture: Arc<Mutex<pcap::Capture<T>>>,
    read_buffer: Vec<u8>,
}

impl<T: Activated + Send + Sync> DataLinkReceiver for DataLinkReceiverImpl<T> {
    fn next(&mut self) -> io::Result<&[u8]> {
        let mut cap = self.capture.lock().unwrap();
        match cap.next() {
            Ok(pkt) => {
                self.read_buffer.truncate(0);
                self.read_buffer.extend(pkt.data);
            }
            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
        };
        Ok(&self.read_buffer)
    }
}

/// Get a list of available network interfaces for the current machine.
pub fn interfaces() -> Vec<NetworkInterface> {
    if let Ok(devices) = pcap::Device::list() {
        devices
            .iter()
            .enumerate()
            .map(|(i, dev)| NetworkInterface {
                name: dev.name.clone(),
                index: i as u32,
                mac: None,
                ips: Vec::new(),
                flags: 0,
            })
            .collect()
    } else {
        vec![]
    }
}
<commit_msg>Fix calculation of pcap read timeout<commit_after>//! Support for sending and receiving data link layer packets using libpcap.
//! Also has support for reading pcap files.

extern crate pcap;

use std::io;
use std::marker::{Send, Sync};
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::time::Duration;

use self::pcap::{Activated, Active};

use Channel::Ethernet;
use {DataLinkReceiver, DataLinkSender, NetworkInterface};

/// Configuration for the pcap datalink backend.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Config {
    /// The size of buffer to use when reading packets. Must be at least
    /// 65516 with pcap.
    pub read_buffer_size: usize,

    /// The read timeout. Defaults to None.
    pub read_timeout: Option<Duration>,
}

impl<'a> From<&'a super::Config> for Config {
    fn from(config: &super::Config) -> Config {
        let mut c = Config {
            read_buffer_size: config.read_buffer_size,
            read_timeout: config.read_timeout,
        };
        // pcap is unique in that the buffer size must be greater or equal to
        // MAXIMUM_SNAPLEN, which is currently hard-coded to 65536
        // So, just reset it to the default.
        if c.read_buffer_size < 65536 {
            c.read_buffer_size = Config::default().read_buffer_size;
        }
        c
    }
}

impl Default for Config {
    fn default() -> Config {
        Config {
            // Just let pcap pick the default size
            read_buffer_size: 0,
            read_timeout: None,
        }
    }
}

/// Create a datalink channel from the provided pcap device.
#[inline]
pub fn channel(network_interface: &NetworkInterface, config: Config) -> io::Result<super::Channel> {
    let cap = match pcap::Capture::from_device(&*network_interface.name) {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    }
    .buffer_size(config.read_buffer_size as i32);
    // Set pcap timeout (in milliseconds).
    // For conversion .as_millis() method could be used as well, but might have
    // a small performance impact as it uses u128 as return type
    let cap = match config.read_timeout {
        Some(to) => cap.timeout((to.as_secs() as u32 * 1000 + to.subsec_millis()) as i32),
        None => cap,
    };
    // Enable promiscuous capture
    let cap = cap.promisc(true);
    let cap = match cap.open() {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    };
    let cap = Arc::new(Mutex::new(cap));
    Ok(Ethernet(
        Box::new(DataLinkSenderImpl {
            capture: cap.clone(),
        }),
        Box::new(DataLinkReceiverImpl {
            capture: cap.clone(),
            read_buffer: vec![0; config.read_buffer_size],
        }),
    ))
}

/// Create a datalink channel from a pcap file.
#[inline]
pub fn from_file<P: AsRef<Path>>(path: P, config: Config) -> io::Result<super::Channel> {
    let cap = match pcap::Capture::from_file(path) {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    };
    let cap = Arc::new(Mutex::new(cap));
    Ok(Ethernet(
        Box::new(InvalidDataLinkSenderImpl {}),
        Box::new(DataLinkReceiverImpl {
            capture: cap.clone(),
            read_buffer: vec![0; config.read_buffer_size],
        }),
    ))
}

struct DataLinkSenderImpl {
    capture: Arc<Mutex<pcap::Capture<Active>>>,
}

impl DataLinkSender for DataLinkSenderImpl {
    #[inline]
    fn build_and_send(
        &mut self,
        num_packets: usize,
        packet_size: usize,
        func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>> {
        for _ in 0..num_packets {
            let mut data = vec![0; packet_size];
            func(&mut data);
            let mut cap = self.capture.lock().unwrap();
            if let Err(e) = cap.sendpacket(data) {
                return Some(Err(io::Error::new(io::ErrorKind::Other, e)));
            }
        }
        Some(Ok(()))
    }

    #[inline]
    fn send_to(&mut self, packet: &[u8], _dst: Option<NetworkInterface>) -> Option<io::Result<()>> {
        let mut cap = self.capture.lock().unwrap();
        Some(match cap.sendpacket(packet) {
            Ok(()) => Ok(()),
            Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
        })
    }
}

struct InvalidDataLinkSenderImpl {}

impl DataLinkSender for InvalidDataLinkSenderImpl {
    #[inline]
    fn build_and_send(
        &mut self,
        _num_packets: usize,
        _packet_size: usize,
        _func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>> {
        None
    }

    #[inline]
    fn send_to(
        &mut self,
        _packet: &[u8],
        _dst: Option<NetworkInterface>,
    ) -> Option<io::Result<()>> {
        None
    }
}

struct DataLinkReceiverImpl<T: Activated + Send + Sync> {
    capture: Arc<Mutex<pcap::Capture<T>>>,
    read_buffer: Vec<u8>,
}

impl<T: Activated + Send + Sync> DataLinkReceiver for DataLinkReceiverImpl<T> {
    fn next(&mut self) -> io::Result<&[u8]> {
        let mut cap = self.capture.lock().unwrap();
        match cap.next() {
            Ok(pkt) => {
                self.read_buffer.truncate(0);
                self.read_buffer.extend(pkt.data);
            }
            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
        };
        Ok(&self.read_buffer)
    }
}

/// Get a list of available network interfaces for the current machine.
pub fn interfaces() -> Vec<NetworkInterface> {
    if let Ok(devices) = pcap::Device::list() {
        devices
            .iter()
            .enumerate()
            .map(|(i, dev)| NetworkInterface {
                name: dev.name.clone(),
                index: i as u32,
                mac: None,
                ips: Vec::new(),
                flags: 0,
            })
            .collect()
    } else {
        vec![]
    }
}
<|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::sync::Arc;

use buffer::Buffer;
use buffer::BufferViewRef;
use descriptor::descriptor::DescriptorType;
use descriptor::descriptor_set::DescriptorSet;
use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
use descriptor::descriptor_set::DescriptorPool;
use descriptor::descriptor_set::DescriptorPoolAlloc;
use descriptor::descriptor_set::UnsafeDescriptorSet;
use descriptor::descriptor_set::DescriptorWrite;
use descriptor::descriptor_set::StdDescriptorPool;
use descriptor::pipeline_layout::PipelineLayoutAbstract;
use device::Device;
use device::DeviceOwned;
use image::sys::Layout;
use sync::AccessFlagBits;
use sync::PipelineStages;

/// A simple immutable descriptor set.
///
/// It is named "simple" because creating such a descriptor set allocates from a pool, and because
/// it can't be modified once created. It is sufficient for most usages, but in some situations
/// you may wish to use something more optimized instead.
///
/// In order to build a `SimpleDescriptorSet`, you need to use a `SimpleDescriptorSetBuilder`. But
/// the easiest way is to use the `simple_descriptor_set!` macro.
///
/// The template parameter of the `SimpleDescriptorSet` is very complex, and you shouldn't try to
/// express it explicitely. If you want to store your descriptor set in a struct or in a `Vec` for
/// example, you are encouraged to turn `SimpleDescriptorSet` into a `Box<DescriptorSet>` or a
/// `Arc<DescriptorSet>`.
///
/// # Example
// TODO:
pub struct SimpleDescriptorSet<R, P = Arc<StdDescriptorPool>> where P: DescriptorPool {
    inner: P::Alloc,
    resources: R,
    layout: Arc<UnsafeDescriptorSetLayout>
}

impl<R, P> SimpleDescriptorSet<R, P> where P: DescriptorPool {
    /// Returns the layout used to create this descriptor set.
    #[inline]
    pub fn set_layout(&self) -> &Arc<UnsafeDescriptorSetLayout> {
        &self.layout
    }
}

unsafe impl<R, P> DescriptorSet for SimpleDescriptorSet<R, P> where P: DescriptorPool {
    #[inline]
    fn inner(&self) -> &UnsafeDescriptorSet {
        self.inner.inner()
    }
}

/// Builds a descriptor set in the form of a `SimpleDescriptorSet` object.
// TODO: more doc
#[macro_export]
macro_rules! simple_descriptor_set {
    ($layout:expr, $set_num:expr, {$($name:ident: $val:expr),*$(,)*}) => ({
        use $crate::descriptor::descriptor_set::SimpleDescriptorSetBuilder;
        use $crate::descriptor::descriptor_set::SimpleDescriptorSetBufferExt;

        // We build an empty `SimpleDescriptorSetBuilder` struct, then adds each element one by
        // one. When done, we call `build()` on the builder.

        let builder = SimpleDescriptorSetBuilder::new($layout, $set_num);

        $(
            // Here `$val` can be either a buffer or an image. However we can't create an extension
            // trait for both buffers and image, because `impl<T: Image> ExtTrait for T {}` would
            // conflict with `impl<T: Buffer> ExtTrait for T {}`.
            //
            // Therefore we use a trick: we create two traits, one for buffers
            // (`SimpleDescriptorSetBufferExt`) and one for images (`SimpleDescriptorSetImageExt`),
            // that both have a method named `add_me`. We import these two traits in scope and
            // call `add_me` on the value, letting Rust dispatch to the right trait. A compilation
            // error will happen if `$val` is both a buffer and an image.
            let builder = $val.add_me(builder, stringify!($name));
        )*

        builder.build()
    });
}

/// Prototype of a `SimpleDescriptorSet`.
///
/// > **Note**: You are encouraged to use the `simple_descriptor_set!` macro instead of
/// > manipulating these internals.
///
/// The template parameter `L` is the pipeline layout to use, and the template parameter `R` is
/// a complex unspecified type that represents the list of resources.
///
/// # Example
// TODO: example here
pub struct SimpleDescriptorSetBuilder<L, R> {
    // The pipeline layout.
    layout: L,
    // Id of the set within the pipeline layout.
    set_id: usize,
    // The writes to perform on a descriptor set in order to put the resources in it.
    writes: Vec<DescriptorWrite>,
    // Holds the resources alive.
    resources: R,
}

impl<L> SimpleDescriptorSetBuilder<L, ()> where L: PipelineLayoutAbstract {
    /// Builds a new prototype for a `SimpleDescriptorSet`. Requires a reference to a pipeline
    /// layout, and the id of the set within the layout.
    ///
    /// # Panic
    ///
    /// - Panics if the set id is out of range.
    ///
    pub fn new(layout: L, set_id: usize) -> SimpleDescriptorSetBuilder<L, ()> {
        assert!(layout.desc().num_sets() > set_id);

        let cap = layout.desc().num_bindings_in_set(set_id).unwrap_or(0);

        SimpleDescriptorSetBuilder {
            layout: layout,
            set_id: set_id,
            writes: Vec::with_capacity(cap),
            resources: (),
        }
    }
}

impl<L, R> SimpleDescriptorSetBuilder<L, R> where L: PipelineLayoutAbstract {
    /// Builds a `SimpleDescriptorSet` from the builder.
    pub fn build(self) -> SimpleDescriptorSet<R, Arc<StdDescriptorPool>> {
        // TODO: check that we filled everything
        let pool = Device::standard_descriptor_pool(self.layout.device());
        let set_layout = self.layout.descriptor_set_layout(self.set_id).unwrap().clone();       // FIXME: error

        let set = unsafe {
            let mut set = pool.alloc(&set_layout).unwrap();      // FIXME: error
            set.inner_mut().write(pool.device(), self.writes.into_iter());
            set
        };

        SimpleDescriptorSet {
            inner: set,
            resources: self.resources,
            layout: set_layout,
        }
    }
}

/// Trait implemented on buffers so that they can be appended to a simple descriptor set builder.
pub unsafe trait SimpleDescriptorSetBufferExt<L, R> {
    /// The new type of the template parameter `R` of the builder.
    type Out;

    /// Appends the buffer to the `SimpleDescriptorSetBuilder`.
    // TODO: return Result
    fn add_me(self, i: SimpleDescriptorSetBuilder<L, R>, name: &str)
              -> SimpleDescriptorSetBuilder<L, Self::Out>;
}

unsafe impl<L, R, T> SimpleDescriptorSetBufferExt<L, R> for T
    where T: Buffer, L: PipelineLayoutAbstract
{
    type Out = (R, SimpleDescriptorSetBuf<T>);

    fn add_me(self, mut i: SimpleDescriptorSetBuilder<L, R>, name: &str)
              -> SimpleDescriptorSetBuilder<L, Self::Out>
    {
        let (set_id, binding_id) = i.layout.desc().descriptor_by_name(name).unwrap();    // TODO: Result instead
        assert_eq!(set_id, i.set_id);       // TODO: Result instead
        let desc = i.layout.desc().descriptor(set_id, binding_id).unwrap();     // TODO: Result instead

        assert!(desc.array_count == 1);     // not implemented
        i.writes.push(match desc.ty.ty().unwrap() {
            DescriptorType::UniformBuffer => unsafe {
                DescriptorWrite::uniform_buffer(binding_id as u32, &self)
            },
            DescriptorType::StorageBuffer => unsafe {
                DescriptorWrite::storage_buffer(binding_id as u32, &self)
            },
            _ => panic!()
        });

        SimpleDescriptorSetBuilder {
            layout: i.layout,
            set_id: i.set_id,
            writes: i.writes,
            resources: (i.resources, SimpleDescriptorSetBuf {
                buffer: self,
                write: !desc.readonly,
                stage: PipelineStages::none(),      // FIXME:
                access: AccessFlagBits::none(),     // FIXME:
            })
        }
    }
}

/*
/// Internal trait related to the `SimpleDescriptorSet` system.
pub unsafe trait SimpleDescriptorSetResourcesCollection {
    #[inline]
    fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>);
}

unsafe impl SimpleDescriptorSetResourcesCollection for () {
    #[inline]
    fn add_transition<'a>(&'a self, _: &mut CommandsListSink<'a>) {
    }
}*/

/// Internal object related to the `SimpleDescriptorSet` system.
pub struct SimpleDescriptorSetBuf<B> {
    buffer: B,
    write: bool,
    stage: PipelineStages,
    access: AccessFlagBits,
}

/*unsafe impl<B> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetBuf<B>
    where B: Buffer
{
    #[inline]
    fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
        // TODO: wrong values
        let stages = PipelineStages {
            compute_shader: true,
            all_graphics: true,
            .. PipelineStages::none()
        };

        let access = AccessFlagBits {
            uniform_read: true,
            shader_read: true,
            shader_write: true,
            .. AccessFlagBits::none()
        };

        sink.add_buffer_transition(&self.buffer, 0, self.buffer.size(), self.write, stages, access);
    }
}*/

/// Internal object related to the `SimpleDescriptorSet` system.
pub struct SimpleDescriptorSetBufView<V> where V: BufferViewRef {
    view: V,
    write: bool,
    stage: PipelineStages,
    access: AccessFlagBits,
}

/*unsafe impl<V> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetBufView<V>
    where V: BufferViewRef, V::Buffer: Buffer
{
    #[inline]
    fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
        // TODO: wrong values
        let stages = PipelineStages {
            compute_shader: true,
            all_graphics: true,
            .. PipelineStages::none()
        };

        let access = AccessFlagBits {
            uniform_read: true,
            shader_read: true,
            shader_write: true,
            .. AccessFlagBits::none()
        };

        sink.add_buffer_transition(self.view.view().buffer(), 0, self.view.view().buffer().size(),
                                   self.write, stages, access);
    }
}*/

/// Internal object related to the `SimpleDescriptorSet` system.
pub struct SimpleDescriptorSetImg<I> {
    image: I,
    write: bool,
    first_mipmap: u32,
    num_mipmaps: u32,
    first_layer: u32,
    num_layers: u32,
    layout: Layout,
    stage: PipelineStages,
    access: AccessFlagBits,
}

/*unsafe impl<I> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetImg<I>
    where I: ImageView
{
    #[inline]
    fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
        // TODO: wrong values
        let stages = PipelineStages {
            compute_shader: true,
            all_graphics: true,
            .. PipelineStages::none()
        };

        let access = AccessFlagBits {
            uniform_read: true,
            input_attachment_read: true,
            shader_read: true,
            shader_write: true,
            .. AccessFlagBits::none()
        };

        // FIXME: adjust layers & mipmaps with the view's parameters
        sink.add_image_transition(self.image.parent(), self.first_layer, self.num_layers,
                                  self.first_mipmap, self.num_mipmaps, self.write,
                                  self.layout, stages, access);
    }
}

unsafe impl<A, B> SimpleDescriptorSetResourcesCollection for (A, B)
    where A: SimpleDescriptorSetResourcesCollection,
          B: SimpleDescriptorSetResourcesCollection
{
    #[inline]
    fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
        self.0.add_transition(sink);
        self.1.add_transition(sink);
    }
}*/
<commit_msg>Add binding images to simple descriptor sets<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::sync::Arc;

use buffer::Buffer;
use buffer::BufferViewRef;
use descriptor::descriptor::DescriptorType;
use descriptor::descriptor_set::DescriptorSet;
use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
use descriptor::descriptor_set::DescriptorPool;
use descriptor::descriptor_set::DescriptorPoolAlloc;
use descriptor::descriptor_set::UnsafeDescriptorSet;
use descriptor::descriptor_set::DescriptorWrite;
use descriptor::descriptor_set::StdDescriptorPool;
use descriptor::pipeline_layout::PipelineLayoutAbstract;
use device::Device;
use device::DeviceOwned;
use image::ImageView;
use image::sys::Layout;
use sampler::Sampler;
use sync::AccessFlagBits;
use sync::PipelineStages;

/// A simple immutable descriptor set.
///
/// It is named "simple" because creating such a descriptor set allocates from a pool, and because
/// it can't be modified once created. It is sufficient for most usages, but in some situations
/// you may wish to use something more optimized instead.
///
/// In order to build a `SimpleDescriptorSet`, you need to use a `SimpleDescriptorSetBuilder`. But
/// the easiest way is to use the `simple_descriptor_set!` macro.
///
/// The template parameter of the `SimpleDescriptorSet` is very complex, and you shouldn't try to
/// express it explicitely. If you want to store your descriptor set in a struct or in a `Vec` for
/// example, you are encouraged to turn `SimpleDescriptorSet` into a `Box<DescriptorSet>` or a
/// `Arc<DescriptorSet>`.
///
/// # Example
// TODO:
pub struct SimpleDescriptorSet<R, P = Arc<StdDescriptorPool>> where P: DescriptorPool {
    inner: P::Alloc,
    resources: R,
    layout: Arc<UnsafeDescriptorSetLayout>
}

impl<R, P> SimpleDescriptorSet<R, P> where P: DescriptorPool {
    /// Returns the layout used to create this descriptor set.
    #[inline]
    pub fn set_layout(&self) -> &Arc<UnsafeDescriptorSetLayout> {
        &self.layout
    }
}

unsafe impl<R, P> DescriptorSet for SimpleDescriptorSet<R, P> where P: DescriptorPool {
    #[inline]
    fn inner(&self) -> &UnsafeDescriptorSet {
        self.inner.inner()
    }
}

/// Builds a descriptor set in the form of a `SimpleDescriptorSet` object.
// TODO: more doc
#[macro_export]
macro_rules! simple_descriptor_set {
    ($layout:expr, $set_num:expr, {$($name:ident: $val:expr),*$(,)*}) => ({
        use $crate::descriptor::descriptor_set::SimpleDescriptorSetBuilder;
        use $crate::descriptor::descriptor_set::SimpleDescriptorSetBufferExt;
        use $crate::descriptor::descriptor_set::SimpleDescriptorSetImageExt;

        // We build an empty `SimpleDescriptorSetBuilder` struct, then adds each element one by
        // one. When done, we call `build()` on the builder.

        let builder = SimpleDescriptorSetBuilder::new($layout, $set_num);

        $(
            // Here `$val` can be either a buffer or an image. However we can't create an extension
            // trait for both buffers and image, because `impl<T: Image> ExtTrait for T {}` would
            // conflict with `impl<T: Buffer> ExtTrait for T {}`.
            //
            // Therefore we use a trick: we create two traits, one for buffers
            // (`SimpleDescriptorSetBufferExt`) and one for images (`SimpleDescriptorSetImageExt`),
            // that both have a method named `add_me`. We import these two traits in scope and
            // call `add_me` on the value, letting Rust dispatch to the right trait. A compilation
            // error will happen if `$val` is both a buffer and an image.
            let builder = $val.add_me(builder, stringify!($name));
        )*

        builder.build()
    });
}

/// Prototype of a `SimpleDescriptorSet`.
///
/// > **Note**: You are encouraged to use the `simple_descriptor_set!` macro instead of
/// > manipulating these internals.
///
/// The template parameter `L` is the pipeline layout to use, and the template parameter `R` is
/// a complex unspecified type that represents the list of resources.
///
/// # Example
// TODO: example here
pub struct SimpleDescriptorSetBuilder<L, R> {
    // The pipeline layout.
    layout: L,
    // Id of the set within the pipeline layout.
    set_id: usize,
    // The writes to perform on a descriptor set in order to put the resources in it.
    writes: Vec<DescriptorWrite>,
    // Holds the resources alive.
    resources: R,
}

impl<L> SimpleDescriptorSetBuilder<L, ()> where L: PipelineLayoutAbstract {
    /// Builds a new prototype for a `SimpleDescriptorSet`. Requires a reference to a pipeline
    /// layout, and the id of the set within the layout.
    ///
    /// # Panic
    ///
    /// - Panics if the set id is out of range.
    ///
    pub fn new(layout: L, set_id: usize) -> SimpleDescriptorSetBuilder<L, ()> {
        assert!(layout.desc().num_sets() > set_id);

        let cap = layout.desc().num_bindings_in_set(set_id).unwrap_or(0);

        SimpleDescriptorSetBuilder {
            layout: layout,
            set_id: set_id,
            writes: Vec::with_capacity(cap),
            resources: (),
        }
    }
}

impl<L, R> SimpleDescriptorSetBuilder<L, R> where L: PipelineLayoutAbstract {
    /// Builds a `SimpleDescriptorSet` from the builder.
    pub fn build(self) -> SimpleDescriptorSet<R, Arc<StdDescriptorPool>> {
        // TODO: check that we filled everything
        let pool = Device::standard_descriptor_pool(self.layout.device());
        let set_layout = self.layout.descriptor_set_layout(self.set_id).unwrap().clone();       // FIXME: error

        let set = unsafe {
            let mut set = pool.alloc(&set_layout).unwrap();      // FIXME: error
            set.inner_mut().write(pool.device(), self.writes.into_iter());
            set
        };

        SimpleDescriptorSet {
            inner: set,
            resources: self.resources,
            layout: set_layout,
        }
    }
}

/// Trait implemented on buffers so that they can be appended to a simple descriptor set builder.
pub unsafe trait SimpleDescriptorSetBufferExt<L, R> {
    /// The new type of the template parameter `R` of the builder.
    type Out;

    /// Appends the buffer to the `SimpleDescriptorSetBuilder`.
    // TODO: return Result
    fn add_me(self, i: SimpleDescriptorSetBuilder<L, R>, name: &str)
              -> SimpleDescriptorSetBuilder<L, Self::Out>;
}

unsafe impl<L, R, T> SimpleDescriptorSetBufferExt<L, R> for T
    where T: Buffer, L: PipelineLayoutAbstract
{
    type Out = (R, SimpleDescriptorSetBuf<T>);

    fn add_me(self, mut i: SimpleDescriptorSetBuilder<L, R>, name: &str)
              -> SimpleDescriptorSetBuilder<L, Self::Out>
    {
        let (set_id, binding_id) = i.layout.desc().descriptor_by_name(name).unwrap();    // TODO: Result instead
        assert_eq!(set_id, i.set_id);       // TODO: Result instead
        let desc = i.layout.desc().descriptor(set_id, binding_id).unwrap();     // TODO: Result instead

        assert!(desc.array_count == 1);     // not implemented
        i.writes.push(match desc.ty.ty().unwrap() {
            DescriptorType::UniformBuffer => unsafe {
                DescriptorWrite::uniform_buffer(binding_id as u32, &self)
            },
            DescriptorType::StorageBuffer => unsafe {
                DescriptorWrite::storage_buffer(binding_id as u32, &self)
            },
            _ => panic!()
        });

        SimpleDescriptorSetBuilder {
            layout: i.layout,
            set_id: i.set_id,
            writes: i.writes,
            resources: (i.resources, SimpleDescriptorSetBuf {
                buffer: self,
                write: !desc.readonly,
                stage: PipelineStages::none(),      // FIXME:
                access: AccessFlagBits::none(),     // FIXME:
            })
        }
    }
}

/// Trait implemented on images so that they can be appended to a simple descriptor set builder.
pub unsafe trait SimpleDescriptorSetImageExt<L, R> {
    /// The new type of the template parameter `R` of the builder.
    type Out;

    /// Appends the image to the `SimpleDescriptorSetBuilder`.
    // TODO: return Result
    fn add_me(self, i: SimpleDescriptorSetBuilder<L, R>, name: &str)
              -> SimpleDescriptorSetBuilder<L, Self::Out>;
}

unsafe impl<L, R, T> SimpleDescriptorSetImageExt<L, R> for T
    where T: ImageView, L: PipelineLayoutAbstract
{
    type Out = (R, SimpleDescriptorSetImg<T>);

    fn add_me(self, mut i: SimpleDescriptorSetBuilder<L, R>, name: &str)
              -> SimpleDescriptorSetBuilder<L, Self::Out>
    {
        let (set_id, binding_id) = i.layout.desc().descriptor_by_name(name).unwrap();    // TODO: Result instead
        assert_eq!(set_id, i.set_id);       // TODO: Result instead
        let desc = i.layout.desc().descriptor(set_id, binding_id).unwrap();     // TODO: Result instead

        assert!(desc.array_count == 1);     // not implemented
        i.writes.push(match desc.ty.ty().unwrap() {
            DescriptorType::SampledImage => unsafe {
                DescriptorWrite::sampled_image(binding_id as u32, &self)
            },
            DescriptorType::StorageImage => unsafe {
                DescriptorWrite::storage_image(binding_id as u32, &self)
            },
            DescriptorType::InputAttachment => unsafe {
                DescriptorWrite::input_attachment(binding_id as u32, &self)
            },
            _ => panic!()
        });

        SimpleDescriptorSetBuilder {
            layout: i.layout,
            set_id: i.set_id,
            writes: i.writes,
            resources: (i.resources, SimpleDescriptorSetImg {
                image: self,
                sampler: None,
                write: !desc.readonly,
                first_mipmap: 0,            // FIXME:
                num_mipmaps: 1,         // FIXME:
                first_layer: 0,         // FIXME:
                num_layers: 1,          // FIXME:
                layout: Layout::General,            // FIXME:
                stage: PipelineStages::none(),          // FIXME:
                access: AccessFlagBits::none(),         // FIXME:
            })
        }
    }
}

unsafe impl<L, R, T> SimpleDescriptorSetImageExt<L, R> for (T, Arc<Sampler>)
    where T: ImageView, L: PipelineLayoutAbstract
{
    type Out = (R, SimpleDescriptorSetImg<T>);

    fn add_me(self, mut i: SimpleDescriptorSetBuilder<L, R>, name: &str)
              -> SimpleDescriptorSetBuilder<L, Self::Out>
    {
        let (set_id, binding_id) = i.layout.desc().descriptor_by_name(name).unwrap();    // TODO: Result instead
        assert_eq!(set_id, i.set_id);       // TODO: Result instead
        let desc = i.layout.desc().descriptor(set_id, binding_id).unwrap();     // TODO: Result instead

        assert!(desc.array_count == 1);     // not implemented
        i.writes.push(match desc.ty.ty().unwrap() {
            DescriptorType::CombinedImageSampler => unsafe {
                DescriptorWrite::combined_image_sampler(binding_id as u32, &self.1, &self.0)
            },
            _ => panic!()
        });

        SimpleDescriptorSetBuilder {
            layout: i.layout,
            set_id: i.set_id,
            writes: i.writes,
            resources: (i.resources, SimpleDescriptorSetImg {
                image: self.0,
                sampler: Some(self.1),
                write: !desc.readonly,
                first_mipmap: 0,            // FIXME:
                num_mipmaps: 1,         // FIXME:
                first_layer: 0,         // FIXME:
                num_layers: 1,          // FIXME:
                layout: Layout::General,            // FIXME:
                stage: PipelineStages::none(),          // FIXME:
                access: AccessFlagBits::none(),         // FIXME:
            })
        }
    }
}

/*
/// Internal trait related to the `SimpleDescriptorSet` system.
pub unsafe trait SimpleDescriptorSetResourcesCollection {
    #[inline]
    fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>);
}

unsafe impl SimpleDescriptorSetResourcesCollection for () {
    #[inline]
    fn add_transition<'a>(&'a self, _: &mut CommandsListSink<'a>) {
    }
}*/

/// Internal object related to the `SimpleDescriptorSet` system.
pub struct SimpleDescriptorSetBuf<B> {
    buffer: B,
    write: bool,
    stage: PipelineStages,
    access: AccessFlagBits,
}

/*unsafe impl<B> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetBuf<B>
    where B: Buffer
{
    #[inline]
    fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
        // TODO: wrong values
        let stages = PipelineStages {
            compute_shader: true,
            all_graphics: true,
            .. PipelineStages::none()
        };

        let access = AccessFlagBits {
            uniform_read: true,
            shader_read: true,
            shader_write: true,
            .. AccessFlagBits::none()
        };

        sink.add_buffer_transition(&self.buffer, 0, self.buffer.size(), self.write, stages, access);
    }
}*/

/// Internal object related to the `SimpleDescriptorSet` system.
pub struct SimpleDescriptorSetBufView<V> where V: BufferViewRef {
    view: V,
    write: bool,
    stage: PipelineStages,
    access: AccessFlagBits,
}

/*unsafe impl<V> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetBufView<V>
    where V: BufferViewRef, V::Buffer: Buffer
{
    #[inline]
    fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
        // TODO: wrong values
        let stages = PipelineStages {
            compute_shader: true,
            all_graphics: true,
            .. PipelineStages::none()
        };

        let access = AccessFlagBits {
            uniform_read: true,
            shader_read: true,
            shader_write: true,
            .. AccessFlagBits::none()
        };

        sink.add_buffer_transition(self.view.view().buffer(), 0, self.view.view().buffer().size(),
                                   self.write, stages, access);
    }
}*/

/// Internal object related to the `SimpleDescriptorSet` system.
pub struct SimpleDescriptorSetImg<I> {
    image: I,
    sampler: Option<Arc<Sampler>>,
    write: bool,
    first_mipmap: u32,
    num_mipmaps: u32,
    first_layer: u32,
    num_layers: u32,
    layout: Layout,
    stage: PipelineStages,
    access: AccessFlagBits,
}

/*unsafe impl<I> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetImg<I>
    where I: ImageView
{
    #[inline]
    fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
        // TODO: wrong values
        let stages = PipelineStages {
            compute_shader: true,
            all_graphics: true,
            .. PipelineStages::none()
        };

        let access = AccessFlagBits {
            uniform_read: true,
            input_attachment_read: true,
            shader_read: true,
            shader_write: true,
            .. AccessFlagBits::none()
        };

        // FIXME: adjust layers & mipmaps with the view's parameters
        sink.add_image_transition(self.image.parent(), self.first_layer, self.num_layers,
                                  self.first_mipmap, self.num_mipmaps, self.write,
                                  self.layout, stages, access);
    }
}

unsafe impl<A, B> SimpleDescriptorSetResourcesCollection for (A, B)
    where A: SimpleDescriptorSetResourcesCollection,
          B: SimpleDescriptorSetResourcesCollection
{
    #[inline]
    fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
        self.0.add_transition(sink);
        self.1.add_transition(sink);
    }
}*/
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0
use crate::config::RoleType;
use diem_types::PeerId;
use serde::{Deserialize, Serialize, Serializer};
use std::fmt;

/// A grouping of common information between all networking code for logging.
/// This should greatly reduce the groupings between these given everywhere, and will allow
/// for logging accordingly.
#[derive(Clone, Eq, PartialEq, Serialize)]
pub struct NetworkContext {
    #[serde(serialize_with = "NetworkId::serialize_str")]
    network_id: NetworkId,
    role: RoleType,
    peer_id: PeerId,
}

impl fmt::Debug for NetworkContext {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

impl fmt::Display for NetworkContext {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "[{},{},{}]",
            self.network_id.as_str(),
            self.role,
            self.peer_id.short_str(),
        )
    }
}

impl NetworkContext {
    pub fn new(network_id: NetworkId, role: RoleType, peer_id: PeerId) -> NetworkContext {
        NetworkContext {
            network_id,
            role,
            peer_id,
        }
    }

    pub fn network_id(&self) -> &NetworkId {
        &self.network_id
    }

    pub fn role(&self) -> RoleType {
        self.role
    }

    pub fn peer_id(&self) -> PeerId {
        self.peer_id
    }

    #[cfg(any(test, feature = "testing", feature = "fuzzing"))]
    pub fn mock_with_peer_id(peer_id: PeerId) -> std::sync::Arc<Self> {
        std::sync::Arc::new(Self::new(
            NetworkId::Validator,
            RoleType::Validator,
            peer_id,
        ))
    }

    #[cfg(any(test, feature = "testing", feature = "fuzzing"))]
    pub fn mock() -> std::sync::Arc<Self> {
        std::sync::Arc::new(Self::new(
            NetworkId::Validator,
            RoleType::Validator,
            PeerId::random(),
        ))
    }
}

/// A representation of the network being used in communication.
/// There should only be one of each NetworkId used for a single node (except for NetworkId::Public),
/// and handshakes should verify that the NetworkId being used is the same during a handshake,
/// to effectively ensure communication is restricted to a network.  Network should be checked that
/// it is not the `DEFAULT_NETWORK`
#[derive(Clone, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(rename = "NetworkId", rename_all = "snake_case")]
pub enum NetworkId {
    Validator,
    Public,
    Private(String),
}

/// An intra-node identifier for a network of a node unique for a network
/// This extra layer on top of `NetworkId` mainly exists for the application-layer (e.g. mempool,
/// state sync) to differentiate between multiple public
/// networks that a node may belong to
#[derive(Clone, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct NodeNetworkId(NetworkId, usize);

impl NodeNetworkId {
    pub fn new(network_id: NetworkId, num_id: usize) -> Self {
        Self(network_id, num_id)
    }

    pub fn network_id(&self) -> NetworkId {
        self.0.clone()
    }
}

impl fmt::Debug for NodeNetworkId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

impl fmt::Display for NodeNetworkId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}", self.0, self.1)
    }
}

/// Default needed to handle downstream structs that use `Default`
impl Default for NetworkId {
    fn default() -> NetworkId {
        NetworkId::Public
    }
}

impl fmt::Debug for NetworkId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

impl fmt::Display for NetworkId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

const VFN_NETWORK: &str = "vfn";

impl NetworkId {
    /// Convenience function to specify the VFN network
    pub fn vfn_network() -> NetworkId {
        NetworkId::Private(VFN_NETWORK.to_string())
    }

    pub fn is_vfn_network(&self) -> bool {
        matches!(self, NetworkId::Private(network) if network == VFN_NETWORK)
    }

    pub fn as_str(&self) -> &str {
        match self {
            NetworkId::Validator => "Validator",
            NetworkId::Public => "Public",
            // We used to return "Private({info})" here; however, it's important
            // to get the network id str without temp allocs, as this is in the
            // metrics/logging hot path. In theory, someone could set their
            // network id as `Private("Validator")`, which would result in
            // confusing metrics/logging output for them, but would not affect
            // correctness.
            NetworkId::Private(info) => info.as_ref(),
        }
    }

    fn serialize_str<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        self.as_str().serialize(serializer)
    }
}

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

    #[test]
    fn test_serialization() {
        let id = NetworkId::vfn_network();
        let encoded = serde_yaml::to_string(&id).unwrap();
        let decoded: NetworkId = serde_yaml::from_str(encoded.as_str()).unwrap();
        assert_eq!(id, decoded);
        let encoded = serde_yaml::to_vec(&id).unwrap();
        let decoded: NetworkId = serde_yaml::from_slice(encoded.as_slice()).unwrap();
        assert_eq!(id, decoded);

        let id = NetworkId::Validator;
        let encoded = serde_yaml::to_string(&id).unwrap();
        let decoded: NetworkId = serde_yaml::from_str(encoded.as_str()).unwrap();
        assert_eq!(id, decoded);
        let encoded = serde_yaml::to_vec(&id).unwrap();
        let decoded: NetworkId = serde_yaml::from_slice(encoded.as_slice()).unwrap();
        assert_eq!(id, decoded);
    }

    #[test]
    fn test_network_context_serialization() {
        let role = RoleType::Validator;
        let peer_id = PeerId::random();
        let context = NetworkContext::new(NetworkId::vfn_network(), role, peer_id);
        let expected = format!(
            "---\nnetwork_id: {}\nrole: {}\npeer_id: {}",
            VFN_NETWORK, role, peer_id
        );
        assert_eq!(expected, serde_yaml::to_string(&context).unwrap());
    }
}
<commit_msg>[test fix] yaml ends with new lines (now)<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0
use crate::config::RoleType;
use diem_types::PeerId;
use serde::{Deserialize, Serialize, Serializer};
use std::fmt;

/// A grouping of common information between all networking code for logging.
/// This should greatly reduce the groupings between these given everywhere, and will allow
/// for logging accordingly.
#[derive(Clone, Eq, PartialEq, Serialize)]
pub struct NetworkContext {
    #[serde(serialize_with = "NetworkId::serialize_str")]
    network_id: NetworkId,
    role: RoleType,
    peer_id: PeerId,
}

impl fmt::Debug for NetworkContext {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

impl fmt::Display for NetworkContext {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "[{},{},{}]",
            self.network_id.as_str(),
            self.role,
            self.peer_id.short_str(),
        )
    }
}

impl NetworkContext {
    pub fn new(network_id: NetworkId, role: RoleType, peer_id: PeerId) -> NetworkContext {
        NetworkContext {
            network_id,
            role,
            peer_id,
        }
    }

    pub fn network_id(&self) -> &NetworkId {
        &self.network_id
    }

    pub fn role(&self) -> RoleType {
        self.role
    }

    pub fn peer_id(&self) -> PeerId {
        self.peer_id
    }

    #[cfg(any(test, feature = "testing", feature = "fuzzing"))]
    pub fn mock_with_peer_id(peer_id: PeerId) -> std::sync::Arc<Self> {
        std::sync::Arc::new(Self::new(
            NetworkId::Validator,
            RoleType::Validator,
            peer_id,
        ))
    }

    #[cfg(any(test, feature = "testing", feature = "fuzzing"))]
    pub fn mock() -> std::sync::Arc<Self> {
        std::sync::Arc::new(Self::new(
            NetworkId::Validator,
            RoleType::Validator,
            PeerId::random(),
        ))
    }
}

/// A representation of the network being used in communication.
/// There should only be one of each NetworkId used for a single node (except for NetworkId::Public),
/// and handshakes should verify that the NetworkId being used is the same during a handshake,
/// to effectively ensure communication is restricted to a network.  Network should be checked that
/// it is not the `DEFAULT_NETWORK`
#[derive(Clone, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(rename = "NetworkId", rename_all = "snake_case")]
pub enum NetworkId {
    Validator,
    Public,
    Private(String),
}

/// An intra-node identifier for a network of a node unique for a network
/// This extra layer on top of `NetworkId` mainly exists for the application-layer (e.g. mempool,
/// state sync) to differentiate between multiple public
/// networks that a node may belong to
#[derive(Clone, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct NodeNetworkId(NetworkId, usize);

impl NodeNetworkId {
    pub fn new(network_id: NetworkId, num_id: usize) -> Self {
        Self(network_id, num_id)
    }

    pub fn network_id(&self) -> NetworkId {
        self.0.clone()
    }
}

impl fmt::Debug for NodeNetworkId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

impl fmt::Display for NodeNetworkId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}", self.0, self.1)
    }
}

/// Default needed to handle downstream structs that use `Default`
impl Default for NetworkId {
    fn default() -> NetworkId {
        NetworkId::Public
    }
}

impl fmt::Debug for NetworkId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

impl fmt::Display for NetworkId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

const VFN_NETWORK: &str = "vfn";

impl NetworkId {
    /// Convenience function to specify the VFN network
    pub fn vfn_network() -> NetworkId {
        NetworkId::Private(VFN_NETWORK.to_string())
    }

    pub fn is_vfn_network(&self) -> bool {
        matches!(self, NetworkId::Private(network) if network == VFN_NETWORK)
    }

    pub fn as_str(&self) -> &str {
        match self {
            NetworkId::Validator => "Validator",
            NetworkId::Public => "Public",
            // We used to return "Private({info})" here; however, it's important
            // to get the network id str without temp allocs, as this is in the
            // metrics/logging hot path. In theory, someone could set their
            // network id as `Private("Validator")`, which would result in
            // confusing metrics/logging output for them, but would not affect
            // correctness.
            NetworkId::Private(info) => info.as_ref(),
        }
    }

    fn serialize_str<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        self.as_str().serialize(serializer)
    }
}

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

    #[test]
    fn test_serialization() {
        let id = NetworkId::vfn_network();
        let encoded = serde_yaml::to_string(&id).unwrap();
        let decoded: NetworkId = serde_yaml::from_str(encoded.as_str()).unwrap();
        assert_eq!(id, decoded);
        let encoded = serde_yaml::to_vec(&id).unwrap();
        let decoded: NetworkId = serde_yaml::from_slice(encoded.as_slice()).unwrap();
        assert_eq!(id, decoded);

        let id = NetworkId::Validator;
        let encoded = serde_yaml::to_string(&id).unwrap();
        let decoded: NetworkId = serde_yaml::from_str(encoded.as_str()).unwrap();
        assert_eq!(id, decoded);
        let encoded = serde_yaml::to_vec(&id).unwrap();
        let decoded: NetworkId = serde_yaml::from_slice(encoded.as_slice()).unwrap();
        assert_eq!(id, decoded);
    }

    #[test]
    fn test_network_context_serialization() {
        let role = RoleType::Validator;
        let peer_id = PeerId::random();
        let context = NetworkContext::new(NetworkId::vfn_network(), role, peer_id);
        let expected = format!(
            "---\nnetwork_id: {}\nrole: {}\npeer_id: {}\n",
            VFN_NETWORK, role, peer_id
        );
        assert_eq!(expected, serde_yaml::to_string(&context).unwrap());
    }
}
<|endoftext|>


<commit_before><commit_msg>Print crate name in profil<commit_after><|endoftext|>


<commit_before>// Copyright 2015 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A parsing state indicates the current status of the parsing. It is mainly used by compiled PEG combinators.

use stream::*;
use self::ParseResult::*;
use std::collections::hash_set::HashSet;
use std::cmp::Ord;
use std::fmt::{Formatter, Debug, Error};

pub trait IntoState<S, T>
{
  fn into_state(self) -> ParseState<S, T>;
}

impl<S, T, R> IntoState<S, T> for R where
  R: Stream<Output=S>,
  S: Ord + Clone + HasNext
{
  fn into_state(self) -> ParseState<S, T> {
    ParseState::new(self.stream())
  }
}

pub struct ParseExpectation<S>
{
  expected: HashSet<&'static str>,
  farthest_read: S
}

impl<S> ParseExpectation<S>
{
  pub fn new(farthest_read: S, expected: Vec<&'static str>) -> ParseExpectation<S> {
    ParseExpectation {
      expected: expected.into_iter().collect(),
      farthest_read: farthest_read
    }
  }
}

impl<S> ParseExpectation<S> where
 S: Location + CodeSnippet
{
  pub fn expected_items(&self) -> String {
    let mut desc = String::new();
    if self.expected.len() > 0 {
      for expect in &self.expected {
        desc.push('`');
        desc.push_str(expect);
        desc.push_str("` or ");
      }
      let len_without_last_or = desc.len() - 4;
      desc.truncate(len_without_last_or);
    }
    desc
  }
}

/// Prints an error message of the form: ```1:1: unexpected `a+1`, expecting `(` or `["0-9"]`.``` where `1:1` is the line and the column where the error occurred.
impl<S> Debug for ParseExpectation<S> where
 S: Location + CodeSnippet
{
  fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
    let location = self.farthest_read.location();
    let expected = self.expected_items();
    let snippet = self.farthest_read.code_snippet(10usize);
    formatter.write_fmt(
      format_args!("{}: unexpected `{}`, expecting {}.", location, snippet, expected))
  }
}

pub enum ParseResult<S, T>
{
  Success(T),
  Partial(T, ParseExpectation<S>),
  Failure(ParseExpectation<S>)
}

impl<S, T> Debug for ParseResult<S, T> where
 T: Debug,
 S: HasNext + Location + CodeSnippet
{
  fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
    match self {
      &Success(ref data) => {
        formatter.write_fmt(format_args!(
          "Full match, got data `{:?}`.", data))
      }
      &Partial(ref data, ref expectation) => {
        formatter.write_fmt(format_args!(
          "Partial match, got data `{:?}`. It stopped because:\n\t",
          data))?;
        expectation.fmt(formatter)
      }
      &Failure(ref expectation) => {
        formatter.write_str("Error:\n\t")?;
        expectation.fmt(formatter)
      }
    }
  }
}

/// `ParseState<S, T>` reads value from the stream `S` and build an AST of type `T`.
/// Error strategy: Even in case of success, we keep error information in case we fail later. Think about parsing "abaa" with `"ab"* "c"`, it will directly fails on `"c"`, so it is better to report an error such as `expected "ab" but got "aa"` since the input partially matches "ab"`.
pub struct ParseState<S, T>
{
  /// The farthest read into the stream at which we encountered an error.
  pub farthest_read: S,
  /// Expected items at position `farthest_read`. Duplicate entries are possible.
  pub expected: Vec<&'static str>,
  pub failed: bool,
  /// The current stream that can be partially or fully consumed.
  pub current: S,
  /// Contains the AST if the current state is successful and `None` if it is erroneous.
  pub data: Option<T>
}

impl<S, T> ParseState<S, T> where
 S: Ord + Clone + HasNext
{
  #[inline]
  pub fn new(stream: S) -> ParseState<S, T> {
    ParseState {
      farthest_read: stream.clone(),
      expected: vec![],
      failed: false,
      current: stream,
      data: None
    }
  }

  pub fn is_failed(&self) -> bool {
    self.failed
  }

  pub fn is_successful(&self) -> bool {
    !self.is_failed()
  }

  #[inline(always)]
  pub fn error(&mut self, _expect: &'static str) {
    self.failed = true;
    if self.current > self.farthest_read {
      self.farthest_read = self.current.clone();
      self.expected = vec![expect];
    }
    else if self.current == self.farthest_read {
      self.expected.push(expect);
    }
  }

  // TODO: find a way to specialize success when U = T.
  #[inline]
  pub fn success(self, data: U) -> ParseState<S, U> {
    ParseState {
      farthest_read: self.farthest_read,
      expected: self.expected,
      failed: false,
      current: self.current,
      data: Some(data)
    }
  }

  #[inline]
  pub fn failure(self) -> ParseState<S, U> {
    ParseState {
      farthest_read: self.farthest_read,
      expected: self.expected,
      failed: true,
      current: self.current,
      data: None
    }
  }

  pub fn mark(&self) -> S {
    assert!(!self.failed, "Marking a failed ParseState is not allowed.");
    self.current.clone()
  }

  pub fn restore_from_failure(self, mark: S) -> ParseState<S, ()> {
    assert!(self.failed, "Restoring a successful ParseState is not allowed.");
    self.restore(mark)
  }

  pub fn restore(self, mark: S) -> ParseState<S, ()> {
    assert!(self.data.is_none(), "Restoring a ParseState with data is not allowed.");
    ParseState {
      farthest_read: self.farthest_read,
      expected: self.expected,
      failed: false,
      current: mark,
      data: None
    }
  }

  /// Transforms `self` into a more usable `ParseResult` value. It is useful when the state is terminal or if the state will not be further transformed.
  pub fn into_result(self) -> ParseResult<S, T> {
    let expectation = ParseExpectation::new(self.farthest_read, self.expected);
    match self.data {
      Some(data) => {
        if self.current.has_next() {
          Partial(data, expectation)
        }
        else {
          Success(data)
        }
      }
      None => {
        assert!(self.failed, "Failure status must be true when extracting a failed result.");
        Failure(expectation)
      }
    }
  }

  pub fn extract_data(self) -> (ParseState<S, ()>, T) {
    assert!(self.is_successful() && self.data.is_some(),
      "Data extraction is only possible if the state is successful and contains data.");
    let data = self.data.unwrap();
    let state = ParseState {
      farthest_read: self.farthest_read,
      expected: self.expected,
      failed: self.failed,
      current: self.current,
      data: None
    };
    (state, data)
  }

  pub fn unwrap_data(self) -> T {
    self.data.expect("data in ParseState (unwrap_data)")
  }
}

impl<S> ParseState<S, ()>
{
  // This is specific to recognizer where unit data does not need to be extracted. We also want to preserve the "no-data" precondition of `restore`.
  pub fn discard_data(&mut self) {
    self.data = None;
  }
}

impl<S, T, I> Iterator for ParseState<S, T> where
 S: Iterator<Item=I>
{
  type Item = I;
  fn next(&mut self) -> Option<Self::Item> {
    self.current.next()
  }
}

impl<S, T, P> ConsumePrefix
 for ParseState<S, T> where
  S: ConsumePrefix

{
  fn consume_prefix(&mut self, prefix: P) -> bool {
    self.current.consume_prefix(prefix)
  }
}
<commit_msg>fix compilation error...<commit_after>// Copyright 2015 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A parsing state indicates the current status of the parsing. It is mainly used by compiled PEG combinators.

use stream::*;
use self::ParseResult::*;
use std::collections::hash_set::HashSet;
use std::cmp::Ord;
use std::fmt::{Formatter, Debug, Error};

pub trait IntoState<S, T>
{
  fn into_state(self) -> ParseState<S, T>;
}

impl<S, T, R> IntoState<S, T> for R where
  R: Stream<Output=S>,
  S: Ord + Clone + HasNext
{
  fn into_state(self) -> ParseState<S, T> {
    ParseState::new(self.stream())
  }
}

pub struct ParseExpectation<S>
{
  expected: HashSet<&'static str>,
  farthest_read: S
}

impl<S> ParseExpectation<S>
{
  pub fn new(farthest_read: S, expected: Vec<&'static str>) -> ParseExpectation<S> {
    ParseExpectation {
      expected: expected.into_iter().collect(),
      farthest_read: farthest_read
    }
  }
}

impl<S> ParseExpectation<S> where
 S: Location + CodeSnippet
{
  pub fn expected_items(&self) -> String {
    let mut desc = String::new();
    if self.expected.len() > 0 {
      for expect in &self.expected {
        desc.push('`');
        desc.push_str(expect);
        desc.push_str("` or ");
      }
      let len_without_last_or = desc.len() - 4;
      desc.truncate(len_without_last_or);
    }
    desc
  }
}

/// Prints an error message of the form: ```1:1: unexpected `a+1`, expecting `(` or `["0-9"]`.``` where `1:1` is the line and the column where the error occurred.
impl<S> Debug for ParseExpectation<S> where
 S: Location + CodeSnippet
{
  fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
    let location = self.farthest_read.location();
    let expected = self.expected_items();
    let snippet = self.farthest_read.code_snippet(10usize);
    formatter.write_fmt(
      format_args!("{}: unexpected `{}`, expecting {}.", location, snippet, expected))
  }
}

pub enum ParseResult<S, T>
{
  Success(T),
  Partial(T, ParseExpectation<S>),
  Failure(ParseExpectation<S>)
}

impl<S, T> Debug for ParseResult<S, T> where
 T: Debug,
 S: HasNext + Location + CodeSnippet
{
  fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
    match self {
      &Success(ref data) => {
        formatter.write_fmt(format_args!(
          "Full match, got data `{:?}`.", data))
      }
      &Partial(ref data, ref expectation) => {
        formatter.write_fmt(format_args!(
          "Partial match, got data `{:?}`. It stopped because:\n\t",
          data))?;
        expectation.fmt(formatter)
      }
      &Failure(ref expectation) => {
        formatter.write_str("Error:\n\t")?;
        expectation.fmt(formatter)
      }
    }
  }
}

/// `ParseState<S, T>` reads value from the stream `S` and build an AST of type `T`.
/// Error strategy: Even in case of success, we keep error information in case we fail later. Think about parsing "abaa" with `"ab"* "c"`, it will directly fails on `"c"`, so it is better to report an error such as `expected "ab" but got "aa"` since the input partially matches "ab"`.
pub struct ParseState<S, T>
{
  /// The farthest read into the stream at which we encountered an error.
  pub farthest_read: S,
  /// Expected items at position `farthest_read`. Duplicate entries are possible.
  pub expected: Vec<&'static str>,
  pub failed: bool,
  /// The current stream that can be partially or fully consumed.
  pub current: S,
  /// Contains the AST if the current state is successful and `None` if it is erroneous.
  pub data: Option<T>
}

impl<S, T> ParseState<S, T> where
 S: Ord + Clone + HasNext
{
  #[inline]
  pub fn new(stream: S) -> ParseState<S, T> {
    ParseState {
      farthest_read: stream.clone(),
      expected: vec![],
      failed: false,
      current: stream,
      data: None
    }
  }

  pub fn is_failed(&self) -> bool {
    self.failed
  }

  pub fn is_successful(&self) -> bool {
    !self.is_failed()
  }

  #[inline(always)]
  pub fn error(&mut self, expect: &'static str) {
    self.failed = true;
    if self.current > self.farthest_read {
      self.farthest_read = self.current.clone();
      self.expected = vec![expect];
    }
    else if self.current == self.farthest_read {
      self.expected.push(expect);
    }
  }

  // TODO: find a way to specialize success when U = T.
  #[inline]
  pub fn success(self, data: U) -> ParseState<S, U> {
    ParseState {
      farthest_read: self.farthest_read,
      expected: self.expected,
      failed: false,
      current: self.current,
      data: Some(data)
    }
  }

  #[inline]
  pub fn failure(self) -> ParseState<S, U> {
    ParseState {
      farthest_read: self.farthest_read,
      expected: self.expected,
      failed: true,
      current: self.current,
      data: None
    }
  }

  pub fn mark(&self) -> S {
    assert!(!self.failed, "Marking a failed ParseState is not allowed.");
    self.current.clone()
  }

  pub fn restore_from_failure(self, mark: S) -> ParseState<S, ()> {
    assert!(self.failed, "Restoring a successful ParseState is not allowed.");
    self.restore(mark)
  }

  pub fn restore(self, mark: S) -> ParseState<S, ()> {
    assert!(self.data.is_none(), "Restoring a ParseState with data is not allowed.");
    ParseState {
      farthest_read: self.farthest_read,
      expected: self.expected,
      failed: false,
      current: mark,
      data: None
    }
  }

  /// Transforms `self` into a more usable `ParseResult` value. It is useful when the state is terminal or if the state will not be further transformed.
  pub fn into_result(self) -> ParseResult<S, T> {
    let expectation = ParseExpectation::new(self.farthest_read, self.expected);
    match self.data {
      Some(data) => {
        if self.current.has_next() {
          Partial(data, expectation)
        }
        else {
          Success(data)
        }
      }
      None => {
        assert!(self.failed, "Failure status must be true when extracting a failed result.");
        Failure(expectation)
      }
    }
  }

  pub fn extract_data(self) -> (ParseState<S, ()>, T) {
    assert!(self.is_successful() && self.data.is_some(),
      "Data extraction is only possible if the state is successful and contains data.");
    let data = self.data.unwrap();
    let state = ParseState {
      farthest_read: self.farthest_read,
      expected: self.expected,
      failed: self.failed,
      current: self.current,
      data: None
    };
    (state, data)
  }

  pub fn unwrap_data(self) -> T {
    self.data.expect("data in ParseState (unwrap_data)")
  }
}

impl<S> ParseState<S, ()>
{
  // This is specific to recognizer where unit data does not need to be extracted. We also want to preserve the "no-data" precondition of `restore`.
  pub fn discard_data(&mut self) {
    self.data = None;
  }
}

impl<S, T, I> Iterator for ParseState<S, T> where
 S: Iterator<Item=I>
{
  type Item = I;
  fn next(&mut self) -> Option<Self::Item> {
    self.current.next()
  }
}

impl<S, T, P> ConsumePrefix
 for ParseState<S, T> where
  S: ConsumePrefix

{
  fn consume_prefix(&mut self, prefix: P) -> bool {
    self.current.consume_prefix(prefix)
  }
}
<|endoftext|>


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

use std::collections::HashSet;

use super::fun::{FnAnalysis, FnAnalysisBody, FnKind};
use crate::conversion::{convert_error::ErrorContext, ConvertError};
use crate::{
    conversion::api::{Api, ApiDetail},
    known_types,
};

/// Remove any APIs which depend on other items which have been ignored.
pub(crate) fn filter_apis_by_ignored_dependents(
    mut apis: Vec<Api<FnAnalysis>>,
) -> Vec<Api<FnAnalysis>> {
    let (ignored_items, valid_items): (Vec<&Api<_>>, Vec<&Api<_>>) = apis.iter().partition(|api| {
        matches!(
            api.detail,
            ApiDetail::IgnoredItem {
                ctx: ErrorContext::Item(..),
                ..
            }
        )
    });
    let mut ignored_items: HashSet<_> = ignored_items
        .into_iter()
        .map(|api| api.typename())
        .collect();
    let valid_types: HashSet<_> = valid_items.into_iter().map(|api| api.typename()).collect();
    let mut iterate_again = true;
    while iterate_again {
        iterate_again = false;
        apis = apis
            .into_iter()
            .map(|api| {
                if api.deps.iter().any(|dep| ignored_items.contains(dep)) {
                    iterate_again = true;
                    ignored_items.insert(api.typename());
                    create_ignore_item(api, ConvertError::IgnoredDependent)
                } else if !api
                    .deps
                    .iter()
                    .all(|dep| valid_types.contains(dep) || known_types().is_known_type(dep))
                {
                    iterate_again = true;
                    ignored_items.insert(api.typename());
                    create_ignore_item(api, ConvertError::UnknownDependentType)
                } else {
                    api
                }
            })
            .collect();
    }
    apis
}

fn create_ignore_item(api: Api<FnAnalysis>, err: ConvertError) -> Api<FnAnalysis> {
    let id = api.typename().get_final_ident();
    Api {
        name: api.typename(),
        original_name: api.original_name,
        deps: HashSet::new(),
        detail: ApiDetail::IgnoredItem {
            err,
            ctx: match api.detail {
                ApiDetail::Function {
                    analysis:
                        FnAnalysisBody {
                            kind: FnKind::Method(self_ty, _),
                            ..
                        },
                    ..
                } => ErrorContext::Method {
                    self_ty: self_ty.get_final_ident(),
                    method: id,
                },
                _ => ErrorContext::Item(id),
            },
        },
    }
}
<commit_msg>Update comment.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;

use super::fun::{FnAnalysis, FnAnalysisBody, FnKind};
use crate::conversion::{convert_error::ErrorContext, ConvertError};
use crate::{
    conversion::api::{Api, ApiDetail},
    known_types,
};

/// Remove any APIs which depend on other items which have been ignored.
/// We also eliminate any APIs that depend on some type that we just don't
/// know about at all. In either case, we don't simply remove the type, but instead
/// replace it with an error marker.
pub(crate) fn filter_apis_by_ignored_dependents(
    mut apis: Vec<Api<FnAnalysis>>,
) -> Vec<Api<FnAnalysis>> {
    let (ignored_items, valid_items): (Vec<&Api<_>>, Vec<&Api<_>>) = apis.iter().partition(|api| {
        matches!(
            api.detail,
            ApiDetail::IgnoredItem {
                ctx: ErrorContext::Item(..),
                ..
            }
        )
    });
    let mut ignored_items: HashSet<_> = ignored_items
        .into_iter()
        .map(|api| api.typename())
        .collect();
    let valid_types: HashSet<_> = valid_items.into_iter().map(|api| api.typename()).collect();
    let mut iterate_again = true;
    while iterate_again {
        iterate_again = false;
        apis = apis
            .into_iter()
            .map(|api| {
                if api.deps.iter().any(|dep| ignored_items.contains(dep)) {
                    iterate_again = true;
                    ignored_items.insert(api.typename());
                    create_ignore_item(api, ConvertError::IgnoredDependent)
                } else if !api
                    .deps
                    .iter()
                    .all(|dep| valid_types.contains(dep) || known_types().is_known_type(dep))
                {
                    iterate_again = true;
                    ignored_items.insert(api.typename());
                    create_ignore_item(api, ConvertError::UnknownDependentType)
                } else {
                    api
                }
            })
            .collect();
    }
    apis
}

fn create_ignore_item(api: Api<FnAnalysis>, err: ConvertError) -> Api<FnAnalysis> {
    let id = api.typename().get_final_ident();
    Api {
        name: api.typename(),
        original_name: api.original_name,
        deps: HashSet::new(),
        detail: ApiDetail::IgnoredItem {
            err,
            ctx: match api.detail {
                ApiDetail::Function {
                    analysis:
                        FnAnalysisBody {
                            kind: FnKind::Method(self_ty, _),
                            ..
                        },
                    ..
                } => ErrorContext::Method {
                    self_ty: self_ty.get_final_ident(),
                    method: id,
                },
                _ => ErrorContext::Item(id),
            },
        },
    }
}
<|endoftext|>


<commit_before>//! The `adder` crate provides functions that add numbers to other numbers.
//!
//! # Examples
//!
//! ```
//! assert_eq!(4, adder::add_two(2));
//! ```

#![feature(test)]
extern crate test;

#[test]
#[should_panic]
fn it_works0() {
    assert!(false);
    assert_eq!("Hello", "world");
}

#[test]
////#[should_panic(expected = "assertion failed")] // this works the same currently
#[should_panic(expected = "failed: false")]
fn it_works2() {
    assert!(false);
    assert_eq!("Hello", "world");
}

/*pub fn add_two(a: i32) -> i32 {
  a + 2
  }*/

#[test]
fn it_works3() {
    assert_eq!(4, add_two(2));
}

#[cfg(test)]
mod tests {
    use super::add_two;

    #[test]
    fn it_works() {
        assert_eq!(4, add_two(2));
    }
}

/// This function adds two to its argument.
///
/// # Examples
///
/// ```
/// use adder::add_two;
///
/// assert_eq!(4, add_two(2));
/// ```
pub fn add_two(a: i32) -> i32 {
    a + 2
}

#[cfg(test)]
mod tests2 {
    use super::*; //glob feature
    use test::Bencher;
    use test;

    #[test]
    fn it_works() {
        assert_eq!(4, add_two(2));
    }

    #[bench]
    fn bench_add_two(b: &mut Bencher) {
        b.iter(|| add_two(2));
        b.iter(|| {
            let mut n = 1000_u32;
            test::black_box(&mut n); // pretend to modify `n`
            (0..n).fold(0, |a, b| a ^ b)
        })
    }
}

<commit_msg>globbing<commit_after>//! The `adder` crate provides functions that add numbers to other numbers.
//!
//! # Examples
//!
//! ```
//! assert_eq!(4, adder::add_two(2));
//! ```
//! (note: this only works in library crates, not binary crates)

#![feature(test)]
extern crate test;

//https://doc.rust-lang.org/nightly/book/testing.html#the-tests-module

#[test]
#[should_panic]
fn it_works0() {
    assert!(false);
    assert_eq!("Hello", "world");
}

#[test]
////#[should_panic(expected = "assertion failed")] // this works the same currently
#[should_panic(expected = "failed: false")]
fn it_works2() {
    assert!(false);
    assert_eq!("Hello", "world");
}

/*pub fn add_two(a: i32) -> i32 {
  a + 2
  }*/

#[test]
fn it_works3() {
    assert_eq!(4, add_two(2));
}

#[cfg(test)]
mod tests {
    //use super::add_two;
    use super::*;

    #[test]
    fn it_works() {
        assert_eq!(4, add_two(2));
    }
}

/// This function adds two to its argument.
///
/// # Examples
///
/// ```
/// use adder::add_two;
///
/// assert_eq!(4, add_two(2));
/// ```
pub fn add_two(a: i32) -> i32 {
    a + 2
}

#[cfg(test)]
mod tests2 {
    use super::*; //glob feature
    use test::Bencher;
    use test;

    #[test]
    fn it_works() {
        assert_eq!(4, add_two(2));
    }

    #[bench]
    fn bench_add_two(b: &mut Bencher) {
        b.iter(|| add_two(2));
        b.iter(|| {
            let mut n = 1000_u32;
            test::black_box(&mut n); // pretend to modify `n`
            (0..n).fold(0, |a, b| a ^ b)
        })
    }
}

<|endoftext|>


<commit_before>use hyper;

use Document;
use Error;
use ErrorResponse;
use IntoDocumentPath;
use Revision;
use client::ClientState;
use action::{self, Action, Request, Response};

/// Action to get document meta-information and application-defined content.
///
/// # Return
///
/// This action returns an `Option` type. The return value is `None` if the
/// action specifies a revision and the document hasn't been modified since
/// that revision. Otherwise, the return value is `Some` and contains the
/// document meta-information and application-defined content.
///
/// # Errors
///
/// The following are some of the errors that may occur as a result of executing
/// this action:
///
///
/// * `Error::NotFound`: The document does not exist.
/// * `Error::Unauthorized`: The client is unauthorized.
///
pub struct GetDocument<'a, P>
    where P: IntoDocumentPath
{
    client_state: &'a ClientState,
    path: P,
    if_none_match: Option<&'a Revision>,
    rev: Option<&'a Revision>,
}

impl<'a, P: IntoDocumentPath> GetDocument<'a, P> {
    #[doc(hidden)]
    pub fn new(client_state: &'a ClientState, path: P) -> Self {
        GetDocument {
            client_state: client_state,
            path: path,
            if_none_match: None,
            rev: None,
        }
    }

    /// Sets the If-None-Match header.
    pub fn if_none_match(mut self, rev: &'a Revision) -> Self {
        self.if_none_match = Some(rev);
        self
    }

    /// Sets the “rev” query parameter to get the document at the given
    /// revision.
    pub fn rev(mut self, rev: &'a Revision) -> Self {
        self.rev = Some(rev);
        self
    }

    impl_action_public_methods!(Option<Document>);
}

impl<'a, P: IntoDocumentPath> Action for GetDocument<'a, P> {
    type Output = Option<Document>;

    fn make_request(self) -> Result<Request, Error> {
        let doc_path = try!(self.path.into_document_path());
        let uri = {
            let mut uri = doc_path.into_uri(self.client_state.uri.clone());
            let mut query = Vec::<(String, String)>::new();
            if let Some(rev) = self.rev {
                query.push(("rev".to_string(), rev.to_string()));
            }
            if !query.is_empty() {
                uri.set_query_from_pairs(query);
            }
            uri
        };
        let request = Request::new(hyper::Get, uri)
                          .set_accept_application_json()
                          .set_if_none_match_revision(self.if_none_match);
        Ok(request)
    }

    fn take_response<R: Response>(mut response: R) -> Result<Self::Output, Error> {
        match response.status() {
            hyper::status::StatusCode::Ok => {
                try!(response.content_type_must_be_application_json());
                let doc = try!(response.decode_json::<Document>());
                Ok(Some(doc))
            }
            hyper::status::StatusCode::NotModified => Ok(None),
            hyper::status::StatusCode::BadRequest => Err(make_couchdb_error!(BadRequest, response)),
            hyper::status::StatusCode::Unauthorized => {
                Err(make_couchdb_error!(Unauthorized, response))
            }
            hyper::status::StatusCode::NotFound => Err(make_couchdb_error!(NotFound, response)),
            _ => Err(Error::UnexpectedHttpStatus { got: response.status() }),
        }
    }
}

#[cfg(test)]
mod tests {

    use hyper;
    use serde_json;

    use DocumentPath;
    use Revision;
    use client::ClientState;
    use action::{Action, JsonResponse, NoContentResponse};
    use super::GetDocument;

    #[test]
    fn make_request_default() {
        let client_state = ClientState::new("http://example.com:1234/").unwrap();
        let action = GetDocument::new(&client_state, "/foo/bar");
        let request = action.make_request().unwrap();
        expect_request_method!(request, hyper::Get);
        expect_request_uri!(request, "http://example.com:1234/foo/bar");
        expect_request_accept_application_json!(request);
    }

    #[test]
    fn make_request_if_none_match() {
        let client_state = ClientState::new("http://example.com:1234/").unwrap();
        let rev = Revision::parse("42-1234567890abcdef1234567890abcdef").unwrap();
        let action = GetDocument::new(&client_state, "/foo/bar").if_none_match(&rev);
        let request = action.make_request().unwrap();
        expect_request_method!(request, hyper::Get);
        expect_request_uri!(request, "http://example.com:1234/foo/bar");
        expect_request_accept_application_json!(request);
        expect_request_if_none_match_revision!(request, "42-1234567890abcdef1234567890abcdef");
    }

    #[test]
    fn make_request_rev() {
        let client_state = ClientState::new("http://example.com:1234/").unwrap();
        let rev = "42-1234567890abcdef1234567890abcdef".parse().unwrap();
        let action = GetDocument::new(&client_state, "/foo/bar").rev(&rev);
        let request = action.make_request().unwrap();
        expect_request_method!(request, hyper::Get);
        expect_request_uri!(request,
                            "http://example.com:\
                             1234/foo/bar?rev=42-1234567890abcdef1234567890abcdef");
        expect_request_accept_application_json!(request);
    }

    #[test]
    fn take_response_ok() {
        let source = serde_json::builder::ObjectBuilder::new()
                         .insert("_id", "foo")
                         .insert("_rev", "42-1234567890abcdef1234567890abcdef")
                         .insert("bar", 17)
                         .unwrap();
        let response = JsonResponse::new(hyper::Ok, &source);
        let got = GetDocument::<DocumentPath>::take_response(response).unwrap();
        let got = got.unwrap();
        assert_eq!(got.id, "foo".into());
        assert_eq!(got.rev,
                   "42-1234567890abcdef1234567890abcdef".parse().unwrap());
        let expected = serde_json::builder::ObjectBuilder::new()
                           .insert("bar", 17)
                           .unwrap();
        let got = got.into_content::<serde_json::Value>().unwrap();
        assert_eq!(expected, got);
    }

    #[test]
    fn take_response_ok_deleted() {
        let source = serde_json::builder::ObjectBuilder::new()
                         .insert("_id", "foo")
                         .insert("_rev", "42-1234567890abcdef1234567890abcdef")
                         .insert("_deleted", true)
                         .unwrap();
        let response = JsonResponse::new(hyper::Ok, &source);
        let got = GetDocument::<DocumentPath>::take_response(response).unwrap();
        let got = got.unwrap();
        assert_eq!(got.id, "foo".into());
        assert_eq!(got.rev,
                   "42-1234567890abcdef1234567890abcdef".parse().unwrap());
        assert!(got.deleted);
        let expected = serde_json::builder::ObjectBuilder::new().unwrap();
        let got = got.into_content::<serde_json::Value>().unwrap();
        assert_eq!(expected, got);
    }

    #[test]
    fn take_response_not_modified() {
        let response = NoContentResponse::new(hyper::status::StatusCode::NotModified);
        let got = GetDocument::<DocumentPath>::take_response(response).unwrap();
        assert!(got.is_none());
    }

    #[test]
    fn take_response_bad_request() {
        let source = serde_json::builder::ObjectBuilder::new()
                         .insert("error", "bad_request")
                         .insert("reason", "Invalid rev format")
                         .unwrap();
        let response = JsonResponse::new(hyper::BadRequest, &source);
        let got = GetDocument::<DocumentPath>::take_response(response);
        expect_couchdb_error!(got, BadRequest);
    }

    #[test]
    fn take_response_not_found() {
        let source = serde_json::builder::ObjectBuilder::new()
                         .insert("error", "not_found")
                         .insert("reason", "missing")
                         .unwrap();
        let response = JsonResponse::new(hyper::NotFound, &source);
        let got = GetDocument::<DocumentPath>::take_response(response);
        expect_couchdb_error!(got, NotFound);
    }

    #[test]
    fn take_response_unauthorized() {
        let source = serde_json::builder::ObjectBuilder::new()
                         .insert("error", "unauthorized")
                         .insert("reason", "blah blah blah")
                         .unwrap();
        let response = JsonResponse::new(hyper::status::StatusCode::Unauthorized, &source);
        let got = GetDocument::<DocumentPath>::take_response(response);
        expect_couchdb_error!(got, Unauthorized);
    }
}
<commit_msg>Custom query iterator for GetDocument<commit_after>use hyper;

use Document;
use Error;
use ErrorResponse;
use IntoDocumentPath;
use Revision;
use client::ClientState;
use action::{self, Action, Request, Response};

enum QueryIteration {
    Rev,
    Done,
}

// The query parameters reside in a separate structure to facilitate iteration,
// which is useful when constructing the URI query string.
struct QueryParams<'a> {
    iteration: QueryIteration,
    rev: Option<&'a Revision>,
}

impl<'a> QueryParams<'a> {
    fn new() -> Self {
        QueryParams {
            iteration: QueryIteration::Rev,
            rev: None,
        }
    }
}

impl<'a> Iterator for QueryParams<'a> {
    type Item = (String, String);

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.iteration {
                QueryIteration::Rev => {
                    self.iteration = QueryIteration::Done;
                    if let Some(ref rev) = self.rev {
                        return Some(("rev".to_string(), rev.to_string()));
                    }
                }
                QueryIteration::Done => {
                    return None;
                }
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.rev.is_none() {
            (0, None)
        } else {
            (1, None)
        }
    }
}

/// Action to get document meta-information and application-defined content.
///
/// # Return
///
/// This action returns an `Option` type. The return value is `None` if the
/// action specifies a revision and the document hasn't been modified since
/// that revision. Otherwise, the return value is `Some` and contains the
/// document meta-information and application-defined content.
///
/// # Errors
///
/// The following are some of the errors that may occur as a result of executing
/// this action:
///
///
/// * `Error::NotFound`: The document does not exist.
/// * `Error::Unauthorized`: The client is unauthorized.
///
pub struct GetDocument<'a, P>
    where P: IntoDocumentPath
{
    client_state: &'a ClientState,
    path: P,
    if_none_match: Option<&'a Revision>,
    query: QueryParams<'a>,
}

impl<'a, P: IntoDocumentPath> GetDocument<'a, P> {
    #[doc(hidden)]
    pub fn new(client_state: &'a ClientState, path: P) -> Self {
        GetDocument {
            client_state: client_state,
            path: path,
            if_none_match: None,
            query: QueryParams::new(),
        }
    }

    /// Sets the If-None-Match header.
    pub fn if_none_match(mut self, rev: &'a Revision) -> Self {
        self.if_none_match = Some(rev);
        self
    }

    /// Sets the “rev” query parameter to get the document at the given
    /// revision.
    pub fn rev(mut self, rev: &'a Revision) -> Self {
        self.query.rev = Some(rev);
        self
    }

    impl_action_public_methods!(Option<Document>);
}

impl<'a, P: IntoDocumentPath> Action for GetDocument<'a, P> {
    type Output = Option<Document>;

    fn make_request(self) -> Result<Request, Error> {
        let doc_path = try!(self.path.into_document_path());
        let uri = {
            let mut uri = doc_path.into_uri(self.client_state.uri.clone());
            if 1 <= self.query.size_hint().0 {
                uri.set_query_from_pairs(self.query);
            }
            uri
        };
        let request = Request::new(hyper::Get, uri)
                          .set_accept_application_json()
                          .set_if_none_match_revision(self.if_none_match);
        Ok(request)
    }

    fn take_response<R: Response>(mut response: R) -> Result<Self::Output, Error> {
        match response.status() {
            hyper::status::StatusCode::Ok => {
                try!(response.content_type_must_be_application_json());
                let doc = try!(response.decode_json::<Document>());
                Ok(Some(doc))
            }
            hyper::status::StatusCode::NotModified => Ok(None),
            hyper::status::StatusCode::BadRequest => Err(make_couchdb_error!(BadRequest, response)),
            hyper::status::StatusCode::Unauthorized => {
                Err(make_couchdb_error!(Unauthorized, response))
            }
            hyper::status::StatusCode::NotFound => Err(make_couchdb_error!(NotFound, response)),
            _ => Err(Error::UnexpectedHttpStatus { got: response.status() }),
        }
    }
}

#[cfg(test)]
mod tests {

    use hyper;
    use serde_json;

    use DocumentPath;
    use Revision;
    use client::ClientState;
    use action::{Action, JsonResponse, NoContentResponse};
    use super::{GetDocument, QueryIteration, QueryParams};

    #[test]
    fn query_iteration() {
        let rev = Revision::parse("42-1234567890abcdef1234567890abcdef").unwrap();
        let query = QueryParams {
            iteration: QueryIteration::Rev,
            rev: Some(&rev),
        };
        let expected = vec![("rev".to_string(), rev.to_string())];
        let got = query.collect::<Vec<_>>();
        assert_eq!(expected, got);
    }

    #[test]
    fn make_request_default() {
        let client_state = ClientState::new("http://example.com:1234/").unwrap();
        let action = GetDocument::new(&client_state, "/foo/bar");
        let request = action.make_request().unwrap();
        expect_request_method!(request, hyper::Get);
        expect_request_uri!(request, "http://example.com:1234/foo/bar");
        expect_request_accept_application_json!(request);
    }

    #[test]
    fn make_request_if_none_match() {
        let client_state = ClientState::new("http://example.com:1234/").unwrap();
        let rev = Revision::parse("42-1234567890abcdef1234567890abcdef").unwrap();
        let action = GetDocument::new(&client_state, "/foo/bar").if_none_match(&rev);
        let request = action.make_request().unwrap();
        expect_request_method!(request, hyper::Get);
        expect_request_uri!(request, "http://example.com:1234/foo/bar");
        expect_request_accept_application_json!(request);
        expect_request_if_none_match_revision!(request, "42-1234567890abcdef1234567890abcdef");
    }

    #[test]
    fn make_request_rev() {
        let client_state = ClientState::new("http://example.com:1234/").unwrap();
        let rev = "42-1234567890abcdef1234567890abcdef".parse().unwrap();
        let action = GetDocument::new(&client_state, "/foo/bar").rev(&rev);
        let request = action.make_request().unwrap();
        expect_request_method!(request, hyper::Get);
        expect_request_uri!(request,
                            "http://example.com:\
                             1234/foo/bar?rev=42-1234567890abcdef1234567890abcdef");
        expect_request_accept_application_json!(request);
    }

    #[test]
    fn take_response_ok() {
        let source = serde_json::builder::ObjectBuilder::new()
                         .insert("_id", "foo")
                         .insert("_rev", "42-1234567890abcdef1234567890abcdef")
                         .insert("bar", 17)
                         .unwrap();
        let response = JsonResponse::new(hyper::Ok, &source);
        let got = GetDocument::<DocumentPath>::take_response(response).unwrap();
        let got = got.unwrap();
        assert_eq!(got.id, "foo".into());
        assert_eq!(got.rev,
                   "42-1234567890abcdef1234567890abcdef".parse().unwrap());
        let expected = serde_json::builder::ObjectBuilder::new()
                           .insert("bar", 17)
                           .unwrap();
        let got = got.into_content::<serde_json::Value>().unwrap();
        assert_eq!(expected, got);
    }

    #[test]
    fn take_response_ok_deleted() {
        let source = serde_json::builder::ObjectBuilder::new()
                         .insert("_id", "foo")
                         .insert("_rev", "42-1234567890abcdef1234567890abcdef")
                         .insert("_deleted", true)
                         .unwrap();
        let response = JsonResponse::new(hyper::Ok, &source);
        let got = GetDocument::<DocumentPath>::take_response(response).unwrap();
        let got = got.unwrap();
        assert_eq!(got.id, "foo".into());
        assert_eq!(got.rev,
                   "42-1234567890abcdef1234567890abcdef".parse().unwrap());
        assert!(got.deleted);
        let expected = serde_json::builder::ObjectBuilder::new().unwrap();
        let got = got.into_content::<serde_json::Value>().unwrap();
        assert_eq!(expected, got);
    }

    #[test]
    fn take_response_not_modified() {
        let response = NoContentResponse::new(hyper::status::StatusCode::NotModified);
        let got = GetDocument::<DocumentPath>::take_response(response).unwrap();
        assert!(got.is_none());
    }

    #[test]
    fn take_response_bad_request() {
        let source = serde_json::builder::ObjectBuilder::new()
                         .insert("error", "bad_request")
                         .insert("reason", "Invalid rev format")
                         .unwrap();
        let response = JsonResponse::new(hyper::BadRequest, &source);
        let got = GetDocument::<DocumentPath>::take_response(response);
        expect_couchdb_error!(got, BadRequest);
    }

    #[test]
    fn take_response_not_found() {
        let source = serde_json::builder::ObjectBuilder::new()
                         .insert("error", "not_found")
                         .insert("reason", "missing")
                         .unwrap();
        let response = JsonResponse::new(hyper::NotFound, &source);
        let got = GetDocument::<DocumentPath>::take_response(response);
        expect_couchdb_error!(got, NotFound);
    }

    #[test]
    fn take_response_unauthorized() {
        let source = serde_json::builder::ObjectBuilder::new()
                         .insert("error", "unauthorized")
                         .insert("reason", "blah blah blah")
                         .unwrap();
        let response = JsonResponse::new(hyper::status::StatusCode::Unauthorized, &source);
        let got = GetDocument::<DocumentPath>::take_response(response);
        expect_couchdb_error!(got, Unauthorized);
    }
}
<|endoftext|>