<commit_before>//! Asynchronous sinks
//!
//! This crate contains the `Sink` trait which allows values to be sent
//! asynchronously.

#![cfg_attr(not(feature = "std"), no_std)]
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
#![warn(clippy::all)]

#![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.16/futures_sink")]

#[cfg(feature = "alloc")]
extern crate alloc;

use futures_core::task::{Context, Poll};
use core::ops::DerefMut;
use core::pin::Pin;

/// A `Sink` is a value into which other values can be sent, asynchronously.
///
/// Basic examples of sinks include the sending side of:
///
/// - Channels
/// - Sockets
/// - Pipes
///
/// In addition to such "primitive" sinks, it's typical to layer additional
/// functionality, such as buffering, on top of an existing sink.
///
/// Sending to a sink is "asynchronous" in the sense that the value may not be
/// sent in its entirety immediately. Instead, values are sent in a two-phase
/// way: first by initiating a send, and then by polling for completion. This
/// two-phase setup is analogous to buffered writing in synchronous code, where
/// writes often succeed immediately, but internally are buffered and are
/// *actually* written only upon flushing.
///
/// In addition, the `Sink` may be *full*, in which case it is not even possible
/// to start the sending process.
///
/// As with `Future` and `Stream`, the `Sink` trait is built from a few core
/// required methods, and a host of default methods for working in a
/// higher-level way. The `Sink::send_all` combinator is of particular
/// importance: you can use it to send an entire stream to a sink, which is
/// the simplest way to ultimately consume a stream.
#[must_use = "sinks do nothing unless polled"]
pub trait Sink<Item> {
    /// The type of value produced by the sink when an error occurs.
    type SinkError;

    /// Attempts to prepare the `Sink` to receive a value.
    ///
    /// This method must be called and return `Poll::Ready(Ok(()))` prior to
    /// each call to `start_send`.
    ///
    /// This method returns `Poll::Ready` once the underlying sink is ready to
    /// receive data. If this method returns `Poll::Pending`, the current task
    /// is registered to be notified (via `cx.waker().wake_by_ref()`) when `poll_ready`
    /// should be called again.
    ///
    /// In most cases, if the sink encounters an error, the sink will
    /// permanently be unable to receive items.
    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>>;

    /// Begin the process of sending a value to the sink.
    /// Each call to this function must be proceeded by a successful call to
    /// `poll_ready` which returned `Poll::Ready(Ok(()))`.
    ///
    /// As the name suggests, this method only *begins* the process of sending
    /// the item. If the sink employs buffering, the item isn't fully processed
    /// until the buffer is fully flushed. Since sinks are designed to work with
    /// asynchronous I/O, the process of actually writing out the data to an
    /// underlying object takes place asynchronously. **You *must* use
    /// `poll_flush` or `poll_close` in order to guarantee completion of a
    /// send**.
    ///
    /// Implementations of `poll_ready` and `start_send` will usually involve
    /// flushing behind the scenes in order to make room for new messages.
    /// It is only necessary to call `poll_flush` if you need to guarantee that
    /// *all* of the items placed into the `Sink` have been sent.
    ///
    /// In most cases, if the sink encounters an error, the sink will
    /// permanently be unable to receive items.
    fn start_send(self: Pin<&mut Self>, item: Item)
                  -> Result<(), Self::SinkError>;

    /// Flush any remaining output from this sink.
    ///
    /// Returns `Poll::Ready(Ok(()))` when no buffered items remain. If this
    /// value is returned then it is guaranteed that all previous values sent
    /// via `start_send` have been flushed.
    ///
    /// Returns `Poll::Pending` if there is more work left to do, in which
    /// case the current task is scheduled (via `cx.waker().wake_by_ref()`) to wake up when
    /// `poll_flush` should be called again.
    ///
    /// In most cases, if the sink encounters an error, the sink will
    /// permanently be unable to receive items.
    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>>;

    /// Flush any remaining output and close this sink, if necessary.
    ///
    /// Returns `Poll::Ready(Ok(()))` when no buffered items remain and the sink
    /// has been successfully closed.
    ///
    /// Returns `Poll::Pending` if there is more work left to do, in which
    /// case the current task is scheduled (via `cx.waker().wake_by_ref()`) to wake up when
    /// `poll_close` should be called again.
    ///
    /// If this function encounters an error, the sink should be considered to
    /// have failed permanently, and no more `Sink` methods should be called.
    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>>;
}

impl<S: ?Sized + Sink<Item> + Unpin, Item> Sink<Item> for &mut S {
    type SinkError = S::SinkError;

    fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::new(&mut **self).poll_ready(cx)
    }

    fn start_send(mut self: Pin<&mut Self>, item: Item) -> Result<(), Self::SinkError> {
        Pin::new(&mut **self).start_send(item)
    }

    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::new(&mut **self).poll_flush(cx)
    }

    fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::new(&mut **self).poll_close(cx)
    }
}

impl
 Sink<Item> for Pin

where
    P: DerefMut + Unpin,
    P::Target: Sink<Item>,
{
    type SinkError = <P::Target as Sink<Item>>::SinkError;

    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::get_mut(self).as_mut().poll_ready(cx)
    }

    fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::SinkError> {
        Pin::get_mut(self).as_mut().start_send(item)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::get_mut(self).as_mut().poll_flush(cx)
    }

    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::get_mut(self).as_mut().poll_close(cx)
    }
}

#[cfg(feature = "std")]
mod channel_impls;

#[cfg(feature = "alloc")]
mod if_alloc {
    use super::*;

    /// The error type for `Vec` and `VecDequeue` when used as `Sink`s.
    /// Values of this type can never be created.
    #[derive(Copy, Clone, Debug)]
    pub enum VecSinkError {}

    impl<T> Sink<T> for ::alloc::vec::Vec<T> {
        type SinkError = VecSinkError;

        fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }

        fn start_send(self: Pin<&mut Self>, item: T) -> Result<(), Self::SinkError> {
            // TODO: impl<T> Unpin for Vec<T> {}
            unsafe { Pin::get_unchecked_mut(self) }.push(item);
            Ok(())
        }

        fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }

        fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }
    }

    impl<T> Sink<T> for ::alloc::collections::VecDeque<T> {
        type SinkError = VecSinkError;

        fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }

        fn start_send(self: Pin<&mut Self>, item: T) -> Result<(), Self::SinkError> {
            // TODO: impl<T> Unpin for Vec<T> {}
            unsafe { Pin::get_unchecked_mut(self) }.push_back(item);
            Ok(())
        }

        fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }

        fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }
    }

    impl<S: ?Sized + Sink<Item> + Unpin, Item> Sink<Item> for ::alloc::boxed::Box<S> {
        type SinkError = S::SinkError;

        fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Pin::new(&mut **self).poll_ready(cx)
        }

        fn start_send(mut self: Pin<&mut Self>, item: Item) -> Result<(), Self::SinkError> {
            Pin::new(&mut **self).start_send(item)
        }

        fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Pin::new(&mut **self).poll_flush(cx)
        }

        fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Pin::new(&mut **self).poll_close(cx)
        }
    }
}

#[cfg(feature = "alloc")]
pub use self::if_alloc::*;
<commit_msg>Fix error in Sink documentation<commit_after>//! Asynchronous sinks
//!
//! This crate contains the `Sink` trait which allows values to be sent
//! asynchronously.

#![cfg_attr(not(feature = "std"), no_std)]
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
#![warn(clippy::all)]

#![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.16/futures_sink")]

#[cfg(feature = "alloc")]
extern crate alloc;

use futures_core::task::{Context, Poll};
use core::ops::DerefMut;
use core::pin::Pin;

/// A `Sink` is a value into which other values can be sent, asynchronously.
///
/// Basic examples of sinks include the sending side of:
///
/// - Channels
/// - Sockets
/// - Pipes
///
/// In addition to such "primitive" sinks, it's typical to layer additional
/// functionality, such as buffering, on top of an existing sink.
///
/// Sending to a sink is "asynchronous" in the sense that the value may not be
/// sent in its entirety immediately. Instead, values are sent in a two-phase
/// way: first by initiating a send, and then by polling for completion. This
/// two-phase setup is analogous to buffered writing in synchronous code, where
/// writes often succeed immediately, but internally are buffered and are
/// *actually* written only upon flushing.
///
/// In addition, the `Sink` may be *full*, in which case it is not even possible
/// to start the sending process.
///
/// As with `Future` and `Stream`, the `Sink` trait is built from a few core
/// required methods, and a host of default methods for working in a
/// higher-level way. The `Sink::send_all` combinator is of particular
/// importance: you can use it to send an entire stream to a sink, which is
/// the simplest way to ultimately consume a stream.
#[must_use = "sinks do nothing unless polled"]
pub trait Sink<Item> {
    /// The type of value produced by the sink when an error occurs.
    type SinkError;

    /// Attempts to prepare the `Sink` to receive a value.
    ///
    /// This method must be called and return `Poll::Ready(Ok(()))` prior to
    /// each call to `start_send`.
    ///
    /// This method returns `Poll::Ready` once the underlying sink is ready to
    /// receive data. If this method returns `Poll::Pending`, the current task
    /// is registered to be notified (via `cx.waker().wake_by_ref()`) when `poll_ready`
    /// should be called again.
    ///
    /// In most cases, if the sink encounters an error, the sink will
    /// permanently be unable to receive items.
    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>>;

    /// Begin the process of sending a value to the sink.
    /// Each call to this function must be preceded by a successful call to
    /// `poll_ready` which returned `Poll::Ready(Ok(()))`.
    ///
    /// As the name suggests, this method only *begins* the process of sending
    /// the item. If the sink employs buffering, the item isn't fully processed
    /// until the buffer is fully flushed. Since sinks are designed to work with
    /// asynchronous I/O, the process of actually writing out the data to an
    /// underlying object takes place asynchronously. **You *must* use
    /// `poll_flush` or `poll_close` in order to guarantee completion of a
    /// send**.
    ///
    /// Implementations of `poll_ready` and `start_send` will usually involve
    /// flushing behind the scenes in order to make room for new messages.
    /// It is only necessary to call `poll_flush` if you need to guarantee that
    /// *all* of the items placed into the `Sink` have been sent.
    ///
    /// In most cases, if the sink encounters an error, the sink will
    /// permanently be unable to receive items.
    fn start_send(self: Pin<&mut Self>, item: Item)
                  -> Result<(), Self::SinkError>;

    /// Flush any remaining output from this sink.
    ///
    /// Returns `Poll::Ready(Ok(()))` when no buffered items remain. If this
    /// value is returned then it is guaranteed that all previous values sent
    /// via `start_send` have been flushed.
    ///
    /// Returns `Poll::Pending` if there is more work left to do, in which
    /// case the current task is scheduled (via `cx.waker().wake_by_ref()`) to wake up when
    /// `poll_flush` should be called again.
    ///
    /// In most cases, if the sink encounters an error, the sink will
    /// permanently be unable to receive items.
    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>>;

    /// Flush any remaining output and close this sink, if necessary.
    ///
    /// Returns `Poll::Ready(Ok(()))` when no buffered items remain and the sink
    /// has been successfully closed.
    ///
    /// Returns `Poll::Pending` if there is more work left to do, in which
    /// case the current task is scheduled (via `cx.waker().wake_by_ref()`) to wake up when
    /// `poll_close` should be called again.
    ///
    /// If this function encounters an error, the sink should be considered to
    /// have failed permanently, and no more `Sink` methods should be called.
    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>>;
}

impl<S: ?Sized + Sink<Item> + Unpin, Item> Sink<Item> for &mut S {
    type SinkError = S::SinkError;

    fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::new(&mut **self).poll_ready(cx)
    }

    fn start_send(mut self: Pin<&mut Self>, item: Item) -> Result<(), Self::SinkError> {
        Pin::new(&mut **self).start_send(item)
    }

    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::new(&mut **self).poll_flush(cx)
    }

    fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::new(&mut **self).poll_close(cx)
    }
}

impl
 Sink<Item> for Pin

where
    P: DerefMut + Unpin,
    P::Target: Sink<Item>,
{
    type SinkError = <P::Target as Sink<Item>>::SinkError;

    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::get_mut(self).as_mut().poll_ready(cx)
    }

    fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::SinkError> {
        Pin::get_mut(self).as_mut().start_send(item)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::get_mut(self).as_mut().poll_flush(cx)
    }

    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
        Pin::get_mut(self).as_mut().poll_close(cx)
    }
}

#[cfg(feature = "std")]
mod channel_impls;

#[cfg(feature = "alloc")]
mod if_alloc {
    use super::*;

    /// The error type for `Vec` and `VecDequeue` when used as `Sink`s.
    /// Values of this type can never be created.
    #[derive(Copy, Clone, Debug)]
    pub enum VecSinkError {}

    impl<T> Sink<T> for ::alloc::vec::Vec<T> {
        type SinkError = VecSinkError;

        fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }

        fn start_send(self: Pin<&mut Self>, item: T) -> Result<(), Self::SinkError> {
            // TODO: impl<T> Unpin for Vec<T> {}
            unsafe { Pin::get_unchecked_mut(self) }.push(item);
            Ok(())
        }

        fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }

        fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }
    }

    impl<T> Sink<T> for ::alloc::collections::VecDeque<T> {
        type SinkError = VecSinkError;

        fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }

        fn start_send(self: Pin<&mut Self>, item: T) -> Result<(), Self::SinkError> {
            // TODO: impl<T> Unpin for Vec<T> {}
            unsafe { Pin::get_unchecked_mut(self) }.push_back(item);
            Ok(())
        }

        fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }

        fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Poll::Ready(Ok(()))
        }
    }

    impl<S: ?Sized + Sink<Item> + Unpin, Item> Sink<Item> for ::alloc::boxed::Box<S> {
        type SinkError = S::SinkError;

        fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Pin::new(&mut **self).poll_ready(cx)
        }

        fn start_send(mut self: Pin<&mut Self>, item: Item) -> Result<(), Self::SinkError> {
            Pin::new(&mut **self).start_send(item)
        }

        fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Pin::new(&mut **self).poll_flush(cx)
        }

        fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::SinkError>> {
            Pin::new(&mut **self).poll_close(cx)
        }
    }
}

#[cfg(feature = "alloc")]
pub use self::if_alloc::*;
<|endoftext|>


<commit_before>use futures::{Async, Poll, Stream};
use lapin::Consumer as ConsumerInner;
use log::trace;

use crate::{confirmation::Watcher, message::Delivery, Error};

#[derive(Clone, Debug)]
pub struct Consumer(pub(crate) ConsumerInner);

impl Stream for Consumer {
    type Item = Delivery;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<Delivery>, Error> {
        trace!("consumer poll; polling transport");
        let mut inner = self.0.inner();
        trace!(
            "consumer poll; acquired inner lock, consumer_tag={}",
            inner.tag()
        );
        if !inner.has_task() {
            inner.set_task(Box::new(Watcher::default()));
        }
        if let Some(delivery) = inner.next_delivery() {
            match delivery {
                Ok(Some(delivery)) => {
                    trace!(
                        "delivery; consumer_tag={}, delivery_tag={:?}",
                        inner.tag(),
                        delivery.delivery_tag
                    );
                    Ok(Async::Ready(Some(delivery)))
                }
                Ok(None) => {
                    trace!("consumer canceled; consumer_tag={}", inner.tag());
                    Ok(Async::Ready(None))
                }
                Err(error) => Err(error),
            }
        } else {
            trace!("delivery; status=NotReady, consumer_tag={}", inner.tag());
            Ok(Async::NotReady)
        }
    }
}
<commit_msg>futures: fix waker for consumer too<commit_after>use futures::{Async, Poll, Stream};
use lapin::Consumer as ConsumerInner;
use log::trace;

use crate::{confirmation::Watcher, message::Delivery, Error};

#[derive(Clone, Debug)]
pub struct Consumer(pub(crate) ConsumerInner);

impl Stream for Consumer {
    type Item = Delivery;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<Delivery>, Error> {
        trace!("consumer poll; polling transport");
        let mut inner = self.0.inner();
        trace!(
            "consumer poll; acquired inner lock, consumer_tag={}",
            inner.tag()
        );
        inner.set_task(Box::new(Watcher::default()));
        if let Some(delivery) = inner.next_delivery() {
            match delivery {
                Ok(Some(delivery)) => {
                    trace!(
                        "delivery; consumer_tag={}, delivery_tag={:?}",
                        inner.tag(),
                        delivery.delivery_tag
                    );
                    Ok(Async::Ready(Some(delivery)))
                }
                Ok(None) => {
                    trace!("consumer canceled; consumer_tag={}", inner.tag());
                    Ok(Async::Ready(None))
                }
                Err(error) => Err(error),
            }
        } else {
            trace!("delivery; status=NotReady, consumer_tag={}", inner.tag());
            Ok(Async::NotReady)
        }
    }
}
<|endoftext|>


<commit_before>//! TODO Documentation

use std::{panic, ptr};
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;

use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{timespec, wlr_subsurface, wlr_surface, wlr_surface_get_main_surface,
                  wlr_surface_get_matrix, wlr_surface_has_buffer, wlr_surface_make_subsurface,
                  wlr_surface_send_enter, wlr_surface_send_frame_done, wlr_surface_send_leave};

use super::{Subsurface, SubsurfaceHandle, SubsurfaceManager, SurfaceState};
use Output;
use errors::{UpgradeHandleErr, UpgradeHandleResult};
use render::Texture;
use utils::c_to_rust_string;

/// The state stored in the wlr_surface user data.
struct InternalSurfaceState {
    /// Used to reconstruct a SurfaceHandle from just an *mut wlr_surface.
    handle: Weak<AtomicBool>,
    /// Weak reference to the manager for the list of subsurfaces.
    /// This is here so that we can reconstruct the Surface from a SurfaceHandle.
    subsurfaces_manager: Weak<Box<SubsurfaceManager>>
}

/// A Wayland object that represents the data that we display on the screen.
///
/// Most surfaces come from Wayland clients, though they can also be created
/// by the compositor directly.
#[derive(Debug)]
pub struct Surface {
    /// The structe that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `SurfaceHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `SurfaceHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The manager of the list of subsurfaces for this surface.
    ///
    /// When the subsurface destruction event fires the manager will deal with
    /// updating the list.
    ///
    /// When you have a reference to the Surface you can access its children
    /// through the getter for this list.
    subsurfaces_manager: Rc<Box<SubsurfaceManager>>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

/// See `Surface` for more information on how to use this structure.
#[derive(Clone, Debug)]
pub struct SurfaceHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// Weak reference to the manager of the list of subsurfaces for this surface.
    ///
    /// Used when reconstructing a `Surface` so that we can access
    /// the list of subsurfaces.
    subsurfaces_manager: Weak<Box<SubsurfaceManager>>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

impl Surface {
    pub(crate) unsafe fn new(surface: *mut wlr_surface) -> Self {
        if !(*surface).data.is_null() {
            panic!("Tried to construct a Surface from an already initialized wlr_surface");
        }
        let liveliness = Rc::new(AtomicBool::new(false));
        let handle = Rc::downgrade(&liveliness);
        let subsurfaces_manager = Rc::new(Surface::create_manager(surface));
        let weak_manager = Rc::downgrade(&subsurfaces_manager);
        (*surface).data = Box::into_raw(Box::new(InternalSurfaceState { handle,
                                                                        subsurfaces_manager:
                                                                            weak_manager }))
                          as _;
        let liveliness = Some(liveliness);
        Surface { liveliness,
                  subsurfaces_manager,
                  surface }
    }

    /// Create the subsurface manager and ensures theat the listeners are
    /// set up correctly to listen for subsurface creation and deletion.
    fn create_manager(surface: *mut wlr_surface) -> Box<SubsurfaceManager> {
        unsafe {
            let mut subsurfaces = vec![];
            wl_list_for_each!((*surface).subsurface_list, parent_link,
                              (subsurface: wlr_subsurface) => {
                                  subsurfaces.push(Subsurface::new(subsurface))
                              });
            let mut manager = SubsurfaceManager::new(subsurfaces);
            for sub_surface in &mut manager.subsurfaces() {
                wl_signal_add(&mut (*sub_surface.as_ptr()).events.destroy as *mut _ as _,
                              manager.subsurface_destroyed_listener() as _);
            }
            wl_signal_add(&mut (*surface).events.new_subsurface as *mut _ as _,
                          manager.subsurface_created_listener() as _);
            manager
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_surface {
        self.surface
    }

    /// Get the surface state.
    pub fn current_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            let state = (*self.surface).current;
            SurfaceState::new(state)
        }
    }

    /// Get the pending surface state.
    pub fn pending_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            let state = (*self.surface).current;
            SurfaceState::new(state)
        }
    }

    /// Get the subsurface.
    pub fn subsurface(&self) -> Subsurface {
        unimplemented!()
    }

    /// Gets a list of handles to the `Subsurface`s of this `Surface`.
    pub fn subsurfaces(&self) -> Vec<SubsurfaceHandle> {
        self.subsurfaces_manager.subsurfaces()
    }

    /// Get the texture of this surface.
    pub fn texture(&self) -> Texture {
        unsafe { Texture::from_ptr((*self.surface).texture) }
    }

    /// Get the lifetime bound role (if one exists) for this surface.
    pub fn role(&self) -> Option<String> {
        unsafe { c_to_rust_string((*self.surface).role) }
    }

    /// Gets a matrix you can pass into wlr_render_with_matrix to display this
    /// surface.
    ///
    /// `matrix` is the output matrix, `projection` is the wlr_output
    /// projection matrix, and `transform` is any additional transformations you want
    /// to perform on the surface (or None/the identity matrix if you don't).
    ///
    /// `transform` is used before the surface is scaled, so its geometry extends
    /// from 0 to 1 in both dimensions.
    pub fn get_matrix<'a, T>(&mut self,
                             matrix: &mut [f32; 16],
                             projection: &[f32; 16],
                             transform: T)
        where T: Into<Option<&'a [f32; 16]>>
    {
        let transform = transform.into()
                                 .map(|transform| transform as *const _)
                                 .unwrap_or_else(|| ptr::null());
        unsafe { wlr_surface_get_matrix(self.surface, matrix, projection, transform) }
    }

    /// Whether or not this surface currently has an attached buffer.
    ///
    /// A surface has an attached buffer when it commits with a non-null buffer in its pending
    /// state.
    ///
    /// A surface will not have a buffer if it has never committed one, has
    /// committed a null buffer, or something went wrong with uploading the buffer.
    pub fn has_buffer(&self) -> bool {
        unsafe { wlr_surface_has_buffer(self.surface) }
    }

    /// Find a subsurface within this surface at the surface-local coordinates.
    ///
    /// Returns the surface and coordinates in the topmost surface coordinate system
    /// or None if no subsurface is found at that location.
    #[allow(unused_variables)]
    pub fn subsurface_at(&mut self,
                         _sx: f32,
                         _sy: f32,
                         _sub_x: &mut f32,
                         _sub_y: &mut f32)
                         -> Option<SubsurfaceHandle> {
        unimplemented!()
    }

    /// Create the subsurface implementation for this surface.
    pub fn make_subsurface(&mut self, parent: &mut Surface, id: u32) {
        unsafe { wlr_surface_make_subsurface(self.surface, parent.as_ptr(), id) }
    }

    /// Get the top of the subsurface tree for this surface.
    pub fn get_main_surface(&self) -> Option<SurfaceHandle> {
        unsafe {
            let surface = wlr_surface_get_main_surface(self.surface);
            if surface.is_null() {
                None
            } else {
                Some(SurfaceHandle::from_ptr(surface))
            }
        }
    }

    pub fn send_enter(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_enter(self.surface, output.as_ptr()) }
    }

    pub fn send_leave(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_leave(self.surface, output.as_ptr()) }
    }

    /// Send the frame done event.
    pub fn send_frame_done(&mut self, duration: Duration) {
        unsafe {
            // FIXME
            // This is converting from a u64 -> i64
            // Something bad could happen!
            let when = timespec { tv_sec: duration.as_secs() as i64,
                                  tv_nsec: duration.subsec_nanos() as i64 };
            wlr_surface_send_frame_done(self.surface, &when);
        }
    }

    /// Get the matrix used to convert the internal byte buffer to use in the
    /// surface.
    pub fn buffer_to_surface_matrix(&self) -> [f32; 16] {
        unsafe { (*self.surface).buffer_to_surface_matrix }
    }

    /// Get the matrix used to convert the surface back to the internal byte
    /// buffer.
    pub fn surface_to_buffer_matrix(&self) -> [f32; 16] {
        unsafe { (*self.surface).surface_to_buffer_matrix }
    }

    /// Creates a weak reference to a `Surface`.
    ///
    /// # Panics
    /// If this `Surface` is a previously upgraded `SurfaceHandle`
    /// then this function will panic.
    pub fn weak_reference(&self) -> SurfaceHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade a previously upgraded OutputHandle");
        SurfaceHandle { handle: Rc::downgrade(arc),
                        surface: self.surface,
                        subsurfaces_manager: Rc::downgrade(&self.subsurfaces_manager) }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Surface")
            .store(val, Ordering::Release);
    }

    unsafe fn from_handle(handle: &SurfaceHandle) -> Self {
        let data = (*handle.surface).data as *mut InternalSurfaceState;
        let subsurfaces_manager = (*data).subsurfaces_manager
                                         .clone()
                                         .upgrade()
                                         .expect("Could not upgrade subsurfaces list");
        Surface { liveliness: None,
                  subsurfaces_manager,
                  surface: handle.surface }
    }
}

impl SurfaceHandle {
    /// Creates an SurfaceHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(surface: *mut wlr_surface) -> Self {
        let data = (*surface).data as *mut InternalSurfaceState;
        let handle = (*data).handle.clone();
        let subsurfaces_manager = (*data).subsurfaces_manager.clone();
        SurfaceHandle { handle,
                        surface,
                        subsurfaces_manager }
    }

    /// Upgrades the surface handle to a reference to the backing `Surface`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Surface`
    /// which may live forever..
    /// But no surface lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Surface> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(Surface::from_handle(self))
            })
    }

    /// Run a function on the referenced Surface, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the surface
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Surface does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Surface`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Surface) -> R
    {
        let mut surface = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut surface)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running surface callback, mutable lock \
                                                    was false for: {:?}",
                                                   surface);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }
}
<commit_msg>Clean up subsurface listeners when surface dies<commit_after>//! TODO Documentation

use std::{panic, ptr};
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{timespec, wlr_subsurface, wlr_surface, wlr_surface_get_main_surface,
                  wlr_surface_get_matrix, wlr_surface_has_buffer, wlr_surface_make_subsurface,
                  wlr_surface_send_enter, wlr_surface_send_frame_done, wlr_surface_send_leave};

use super::{Subsurface, SubsurfaceHandle, SubsurfaceManager, SurfaceState};
use Output;
use errors::{UpgradeHandleErr, UpgradeHandleResult};
use render::Texture;
use utils::c_to_rust_string;

/// The state stored in the wlr_surface user data.
struct InternalSurfaceState {
    /// Used to reconstruct a SurfaceHandle from just an *mut wlr_surface.
    handle: Weak<AtomicBool>,
    /// Weak reference to the manager for the list of subsurfaces.
    /// This is here so that we can reconstruct the Surface from a SurfaceHandle.
    subsurfaces_manager: Weak<Box<SubsurfaceManager>>
}

/// A Wayland object that represents the data that we display on the screen.
///
/// Most surfaces come from Wayland clients, though they can also be created
/// by the compositor directly.
#[derive(Debug)]
pub struct Surface {
    /// The structe that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `SurfaceHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `SurfaceHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The manager of the list of subsurfaces for this surface.
    ///
    /// When the subsurface destruction event fires the manager will deal with
    /// updating the list.
    ///
    /// When you have a reference to the Surface you can access its children
    /// through the getter for this list.
    subsurfaces_manager: Rc<Box<SubsurfaceManager>>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

/// See `Surface` for more information on how to use this structure.
#[derive(Clone, Debug)]
pub struct SurfaceHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// Weak reference to the manager of the list of subsurfaces for this surface.
    ///
    /// Used when reconstructing a `Surface` so that we can access
    /// the list of subsurfaces.
    subsurfaces_manager: Weak<Box<SubsurfaceManager>>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

impl Surface {
    pub(crate) unsafe fn new(surface: *mut wlr_surface) -> Self {
        if !(*surface).data.is_null() {
            panic!("Tried to construct a Surface from an already initialized wlr_surface");
        }
        let liveliness = Rc::new(AtomicBool::new(false));
        let handle = Rc::downgrade(&liveliness);
        let subsurfaces_manager = Rc::new(Surface::create_manager(surface));
        let weak_manager = Rc::downgrade(&subsurfaces_manager);
        (*surface).data = Box::into_raw(Box::new(InternalSurfaceState { handle,
                                                                        subsurfaces_manager:
                                                                            weak_manager }))
                          as _;
        let liveliness = Some(liveliness);
        Surface { liveliness,
                  subsurfaces_manager,
                  surface }
    }

    /// Create the subsurface manager and ensures theat the listeners are
    /// set up correctly to listen for subsurface creation and deletion.
    fn create_manager(surface: *mut wlr_surface) -> Box<SubsurfaceManager> {
        unsafe {
            let mut subsurfaces = vec![];
            wl_list_for_each!((*surface).subsurface_list, parent_link,
                              (subsurface: wlr_subsurface) => {
                                  subsurfaces.push(Subsurface::new(subsurface))
                              });
            let mut manager = SubsurfaceManager::new(subsurfaces);
            for sub_surface in &mut manager.subsurfaces() {
                wl_signal_add(&mut (*sub_surface.as_ptr()).events.destroy as *mut _ as _,
                              manager.subsurface_destroyed_listener() as _);
            }
            wl_signal_add(&mut (*surface).events.new_subsurface as *mut _ as _,
                          manager.subsurface_created_listener() as _);
            manager
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_surface {
        self.surface
    }

    /// Get the surface state.
    pub fn current_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            let state = (*self.surface).current;
            SurfaceState::new(state)
        }
    }

    /// Get the pending surface state.
    pub fn pending_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            let state = (*self.surface).current;
            SurfaceState::new(state)
        }
    }

    /// Get the subsurface.
    pub fn subsurface(&self) -> Subsurface {
        unimplemented!()
    }

    /// Gets a list of handles to the `Subsurface`s of this `Surface`.
    pub fn subsurfaces(&self) -> Vec<SubsurfaceHandle> {
        self.subsurfaces_manager.subsurfaces()
    }

    /// Get the texture of this surface.
    pub fn texture(&self) -> Texture {
        unsafe { Texture::from_ptr((*self.surface).texture) }
    }

    /// Get the lifetime bound role (if one exists) for this surface.
    pub fn role(&self) -> Option<String> {
        unsafe { c_to_rust_string((*self.surface).role) }
    }

    /// Gets a matrix you can pass into wlr_render_with_matrix to display this
    /// surface.
    ///
    /// `matrix` is the output matrix, `projection` is the wlr_output
    /// projection matrix, and `transform` is any additional transformations you want
    /// to perform on the surface (or None/the identity matrix if you don't).
    ///
    /// `transform` is used before the surface is scaled, so its geometry extends
    /// from 0 to 1 in both dimensions.
    pub fn get_matrix<'a, T>(&mut self,
                             matrix: &mut [f32; 16],
                             projection: &[f32; 16],
                             transform: T)
        where T: Into<Option<&'a [f32; 16]>>
    {
        let transform = transform.into()
                                 .map(|transform| transform as *const _)
                                 .unwrap_or_else(|| ptr::null());
        unsafe { wlr_surface_get_matrix(self.surface, matrix, projection, transform) }
    }

    /// Whether or not this surface currently has an attached buffer.
    ///
    /// A surface has an attached buffer when it commits with a non-null buffer in its pending
    /// state.
    ///
    /// A surface will not have a buffer if it has never committed one, has
    /// committed a null buffer, or something went wrong with uploading the buffer.
    pub fn has_buffer(&self) -> bool {
        unsafe { wlr_surface_has_buffer(self.surface) }
    }

    /// Find a subsurface within this surface at the surface-local coordinates.
    ///
    /// Returns the surface and coordinates in the topmost surface coordinate system
    /// or None if no subsurface is found at that location.
    #[allow(unused_variables)]
    pub fn subsurface_at(&mut self,
                         _sx: f32,
                         _sy: f32,
                         _sub_x: &mut f32,
                         _sub_y: &mut f32)
                         -> Option<SubsurfaceHandle> {
        unimplemented!()
    }

    /// Create the subsurface implementation for this surface.
    pub fn make_subsurface(&mut self, parent: &mut Surface, id: u32) {
        unsafe { wlr_surface_make_subsurface(self.surface, parent.as_ptr(), id) }
    }

    /// Get the top of the subsurface tree for this surface.
    pub fn get_main_surface(&self) -> Option<SurfaceHandle> {
        unsafe {
            let surface = wlr_surface_get_main_surface(self.surface);
            if surface.is_null() {
                None
            } else {
                Some(SurfaceHandle::from_ptr(surface))
            }
        }
    }

    pub fn send_enter(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_enter(self.surface, output.as_ptr()) }
    }

    pub fn send_leave(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_leave(self.surface, output.as_ptr()) }
    }

    /// Send the frame done event.
    pub fn send_frame_done(&mut self, duration: Duration) {
        unsafe {
            // FIXME
            // This is converting from a u64 -> i64
            // Something bad could happen!
            let when = timespec { tv_sec: duration.as_secs() as i64,
                                  tv_nsec: duration.subsec_nanos() as i64 };
            wlr_surface_send_frame_done(self.surface, &when);
        }
    }

    /// Get the matrix used to convert the internal byte buffer to use in the
    /// surface.
    pub fn buffer_to_surface_matrix(&self) -> [f32; 16] {
        unsafe { (*self.surface).buffer_to_surface_matrix }
    }

    /// Get the matrix used to convert the surface back to the internal byte
    /// buffer.
    pub fn surface_to_buffer_matrix(&self) -> [f32; 16] {
        unsafe { (*self.surface).surface_to_buffer_matrix }
    }

    /// Creates a weak reference to a `Surface`.
    ///
    /// # Panics
    /// If this `Surface` is a previously upgraded `SurfaceHandle`
    /// then this function will panic.
    pub fn weak_reference(&self) -> SurfaceHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade a previously upgraded OutputHandle");
        SurfaceHandle { handle: Rc::downgrade(arc),
                        surface: self.surface,
                        subsurfaces_manager: Rc::downgrade(&self.subsurfaces_manager) }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Surface")
            .store(val, Ordering::Release);
    }

    unsafe fn from_handle(handle: &SurfaceHandle) -> Self {
        let data = (*handle.surface).data as *mut InternalSurfaceState;
        let subsurfaces_manager = (*data).subsurfaces_manager
                                         .clone()
                                         .upgrade()
                                         .expect("Could not upgrade subsurfaces list");
        Surface { liveliness: None,
                  subsurfaces_manager,
                  surface: handle.surface }
    }
}

impl SurfaceHandle {
    /// Creates an SurfaceHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(surface: *mut wlr_surface) -> Self {
        let data = (*surface).data as *mut InternalSurfaceState;
        let handle = (*data).handle.clone();
        let subsurfaces_manager = (*data).subsurfaces_manager.clone();
        SurfaceHandle { handle,
                        surface,
                        subsurfaces_manager }
    }

    /// Upgrades the surface handle to a reference to the backing `Surface`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Surface`
    /// which may live forever..
    /// But no surface lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Surface> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(Surface::from_handle(self))
            })
    }

    /// Run a function on the referenced Surface, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the surface
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Surface does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Surface`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Surface) -> R
    {
        let mut surface = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut surface)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running surface callback, mutable lock \
                                                    was false for: {:?}",
                                                   surface);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }
}

impl Drop for Surface {
    fn drop(&mut self) {
        unsafe {
            let manager = Rc::into_raw(self.subsurfaces_manager.clone()) as *mut SubsurfaceManager;
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*(*manager).subsurface_created_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*(*manager).subsurface_destroyed_listener()).link as *mut _ as _);
        }
    }
}
<|endoftext|>


<commit_before>extern crate zip;
extern crate walkdir;

use std::io::prelude::*;
use std::io::{Write, Seek};
use std::iter::Iterator;
use zip::write::FileOptions;
use zip::result::ZipError;

use walkdir::{WalkDir, DirEntry};
use std::path::Path;
use std::fs::File;

fn main() {
    std::process::exit(real_main());
}

const METHOD_STORED : Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Stored);

#[cfg(feature = "deflate")]
const METHOD_DEFLATED : Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Deflated);
#[cfg(not(feature = "deflate"))]
const METHOD_DEFLATED : Option<zip::CompressionMethod> = None;

#[cfg(feature = "bzip2")]
const METHOD_BZIP2 : Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Bzip2);
#[cfg(not(feature = "bzip2"))]
const METHOD_BZIP2 : Option<zip::CompressionMethod> = None;

fn real_main() -> i32 {
    let args: Vec<_> = std::env::args().collect();
    if args.len() < 3 {
        println!("Usage: {} <source_directory> <destination_zipfile>",
                 args[0]);
        return 1;
    }

    let src_dir = &*args[1];
    let dst_file = &*args[2];
    for &method in [METHOD_STORED, METHOD_DEFLATED, METHOD_BZIP2].iter() {
        if method.is_none() { continue }
        match doit(src_dir, dst_file, method.unwrap()) {
            Ok(_) => println!("done: {} written to {}", src_dir, dst_file),
            Err(e) => println!("Error: {:?}", e),
        }
    }

    return 0;
}

fn zip_dir<T>(it: &mut Iterator<Item=DirEntry>, prefix: &str, writer: T, method: zip::CompressionMethod)
              -> zip::result::ZipResult<()>
    where T: Write+Seek
{
    let mut zip = zip::ZipWriter::new(writer);
    let options = FileOptions::default()
        .compression_method(method)
        .unix_permissions(0o755);

    let mut buffer = Vec::new();
    for entry in it {
        let path = entry.path();
        let name = path.strip_prefix(Path::new(prefix))
            .unwrap()
            .to_str()
            .unwrap();

        if path.is_file() {
            println!("adding {:?} as {:?} ...", path, name);
            zip.start_file(name, options)?;
            let mut f = File::open(path)?;

            f.read_to_end(&mut buffer)?;
            zip.write_all(&*buffer)?;
            buffer.clear();
        }
    }
    zip.finish()?;
    Result::Ok(())
}

fn doit(src_dir: &str, dst_file: &str, method: zip::CompressionMethod) -> zip::result::ZipResult<()> {
    if !Path::new(src_dir).is_dir() {
        return Err(ZipError::FileNotFound);
    }

    let path = Path::new(dst_file);
    let file = File::create(&path).unwrap();

    let walkdir = WalkDir::new(src_dir.to_string());
    let it = walkdir.into_iter();

    zip_dir(&mut it.filter_map(|e| e.ok()), src_dir, file, method)?;

    Ok(())
}<commit_msg>Use add_directory in write_dir example<commit_after>extern crate zip;
extern crate walkdir;

use std::io::prelude::*;
use std::io::{Write, Seek};
use std::iter::Iterator;
use zip::write::FileOptions;
use zip::result::ZipError;

use walkdir::{WalkDir, DirEntry};
use std::path::Path;
use std::fs::File;

fn main() {
    std::process::exit(real_main());
}

const METHOD_STORED : Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Stored);

#[cfg(feature = "deflate")]
const METHOD_DEFLATED : Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Deflated);
#[cfg(not(feature = "deflate"))]
const METHOD_DEFLATED : Option<zip::CompressionMethod> = None;

#[cfg(feature = "bzip2")]
const METHOD_BZIP2 : Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Bzip2);
#[cfg(not(feature = "bzip2"))]
const METHOD_BZIP2 : Option<zip::CompressionMethod> = None;

fn real_main() -> i32 {
    let args: Vec<_> = std::env::args().collect();
    if args.len() < 3 {
        println!("Usage: {} <source_directory> <destination_zipfile>",
                 args[0]);
        return 1;
    }

    let src_dir = &*args[1];
    let dst_file = &*args[2];
    for &method in [METHOD_STORED, METHOD_DEFLATED, METHOD_BZIP2].iter() {
        if method.is_none() { continue }
        match doit(src_dir, dst_file, method.unwrap()) {
            Ok(_) => println!("done: {} written to {}", src_dir, dst_file),
            Err(e) => println!("Error: {:?}", e),
        }
    }

    return 0;
}

fn zip_dir<T>(it: &mut Iterator<Item=DirEntry>, prefix: &str, writer: T, method: zip::CompressionMethod)
              -> zip::result::ZipResult<()>
    where T: Write+Seek
{
    let mut zip = zip::ZipWriter::new(writer);
    let options = FileOptions::default()
        .compression_method(method)
        .unix_permissions(0o755);

    let mut buffer = Vec::new();
    for entry in it {
        let path = entry.path();
        let name = path.strip_prefix(Path::new(prefix))
            .unwrap()
            .to_str()
            .unwrap();

        // Write file or directory explicitly
        // Some unzip tools unzip files with directory paths correctly, some do not!
        if path.is_file() {
            println!("adding file {:?} as {:?} ...", path, name);
            zip.start_file(name, options)?;
            let mut f = File::open(path)?;

            f.read_to_end(&mut buffer)?;
            zip.write_all(&*buffer)?;
            buffer.clear();
        } else if !name.is_empty() {
            // Only if not root! Avoids path spec / warning
            // and mapname conversion failed error on unzip
            println!("adding dir {:?} as {:?} ...", path, name);
            zip.add_directory(name, options)?;
        }
    }
    zip.finish()?;
    Result::Ok(())
}

fn doit(src_dir: &str, dst_file: &str, method: zip::CompressionMethod) -> zip::result::ZipResult<()> {
    if !Path::new(src_dir).is_dir() {
        return Err(ZipError::FileNotFound);
    }

    let path = Path::new(dst_file);
    let file = File::create(&path).unwrap();

    let walkdir = WalkDir::new(src_dir.to_string());
    let it = walkdir.into_iter();

    zip_dir(&mut it.filter_map(|e| e.ok()), src_dir, file, method)?;

    Ok(())
}
<|endoftext|>


<commit_before>//! Value splitting.
//!
//! Some value types are too large to fit in registers, so they need to be split into smaller parts
//! that the ISA can operate on. There's two dimensions of splitting, represented by two
//! complementary instruction pairs:
//!
//! - `isplit` and `iconcat` for splitting integer types into smaller integers.
//! - `vsplit` and `vconcat` for splitting vector types into smaller vector types with the same
//!   lane types.
//!
//! There is no floating point splitting. If an ISA doesn't support `f64` values, they probably
//! have to be bit-cast to `i64` and possibly split into two `i32` values that fit in registers.
//! This breakdown is handled by the ABI lowering.
//!
//! When legalizing a single instruction, it is wrapped in splits and concatenations:
//!
//!```cton
//!     v1 = bxor.i64 v2, v3
//! ```
//!
//! becomes:
//!
//!```cton
//!     v20, v21 = isplit v2
//!     v30, v31 = isplit v3
//!     v10 = bxor.i32 v20, v30
//!     v11 = bxor.i32 v21, v31
//!     v1 = iconcat v10, v11
//! ```
//!
//! This local expansion approach still leaves the original `i64` values in the code as operands on
//! the `split` and `concat` instructions. It also creates a lot of redundant code to clean up as
//! values are constantly split and concatenated.
//!
//! # Optimized splitting
//!
//! We can eliminate a lot of the splitting code quite easily. Whenever we need to split a value,
//! first check if the value is defined by the corresponding concatenation. If so, then just use
//! the two concatenation inputs directly:
//!
//! ```cton
//!     v4 = iadd_imm.i64 v1, 1
//! ```
//!
//! becomes, using the expanded code from above:
//!
//! ```cton
//!     v40, v5 = iadd_imm_cout.i32 v10, 1
//!     v6 = bint.i32
//!     v41 = iadd.i32 v11, v6
//!     v4 = iconcat v40, v41
//! ```
//!
//! This means that the `iconcat` instructions defining `v1` and `v4` end up with no uses, so they
//! can be trivially deleted by a dead code elimination pass.
//!
//! # EBB arguments
//!
//! If all instructions that produce an `i64` value are legalized as above, we will eventually end
//! up with no `i64` values anywhere, except for EBB arguments. We can work around this by
//! iteratively splitting EBB arguments too. That should leave us with no illegal value types
//! anywhere.
//!
//! It is possible to have circular dependencies of EBB arguments that are never used by any real
//! instructions. These loops will remain in the program.

use flowgraph::ControlFlowGraph;
use ir::{DataFlowGraph, Ebb, Inst, Cursor, Value, Type, Opcode, ValueDef, InstructionData,
         InstBuilder};
use std::iter;

/// Split `value` into two values using the `isplit` semantics. Do this by reusing existing values
/// if possible.
pub fn isplit(dfg: &mut DataFlowGraph,
              cfg: &ControlFlowGraph,
              pos: &mut Cursor,
              value: Value)
              -> (Value, Value) {
    split_any(dfg, cfg, pos, value, Opcode::Iconcat)
}

/// Split `value` into halves using the `vsplit` semantics. Do this by reusing existing values if
/// possible.
pub fn vsplit(dfg: &mut DataFlowGraph,
              cfg: &ControlFlowGraph,
              pos: &mut Cursor,
              value: Value)
              -> (Value, Value) {
    split_any(dfg, cfg, pos, value, Opcode::Vconcat)
}

/// After splitting an EBB argument, we need to go back and fix up all of the predecessor
/// instructions. This is potentially a recursive operation, but we don't implement it recursively
/// since that could use up too muck stack.
///
/// Instead, the repairs are deferred and placed on a work list in stack form.
struct Repair {
    concat: Opcode,
    // The argument type after splitting.
    split_type: Type,
    // The destination EBB whose arguments have been split.
    ebb: Ebb,
    // Number of the original EBB argument which has been replaced by the low part.
    num: usize,
    // Number of the new EBB argument which represents the high part after the split.
    hi_num: usize,
}

/// Generic version of `isplit` and `vsplit` controlled by the `concat` opcode.
fn split_any(dfg: &mut DataFlowGraph,
             cfg: &ControlFlowGraph,
             pos: &mut Cursor,
             value: Value,
             concat: Opcode)
             -> (Value, Value) {
    let saved_pos = pos.position();
    let mut repairs = Vec::new();
    let result = split_value(dfg, pos, value, concat, &mut repairs);

    // We have split the value requested, and now we may need to fix some EBB predecessors.
    while let Some(repair) = repairs.pop() {
        for &(_, inst) in cfg.get_predecessors(repair.ebb) {
            let branch_opc = dfg[inst].opcode();
            assert!(branch_opc.is_branch(),
                    "Predecessor not a branch: {}",
                    dfg.display_inst(inst));
            let fixed_args = branch_opc.constraints().fixed_value_arguments();
            let mut args = dfg[inst]
                .take_value_list()
                .expect("Branches must have value lists.");
            let num_args = args.len(&dfg.value_lists);
            // Get the old value passed to the EBB argument we're repairing.
            let old_arg = args.get(fixed_args + repair.num, &dfg.value_lists)
                .expect("Too few branch arguments");

            // It's possible that the CFG's predecessor list has duplicates. Detect them here.
            if dfg.value_type(old_arg) == repair.split_type {
                dfg[inst].put_value_list(args);
                continue;
            }

            // Split the old argument, possibly causing more repairs to be scheduled.
            pos.goto_inst(inst);
            let (lo, hi) = split_value(dfg, pos, old_arg, repair.concat, &mut repairs);

            // The `lo` part replaces the original argument.
            *args.get_mut(fixed_args + repair.num, &mut dfg.value_lists)
                 .unwrap() = lo;

            // The `hi` part goes at the end. Since multiple repairs may have been scheduled to the
            // same EBB, there could be multiple arguments missing.
            if num_args > fixed_args + repair.hi_num {
                *args.get_mut(fixed_args + repair.hi_num, &mut dfg.value_lists)
                     .unwrap() = hi;
            } else {
                // We need to append one or more arguments. If we're adding more than one argument,
                // there must be pending repairs on the stack that will fill in the correct values
                // instead of `hi`.
                args.extend(iter::repeat(hi).take(1 + fixed_args + repair.hi_num - num_args),
                            &mut dfg.value_lists);
            }

            // Put the value list back after manipulating it.
            dfg[inst].put_value_list(args);
        }
    }

    pos.set_position(saved_pos);
    result
}

/// Split a single value using the integer or vector semantics given by the `concat` opcode.
///
/// If the value is defined by a `concat` instruction, just reuse the operand values of that
/// instruction.
///
/// Return the two new values representing the parts of `value`.
fn split_value(dfg: &mut DataFlowGraph,
               pos: &mut Cursor,
               value: Value,
               concat: Opcode,
               repairs: &mut Vec<Repair>)
               -> (Value, Value) {
    let value = dfg.resolve_copies(value);
    let mut reuse = None;

    match dfg.value_def(value) {
        ValueDef::Res(inst, num) => {
            // This is an instruction result. See if the value was created by a `concat`
            // instruction.
            if let InstructionData::Binary { opcode, args, .. } = dfg[inst] {
                assert_eq!(num, 0);
                if opcode == concat {
                    reuse = Some((args[0], args[1]));
                }
            }
        }
        ValueDef::Arg(ebb, num) => {
            // This is an EBB argument. We can split the argument value unless this is the entry
            // block.
            if pos.layout.entry_block() != Some(ebb) {
                // We are going to replace the argument at `num` with two new arguments.
                // Determine the new value types.
                let ty = dfg.value_type(value);
                let split_type = match concat {
                    Opcode::Iconcat => ty.half_width().expect("Invalid type for isplit"),
                    Opcode::Vconcat => ty.half_vector().expect("Invalid type for vsplit"),
                    _ => panic!("Unhandled concat opcode: {}", concat),
                };

                // Since the `repairs` stack potentially contains other argument numbers for `ebb`,
                // avoid shifting and renumbering EBB arguments. It could invalidate other
                // `repairs` entries.
                //
                // Replace the original `value` with the low part, and append the high part at the
                // end of the argument list.
                let lo = dfg.replace_ebb_arg(value, split_type);
                let hi_num = dfg.num_ebb_args(ebb);
                let hi = dfg.append_ebb_arg(ebb, split_type);
                reuse = Some((lo, hi));

                // Now the original value is dangling. Insert a concatenation instruction that can
                // compute it from the two new arguments. This also serves as a record of what we
                // did so a future call to this function doesn't have to redo the work.
                //
                // Note that it is safe to move `pos` here since `reuse` was set above, so we don't
                // need to insert a split instruction before returning.
                pos.goto_top(ebb);
                pos.next_inst();
                let concat_inst = dfg.ins(pos).Binary(concat, split_type, lo, hi).0;
                let concat_val = dfg.first_result(concat_inst);
                dfg.change_to_alias(value, concat_val);

                // Finally, splitting the EBB argument is not enough. We also have to repair all
                // of the predecessor instructions that branch here.
                add_repair(concat, split_type, ebb, num, hi_num, repairs);
            }
        }
    }

    // Did the code above succeed in finding values we can reuse?
    if let Some(pair) = reuse {
        pair
    } else {
        // No, we'll just have to insert the requested split instruction at `pos`. Note that `pos`
        // has not been moved by the EBB argument code above when `reuse` is `None`.
        match concat {
            Opcode::Iconcat => dfg.ins(pos).isplit(value),
            Opcode::Vconcat => dfg.ins(pos).vsplit(value),
            _ => panic!("Unhandled concat opcode: {}", concat),
        }
    }
}

// Add a repair entry to the work list.
fn add_repair(concat: Opcode,
              split_type: Type,
              ebb: Ebb,
              num: usize,
              hi_num: usize,
              repairs: &mut Vec<Repair>) {
    repairs.push(Repair {
                     concat: concat,
                     split_type: split_type,
                     ebb: ebb,
                     num: num,
                     hi_num: hi_num,
                 });
}

/// Strip concat-split chains. Return a simpler way of computing the same value.
///
/// Given this input:
///
/// ```cton
///     v10 = iconcat v1, v2
///     v11, v12 = isplit v10
/// ```
///
/// This function resolves `v11` to `v1` and `v12` to `v2`.
fn resolve_splits(dfg: &DataFlowGraph, value: Value) -> Value {
    let value = dfg.resolve_copies(value);

    // Deconstruct a split instruction.
    let split_res;
    let concat_opc;
    let split_arg;
    if let ValueDef::Res(inst, num) = dfg.value_def(value) {
        split_res = num;
        concat_opc = match dfg[inst].opcode() {
            Opcode::Isplit => Opcode::Iconcat,
            Opcode::Vsplit => Opcode::Vconcat,
            _ => return value,
        };
        split_arg = dfg.inst_args(inst)[0];
    } else {
        return value;
    }

    // See if split_arg is defined by a concatenation instruction.
    if let ValueDef::Res(inst, _) = dfg.value_def(split_arg) {
        if dfg[inst].opcode() == concat_opc {
            return dfg.inst_args(inst)[split_res];
        }
    }

    value
}

/// Simplify the arguments to a branch *after* the instructions leading up to the branch have been
/// legalized.
///
/// The branch argument repairs performed by `split_any()` above may be performed on branches that
/// have not yet been legalized. The repaired arguments can be defined by actual split
/// instructions in that case.
///
/// After legalizing the instructions computing the value that was split, it is likely that we can
/// avoid depending on the split instruction. Its input probably comes from a concatenation.
pub fn simplify_branch_arguments(dfg: &mut DataFlowGraph, branch: Inst) {
    let mut new_args = Vec::new();

    for &arg in dfg.inst_args(branch) {
        let new_arg = resolve_splits(dfg, arg);
        new_args.push(new_arg);
    }

    dfg.inst_args_mut(branch).copy_from_slice(&new_args);
}
<commit_msg>Avoid creating value aliases in legalizer/split.rs.<commit_after>//! Value splitting.
//!
//! Some value types are too large to fit in registers, so they need to be split into smaller parts
//! that the ISA can operate on. There's two dimensions of splitting, represented by two
//! complementary instruction pairs:
//!
//! - `isplit` and `iconcat` for splitting integer types into smaller integers.
//! - `vsplit` and `vconcat` for splitting vector types into smaller vector types with the same
//!   lane types.
//!
//! There is no floating point splitting. If an ISA doesn't support `f64` values, they probably
//! have to be bit-cast to `i64` and possibly split into two `i32` values that fit in registers.
//! This breakdown is handled by the ABI lowering.
//!
//! When legalizing a single instruction, it is wrapped in splits and concatenations:
//!
//!```cton
//!     v1 = bxor.i64 v2, v3
//! ```
//!
//! becomes:
//!
//!```cton
//!     v20, v21 = isplit v2
//!     v30, v31 = isplit v3
//!     v10 = bxor.i32 v20, v30
//!     v11 = bxor.i32 v21, v31
//!     v1 = iconcat v10, v11
//! ```
//!
//! This local expansion approach still leaves the original `i64` values in the code as operands on
//! the `split` and `concat` instructions. It also creates a lot of redundant code to clean up as
//! values are constantly split and concatenated.
//!
//! # Optimized splitting
//!
//! We can eliminate a lot of the splitting code quite easily. Whenever we need to split a value,
//! first check if the value is defined by the corresponding concatenation. If so, then just use
//! the two concatenation inputs directly:
//!
//! ```cton
//!     v4 = iadd_imm.i64 v1, 1
//! ```
//!
//! becomes, using the expanded code from above:
//!
//! ```cton
//!     v40, v5 = iadd_imm_cout.i32 v10, 1
//!     v6 = bint.i32
//!     v41 = iadd.i32 v11, v6
//!     v4 = iconcat v40, v41
//! ```
//!
//! This means that the `iconcat` instructions defining `v1` and `v4` end up with no uses, so they
//! can be trivially deleted by a dead code elimination pass.
//!
//! # EBB arguments
//!
//! If all instructions that produce an `i64` value are legalized as above, we will eventually end
//! up with no `i64` values anywhere, except for EBB arguments. We can work around this by
//! iteratively splitting EBB arguments too. That should leave us with no illegal value types
//! anywhere.
//!
//! It is possible to have circular dependencies of EBB arguments that are never used by any real
//! instructions. These loops will remain in the program.

use flowgraph::ControlFlowGraph;
use ir::{DataFlowGraph, Ebb, Inst, Cursor, Value, Type, Opcode, ValueDef, InstructionData,
         InstBuilder};
use std::iter;

/// Split `value` into two values using the `isplit` semantics. Do this by reusing existing values
/// if possible.
pub fn isplit(dfg: &mut DataFlowGraph,
              cfg: &ControlFlowGraph,
              pos: &mut Cursor,
              value: Value)
              -> (Value, Value) {
    split_any(dfg, cfg, pos, value, Opcode::Iconcat)
}

/// Split `value` into halves using the `vsplit` semantics. Do this by reusing existing values if
/// possible.
pub fn vsplit(dfg: &mut DataFlowGraph,
              cfg: &ControlFlowGraph,
              pos: &mut Cursor,
              value: Value)
              -> (Value, Value) {
    split_any(dfg, cfg, pos, value, Opcode::Vconcat)
}

/// After splitting an EBB argument, we need to go back and fix up all of the predecessor
/// instructions. This is potentially a recursive operation, but we don't implement it recursively
/// since that could use up too muck stack.
///
/// Instead, the repairs are deferred and placed on a work list in stack form.
struct Repair {
    concat: Opcode,
    // The argument type after splitting.
    split_type: Type,
    // The destination EBB whose arguments have been split.
    ebb: Ebb,
    // Number of the original EBB argument which has been replaced by the low part.
    num: usize,
    // Number of the new EBB argument which represents the high part after the split.
    hi_num: usize,
}

/// Generic version of `isplit` and `vsplit` controlled by the `concat` opcode.
fn split_any(dfg: &mut DataFlowGraph,
             cfg: &ControlFlowGraph,
             pos: &mut Cursor,
             value: Value,
             concat: Opcode)
             -> (Value, Value) {
    let saved_pos = pos.position();
    let mut repairs = Vec::new();
    let result = split_value(dfg, pos, value, concat, &mut repairs);

    // We have split the value requested, and now we may need to fix some EBB predecessors.
    while let Some(repair) = repairs.pop() {
        for &(_, inst) in cfg.get_predecessors(repair.ebb) {
            let branch_opc = dfg[inst].opcode();
            assert!(branch_opc.is_branch(),
                    "Predecessor not a branch: {}",
                    dfg.display_inst(inst));
            let fixed_args = branch_opc.constraints().fixed_value_arguments();
            let mut args = dfg[inst]
                .take_value_list()
                .expect("Branches must have value lists.");
            let num_args = args.len(&dfg.value_lists);
            // Get the old value passed to the EBB argument we're repairing.
            let old_arg = args.get(fixed_args + repair.num, &dfg.value_lists)
                .expect("Too few branch arguments");

            // It's possible that the CFG's predecessor list has duplicates. Detect them here.
            if dfg.value_type(old_arg) == repair.split_type {
                dfg[inst].put_value_list(args);
                continue;
            }

            // Split the old argument, possibly causing more repairs to be scheduled.
            pos.goto_inst(inst);
            let (lo, hi) = split_value(dfg, pos, old_arg, repair.concat, &mut repairs);

            // The `lo` part replaces the original argument.
            *args.get_mut(fixed_args + repair.num, &mut dfg.value_lists)
                 .unwrap() = lo;

            // The `hi` part goes at the end. Since multiple repairs may have been scheduled to the
            // same EBB, there could be multiple arguments missing.
            if num_args > fixed_args + repair.hi_num {
                *args.get_mut(fixed_args + repair.hi_num, &mut dfg.value_lists)
                     .unwrap() = hi;
            } else {
                // We need to append one or more arguments. If we're adding more than one argument,
                // there must be pending repairs on the stack that will fill in the correct values
                // instead of `hi`.
                args.extend(iter::repeat(hi).take(1 + fixed_args + repair.hi_num - num_args),
                            &mut dfg.value_lists);
            }

            // Put the value list back after manipulating it.
            dfg[inst].put_value_list(args);
        }
    }

    pos.set_position(saved_pos);
    result
}

/// Split a single value using the integer or vector semantics given by the `concat` opcode.
///
/// If the value is defined by a `concat` instruction, just reuse the operand values of that
/// instruction.
///
/// Return the two new values representing the parts of `value`.
fn split_value(dfg: &mut DataFlowGraph,
               pos: &mut Cursor,
               value: Value,
               concat: Opcode,
               repairs: &mut Vec<Repair>)
               -> (Value, Value) {
    let value = dfg.resolve_copies(value);
    let mut reuse = None;

    match dfg.value_def(value) {
        ValueDef::Res(inst, num) => {
            // This is an instruction result. See if the value was created by a `concat`
            // instruction.
            if let InstructionData::Binary { opcode, args, .. } = dfg[inst] {
                assert_eq!(num, 0);
                if opcode == concat {
                    reuse = Some((args[0], args[1]));
                }
            }
        }
        ValueDef::Arg(ebb, num) => {
            // This is an EBB argument. We can split the argument value unless this is the entry
            // block.
            if pos.layout.entry_block() != Some(ebb) {
                // We are going to replace the argument at `num` with two new arguments.
                // Determine the new value types.
                let ty = dfg.value_type(value);
                let split_type = match concat {
                    Opcode::Iconcat => ty.half_width().expect("Invalid type for isplit"),
                    Opcode::Vconcat => ty.half_vector().expect("Invalid type for vsplit"),
                    _ => panic!("Unhandled concat opcode: {}", concat),
                };

                // Since the `repairs` stack potentially contains other argument numbers for `ebb`,
                // avoid shifting and renumbering EBB arguments. It could invalidate other
                // `repairs` entries.
                //
                // Replace the original `value` with the low part, and append the high part at the
                // end of the argument list.
                let lo = dfg.replace_ebb_arg(value, split_type);
                let hi_num = dfg.num_ebb_args(ebb);
                let hi = dfg.append_ebb_arg(ebb, split_type);
                reuse = Some((lo, hi));

                // Now the original value is dangling. Insert a concatenation instruction that can
                // compute it from the two new arguments. This also serves as a record of what we
                // did so a future call to this function doesn't have to redo the work.
                //
                // Note that it is safe to move `pos` here since `reuse` was set above, so we don't
                // need to insert a split instruction before returning.
                pos.goto_top(ebb);
                pos.next_inst();
                dfg.ins(pos)
                    .with_result(value)
                    .Binary(concat, split_type, lo, hi);

                // Finally, splitting the EBB argument is not enough. We also have to repair all
                // of the predecessor instructions that branch here.
                add_repair(concat, split_type, ebb, num, hi_num, repairs);
            }
        }
    }

    // Did the code above succeed in finding values we can reuse?
    if let Some(pair) = reuse {
        pair
    } else {
        // No, we'll just have to insert the requested split instruction at `pos`. Note that `pos`
        // has not been moved by the EBB argument code above when `reuse` is `None`.
        match concat {
            Opcode::Iconcat => dfg.ins(pos).isplit(value),
            Opcode::Vconcat => dfg.ins(pos).vsplit(value),
            _ => panic!("Unhandled concat opcode: {}", concat),
        }
    }
}

// Add a repair entry to the work list.
fn add_repair(concat: Opcode,
              split_type: Type,
              ebb: Ebb,
              num: usize,
              hi_num: usize,
              repairs: &mut Vec<Repair>) {
    repairs.push(Repair {
                     concat: concat,
                     split_type: split_type,
                     ebb: ebb,
                     num: num,
                     hi_num: hi_num,
                 });
}

/// Strip concat-split chains. Return a simpler way of computing the same value.
///
/// Given this input:
///
/// ```cton
///     v10 = iconcat v1, v2
///     v11, v12 = isplit v10
/// ```
///
/// This function resolves `v11` to `v1` and `v12` to `v2`.
fn resolve_splits(dfg: &DataFlowGraph, value: Value) -> Value {
    let value = dfg.resolve_copies(value);

    // Deconstruct a split instruction.
    let split_res;
    let concat_opc;
    let split_arg;
    if let ValueDef::Res(inst, num) = dfg.value_def(value) {
        split_res = num;
        concat_opc = match dfg[inst].opcode() {
            Opcode::Isplit => Opcode::Iconcat,
            Opcode::Vsplit => Opcode::Vconcat,
            _ => return value,
        };
        split_arg = dfg.inst_args(inst)[0];
    } else {
        return value;
    }

    // See if split_arg is defined by a concatenation instruction.
    if let ValueDef::Res(inst, _) = dfg.value_def(split_arg) {
        if dfg[inst].opcode() == concat_opc {
            return dfg.inst_args(inst)[split_res];
        }
    }

    value
}

/// Simplify the arguments to a branch *after* the instructions leading up to the branch have been
/// legalized.
///
/// The branch argument repairs performed by `split_any()` above may be performed on branches that
/// have not yet been legalized. The repaired arguments can be defined by actual split
/// instructions in that case.
///
/// After legalizing the instructions computing the value that was split, it is likely that we can
/// avoid depending on the split instruction. Its input probably comes from a concatenation.
pub fn simplify_branch_arguments(dfg: &mut DataFlowGraph, branch: Inst) {
    let mut new_args = Vec::new();

    for &arg in dfg.inst_args(branch) {
        let new_arg = resolve_splits(dfg, arg);
        new_args.push(new_arg);
    }

    dfg.inst_args_mut(branch).copy_from_slice(&new_args);
}
<|endoftext|>


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

pub fn fptr_is_null(fptr: *const u8) -> bool {
    fptr.is_null()
}
<commit_msg>embedding: add eutil::slice_to_str() convenience function<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use libc::c_int;
use std::slice;
use std::str;

pub fn fptr_is_null(fptr: *const u8) -> bool {
    fptr.is_null()
}

pub fn slice_to_str(s: *const u8, l: uint, f: |&str| -> c_int) -> c_int {
    unsafe {
        slice::raw::buf_as_slice(s, l, |result| {
             match str::from_utf8(result) {
                  Some(ruststr) => {
                       f(ruststr)
                  },
                  None => 0
             }
        })
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::collections::HashMap;

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("08.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

#[derive(Debug)]
struct Node(Vec<usize>);

struct Graph {
    nodes: Vec<Node>,
    children: HashMap<usize, Vec<usize>>
}

impl Graph {
    fn new() -> Graph {
        Graph {
            nodes: vec![],
            children: HashMap::new()
        }
    }
}

fn parse_node(graph: &mut Graph, tokens: &[usize]) -> Option<(usize, usize)> {
    if tokens.len() < 2 {
        return None;
    }

    let children_count = *tokens.get(0).unwrap();
    let metadata_count = *tokens.get(1).unwrap();
    let mut start = 2;
    let mut children_ids = vec![];

    for _ in 0..children_count {
        let (node_id, length) = match parse_node(graph, &tokens[start..]) {
            Some(x) => x,
            _ => return None
        };

        children_ids.push(node_id);
        start += length;
    }

    let length = start + metadata_count;
    let metadata = tokens[start..length].to_vec();

    if metadata.len() != metadata_count {
        return None;
    }

    let node = Node(metadata);
    let node_id = graph.nodes.len();

    graph.nodes.push(node);
    graph.children.insert(node_id, children_ids);

    Some((node_id, length))
}

fn parse_input(input: &str) -> Option<(Graph, usize)> {
    let mut graph = Graph::new();
    let tokens: Vec<usize> = input.split(' ').filter_map(|x| x.parse::<usize>().ok()).collect();

    parse_node(&mut graph, &tokens[..])
    .map(|(root_id, _)| (graph, root_id))
}

fn get_value(graph: &Graph, id: usize) -> usize {
    let metadata = match graph.nodes.get(id) {
        Some(node) => &node.0,
        _ => return 0
    };

    let children = graph.children.get(&id);

    if children.map(|v| v.len()).unwrap_or(0) == 0 {
        metadata.iter().cloned().sum::<usize>()
    } else {
        metadata.iter()
        .map(|&index| {
            children.unwrap()
            .get(index - 1)
            .map(|&child_id| get_value(graph, child_id))
            .unwrap_or(0)
        })
        .sum::<usize>()
    }
}

fn main() {
    let input = get_input().unwrap();
    let (graph, root_id) = match parse_input(input.trim()) {
        Some(x) => x,
        _ => return
    };

    let metadata_sum = graph.nodes.iter()
        .flat_map(|&Node(ref v)| v.iter())
        .cloned()
        .sum::<usize>();

    println!("Part 1: {}", metadata_sum);

    let value = get_value(&graph, root_id);

    println!("Part 2: {}", value);
}
<commit_msg>Simplify code<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::collections::HashMap;

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("08.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

#[derive(Debug)]
struct Node(Vec<usize>);

struct Graph {
    nodes: Vec<Node>,
    children: HashMap<usize, Vec<usize>>
}

impl Graph {
    fn new() -> Graph {
        Graph {
            nodes: vec![],
            children: HashMap::new()
        }
    }
}

fn parse_node<T>(graph: &mut Graph, tokens: &mut T) -> Option<usize>
where T: Iterator<Item = usize> {
    let (children_count, metadata_count) = match (tokens.next(), tokens.next()) {
        (Some(x), Some(y)) => (x, y),
        _ => return None
    };

    let children_ids: Vec<usize> = (0..children_count)
        .filter_map(|_| parse_node(graph, tokens))
        .collect();

    let metadata: Vec<usize> = (0..metadata_count)
        .filter_map(|_| tokens.next())
        .collect();

    let node = Node(metadata);
    let node_id = graph.nodes.len();

    graph.nodes.push(node);
    graph.children.insert(node_id, children_ids);

    Some(node_id)
}

fn parse_input(input: &str) -> Option<(Graph, usize)> {
    let mut graph = Graph::new();
    let mut tokens = input.split(' ').filter_map(|x| x.parse::<usize>().ok());

    parse_node(&mut graph, &mut tokens)
    .map(|root_id| (graph, root_id))
}

fn get_value(graph: &Graph, id: usize) -> usize {
    let metadata = match graph.nodes.get(id) {
        Some(node) => &node.0,
        _ => return 0
    };

    let children = graph.children.get(&id);

    if children.map(|v| v.len()).unwrap_or(0) == 0 {
        metadata.iter().cloned().sum::<usize>()
    } else {
        metadata.iter()
        .map(|&index| {
            children.unwrap()
            .get(index - 1)
            .map(|&child_id| get_value(graph, child_id))
            .unwrap_or(0)
        })
        .sum::<usize>()
    }
}

fn main() {
    let input = get_input().unwrap();
    let (graph, root_id) = match parse_input(input.trim()) {
        Some(x) => x,
        _ => return
    };

    let metadata_sum = graph.nodes.iter()
        .flat_map(|&Node(ref v)| v.iter())
        .cloned()
        .sum::<usize>();

    println!("Part 1: {}", metadata_sum);

    let value = get_value(&graph, root_id);

    println!("Part 2: {}", value);
}
<|endoftext|>