<commit_before>//! Handle network connections for a varlink service

//#![feature(getpid)]
//use std::process;
// FIXME
use libc::getpid;
use std::env;
use std::fs;
use std::io;
use std::io::{Error, ErrorKind, Read, Write};
use std::net::{Shutdown, TcpListener, TcpStream};
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::os::unix::net::{UnixListener, UnixStream};
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
// FIXME: abstract unix domains sockets still not in std
// FIXME: https://github.com/rust-lang/rust/issues/14194
use unix_socket::UnixListener as AbstractUnixListener;

enum VarlinkListener {
    TCP(TcpListener),
    UNIX(UnixListener),
}

enum VarlinkStream {
    TCP(TcpStream),
    UNIX(UnixStream),
}

impl<'a> VarlinkStream {
    pub fn split(&mut self) -> io::Result<(Box<Read + Send + Sync>, Box<Write + Send + Sync>)> {
        match *self {
            VarlinkStream::TCP(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
            VarlinkStream::UNIX(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
        }
    }
    pub fn shutdown(&mut self) -> io::Result<()> {
        match *self {
            VarlinkStream::TCP(ref mut s) => s.shutdown(Shutdown::Both),
            VarlinkStream::UNIX(ref mut s) => s.shutdown(Shutdown::Both),
        }
    }
}

fn activation_listener() -> io::Result<Option<UnixListener>> {
    match env::var("LISTEN_FDS") {
        Ok(ref nfds) if nfds.parse::<u32>() == Ok(1) => {}
        _ => return Ok(None),
    }

    unsafe {
        match env::var("LISTEN_PID") {
            //FIXME: replace Ok(getpid()) with Ok(process::id())
            Ok(ref pid) if pid.parse::<i32>() == Ok(getpid()) => {}
            _ => return Ok(None),
        }

        //syscall.CloseOnExec(3)
        let listener = UnixListener::from_raw_fd(3);
        env::remove_var("LISTEN_PID");
        env::remove_var("LISTEN_FDS");

        Ok(Some(listener))
    }
}

//FIXME: add Drop with shutdown() and unix file removal
impl VarlinkListener {
    pub fn new(address: &str) -> io::Result<Self> {
        if let Some(l) = activation_listener()? {
            return Ok(VarlinkListener::UNIX(l));
        }

        if address.starts_with("tcp:") {
            Ok(VarlinkListener::TCP(TcpListener::bind(&address[4..])?))
        } else if address.starts_with("unix:") {
            let mut addr = String::from(address[5..].split(";").next().unwrap());
            if addr.starts_with("@") {
                addr = addr.replacen("@", "\0", 1);
                let l = AbstractUnixListener::bind(addr)?;
                unsafe {
                    return Ok(VarlinkListener::UNIX(UnixListener::from_raw_fd(
                        l.into_raw_fd(),
                    )));
                }
            }
            // ignore error on non-existant file
            let _ = fs::remove_file(&*addr);
            Ok(VarlinkListener::UNIX(UnixListener::bind(addr)?))
        } else {
            Err(Error::new(ErrorKind::Other, "unknown varlink address"))
        }
    }

    pub fn accept(&self) -> io::Result<VarlinkStream> {
        match self {
            &VarlinkListener::TCP(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::TCP(s))
            }
            &VarlinkListener::UNIX(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::UNIX(s))
            }
        }
    }
    pub fn set_nonblocking(&self, b: bool) -> io::Result<()> {
        match self {
            &VarlinkListener::TCP(ref l) => l.set_nonblocking(b),
            &VarlinkListener::UNIX(ref l) => l.set_nonblocking(b),
        }
    }
}

enum Message {
    NewJob(Job),
    Terminate,
}

struct ThreadPool {
    workers: Vec<Worker>,
    sender: mpsc::Sender<Message>,
}

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Job = Box<FnBox + Send + 'static>;

impl ThreadPool {
    /// Create a new ThreadPool.
    ///
    /// The size is the number of threads in the pool.
    ///
    /// # Panics
    ///
    /// The `new` function will panic if the size is zero.
    pub fn new(size: usize) -> ThreadPool {
        assert!(size > 0);

        let (sender, receiver) = mpsc::channel();

        let receiver = Arc::new(Mutex::new(receiver));

        let mut workers = Vec::with_capacity(size);

        for _ in 0..size {
            workers.push(Worker::new(Arc::clone(&receiver)));
        }

        ThreadPool { workers, sender }
    }

    pub fn execute<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static,
    {
        let job = Box::new(f);

        self.sender.send(Message::NewJob(job)).unwrap();
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        for _ in &mut self.workers {
            self.sender.send(Message::Terminate).unwrap();
        }

        for worker in &mut self.workers {
            if let Some(thread) = worker.thread.take() {
                thread.join().unwrap();
            }
        }
    }
}

struct Worker {
    thread: Option<thread::JoinHandle<()>>,
}

impl Worker {
    fn new(receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
        let thread = thread::spawn(move || loop {
            let message = receiver.lock().unwrap().recv().unwrap();

            match message {
                Message::NewJob(job) => {
                    job.call_box();
                }
                Message::Terminate => {
                    break;
                }
            }
        });

        Worker {
            thread: Some(thread),
        }
    }
}

pub enum ServerError {
    IoError(Error),
    AcceptTimeout,
}

impl From<Error> for ServerError {
    fn from(e: Error) -> Self {
        ServerError::IoError(e)
    }
}

pub fn do_listen(
    service: ::VarlinkService,
    addr: &str,
    workers: usize,
    accept_timeout: u64,
) -> Result<(), ServerError> {
    let service = Arc::new(service);
    let listener = Arc::new(VarlinkListener::new(addr)?);
    listener.set_nonblocking(false)?;
    let pool = ThreadPool::new(workers);

    loop {
        let mut stream: VarlinkStream;
        if accept_timeout != 0 {
            let listener = listener.clone();
            let (sender, receiver) = mpsc::channel();

            let _t = thread::spawn(move || {
                match sender.send(listener.accept()) {
                    Ok(()) => {} // everything good
                    Err(_) => {} // we have been released, don't panic
                }
            });

            stream = match receiver.recv_timeout(Duration::from_secs(accept_timeout)) {
                Ok(s) => s?,
                Err(_) => return Err(ServerError::AcceptTimeout),
            };
        } else {
            stream = listener.accept()?;
        }

        let service = service.clone();

        pool.execute(move || {
            let (mut r, mut w) = stream.split().expect("Could not split stream");

            if let Err(_e) = service.handle(&mut r, &mut w) {
                //println!("Handle Error: {}", e);
                let _ = stream.shutdown();
            }
        });
    }
}
<commit_msg>add socket activation for TCP<commit_after>//! Handle network connections for a varlink service

//#![feature(getpid)]
//use std::process;
// FIXME
use libc::getpid;
use std::env;
use std::fs;
use std::io;
use std::io::{Error, ErrorKind, Read, Write};
use std::net::{Shutdown, TcpListener, TcpStream};
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::os::unix::net::{UnixListener, UnixStream};
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
// FIXME: abstract unix domains sockets still not in std
// FIXME: https://github.com/rust-lang/rust/issues/14194
use unix_socket::UnixListener as AbstractUnixListener;

enum VarlinkListener {
    TCP(TcpListener),
    UNIX(UnixListener),
}

enum VarlinkStream {
    TCP(TcpStream),
    UNIX(UnixStream),
}

impl<'a> VarlinkStream {
    pub fn split(&mut self) -> io::Result<(Box<Read + Send + Sync>, Box<Write + Send + Sync>)> {
        match *self {
            VarlinkStream::TCP(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
            VarlinkStream::UNIX(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
        }
    }
    pub fn shutdown(&mut self) -> io::Result<()> {
        match *self {
            VarlinkStream::TCP(ref mut s) => s.shutdown(Shutdown::Both),
            VarlinkStream::UNIX(ref mut s) => s.shutdown(Shutdown::Both),
        }
    }
}

fn activation_listener() -> io::Result<Option<i32>> {
    match env::var("LISTEN_FDS") {
        Ok(ref nfds) if nfds.parse::<u32>() == Ok(1) => {}
        _ => return Ok(None),
    }

    unsafe {
        match env::var("LISTEN_PID") {
            //FIXME: replace Ok(getpid()) with Ok(process::id())
            Ok(ref pid) if pid.parse::<i32>() == Ok(getpid()) => {}
            _ => return Ok(None),
        }

        //syscall.CloseOnExec(3)
        //let listener = UnixListener::from_raw_fd(3);
        env::remove_var("LISTEN_PID");
        env::remove_var("LISTEN_FDS");

        Ok(Some(3))
    }
}

//FIXME: add Drop with shutdown() and unix file removal
impl VarlinkListener {
    pub fn new(address: &str) -> io::Result<Self> {
        if let Some(l) = activation_listener()? {
            if address.starts_with("tcp:") {
                unsafe {
                    return Ok(VarlinkListener::TCP(TcpListener::from_raw_fd(l)));
                }
            } else if address.starts_with("unix:") {
                unsafe {
                    return Ok(VarlinkListener::UNIX(UnixListener::from_raw_fd(l)));
                }
            } else {
                return Err(Error::new(ErrorKind::Other, "unknown varlink address"));
            }
        }

        if address.starts_with("tcp:") {
            Ok(VarlinkListener::TCP(TcpListener::bind(&address[4..])?))
        } else if address.starts_with("unix:") {
            let mut addr = String::from(address[5..].split(";").next().unwrap());
            if addr.starts_with("@") {
                addr = addr.replacen("@", "\0", 1);
                let l = AbstractUnixListener::bind(addr)?;
                unsafe {
                    return Ok(VarlinkListener::UNIX(UnixListener::from_raw_fd(
                        l.into_raw_fd(),
                    )));
                }
            }
            // ignore error on non-existant file
            let _ = fs::remove_file(&*addr);
            Ok(VarlinkListener::UNIX(UnixListener::bind(addr)?))
        } else {
            Err(Error::new(ErrorKind::Other, "unknown varlink address"))
        }
    }

    pub fn accept(&self) -> io::Result<VarlinkStream> {
        match self {
            &VarlinkListener::TCP(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::TCP(s))
            }
            &VarlinkListener::UNIX(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::UNIX(s))
            }
        }
    }
    pub fn set_nonblocking(&self, b: bool) -> io::Result<()> {
        match self {
            &VarlinkListener::TCP(ref l) => l.set_nonblocking(b),
            &VarlinkListener::UNIX(ref l) => l.set_nonblocking(b),
        }
    }
}

enum Message {
    NewJob(Job),
    Terminate,
}

struct ThreadPool {
    workers: Vec<Worker>,
    sender: mpsc::Sender<Message>,
}

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Job = Box<FnBox + Send + 'static>;

impl ThreadPool {
    /// Create a new ThreadPool.
    ///
    /// The size is the number of threads in the pool.
    ///
    /// # Panics
    ///
    /// The `new` function will panic if the size is zero.
    pub fn new(size: usize) -> ThreadPool {
        assert!(size > 0);

        let (sender, receiver) = mpsc::channel();

        let receiver = Arc::new(Mutex::new(receiver));

        let mut workers = Vec::with_capacity(size);

        for _ in 0..size {
            workers.push(Worker::new(Arc::clone(&receiver)));
        }

        ThreadPool { workers, sender }
    }

    pub fn execute<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static,
    {
        let job = Box::new(f);

        self.sender.send(Message::NewJob(job)).unwrap();
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        for _ in &mut self.workers {
            self.sender.send(Message::Terminate).unwrap();
        }

        for worker in &mut self.workers {
            if let Some(thread) = worker.thread.take() {
                thread.join().unwrap();
            }
        }
    }
}

struct Worker {
    thread: Option<thread::JoinHandle<()>>,
}

impl Worker {
    fn new(receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
        let thread = thread::spawn(move || loop {
            let message = receiver.lock().unwrap().recv().unwrap();

            match message {
                Message::NewJob(job) => {
                    job.call_box();
                }
                Message::Terminate => {
                    break;
                }
            }
        });

        Worker {
            thread: Some(thread),
        }
    }
}

pub enum ServerError {
    IoError(Error),
    AcceptTimeout,
}

impl From<Error> for ServerError {
    fn from(e: Error) -> Self {
        ServerError::IoError(e)
    }
}

pub fn do_listen(
    service: ::VarlinkService,
    addr: &str,
    workers: usize,
    accept_timeout: u64,
) -> Result<(), ServerError> {
    let service = Arc::new(service);
    let listener = Arc::new(VarlinkListener::new(addr)?);
    listener.set_nonblocking(false)?;
    let pool = ThreadPool::new(workers);

    loop {
        let mut stream: VarlinkStream;
        if accept_timeout != 0 {
            let listener = listener.clone();
            let (sender, receiver) = mpsc::channel();

            let _t = thread::spawn(move || {
                match sender.send(listener.accept()) {
                    Ok(()) => {} // everything good
                    Err(_) => {} // we have been released, don't panic
                }
            });

            stream = match receiver.recv_timeout(Duration::from_secs(accept_timeout)) {
                Ok(s) => s?,
                Err(_) => return Err(ServerError::AcceptTimeout),
            };
        } else {
            stream = listener.accept()?;
        }

        let service = service.clone();

        pool.execute(move || {
            let (mut r, mut w) = stream.split().expect("Could not split stream");

            if let Err(_e) = service.handle(&mut r, &mut w) {
                //println!("Handle Error: {}", e);
                let _ = stream.shutdown();
            }
        });
    }
}
<|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::mem;
use std::ptr;
use std::sync::Arc;
use smallvec::SmallVec;

use buffer::Buffer;
use descriptor_set::layout_def::Layout;
use descriptor_set::layout_def::SetLayout;
use descriptor_set::layout_def::SetLayoutWrite;
use descriptor_set::layout_def::SetLayoutInit;
use descriptor_set::layout_def::DescriptorWrite;
use descriptor_set::layout_def::DescriptorBind;
use descriptor_set::pool::DescriptorPool;
use device::Device;
use image::ImageView;
use sampler::Sampler;

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

/// An actual descriptor set with the resources that are binded to it.
pub struct DescriptorSet<S> {
    set: vk::DescriptorSet,
    pool: Arc<DescriptorPool>,
    layout: Arc<DescriptorSetLayout<S>>,

    // Here we store the resources used by the descriptor set.
    // TODO: for the moment even when a resource is overwritten it stays in these lists
    resources_samplers: Vec<Arc<Sampler>>,
    resources_image_views: Vec<Arc<ImageView>>,
    resources_buffers: Vec<Arc<Buffer>>,
}

impl<S> DescriptorSet<S> where S: SetLayout {
    ///
    /// # Panic
    ///
    /// - Panicks if the pool and the layout were not created from the same `Device`.
    ///
    pub fn new<I>(pool: &Arc<DescriptorPool>, layout: &Arc<DescriptorSetLayout<S>>, init: I)
                  -> Result<Arc<DescriptorSet<S>>, OomError>
        where S: SetLayoutInit<I>
    {
        unsafe {
            let mut set = try!(DescriptorSet::uninitialized(pool, layout));
            Arc::get_mut(&mut set).unwrap().unchecked_write(layout.layout().decode(init));
            Ok(set)
        }
    }

    ///
    /// # Panic
    ///
    /// - Panicks if the pool and the layout were not created from the same `Device`.
    ///
    // FIXME: this has to check whether there's still enough room in the pool
    pub unsafe fn uninitialized(pool: &Arc<DescriptorPool>, layout: &Arc<DescriptorSetLayout<S>>)
                                -> Result<Arc<DescriptorSet<S>>, OomError>
    {
        assert_eq!(&**pool.device() as *const Device, &*layout.device as *const Device);

        let vk = pool.device().pointers();

        let set = {
            let pool_obj = pool.internal_object_guard();

            let infos = vk::DescriptorSetAllocateInfo {
                sType: vk::STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
                pNext: ptr::null(),
                descriptorPool: *pool_obj,
                descriptorSetCount: 1,
                pSetLayouts: &layout.layout,
            };

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

        Ok(Arc::new(DescriptorSet {
            set: set,
            pool: pool.clone(),
            layout: layout.clone(),

            resources_samplers: Vec::new(),
            resources_image_views: Vec::new(),
            resources_buffers: Vec::new(),
        }))
    }

    /// Modifies a descriptor set.
    ///
    /// The parameter depends on your implementation of `SetLayout`.
    ///
    /// This function trusts the implementation of `SetLayout` when it comes to making sure
    /// that the correct resource type is written to the correct descriptor.
    pub fn write<W>(&mut self, write: W)
        where S: SetLayoutWrite<W>
    {
        let write = self.layout.layout().decode(write);
        unsafe { self.unchecked_write(write); }
    }

    /// Modifies a descriptor set without checking that the writes are correct.
    pub unsafe fn unchecked_write(&mut self, write: Vec<DescriptorWrite>) {
        let vk = self.pool.device().pointers();

        // TODO: how do we remove the existing resources that are overwritten?

        // This function uses multiple closures which all borrow `self`. In order to satisfy the
        // borrow checker, we extract references to the members here.
        let ref mut self_resources_buffers = self.resources_buffers;
        let ref mut self_resources_samplers = self.resources_samplers;
        let ref mut self_resources_image_views = self.resources_image_views;
        let self_set = self.set;

        let buffer_descriptors = write.iter().filter_map(|write| {
            match write.content {
                DescriptorBind::UniformBuffer { ref buffer, offset, size } |
                DescriptorBind::DynamicUniformBuffer { ref buffer, offset, size } => {
                    assert!(buffer.inner_buffer().usage_uniform_buffer());
                    self_resources_buffers.push(buffer.clone());
                    Some(vk::DescriptorBufferInfo {
                        buffer: buffer.inner_buffer().internal_object(),
                        offset: offset as u64,
                        range: size as u64,
                    })
                },
                DescriptorBind::StorageBuffer { ref buffer, offset, size } |
                DescriptorBind::DynamicStorageBuffer { ref buffer, offset, size } => {
                    assert!(buffer.inner_buffer().usage_storage_buffer());
                    self_resources_buffers.push(buffer.clone());
                    Some(vk::DescriptorBufferInfo {
                        buffer: buffer.inner_buffer().internal_object(),
                        offset: offset as u64,
                        range: size as u64,
                    })
                },
                _ => None
            }
        }).collect::<SmallVec<[_; 64]>>();

        let image_descriptors = write.iter().filter_map(|write| {
            match write.content {
                DescriptorBind::Sampler(ref sampler) => {
                    self_resources_samplers.push(sampler.clone());
                    Some(vk::DescriptorImageInfo {
                        sampler: sampler.internal_object(),
                        imageView: 0,
                        imageLayout: 0,
                    })
                },
                DescriptorBind::CombinedImageSampler(ref sampler, ref image, layout) => {
                    assert!(image.inner_view().usage_sampled());
                    self_resources_samplers.push(sampler.clone());
                    self_resources_image_views.push(image.clone());
                    Some(vk::DescriptorImageInfo {
                        sampler: sampler.internal_object(),
                        imageView: image.inner_view().internal_object(),
                        imageLayout: layout as u32,
                    })
                },
                DescriptorBind::StorageImage(ref image, layout) => {
                    assert!(image.inner_view().usage_storage());
                    self_resources_image_views.push(image.clone());
                    Some(vk::DescriptorImageInfo {
                        sampler: 0,
                        imageView: image.inner_view().internal_object(),
                        imageLayout: layout as u32,
                    })
                },
                DescriptorBind::SampledImage(ref image, layout) => {
                    assert!(image.inner_view().usage_sampled());
                    self_resources_image_views.push(image.clone());
                    Some(vk::DescriptorImageInfo {
                        sampler: 0,
                        imageView: image.inner_view().internal_object(),
                        imageLayout: layout as u32,
                    })
                },
                DescriptorBind::InputAttachment(ref image, layout) => {
                    assert!(image.inner_view().usage_input_attachment());
                    self_resources_image_views.push(image.clone());
                    Some(vk::DescriptorImageInfo {
                        sampler: 0,
                        imageView: image.inner_view().internal_object(),
                        imageLayout: layout as u32,
                    })
                },
                _ => None
            }
        }).collect::<SmallVec<[_; 64]>>();

        let mut next_buffer_desc = 0;
        let mut next_image_desc = 0;

        let vk_writes = write.iter().map(|write| {
            let (buffer_info, image_info) = match write.content {
                DescriptorBind::Sampler(_) | DescriptorBind::CombinedImageSampler(_, _ ,_) |
                DescriptorBind::SampledImage(_, _) | DescriptorBind::StorageImage(_, _) |
                DescriptorBind::InputAttachment(_, _) => {
                    let img = image_descriptors.as_ptr().offset(next_image_desc as isize);
                    next_image_desc += 1;
                    (ptr::null(), img)
                },
                //DescriptorBind::UniformTexelBuffer(_) | DescriptorBind::StorageTexelBuffer(_) =>
                DescriptorBind::UniformBuffer { .. } | DescriptorBind::StorageBuffer { .. } |
                DescriptorBind::DynamicUniformBuffer { .. } |
                DescriptorBind::DynamicStorageBuffer { .. } => {
                    let buf = buffer_descriptors.as_ptr().offset(next_buffer_desc as isize);
                    next_buffer_desc += 1;
                    (buf, ptr::null())
                },
            };

            // FIXME: the descriptor set must be synchronized
            vk::WriteDescriptorSet {
                sType: vk::STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
                pNext: ptr::null(),
                dstSet: self_set,
                dstBinding: write.binding,
                dstArrayElement: write.array_element,
                descriptorCount: 1,
                descriptorType: write.content.ty() as u32,
                pImageInfo: image_info,
                pBufferInfo: buffer_info,
                pTexelBufferView: ptr::null(),      // TODO:
            }
        }).collect::<SmallVec<[_; 64]>>();

        debug_assert_eq!(next_buffer_desc, buffer_descriptors.len());
        debug_assert_eq!(next_image_desc, image_descriptors.len());

        if !vk_writes.is_empty() {
            vk.UpdateDescriptorSets(self.pool.device().internal_object(),
                                    vk_writes.len() as u32, vk_writes.as_ptr(), 0, ptr::null());
        }
    }
}

unsafe impl<S> VulkanObject for DescriptorSet<S> {
    type Object = vk::DescriptorSet;

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

impl<S> Drop for DescriptorSet<S> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.pool.device().pointers();
            vk.FreeDescriptorSets(self.pool.device().internal_object(),
                                  *self.pool.internal_object_guard(), 1, &self.set);
        }
    }
}

/// Implemented on all `DescriptorSet` objects. Hides the template parameters.
pub unsafe trait AbstractDescriptorSet: ::VulkanObjectU64 {}
unsafe impl<S> AbstractDescriptorSet for DescriptorSet<S> {}

/// Describes the layout of all descriptors within a descriptor set.
pub struct DescriptorSetLayout<S> {
    layout: vk::DescriptorSetLayout,
    device: Arc<Device>,
    description: S,
}

impl<S> DescriptorSetLayout<S> where S: SetLayout {
    pub fn new(device: &Arc<Device>, description: S)
               -> Result<Arc<DescriptorSetLayout<S>>, OomError>
    {
        let vk = device.pointers();

        let bindings = description.descriptors().into_iter().map(|desc| {
            vk::DescriptorSetLayoutBinding {
                binding: desc.binding,
                descriptorType: desc.ty.vk_enum(),
                descriptorCount: desc.array_count,
                stageFlags: desc.stages.into(),
                pImmutableSamplers: ptr::null(),        // FIXME: not yet implemented
            }
        }).collect::<SmallVec<[_; 64]>>();

        let layout = unsafe {
            let infos = vk::DescriptorSetLayoutCreateInfo {
                sType: vk::STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                bindingCount: bindings.len() as u32,
                pBindings: bindings.as_ptr(),
            };

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

        Ok(Arc::new(DescriptorSetLayout {
            layout: layout,
            device: device.clone(),
            description: description,
        }))
    }

    #[inline]
    pub fn layout(&self) -> &S {
        &self.description
    }
}

unsafe impl<S> VulkanObject for DescriptorSetLayout<S> {
    type Object = vk::DescriptorSetLayout;

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

impl<S> Drop for DescriptorSetLayout<S> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyDescriptorSetLayout(self.device.internal_object(), self.layout, ptr::null());
        }
    }
}

/// Implemented on all `DescriptorSetLayout` objects. Hides the template parameters.
pub unsafe trait AbstractDescriptorSetLayout: ::VulkanObjectU64 {}
unsafe impl<S> AbstractDescriptorSetLayout for DescriptorSetLayout<S> {}

/// A collection of `DescriptorSetLayout` structs.
// TODO: push constants.
pub struct PipelineLayout<P> {
    device: Arc<Device>,
    layout: vk::PipelineLayout,
    description: P,
    layouts: Vec<Arc<AbstractDescriptorSetLayout>>,     // TODO: is it necessary to keep the layouts alive? check the specs
}

impl<P> PipelineLayout<P> where P: Layout {
    /// Creates a new `PipelineLayout`.
    pub fn new(device: &Arc<Device>, description: P, layouts: P::DescriptorSetLayouts)
               -> Result<Arc<PipelineLayout<P>>, OomError>
    {
        let vk = device.pointers();

        let layouts = description.decode_descriptor_set_layouts(layouts);
        let layouts_ids = layouts.iter().map(|l| {
            // FIXME: check that they belong to the same device
            ::VulkanObjectU64::internal_object(&**l)
        }).collect::<SmallVec<[_; 32]>>();

        let layout = unsafe {
            let infos = vk::PipelineLayoutCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                setLayoutCount: layouts_ids.len() as u32,
                pSetLayouts: layouts_ids.as_ptr(),
                pushConstantRangeCount: 0,      // TODO: unimplemented
                pPushConstantRanges: ptr::null(),    // TODO: unimplemented
            };

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

        Ok(Arc::new(PipelineLayout {
            device: device.clone(),
            layout: layout,
            description: description,
            layouts: layouts,
        }))
    }

    #[inline]
    pub fn layout(&self) -> &P {
        &self.description
    }
}

unsafe impl<P> VulkanObject for PipelineLayout<P> {
    type Object = vk::PipelineLayout;

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

impl<P> Drop for PipelineLayout<P> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyPipelineLayout(self.device.internal_object(), self.layout, ptr::null());
        }
    }
}
<commit_msg>Check for identity swizzle in image views bound as input atch or storage<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::mem;
use std::ptr;
use std::sync::Arc;
use smallvec::SmallVec;

use buffer::Buffer;
use descriptor_set::layout_def::Layout;
use descriptor_set::layout_def::SetLayout;
use descriptor_set::layout_def::SetLayoutWrite;
use descriptor_set::layout_def::SetLayoutInit;
use descriptor_set::layout_def::DescriptorWrite;
use descriptor_set::layout_def::DescriptorBind;
use descriptor_set::pool::DescriptorPool;
use device::Device;
use image::ImageView;
use sampler::Sampler;

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

/// An actual descriptor set with the resources that are binded to it.
pub struct DescriptorSet<S> {
    set: vk::DescriptorSet,
    pool: Arc<DescriptorPool>,
    layout: Arc<DescriptorSetLayout<S>>,

    // Here we store the resources used by the descriptor set.
    // TODO: for the moment even when a resource is overwritten it stays in these lists
    resources_samplers: Vec<Arc<Sampler>>,
    resources_image_views: Vec<Arc<ImageView>>,
    resources_buffers: Vec<Arc<Buffer>>,
}

impl<S> DescriptorSet<S> where S: SetLayout {
    ///
    /// # Panic
    ///
    /// - Panicks if the pool and the layout were not created from the same `Device`.
    ///
    pub fn new<I>(pool: &Arc<DescriptorPool>, layout: &Arc<DescriptorSetLayout<S>>, init: I)
                  -> Result<Arc<DescriptorSet<S>>, OomError>
        where S: SetLayoutInit<I>
    {
        unsafe {
            let mut set = try!(DescriptorSet::uninitialized(pool, layout));
            Arc::get_mut(&mut set).unwrap().unchecked_write(layout.layout().decode(init));
            Ok(set)
        }
    }

    ///
    /// # Panic
    ///
    /// - Panicks if the pool and the layout were not created from the same `Device`.
    ///
    // FIXME: this has to check whether there's still enough room in the pool
    pub unsafe fn uninitialized(pool: &Arc<DescriptorPool>, layout: &Arc<DescriptorSetLayout<S>>)
                                -> Result<Arc<DescriptorSet<S>>, OomError>
    {
        assert_eq!(&**pool.device() as *const Device, &*layout.device as *const Device);

        let vk = pool.device().pointers();

        let set = {
            let pool_obj = pool.internal_object_guard();

            let infos = vk::DescriptorSetAllocateInfo {
                sType: vk::STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
                pNext: ptr::null(),
                descriptorPool: *pool_obj,
                descriptorSetCount: 1,
                pSetLayouts: &layout.layout,
            };

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

        Ok(Arc::new(DescriptorSet {
            set: set,
            pool: pool.clone(),
            layout: layout.clone(),

            resources_samplers: Vec::new(),
            resources_image_views: Vec::new(),
            resources_buffers: Vec::new(),
        }))
    }

    /// Modifies a descriptor set.
    ///
    /// The parameter depends on your implementation of `SetLayout`.
    ///
    /// This function trusts the implementation of `SetLayout` when it comes to making sure
    /// that the correct resource type is written to the correct descriptor.
    pub fn write<W>(&mut self, write: W)
        where S: SetLayoutWrite<W>
    {
        let write = self.layout.layout().decode(write);
        unsafe { self.unchecked_write(write); }
    }

    /// Modifies a descriptor set without checking that the writes are correct.
    pub unsafe fn unchecked_write(&mut self, write: Vec<DescriptorWrite>) {
        let vk = self.pool.device().pointers();

        // TODO: how do we remove the existing resources that are overwritten?

        // This function uses multiple closures which all borrow `self`. In order to satisfy the
        // borrow checker, we extract references to the members here.
        let ref mut self_resources_buffers = self.resources_buffers;
        let ref mut self_resources_samplers = self.resources_samplers;
        let ref mut self_resources_image_views = self.resources_image_views;
        let self_set = self.set;

        let buffer_descriptors = write.iter().filter_map(|write| {
            match write.content {
                DescriptorBind::UniformBuffer { ref buffer, offset, size } |
                DescriptorBind::DynamicUniformBuffer { ref buffer, offset, size } => {
                    assert!(buffer.inner_buffer().usage_uniform_buffer());
                    self_resources_buffers.push(buffer.clone());
                    Some(vk::DescriptorBufferInfo {
                        buffer: buffer.inner_buffer().internal_object(),
                        offset: offset as u64,
                        range: size as u64,
                    })
                },
                DescriptorBind::StorageBuffer { ref buffer, offset, size } |
                DescriptorBind::DynamicStorageBuffer { ref buffer, offset, size } => {
                    assert!(buffer.inner_buffer().usage_storage_buffer());
                    self_resources_buffers.push(buffer.clone());
                    Some(vk::DescriptorBufferInfo {
                        buffer: buffer.inner_buffer().internal_object(),
                        offset: offset as u64,
                        range: size as u64,
                    })
                },
                _ => None
            }
        }).collect::<SmallVec<[_; 64]>>();

        let image_descriptors = write.iter().filter_map(|write| {
            match write.content {
                DescriptorBind::Sampler(ref sampler) => {
                    self_resources_samplers.push(sampler.clone());
                    Some(vk::DescriptorImageInfo {
                        sampler: sampler.internal_object(),
                        imageView: 0,
                        imageLayout: 0,
                    })
                },
                DescriptorBind::CombinedImageSampler(ref sampler, ref image, layout) => {
                    assert!(image.inner_view().usage_sampled());
                    self_resources_samplers.push(sampler.clone());
                    self_resources_image_views.push(image.clone());
                    Some(vk::DescriptorImageInfo {
                        sampler: sampler.internal_object(),
                        imageView: image.inner_view().internal_object(),
                        imageLayout: layout as u32,
                    })
                },
                DescriptorBind::StorageImage(ref image, layout) => {
                    assert!(image.inner_view().usage_storage());
                    assert!(image.identity_swizzle());
                    self_resources_image_views.push(image.clone());
                    Some(vk::DescriptorImageInfo {
                        sampler: 0,
                        imageView: image.inner_view().internal_object(),
                        imageLayout: layout as u32,
                    })
                },
                DescriptorBind::SampledImage(ref image, layout) => {
                    assert!(image.inner_view().usage_sampled());
                    self_resources_image_views.push(image.clone());
                    Some(vk::DescriptorImageInfo {
                        sampler: 0,
                        imageView: image.inner_view().internal_object(),
                        imageLayout: layout as u32,
                    })
                },
                DescriptorBind::InputAttachment(ref image, layout) => {
                    assert!(image.inner_view().usage_input_attachment());
                    assert!(image.identity_swizzle());
                    self_resources_image_views.push(image.clone());
                    Some(vk::DescriptorImageInfo {
                        sampler: 0,
                        imageView: image.inner_view().internal_object(),
                        imageLayout: layout as u32,
                    })
                },
                _ => None
            }
        }).collect::<SmallVec<[_; 64]>>();

        let mut next_buffer_desc = 0;
        let mut next_image_desc = 0;

        let vk_writes = write.iter().map(|write| {
            let (buffer_info, image_info) = match write.content {
                DescriptorBind::Sampler(_) | DescriptorBind::CombinedImageSampler(_, _ ,_) |
                DescriptorBind::SampledImage(_, _) | DescriptorBind::StorageImage(_, _) |
                DescriptorBind::InputAttachment(_, _) => {
                    let img = image_descriptors.as_ptr().offset(next_image_desc as isize);
                    next_image_desc += 1;
                    (ptr::null(), img)
                },
                //DescriptorBind::UniformTexelBuffer(_) | DescriptorBind::StorageTexelBuffer(_) =>
                DescriptorBind::UniformBuffer { .. } | DescriptorBind::StorageBuffer { .. } |
                DescriptorBind::DynamicUniformBuffer { .. } |
                DescriptorBind::DynamicStorageBuffer { .. } => {
                    let buf = buffer_descriptors.as_ptr().offset(next_buffer_desc as isize);
                    next_buffer_desc += 1;
                    (buf, ptr::null())
                },
            };

            // FIXME: the descriptor set must be synchronized
            vk::WriteDescriptorSet {
                sType: vk::STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
                pNext: ptr::null(),
                dstSet: self_set,
                dstBinding: write.binding,
                dstArrayElement: write.array_element,
                descriptorCount: 1,
                descriptorType: write.content.ty() as u32,
                pImageInfo: image_info,
                pBufferInfo: buffer_info,
                pTexelBufferView: ptr::null(),      // TODO:
            }
        }).collect::<SmallVec<[_; 64]>>();

        debug_assert_eq!(next_buffer_desc, buffer_descriptors.len());
        debug_assert_eq!(next_image_desc, image_descriptors.len());

        if !vk_writes.is_empty() {
            vk.UpdateDescriptorSets(self.pool.device().internal_object(),
                                    vk_writes.len() as u32, vk_writes.as_ptr(), 0, ptr::null());
        }
    }
}

unsafe impl<S> VulkanObject for DescriptorSet<S> {
    type Object = vk::DescriptorSet;

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

impl<S> Drop for DescriptorSet<S> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.pool.device().pointers();
            vk.FreeDescriptorSets(self.pool.device().internal_object(),
                                  *self.pool.internal_object_guard(), 1, &self.set);
        }
    }
}

/// Implemented on all `DescriptorSet` objects. Hides the template parameters.
pub unsafe trait AbstractDescriptorSet: ::VulkanObjectU64 {}
unsafe impl<S> AbstractDescriptorSet for DescriptorSet<S> {}

/// Describes the layout of all descriptors within a descriptor set.
pub struct DescriptorSetLayout<S> {
    layout: vk::DescriptorSetLayout,
    device: Arc<Device>,
    description: S,
}

impl<S> DescriptorSetLayout<S> where S: SetLayout {
    pub fn new(device: &Arc<Device>, description: S)
               -> Result<Arc<DescriptorSetLayout<S>>, OomError>
    {
        let vk = device.pointers();

        let bindings = description.descriptors().into_iter().map(|desc| {
            vk::DescriptorSetLayoutBinding {
                binding: desc.binding,
                descriptorType: desc.ty.vk_enum(),
                descriptorCount: desc.array_count,
                stageFlags: desc.stages.into(),
                pImmutableSamplers: ptr::null(),        // FIXME: not yet implemented
            }
        }).collect::<SmallVec<[_; 64]>>();

        let layout = unsafe {
            let infos = vk::DescriptorSetLayoutCreateInfo {
                sType: vk::STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                bindingCount: bindings.len() as u32,
                pBindings: bindings.as_ptr(),
            };

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

        Ok(Arc::new(DescriptorSetLayout {
            layout: layout,
            device: device.clone(),
            description: description,
        }))
    }

    #[inline]
    pub fn layout(&self) -> &S {
        &self.description
    }
}

unsafe impl<S> VulkanObject for DescriptorSetLayout<S> {
    type Object = vk::DescriptorSetLayout;

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

impl<S> Drop for DescriptorSetLayout<S> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyDescriptorSetLayout(self.device.internal_object(), self.layout, ptr::null());
        }
    }
}

/// Implemented on all `DescriptorSetLayout` objects. Hides the template parameters.
pub unsafe trait AbstractDescriptorSetLayout: ::VulkanObjectU64 {}
unsafe impl<S> AbstractDescriptorSetLayout for DescriptorSetLayout<S> {}

/// A collection of `DescriptorSetLayout` structs.
// TODO: push constants.
pub struct PipelineLayout<P> {
    device: Arc<Device>,
    layout: vk::PipelineLayout,
    description: P,
    layouts: Vec<Arc<AbstractDescriptorSetLayout>>,     // TODO: is it necessary to keep the layouts alive? check the specs
}

impl<P> PipelineLayout<P> where P: Layout {
    /// Creates a new `PipelineLayout`.
    pub fn new(device: &Arc<Device>, description: P, layouts: P::DescriptorSetLayouts)
               -> Result<Arc<PipelineLayout<P>>, OomError>
    {
        let vk = device.pointers();

        let layouts = description.decode_descriptor_set_layouts(layouts);
        let layouts_ids = layouts.iter().map(|l| {
            // FIXME: check that they belong to the same device
            ::VulkanObjectU64::internal_object(&**l)
        }).collect::<SmallVec<[_; 32]>>();

        let layout = unsafe {
            let infos = vk::PipelineLayoutCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                setLayoutCount: layouts_ids.len() as u32,
                pSetLayouts: layouts_ids.as_ptr(),
                pushConstantRangeCount: 0,      // TODO: unimplemented
                pPushConstantRanges: ptr::null(),    // TODO: unimplemented
            };

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

        Ok(Arc::new(PipelineLayout {
            device: device.clone(),
            layout: layout,
            description: description,
            layouts: layouts,
        }))
    }

    #[inline]
    pub fn layout(&self) -> &P {
        &self.description
    }
}

unsafe impl<P> VulkanObject for PipelineLayout<P> {
    type Object = vk::PipelineLayout;

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

impl<P> Drop for PipelineLayout<P> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyPipelineLayout(self.device.internal_object(), self.layout, ptr::null());
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Stupid stupid<commit_after><|endoftext|>


<commit_before>use std::io::{File};
use std::slice;
use std::fmt;

#[deriving(Show)]
enum OPCode {
    NOP,
    PUSH,
    POP,
    LOAD,
    STORE,
    JMP,
    JZ,
    JNZ,
    ADD,
    SUB,
    MUL,
    DIV,
    PRINT,
    STOP
}

impl fmt::Show for VM {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "Stack Pointer: {}\nInstruction Pointer: {}\nRegisters: {}\nInstructions: {}",
               self.sp,
               self.ip,
               self.register.as_slice(),
               self.instructions.slice(self.ip,self.ip+10))
    }
}

fn new() -> VM {
    VM{sp:0, ip:0, register:[0, ..16], stack:[0, ..256], instructions:[0, ..65536]}
}

impl VM {
    fn push(&mut self) -> () {
        if self.sp >= 254 { fail!("Stack overflow at line {}", self.ip); }
        self.stack[self.sp] = 0;
        for i in range(0, 4) {
            self.stack[self.sp] += self.instructions[self.ip+1+i] as i32 << 8*i;
        }
        self.sp += 1;
        self.ip += 5;
    }

    fn bare_pop(&mut self) -> () {
        let _ = self.pop();
    }

    fn pop(&mut self) -> i32 {
        if self.sp > 0 {
            self.sp -= 1;
        } else {
            fail!("Attempted to pop empty stack at line {}", self.ip);
        }
        self.stack[self.sp]
    }

    fn load(&mut self) -> () {
        let r = self.instructions[self.ip+1];
        self.stack[self.sp] = self.register[r as uint];
        self.sp += 1;
        self.ip += 2;
    }

    fn store(&mut self) -> () {
        let r = self.instructions[self.ip + 1];
        self.register[r as uint] = self.pop();
        self.ip += 2;
    }

    fn jump(&mut self) -> () {
        let mut dest = self.instructions[self.ip+1] as uint;
        dest += self.instructions[self.ip+2] as uint << 8;
        self.ip = dest;
    }

    fn jz(&mut self) -> () {
        let tos = self.pop();
        if tos == 0 {
            self.jump();
        } else {
            self.ip += 3;
        }
    }

    fn jnz(&mut self) -> () {
        let tos = self.pop();
        if tos != 0 {
            self.jump();
        } else{
            self.ip += 3;
        }
    }

    fn add(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s1 + s2;
        self.sp += 1;
        self.ip += 1;
    }

    fn sub(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 - s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn mul(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 * s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn div(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 / s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn print(&mut self) -> () {
        let tos = self.pop();
        println!("{}", tos);
        self.ip += 1;
    }

    fn execute(&mut self) -> () {
        let mut i = 0u;
        loop {
            println!("{}", self);
            println!("Stack: {}\n", self.stack.slice(0,10));
            match self.instructions[self.ip] {
                0x00 => (),
                0x01 => self.push(),
                0x02 => self.bare_pop(),
                0x03 => self.load(),
                0x04 => self.store(),
                0x05 => self.jump(),
                0x06 => self.jz(),
                0x07 => self.jnz(),
                0x08 => self.add(),
                0x09 => self.sub(),
                0x0a => self.mul(),
                0x0b => self.div(),
                0x0c => self.print(),
                0x0d => break,
                x => println!("Encountered {}", x)
            }
            i += 1;
            //if i > 15 {break;}
        }
    }
}

struct VM  {
    sp : uint,
    ip : uint,
    register : [i32, ..16],
    stack : [i32, ..256],
    instructions : [u8, ..65536],
}

fn main() {
    let mut x  = new();
    match File::open(&Path::new("factorial.bcm")).read_to_end() {
        Ok(contents) => slice::bytes::copy_memory(x.instructions, contents.as_slice()),
        Err(e) => println!("Failed to read factorial.bcm with error {}", e),
    }

    x.execute();

}
<commit_msg>Add matching on OPCodes!!<commit_after>use std::io::{File};
use std::slice;
use std::fmt;
use std::num::FromPrimitive;

#[deriving(Show, FromPrimitive)]
enum OPCode {
    NOP = 0x00,
    PUSH,
    POP,
    LOAD,
    STORE,
    JMP,
    JZ,
    JNZ,
    ADD,
    SUB,
    MUL,
    DIV,
    PRINT,
    STOP
}

impl fmt::Show for VM {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "Stack Pointer: {}\nInstruction Pointer: {}\nRegisters: {}\nInstructions: {}",
               self.sp,
               self.ip,
               self.register.as_slice(),
               self.instructions.slice(self.ip,self.ip+10))
    }
}

fn new() -> VM {
    VM{sp:0, ip:0, register:[0, ..16], stack:[0, ..256], instructions:[0, ..65536]}
}

impl VM {
    fn push(&mut self) -> () {
        if self.sp >= 254 { fail!("Stack overflow at line {}", self.ip); }
        self.stack[self.sp] = 0;
        for i in range(0, 4) {
            self.stack[self.sp] += self.instructions[self.ip+1+i] as i32 << 8*i;
        }
        self.sp += 1;
        self.ip += 5;
    }

    fn bare_pop(&mut self) -> () {
        let _ = self.pop();
    }

    fn pop(&mut self) -> i32 {
        if self.sp > 0 {
            self.sp -= 1;
        } else {
            fail!("Attempted to pop empty stack at line {}", self.ip);
        }
        self.stack[self.sp]
    }

    fn load(&mut self) -> () {
        let r = self.instructions[self.ip+1];
        self.stack[self.sp] = self.register[r as uint];
        self.sp += 1;
        self.ip += 2;
    }

    fn store(&mut self) -> () {
        let r = self.instructions[self.ip + 1];
        self.register[r as uint] = self.pop();
        self.ip += 2;
    }

    fn jump(&mut self) -> () {
        let mut dest = self.instructions[self.ip+1] as uint;
        dest += self.instructions[self.ip+2] as uint << 8;
        self.ip = dest;
    }

    fn jz(&mut self) -> () {
        let tos = self.pop();
        if tos == 0 {
            self.jump();
        } else {
            self.ip += 3;
        }
    }

    fn jnz(&mut self) -> () {
        let tos = self.pop();
        if tos != 0 {
            self.jump();
        } else{
            self.ip += 3;
        }
    }

    fn add(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s1 + s2;
        self.sp += 1;
        self.ip += 1;
    }

    fn sub(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 - s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn mul(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 * s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn div(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 / s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn print(&mut self) -> () {
        let tos = self.pop();
        println!("{}", tos);
        self.ip += 1;
    }

    fn execute(&mut self) -> () {
        let mut i = 0u;
        loop {
            println!("{}", self);
            println!("Stack: {}\n", self.stack.slice(0,10));
            let op: Option<OPCode> = FromPrimitive::from_u8(self.instructions[self.ip]);
            match op {
                Some(code) => match code {
                    NOP => (),
                    PUSH => self.push(),
                    POP => self.bare_pop(),
                    LOAD => self.load(),
                    STORE => self.store(),
                    JMP => self.jump(),
                    JZ => self.jz(),
                    JNZ => self.jnz(),
                    ADD => self.add(),
                    SUB => self.sub(),
                    MUL => self.mul(),
                    DIV => self.div(),
                    PRINT => self.print(),
                    STOP => break,
                },
                None => println!("Invalid OPCode encountered at {}", self.ip)
            }
            i += 1;
            //if i > 15 {break;}
        }
    }
}

struct VM  {
    sp : uint,
    ip : uint,
    register : [i32, ..16],
    stack : [i32, ..256],
    instructions : [u8, ..65536],
}

fn main() {
    let mut x  = new();
    match File::open(&Path::new("factorial.bcm")).read_to_end() {
        Ok(contents) => slice::bytes::copy_memory(x.instructions, contents.as_slice()),
        Err(e) => println!("Failed to read factorial.bcm with error {}", e),
    }

    x.execute();

}
<|endoftext|>


<commit_before>use std::cell::RefCell;

use proc_macro2::{Delimiter, Span};

use buffer::Cursor;
use error::{self, Error};
use span::IntoSpans;
use token::Token;

/// Support for checking the next token in a stream to decide how to parse.
///
/// An important advantage over [`ParseStream::peek`] is that here we
/// automatically construct an appropriate error message based on the token
/// alternatives that get peeked. If you are producing your own error message,
/// go ahead and use `ParseStream::peek` instead.
///
/// Use [`ParseStream::lookahead1`] to construct this object.
///
/// [`ParseStream::peek`]: struct.ParseBuffer.html#method.peek
/// [`ParseStream::lookahead1`]: struct.ParseBuffer.html#method.lookahead1
///
/// # Example
///
/// ```
/// # extern crate syn;
/// #
/// use syn::{ConstParam, Ident, Lifetime, LifetimeDef, Token, TypeParam};
/// use syn::parse::{Parse, ParseStream, Result};
///
/// // A generic parameter, a single one of the comma-separated elements inside
/// // angle brackets in:
/// //
/// //     fn f<T: Clone, 'a, 'b: 'a, const N: usize>() { ... }
/// //
/// // On invalid input, lookahead gives us a reasonable error message.
/// //
/// //     error: expected one of: identifier, lifetime, `const`
/// //       |
/// //     5 |     fn f<!Sized>() {}
/// //       |          ^
/// enum GenericParam {
///     Type(TypeParam),
///     Lifetime(LifetimeDef),
///     Const(ConstParam),
/// }
///
/// impl Parse for GenericParam {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let lookahead = input.lookahead1();
///         if lookahead.peek(Ident) {
///             input.parse().map(GenericParam::Type)
///         } else if lookahead.peek(Lifetime) {
///             input.parse().map(GenericParam::Lifetime)
///         } else if lookahead.peek(Token![const]) {
///             input.parse().map(GenericParam::Const)
///         } else {
///             Err(lookahead.error())
///         }
///     }
/// }
/// #
/// # fn main() {}
/// ```
pub struct Lookahead1<'a> {
    scope: Span,
    cursor: Cursor<'a>,
    comparisons: RefCell<Vec<&'static str>>,
}

pub fn new(scope: Span, cursor: Cursor) -> Lookahead1 {
    Lookahead1 {
        scope: scope,
        cursor: cursor,
        comparisons: RefCell::new(Vec::new()),
    }
}

impl<'a> Lookahead1<'a> {
    pub fn peek<T: Peek>(&self, token: T) -> bool {
        let _ = token;
        if T::Token::peek(self.cursor) {
            return true;
        }
        self.comparisons.borrow_mut().push(T::Token::display());
        false
    }

    pub fn error(self) -> Error {
        let comparisons = self.comparisons.borrow();
        match comparisons.len() {
            0 => if self.cursor.eof() {
                Error::new(self.scope, "unexpected end of input")
            } else {
                Error::new(self.cursor.span(), "unexpected token")
            },
            1 => {
                let message = format!("expected {}", comparisons[0]);
                error::new_at(self.scope, self.cursor, message)
            }
            _ => {
                let join = comparisons.join(", ");
                let message = format!("expected one of: {}", join);
                error::new_at(self.scope, self.cursor, message)
            }
        }
    }
}

/// Types that can be parsed by looking at just one token.
///
/// Use [`ParseStream::peek`] to peek one of these types in a parse stream
/// without consuming it from the stream.
///
/// This trait is sealed and cannot be implemented for types outside of Syn.
///
/// [`ParseStream::peek`]: struct.ParseBuffer.html#method.peek
pub trait Peek: private::Sealed {
    // Not public API.
    #[doc(hidden)]
    type Token: Token;
}

impl<F: FnOnce(TokenMarker) -> T, T: Token> Peek for F {
    type Token = T;
}

pub enum TokenMarker {}

impl<S> IntoSpans<S> for TokenMarker {
    fn into_spans(self) -> S {
        match self {}
    }
}

pub fn is_delimiter(cursor: Cursor, delimiter: Delimiter) -> bool {
    cursor.group(delimiter).is_some()
}

mod private {
    use super::{Token, TokenMarker};
    pub trait Sealed {}
    impl<F: FnOnce(TokenMarker) -> T, T: Token> Sealed for F {}
}
<commit_msg>Compile less of Lookahead1::peek for each token<commit_after>use std::cell::RefCell;

use proc_macro2::{Delimiter, Span};

use buffer::Cursor;
use error::{self, Error};
use span::IntoSpans;
use token::Token;

/// Support for checking the next token in a stream to decide how to parse.
///
/// An important advantage over [`ParseStream::peek`] is that here we
/// automatically construct an appropriate error message based on the token
/// alternatives that get peeked. If you are producing your own error message,
/// go ahead and use `ParseStream::peek` instead.
///
/// Use [`ParseStream::lookahead1`] to construct this object.
///
/// [`ParseStream::peek`]: struct.ParseBuffer.html#method.peek
/// [`ParseStream::lookahead1`]: struct.ParseBuffer.html#method.lookahead1
///
/// # Example
///
/// ```
/// # extern crate syn;
/// #
/// use syn::{ConstParam, Ident, Lifetime, LifetimeDef, Token, TypeParam};
/// use syn::parse::{Parse, ParseStream, Result};
///
/// // A generic parameter, a single one of the comma-separated elements inside
/// // angle brackets in:
/// //
/// //     fn f<T: Clone, 'a, 'b: 'a, const N: usize>() { ... }
/// //
/// // On invalid input, lookahead gives us a reasonable error message.
/// //
/// //     error: expected one of: identifier, lifetime, `const`
/// //       |
/// //     5 |     fn f<!Sized>() {}
/// //       |          ^
/// enum GenericParam {
///     Type(TypeParam),
///     Lifetime(LifetimeDef),
///     Const(ConstParam),
/// }
///
/// impl Parse for GenericParam {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let lookahead = input.lookahead1();
///         if lookahead.peek(Ident) {
///             input.parse().map(GenericParam::Type)
///         } else if lookahead.peek(Lifetime) {
///             input.parse().map(GenericParam::Lifetime)
///         } else if lookahead.peek(Token![const]) {
///             input.parse().map(GenericParam::Const)
///         } else {
///             Err(lookahead.error())
///         }
///     }
/// }
/// #
/// # fn main() {}
/// ```
pub struct Lookahead1<'a> {
    scope: Span,
    cursor: Cursor<'a>,
    comparisons: RefCell<Vec<&'static str>>,
}

pub fn new(scope: Span, cursor: Cursor) -> Lookahead1 {
    Lookahead1 {
        scope: scope,
        cursor: cursor,
        comparisons: RefCell::new(Vec::new()),
    }
}

fn peek_impl(
    lookahead: &Lookahead1,
    peek: fn(Cursor) -> bool,
    display: fn() -> &'static str,
) -> bool {
    if peek(lookahead.cursor) {
        return true;
    }
    lookahead.comparisons.borrow_mut().push(display());
    false
}

impl<'a> Lookahead1<'a> {
    pub fn peek<T: Peek>(&self, token: T) -> bool {
        let _ = token;
        peek_impl(self, T::Token::peek, T::Token::display)
    }

    pub fn error(self) -> Error {
        let comparisons = self.comparisons.borrow();
        match comparisons.len() {
            0 => if self.cursor.eof() {
                Error::new(self.scope, "unexpected end of input")
            } else {
                Error::new(self.cursor.span(), "unexpected token")
            },
            1 => {
                let message = format!("expected {}", comparisons[0]);
                error::new_at(self.scope, self.cursor, message)
            }
            _ => {
                let join = comparisons.join(", ");
                let message = format!("expected one of: {}", join);
                error::new_at(self.scope, self.cursor, message)
            }
        }
    }
}

/// Types that can be parsed by looking at just one token.
///
/// Use [`ParseStream::peek`] to peek one of these types in a parse stream
/// without consuming it from the stream.
///
/// This trait is sealed and cannot be implemented for types outside of Syn.
///
/// [`ParseStream::peek`]: struct.ParseBuffer.html#method.peek
pub trait Peek: private::Sealed {
    // Not public API.
    #[doc(hidden)]
    type Token: Token;
}

impl<F: FnOnce(TokenMarker) -> T, T: Token> Peek for F {
    type Token = T;
}

pub enum TokenMarker {}

impl<S> IntoSpans<S> for TokenMarker {
    fn into_spans(self) -> S {
        match self {}
    }
}

pub fn is_delimiter(cursor: Cursor, delimiter: Delimiter) -> bool {
    cursor.group(delimiter).is_some()
}

mod private {
    use super::{Token, TokenMarker};
    pub trait Sealed {}
    impl<F: FnOnce(TokenMarker) -> T, T: Token> Sealed for F {}
}
<|endoftext|>


<commit_before>use std::borrow::Cow;

use Code;

#[cfg(all(feature = "validation", feature = "validation-sha2"))]
use validation::Validator;

#[cfg(all(feature = "validation", feature = "validation-sha2"))]
use validation::sha2::{Sha256Validator,Sha512Validator};

#[derive(Debug)]
pub struct MultiHash<'a> {
    code: Code,
    digest: Cow<'a, [u8]>,
}

impl<'a> MultiHash<'a> {
    pub fn new(code: Code, digest: Cow<'a, [u8]>) -> MultiHash<'a> {
        MultiHash {
            code: code,
            digest: digest,
        }
    }

    // TODO: Return real error
    pub fn decode(buffer: &[u8]) -> Result<MultiHash, &'static str> {
        if buffer.len() < 1 { return Err("No code"); }
        if buffer.len() < 2 { return Err("No length"); }
        let code = try!(Code::from_byte(buffer[0]));
        let length = buffer[1] as usize;
        if buffer.len() != length + 2 { return Err("Wrong length") }

        Ok(MultiHash {
            code: code,
            digest: Cow::Borrowed(&buffer[2..]),
        })
    }

    pub fn code(&self) -> Code {
        self.code
    }

    pub fn digest(&self) -> &[u8] {
        &*self.digest
    }

    #[cfg(all(feature = "validation", feature = "validation-sha2"))]
    pub fn validate(&self, data: &[u8]) -> Result<bool, Cow<'static, str>> {
        if self.code.to_byte() == 0x12 {
            Sha256Validator.validate(self.digest.as_ref(), data)
        } else if self.code.to_byte() == 0x13 {
            Sha512Validator.validate(self.digest.as_ref(), data)
        } else {
            Err("Unknown code".into())
        }
    }
}

impl<'a> Eq for MultiHash<'a> {}
impl<'a> PartialEq for MultiHash<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.code == other.code
            && self.digest().len() == other.digest().len()
            && self.digest().iter().zip(other.digest().iter()).all(|(l,r)| l == r)
    }
}

#[cfg(test)]
mod tests {
    use std::borrow::Cow;
    use { Code, MultiHash, ShaVariant };

    #[test]
    fn valid() {
        let digest: &[u8] = &[0xde, 0xad, 0xbe, 0xef];
        let buffer: &[u8] = &[0x11, 0x04, 0xde, 0xad, 0xbe, 0xef];
        assert_eq!(
            Ok(MultiHash::new(Code::Sha(ShaVariant::Sha1), Cow::Borrowed(digest))),
            MultiHash::decode(buffer));
    }

    #[test]
    fn no_code() {
        let buffer: &[u8] = &[];
        assert!(MultiHash::decode(buffer).is_err());
    }

    #[test]
    fn no_len() {
        let buffer: &[u8] = &[0x11];
        assert!(MultiHash::decode(buffer).is_err());
    }

    #[test]
    fn bad_code() {
        let buffer: &[u8] = &[0x90, 0x04, 0xde, 0xad, 0xbe, 0xef];
        assert!(MultiHash::decode(buffer).is_err());
    }

    #[test]
    fn short_digest() {
        let buffer: &[u8] = &[0x11, 0x05, 0xde, 0xad, 0xbe, 0xef];
        assert!(MultiHash::decode(buffer).is_err());
    }

    #[test]
    fn long_digest() {
        let buffer: &[u8] = &[0x11, 0x03, 0xde, 0xad, 0xbe, 0xef];
        assert!(MultiHash::decode(buffer).is_err());
    }
}
<commit_msg>Add method to get the expected length<commit_after>use std::borrow::Cow;

use Code;

#[cfg(all(feature = "validation", feature = "validation-sha2"))]
use validation::Validator;

#[cfg(all(feature = "validation", feature = "validation-sha2"))]
use validation::sha2::{Sha256Validator,Sha512Validator};

#[derive(Debug)]
pub struct MultiHash<'a> {
    code: Code,
    digest: Cow<'a, [u8]>,
}

impl<'a> MultiHash<'a> {
    pub fn new(code: Code, digest: Cow<'a, [u8]>) -> MultiHash<'a> {
        MultiHash {
            code: code,
            digest: digest,
        }
    }

    // TODO: Return real error
    pub fn decode(buffer: &[u8]) -> Result<MultiHash, &'static str> {
        if buffer.len() < 1 { return Err("No code"); }
        if buffer.len() < 2 { return Err("No length"); }
        let code = try!(Code::from_byte(buffer[0]));
        let length = buffer[1] as usize;
        if buffer.len() != length + 2 { return Err("Wrong length") }

        Ok(MultiHash {
            code: code,
            digest: Cow::Borrowed(&buffer[2..]),
        })
    }

    pub fn code(&self) -> Code {
        self.code
    }

    pub fn digest(&self) -> &[u8] {
        &*self.digest
    }

    /// The length of this multihash when writing to a byte stream
    pub fn len(&self) -> usize {
        self.digest.len() + 2
    }

    #[cfg(all(feature = "validation", feature = "validation-sha2"))]
    pub fn validate(&self, data: &[u8]) -> Result<bool, Cow<'static, str>> {
        if self.code.to_byte() == 0x12 {
            Sha256Validator.validate(self.digest.as_ref(), data)
        } else if self.code.to_byte() == 0x13 {
            Sha512Validator.validate(self.digest.as_ref(), data)
        } else {
            Err("Unknown code".into())
        }
    }
}

impl<'a> Eq for MultiHash<'a> {}
impl<'a> PartialEq for MultiHash<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.code == other.code
            && self.digest().len() == other.digest().len()
            && self.digest().iter().zip(other.digest().iter()).all(|(l,r)| l == r)
    }
}

#[cfg(test)]
mod tests {
    use std::borrow::Cow;
    use { Code, MultiHash, ShaVariant };

    #[test]
    fn valid() {
        let digest: &[u8] = &[0xde, 0xad, 0xbe, 0xef];
        let buffer: &[u8] = &[0x11, 0x04, 0xde, 0xad, 0xbe, 0xef];
        assert_eq!(
            Ok(MultiHash::new(Code::Sha(ShaVariant::Sha1), Cow::Borrowed(digest))),
            MultiHash::decode(buffer));
    }

    #[test]
    fn no_code() {
        let buffer: &[u8] = &[];
        assert!(MultiHash::decode(buffer).is_err());
    }

    #[test]
    fn no_len() {
        let buffer: &[u8] = &[0x11];
        assert!(MultiHash::decode(buffer).is_err());
    }

    #[test]
    fn bad_code() {
        let buffer: &[u8] = &[0x90, 0x04, 0xde, 0xad, 0xbe, 0xef];
        assert!(MultiHash::decode(buffer).is_err());
    }

    #[test]
    fn short_digest() {
        let buffer: &[u8] = &[0x11, 0x05, 0xde, 0xad, 0xbe, 0xef];
        assert!(MultiHash::decode(buffer).is_err());
    }

    #[test]
    fn long_digest() {
        let buffer: &[u8] = &[0x11, 0x03, 0xde, 0xad, 0xbe, 0xef];
        assert!(MultiHash::decode(buffer).is_err());
    }
}
<|endoftext|>


<commit_before>#![cfg(unix)]

use assert_cmd::Command;
use tempfile::tempdir;

use std::{
    env::{consts::DLL_SUFFIX, var_os},
    ffi::OsString,
    fs::{self, create_dir, create_dir_all, remove_file, set_permissions, File},
    io::Write,
    os::unix::{
        fs::symlink,
        prelude::{OsStrExt, PermissionsExt},
    },
    path::{Path, PathBuf},
};

struct StopServer;
impl Drop for StopServer {
    fn drop(&mut self) {
        Command::cargo_bin("sccache")
            .unwrap()
            .arg("--stop-server")
            .unwrap();
    }
}

// (temp dir)
// ├── rust // symlinks to rust1 on the first run and rust2 on the second
// ├── rust1/
// │  ├── bin
// │  │  └── rustc
// │  ├── lib
// │  │  └── driver.so -> ../driver.so
// │  └── driver.so
// ├── rust2/
// │  ├── bin
// │  │  └── rustc
// │  ├── lib
// │  │  └── driver.so -> ../driver.so
// │  └── driver.so
// ├── sccache/
// ├── counter // increases by 1 for every compilation that is not cached
// ├── RUST_FILE // compile output copied from counter, same content means it was cached
// └── RUST_FILE.rs
#[test]
fn test_symlinks() {
    let root = tempdir().unwrap();
    let root = root.path();

    fs::write(root.join("counter"), b"0").unwrap();
    fs::write(root.join("RUST_FILE.rs"), []).unwrap();

    create_mock_rustc(root.join("rust1"));
    create_mock_rustc(root.join("rust2"));

    let rust = root.join("rust");
    let bin = rust.join("bin");
    let out_file = root.join("RUST_FILE");

    symlink(root.join("rust1"), &rust).unwrap();
    let _stop_server = StopServer;
    run_sccache(root, &bin);
    let output1 = fs::read(&out_file).unwrap();

    remove_file(&rust).unwrap();
    symlink(root.join("rust2"), &rust).unwrap();
    run_sccache(root, &bin);
    let output2 = fs::read(out_file).unwrap();

    assert_ne!(output1, output2);
}

fn create_mock_rustc(dir: PathBuf) {
    let bin = dir.join("bin");
    create_dir_all(&bin).unwrap();

    let dll_name = format!("driver{DLL_SUFFIX}");
    let dll = dir.join(&dll_name);
    fs::write(&dll, dir.as_os_str().as_bytes()).unwrap();

    let lib = dir.join("lib");
    create_dir(&lib).unwrap();
    symlink(dll, lib.join(&dll_name)).unwrap();

    let rustc = bin.join("rustc");
    write!(
        File::create(&rustc).unwrap(),
        r#"#!/usr/bin/env bash

set -e
build=0

while (( "$#" )); do
    case "$1" in
        -vV)
            echo rustc 1.0.0
            exec echo "host: unknown"
            ;;
        --print=sysroot)
            exec echo {}
            ;;
        --print)
            shift
            if [ "$1" = file-names ]; then
                exec echo RUST_FILE.rs
            fi
            ;;
        --emit)
            shift
            if [ "$1" = dep-info ]; then
                echo "deps.d: RUST_FILE.rs" > "$3"
                exec echo "RUST_FILE.rs:" "$3"
            fi
            ;;
        RUST_FILE.rs)
            build=1
            ;;
    esac
    shift
done

if (( $build )); then
    echo $(("$(cat counter)" + 1)) > counter
    cp counter RUST_FILE
fi
"#,
        dir.display(),
    )
    .unwrap();

    let mut perm = rustc.metadata().unwrap().permissions();
    perm.set_mode(0o755);
    set_permissions(&rustc, perm).unwrap();
}

fn run_sccache(root: &Path, path: &Path) {
    let mut paths: OsString = path.into();
    paths.push(":");
    paths.push(var_os("PATH").unwrap());

    Command::cargo_bin("sccache")
        .unwrap()
        .current_dir(root)
        .env("PATH", paths)
        .env("SCCACHE_DIR", root.join("sccache"))
        .arg("rustc")
        .arg("RUST_FILE.rs")
        .arg("--crate-name=sccache-rustc-tests")
        .arg("--crate-type=lib")
        .arg("--emit=link")
        .arg("--out-dir")
        .arg(root)
        .unwrap();
}
<commit_msg>fix `invalid character in crate name` in test_symlinks<commit_after>#![cfg(unix)]

use assert_cmd::Command;
use tempfile::tempdir;

use std::{
    env::{consts::DLL_SUFFIX, var_os},
    ffi::OsString,
    fs::{self, create_dir, create_dir_all, remove_file, set_permissions, File},
    io::Write,
    os::unix::{
        fs::symlink,
        prelude::{OsStrExt, PermissionsExt},
    },
    path::{Path, PathBuf},
};

struct StopServer;
impl Drop for StopServer {
    fn drop(&mut self) {
        Command::cargo_bin("sccache")
            .unwrap()
            .arg("--stop-server")
            .unwrap();
    }
}

// (temp dir)
// ├── rust // symlinks to rust1 on the first run and rust2 on the second
// ├── rust1/
// │  ├── bin
// │  │  └── rustc
// │  ├── lib
// │  │  └── driver.so -> ../driver.so
// │  └── driver.so
// ├── rust2/
// │  ├── bin
// │  │  └── rustc
// │  ├── lib
// │  │  └── driver.so -> ../driver.so
// │  └── driver.so
// ├── sccache/
// ├── counter // increases by 1 for every compilation that is not cached
// ├── RUST_FILE // compile output copied from counter, same content means it was cached
// └── RUST_FILE.rs
#[test]
fn test_symlinks() {
    let root = tempdir().unwrap();
    let root = root.path();

    fs::write(root.join("counter"), b"0").unwrap();
    fs::write(root.join("RUST_FILE.rs"), []).unwrap();

    create_mock_rustc(root.join("rust1"));
    create_mock_rustc(root.join("rust2"));

    let rust = root.join("rust");
    let bin = rust.join("bin");
    let out_file = root.join("RUST_FILE");

    symlink(root.join("rust1"), &rust).unwrap();
    drop(StopServer);
    let _stop_server = StopServer;
    run_sccache(root, &bin);
    let output1 = fs::read(&out_file).unwrap();

    remove_file(&rust).unwrap();
    symlink(root.join("rust2"), &rust).unwrap();
    run_sccache(root, &bin);
    let output2 = fs::read(out_file).unwrap();

    assert_ne!(output1, output2);
}

fn create_mock_rustc(dir: PathBuf) {
    let bin = dir.join("bin");
    create_dir_all(&bin).unwrap();

    let dll_name = format!("driver{DLL_SUFFIX}");
    let dll = dir.join(&dll_name);
    fs::write(&dll, dir.as_os_str().as_bytes()).unwrap();

    let lib = dir.join("lib");
    create_dir(&lib).unwrap();
    symlink(dll, lib.join(&dll_name)).unwrap();

    let rustc = bin.join("rustc");
    write!(
        File::create(&rustc).unwrap(),
        r#"#!/usr/bin/env bash

set -e
build=0

while (( "$#" )); do
    case "$1" in
        -vV)
            echo rustc 1.0.0
            exec echo "host: unknown"
            ;;
        --print=sysroot)
            exec echo {}
            ;;
        --print)
            shift
            if [ "$1" = file-names ]; then
                exec echo RUST_FILE.rs
            fi
            ;;
        --emit)
            shift
            if [ "$1" = dep-info ]; then
                echo "deps.d: RUST_FILE.rs" > "$3"
                exec echo "RUST_FILE.rs:" "$3"
            fi
            ;;
        RUST_FILE.rs)
            build=1
            ;;
    esac
    shift
done

if (( $build )); then
    echo $(("$(cat counter)" + 1)) > counter
    cp counter RUST_FILE
fi
"#,
        dir.display(),
    )
    .unwrap();

    let mut perm = rustc.metadata().unwrap().permissions();
    perm.set_mode(0o755);
    set_permissions(&rustc, perm).unwrap();
}

fn run_sccache(root: &Path, path: &Path) {
    let mut paths: OsString = path.into();
    paths.push(":");
    paths.push(var_os("PATH").unwrap());

    Command::cargo_bin("sccache")
        .unwrap()
        .current_dir(root)
        .env("PATH", paths)
        .env("SCCACHE_DIR", root.join("sccache"))
        .arg("rustc")
        .arg("RUST_FILE.rs")
        .arg("--crate-name=sccache_rustc_tests")
        .arg("--crate-type=lib")
        .arg("--emit=link")
        .arg("--out-dir")
        .arg(root)
        .unwrap();
}
<|endoftext|>


<commit_before>use syntax::ast;
use syntax::codemap::DUMMY_SP;
use syntax::ptr::P;

use aster::AstBuilder;
use aster::path::IntoPath;
use aster::lifetime::{IntoLifetime, IntoLifetimeDef};

#[test]
fn test_ty_param_empty() {
    let builder = AstBuilder::new();
    let ty_param = builder.ty_param("T").build();

    assert_eq!(
        ty_param,
        ast::TyParam {
            ident: builder.id("T"),
            id: ast::DUMMY_NODE_ID,
            bounds: P::new(),
            default: None,
            span: DUMMY_SP,
        }
    );
}

#[test]
fn test_ty_param_default() {
    let builder = AstBuilder::new();
    let ty_param = builder.ty_param("T")
        .default()
        .usize()
        .build();

    assert_eq!(
        ty_param,
        ast::TyParam {
            ident: builder.id("T"),
            id: ast::DUMMY_NODE_ID,
            bounds: P::new(),
            default: Some(builder.ty().usize()),
            span: DUMMY_SP,
        }
    );
}

#[test]
fn test_ty_param_bounds() {
    let builder = AstBuilder::new();
    let ty_param = builder.ty_param("T")
        .bound().trait_("Trait")
            .lifetime("'a").build()
            .build()
        .bound().maybe_trait("Sized").build()
        .bound().lifetime("'b")
        .build();

    assert_eq!(
        ty_param,
        ast::TyParam {
            ident: builder.id("T"),
            id: ast::DUMMY_NODE_ID,
            bounds: P::from_vec(vec![
                ast::TyParamBound::TraitTyParamBound(
                    ast::PolyTraitRef {
                        bound_lifetimes: vec![
                            "'a".into_lifetime_def(),
                        ],
                        trait_ref: ast::TraitRef {
                            path: "Trait".into_path(),
                            ref_id: ast::DUMMY_NODE_ID,
                        },
                        span: DUMMY_SP,
                    },
                    ast::TraitBoundModifier::None,
                ),
                ast::TyParamBound::TraitTyParamBound(
                    ast::PolyTraitRef {
                        bound_lifetimes: Vec::new(),
                        trait_ref: ast::TraitRef {
                            path: "Sized".into_path(),
                            ref_id: ast::DUMMY_NODE_ID,
                        },
                        span: DUMMY_SP,
                    },
                    ast::TraitBoundModifier::Maybe,
                ),
                ast::TyParamBound::RegionTyParamBound(
                    "'b".into_lifetime()
                ),
            ]),
            default: None,
            span: DUMMY_SP,
        }
    );
}
<commit_msg>Fix test cases with missing 'attrs' field<commit_after>use syntax::ast;
use syntax::codemap::DUMMY_SP;
use syntax::ptr::P;

use aster::AstBuilder;
use aster::path::IntoPath;
use aster::lifetime::{IntoLifetime, IntoLifetimeDef};

#[test]
fn test_ty_param_empty() {
    let builder = AstBuilder::new();
    let ty_param = builder.ty_param("T").build();

    assert_eq!(
        ty_param,
        ast::TyParam {
            attrs: ast::ThinVec::new(),
            ident: builder.id("T"),
            id: ast::DUMMY_NODE_ID,
            bounds: P::new(),
            default: None,
            span: DUMMY_SP,
        }
    );
}

#[test]
fn test_ty_param_default() {
    let builder = AstBuilder::new();
    let ty_param = builder.ty_param("T")
        .default()
        .usize()
        .build();

    assert_eq!(
        ty_param,
        ast::TyParam {
            attrs: ast::ThinVec::new(),
            ident: builder.id("T"),
            id: ast::DUMMY_NODE_ID,
            bounds: P::new(),
            default: Some(builder.ty().usize()),
            span: DUMMY_SP,
        }
    );
}

#[test]
fn test_ty_param_bounds() {
    let builder = AstBuilder::new();
    let ty_param = builder.ty_param("T")
        .bound().trait_("Trait")
            .lifetime("'a").build()
            .build()
        .bound().maybe_trait("Sized").build()
        .bound().lifetime("'b")
        .build();

    assert_eq!(
        ty_param,
        ast::TyParam {
            attrs: ast::ThinVec::new(),
            ident: builder.id("T"),
            id: ast::DUMMY_NODE_ID,
            bounds: P::from_vec(vec![
                ast::TyParamBound::TraitTyParamBound(
                    ast::PolyTraitRef {
                        bound_lifetimes: vec![
                            "'a".into_lifetime_def(),
                        ],
                        trait_ref: ast::TraitRef {
                            path: "Trait".into_path(),
                            ref_id: ast::DUMMY_NODE_ID,
                        },
                        span: DUMMY_SP,
                    },
                    ast::TraitBoundModifier::None,
                ),
                ast::TyParamBound::TraitTyParamBound(
                    ast::PolyTraitRef {
                        bound_lifetimes: Vec::new(),
                        trait_ref: ast::TraitRef {
                            path: "Sized".into_path(),
                            ref_id: ast::DUMMY_NODE_ID,
                        },
                        span: DUMMY_SP,
                    },
                    ast::TraitBoundModifier::Maybe,
                ),
                ast::TyParamBound::RegionTyParamBound(
                    "'b".into_lifetime()
                ),
            ]),
            default: None,
            span: DUMMY_SP,
        }
    );
}
<|endoftext|>


<commit_before>use ruma_serde::urlencoded;
use serde::Serialize;
use url::form_urlencoded::Serializer as Encoder;

#[derive(Serialize)]
struct NewType<T>(T);

#[test]
fn serialize_newtype_i32() {
    let params = &[("field", Some(NewType(11)))];
    assert_eq!(urlencoded::to_string(params), Ok("field=11".to_owned()));
}

#[test]
fn serialize_option_map_int() {
    let params = &[("first", Some(23)), ("middle", None), ("last", Some(42))];

    assert_eq!(
        urlencoded::to_string(params),
        Ok("first=23&last=42".to_owned())
    );
}

#[test]
fn serialize_option_map_string() {
    let params = &[
        ("first", Some("hello")),
        ("middle", None),
        ("last", Some("world")),
    ];

    assert_eq!(
        urlencoded::to_string(params),
        Ok("first=hello&last=world".to_owned())
    );
}

#[test]
fn serialize_option_map_bool() {
    let params = &[("one", Some(true)), ("two", Some(false))];

    assert_eq!(
        urlencoded::to_string(params),
        Ok("one=true&two=false".to_owned())
    );
}

#[test]
fn serialize_map_bool() {
    let params = &[("one", true), ("two", false)];

    assert_eq!(
        urlencoded::to_string(params),
        Ok("one=true&two=false".to_owned())
    );
}

#[derive(Serialize)]
enum X {
    A,
    B,
    C,
}

#[test]
fn serialize_unit_enum() {
    let params = &[("one", X::A), ("two", X::B), ("three", X::C)];
    assert_eq!(
        urlencoded::to_string(params),
        Ok("one=A&two=B&three=C".to_owned())
    );
}

#[derive(Serialize)]
struct Unit;

#[test]
fn serialize_unit_struct() {
    assert_eq!(urlencoded::to_string(Unit), Ok("".to_owned()));
}

#[test]
fn serialize_unit_type() {
    assert_eq!(urlencoded::to_string(()), Ok("".to_owned()));
}

#[derive(Serialize)]
struct Wrapper<T> {
    item: T,
}

#[derive(Serialize)]
struct NewStruct {
    list: Vec<String>,
}

#[derive(Serialize)]
struct Struct {
    list: Vec<Option<String>>,
}

#[derive(Serialize)]
struct ListStruct {
    list: Vec<NewType<usize>>,
}

#[test]
fn serialize_newstruct() {
    let s = NewStruct {
        list: vec!["hello".into(), "world".into()],
    };
    assert_eq!(
        "list=hello&list=world".to_string(),
        urlencoded::to_string(s).unwrap()
    );
}

#[test]
fn serialize_vec_bool() {
    let params = Wrapper {
        item: vec![true, false, false],
    };
    assert_eq!(
        urlencoded::to_string(params).unwrap(),
        "item=true&item=false&item=false".to_owned()
    );
}

#[test]
fn serialize_vec_num() {
    let params = Wrapper {
        item: vec![0, 1, 2],
    };
    assert_eq!(
        urlencoded::to_string(params).unwrap(),
        "item=0&item=1&item=2".to_owned()
    );
}

#[test]
fn serialize_vec_str() {
    let params = Wrapper {
        item: vec!["hello", "world", "hello"],
    };
    assert_eq!(
        urlencoded::to_string(params).unwrap(),
        "item=hello&item=world&item=hello".to_owned()
    );
}

#[test]
fn serialize_struct_opt() {
    let s = Struct {
        list: vec![Some("hello".into()), Some("world".into())],
    };
    assert_eq!(
        "list=hello&list=world".to_string(),
        urlencoded::to_string(s).unwrap()
    );
}

#[test]
fn serialize_struct_newtype() {
    let s = ListStruct {
        list: vec![NewType(0), NewType(1)],
    };
    assert_eq!(
        "list=0&list=1".to_string(),
        urlencoded::to_string(s).unwrap()
    );
}

#[test]
fn serialize_struct_unit_enum() {
    let params = Wrapper {
        item: vec![X::A, X::B, X::C],
    };
    assert_eq!(
        urlencoded::to_string(params),
        Ok("item=A&item=B&item=C".to_owned())
    );
}

#[test]
fn serialize_map() {
    let mut s = std::collections::BTreeMap::new();
    s.insert("hello", "world");
    s.insert("seri", "alize");
    s.insert("matrix", "ruma");

    let encoded = urlencoded::to_string(s).unwrap();
    assert_eq!("hello=world&matrix=ruma&seri=alize", encoded);
}

#[derive(Serialize)]
struct Nested<T> {
    item: T,
}

#[derive(Serialize)]
struct Inner {
    c: String,
    a: usize,
    b: String,
}

#[derive(Debug, Serialize, PartialEq)]
struct InnerList<T> {
    list: Vec<T>,
}

#[test]
#[ignore]
fn serialize_nested() {
    let mut encoder = Encoder::new(String::new());

    let s = Nested {
        item: Inner {
            c: "hello".into(),
            a: 10,
            b: "bye".into(),
        },
    };
    assert_eq!(
        encoder
            .append_pair("item", r#"{"c":"hello","a":10,"b":"bye"}"#)
            .finish(),
        urlencoded::to_string(s).unwrap()
    );
}

#[test]
#[ignore]
fn serialize_nested_list() {
    let mut encoder = Encoder::new(String::new());

    let s = Nested {
        item: InnerList {
            list: vec![1, 2, 3],
        },
    };
    assert_eq!(
        encoder.append_pair("item", r#"{"list":[1,2,3]}"#).finish(),
        urlencoded::to_string(s).unwrap()
    );
}

#[test]
#[ignore]
fn serialize_nested_list_option() {
    let mut encoder = Encoder::new(String::new());

    let s = Nested {
        item: InnerList {
            list: vec![Some(1), Some(2), None],
        },
    };
    assert_eq!(
        encoder
            .append_pair("item", r#"{"list":[1,2,null]}"#)
            .finish(),
        urlencoded::to_string(s).unwrap()
    );
}
<commit_msg>Update serialization tests<commit_after>use ruma_serde::urlencoded;
use serde::Serialize;
use url::form_urlencoded::Serializer as Encoder;

#[derive(Serialize)]
struct NewType<T>(T);

#[test]
fn serialize_newtype_i32() {
    let params = &[("field", Some(NewType(11)))];
    assert_eq!(urlencoded::to_string(params), Ok("field=11".to_owned()));
}

#[test]
fn serialize_option_map_int() {
    let params = &[("first", Some(23)), ("middle", None), ("last", Some(42))];

    assert_eq!(
        urlencoded::to_string(params),
        Ok("first=23&last=42".to_owned())
    );
}

#[test]
fn serialize_option_map_string() {
    let params = &[
        ("first", Some("hello")),
        ("middle", None),
        ("last", Some("world")),
    ];

    assert_eq!(
        urlencoded::to_string(params),
        Ok("first=hello&last=world".to_owned())
    );
}

#[test]
fn serialize_option_map_bool() {
    let params = &[("one", Some(true)), ("two", Some(false))];

    assert_eq!(
        urlencoded::to_string(params),
        Ok("one=true&two=false".to_owned())
    );
}

#[test]
fn serialize_map_bool() {
    let params = &[("one", true), ("two", false)];

    assert_eq!(
        urlencoded::to_string(params),
        Ok("one=true&two=false".to_owned())
    );
}

#[derive(Serialize)]
enum X {
    A,
    B,
    C,
}

#[test]
fn serialize_unit_enum() {
    let params = &[("one", X::A), ("two", X::B), ("three", X::C)];
    assert_eq!(
        urlencoded::to_string(params),
        Ok("one=A&two=B&three=C".to_owned())
    );
}

#[derive(Serialize)]
struct Unit;

#[test]
fn serialize_unit_struct() {
    assert_eq!(urlencoded::to_string(Unit), Ok("".to_owned()));
}

#[test]
fn serialize_unit_type() {
    assert_eq!(urlencoded::to_string(()), Ok("".to_owned()));
}

#[test]
fn serialize_list_of_str() {
    let s = &[("list", vec!["hello", "world"])];

    assert_eq!(
        urlencoded::to_string(s),
        Ok("list=hello&list=world".to_owned())
    );
}

#[test]
fn serialize_multiple_lists() {
    #[derive(Serialize)]
    struct Lists {
        xs: Vec<bool>,
        ys: Vec<u32>,
    }

    let params = Lists {
        xs: vec![true, false],
        ys: vec![3, 2, 1],
    };

    assert_eq!(
        urlencoded::to_string(params),
        Ok("xs=true&xs=false&ys=3&ys=2&ys=1".to_owned())
    );
}

#[test]
fn serialize_vec_num() {
    let params = [("item", vec![0, 1, 2])];
    assert_eq!(
        urlencoded::to_string(params),
        Ok("item=0&item=1&item=2".to_owned())
    );
}

#[test]
fn serialize_vec_str() {
    let params = &[("item", vec!["hello", "world", "hello"])];
    assert_eq!(
        urlencoded::to_string(params),
        Ok("item=hello&item=world&item=hello".to_owned())
    );
}

#[test]
fn serialize_struct_opt() {
    let s = &[("list", vec![Some("hello"), Some("world")])];
    assert_eq!(
        urlencoded::to_string(s),
        Ok("list=hello&list=world".to_string())
    );
}

#[test]
fn serialize_struct_newtype() {
    let s = &[("list", vec![NewType(0), NewType(1)])];
    assert_eq!(
        "list=0&list=1".to_string(),
        urlencoded::to_string(s).unwrap()
    );
}

#[test]
fn serialize_struct_unit_enum() {
    let params = &[("item", vec![X::A, X::B, X::C])];
    assert_eq!(
        urlencoded::to_string(params),
        Ok("item=A&item=B&item=C".to_owned())
    );
}

#[test]
fn serialize_map() {
    let mut s = std::collections::BTreeMap::new();
    s.insert("hello", "world");
    s.insert("seri", "alize");
    s.insert("matrix", "ruma");

    let encoded = urlencoded::to_string(s).unwrap();
    assert_eq!("hello=world&matrix=ruma&seri=alize", encoded);
}

#[derive(Serialize)]
struct Nested<T> {
    item: T,
}

#[derive(Serialize)]
struct Inner {
    c: String,
    a: usize,
    b: String,
}

#[derive(Debug, Serialize, PartialEq)]
struct InnerList<T> {
    list: Vec<T>,
}

#[test]
#[ignore]
fn serialize_nested() {
    let mut encoder = Encoder::new(String::new());

    let s = Nested {
        item: Inner {
            c: "hello".into(),
            a: 10,
            b: "bye".into(),
        },
    };
    assert_eq!(
        encoder
            .append_pair("item", r#"{"c":"hello","a":10,"b":"bye"}"#)
            .finish(),
        urlencoded::to_string(s).unwrap()
    );
}

#[test]
#[ignore]
fn serialize_nested_list() {
    let mut encoder = Encoder::new(String::new());

    let s = Nested {
        item: InnerList {
            list: vec![1, 2, 3],
        },
    };
    assert_eq!(
        encoder.append_pair("item", r#"{"list":[1,2,3]}"#).finish(),
        urlencoded::to_string(s).unwrap()
    );
}

#[test]
#[ignore]
fn serialize_nested_list_option() {
    let mut encoder = Encoder::new(String::new());

    let s = Nested {
        item: InnerList {
            list: vec![Some(1), Some(2), None],
        },
    };
    assert_eq!(
        encoder
            .append_pair("item", r#"{"list":[1,2,null]}"#)
            .finish(),
        urlencoded::to_string(s).unwrap()
    );
}
<|endoftext|>