<commit_before>use crate::error;
use std::io;

pub trait LZBuffer {
    fn len(&self) -> usize;
    // Retrieve the last byte or return a default
    fn last_or(&self, lit: u8) -> u8;
    // Retrieve the n-th last byte
    fn last_n(&self, dist: usize) -> error::Result<u8>;
    // Append a literal
    fn append_literal(&mut self, lit: u8) -> error::Result<()>;
    // Fetch an LZ sequence (length, distance) from inside the buffer
    fn append_lz(&mut self, len: usize, dist: usize) -> error::Result<()>;
    // Flush the buffer to the output
    fn finish(self) -> io::Result<()>;
}

// An accumulating buffer for LZ sequences
pub struct LZAccumBuffer<'a, W>
where
    W: 'a + io::Write,
{
    stream: &'a mut W, // Output sink
    buf: Vec<u8>,      // Buffer
    memlimit: usize,   // Buffer memory limit
    len: usize,        // Total number of bytes sent through the buffer
}

impl<'a, W> LZAccumBuffer<'a, W>
where
    W: io::Write,
{
    pub fn from_stream(stream: &'a mut W) -> Self {
        Self::from_stream_with_memlimit(stream, std::usize::MAX)
    }

    pub fn from_stream_with_memlimit(stream: &'a mut W, memlimit: usize) -> Self {
        Self {
            stream,
            buf: Vec::new(),
            memlimit,
            len: 0,
        }
    }

    // Append bytes
    pub fn append_bytes(&mut self, buf: &[u8]) {
        self.buf.extend_from_slice(buf);
        self.len += buf.len();
    }

    // Reset the internal dictionary
    pub fn reset(&mut self) -> io::Result<()> {
        self.stream.write_all(self.buf.as_slice())?;
        self.buf.clear();
        // TODO: clear the length ?
        Ok(())
    }
}

impl<'a, W> LZBuffer for LZAccumBuffer<'a, W>
where
    W: io::Write,
{
    fn len(&self) -> usize {
        self.len
    }

    // Retrieve the last byte or return a default
    fn last_or(&self, lit: u8) -> u8 {
        let buf_len = self.buf.len();
        if buf_len == 0 {
            lit
        } else {
            self.buf[buf_len - 1]
        }
    }

    // Retrieve the n-th last byte
    fn last_n(&self, dist: usize) -> error::Result<u8> {
        let buf_len = self.buf.len();
        if dist > buf_len {
            return Err(error::Error::LZMAError(format!(
                "Match distance {} is beyond output size {}",
                dist, buf_len
            )));
        }

        Ok(self.buf[buf_len - dist])
    }

    // Append a literal
    fn append_literal(&mut self, lit: u8) -> error::Result<()> {
        let new_len = self.len + 1;

        if new_len > self.memlimit {
            Err(error::Error::LZMAError(format!(
                "exceeded memory limit of {}",
                self.memlimit
            )))
        } else {
            self.buf.push(lit);
            self.len = new_len;
            Ok(())
        }
    }

    // Fetch an LZ sequence (length, distance) from inside the buffer
    fn append_lz(&mut self, len: usize, dist: usize) -> error::Result<()> {
        lzma_debug!("LZ {{ len: {}, dist: {} }}", len, dist);
        let buf_len = self.buf.len();
        if dist > buf_len {
            return Err(error::Error::LZMAError(format!(
                "LZ distance {} is beyond output size {}",
                dist, buf_len
            )));
        }

        let mut offset = buf_len - dist;
        for _ in 0..len {
            let x = self.buf[offset];
            self.buf.push(x);
            offset += 1;
        }
        self.len += len;
        Ok(())
    }

    // Flush the buffer to the output
    fn finish(self) -> io::Result<()> {
        self.stream.write_all(self.buf.as_slice())?;
        self.stream.flush()?;
        Ok(())
    }
}

// A circular buffer for LZ sequences
pub struct LZCircularBuffer<'a, W>
where
    W: 'a + io::Write,
{
    stream: &'a mut W, // Output sink
    buf: Vec<u8>,      // Circular buffer
    dict_size: usize,  // Length of the buffer
    memlimit: usize,   // Buffer memory limit
    cursor: usize,     // Current position
    len: usize,        // Total number of bytes sent through the buffer
}

impl<'a, W> LZCircularBuffer<'a, W>
where
    W: io::Write,
{
    pub fn from_stream_with_memlimit(stream: &'a mut W, dict_size: usize, memlimit: usize) -> Self {
        lzma_info!("Dict size in LZ buffer: {}", dict_size);
        Self {
            stream,
            buf: Vec::new(),
            dict_size,
            memlimit,
            cursor: 0,
            len: 0,
        }
    }

    fn get(&self, index: usize) -> u8 {
        *self.buf.get(index).unwrap_or(&0)
    }

    fn set(&mut self, index: usize, value: u8) -> error::Result<()> {
        let new_len = index + 1;

        if new_len > self.memlimit {
            Err(error::Error::LZMAError(format!(
                "exceeded memory limit of {}",
                self.memlimit
            )))
        } else {
            if self.buf.len() < new_len {
                self.buf.resize(new_len, 0);
            }
            self.buf[index] = value;
            Ok(())
        }
    }
}

impl<'a, W> LZBuffer for LZCircularBuffer<'a, W>
where
    W: io::Write,
{
    fn len(&self) -> usize {
        self.len
    }

    // Retrieve the last byte or return a default
    fn last_or(&self, lit: u8) -> u8 {
        if self.len == 0 {
            lit
        } else {
            self.get((self.dict_size + self.cursor - 1) % self.dict_size)
        }
    }

    // Retrieve the n-th last byte
    fn last_n(&self, dist: usize) -> error::Result<u8> {
        if dist > self.dict_size {
            return Err(error::Error::LZMAError(format!(
                "Match distance {} is beyond dictionary size {}",
                dist, self.dict_size
            )));
        }
        if dist > self.len {
            return Err(error::Error::LZMAError(format!(
                "Match distance {} is beyond output size {}",
                dist, self.len
            )));
        }

        let offset = (self.dict_size + self.cursor - dist) % self.dict_size;
        Ok(self.get(offset))
    }

    // Append a literal
    fn append_literal(&mut self, lit: u8) -> error::Result<()> {
        self.set(self.cursor, lit)?;
        self.cursor += 1;
        self.len += 1;

        // Flush the circular buffer to the output
        if self.cursor == self.dict_size {
            self.stream.write_all(self.buf.as_slice())?;
            self.cursor = 0;
        }

        Ok(())
    }

    // Fetch an LZ sequence (length, distance) from inside the buffer
    fn append_lz(&mut self, len: usize, dist: usize) -> error::Result<()> {
        lzma_debug!("LZ {{ len: {}, dist: {} }}", len, dist);
        if dist > self.dict_size {
            return Err(error::Error::LZMAError(format!(
                "LZ distance {} is beyond dictionary size {}",
                dist, self.dict_size
            )));
        }
        if dist > self.len {
            return Err(error::Error::LZMAError(format!(
                "LZ distance {} is beyond output size {}",
                dist, self.len
            )));
        }

        let mut offset = (self.dict_size + self.cursor - dist) % self.dict_size;
        for _ in 0..len {
            let x = self.get(offset);
            self.append_literal(x)?;
            offset += 1;
            if offset == self.dict_size {
                offset = 0
            }
        }
        Ok(())
    }

    // Flush the buffer to the output
    fn finish(self) -> io::Result<()> {
        if self.cursor > 0 {
            self.stream.write_all(&self.buf[0..self.cursor])?;
            self.stream.flush()?;
        }
        Ok(())
    }
}
<commit_msg>lzbuffer: only check memlimit on resize<commit_after>use crate::error;
use std::io;

pub trait LZBuffer {
    fn len(&self) -> usize;
    // Retrieve the last byte or return a default
    fn last_or(&self, lit: u8) -> u8;
    // Retrieve the n-th last byte
    fn last_n(&self, dist: usize) -> error::Result<u8>;
    // Append a literal
    fn append_literal(&mut self, lit: u8) -> error::Result<()>;
    // Fetch an LZ sequence (length, distance) from inside the buffer
    fn append_lz(&mut self, len: usize, dist: usize) -> error::Result<()>;
    // Flush the buffer to the output
    fn finish(self) -> io::Result<()>;
}

// An accumulating buffer for LZ sequences
pub struct LZAccumBuffer<'a, W>
where
    W: 'a + io::Write,
{
    stream: &'a mut W, // Output sink
    buf: Vec<u8>,      // Buffer
    memlimit: usize,   // Buffer memory limit
    len: usize,        // Total number of bytes sent through the buffer
}

impl<'a, W> LZAccumBuffer<'a, W>
where
    W: io::Write,
{
    pub fn from_stream(stream: &'a mut W) -> Self {
        Self::from_stream_with_memlimit(stream, std::usize::MAX)
    }

    pub fn from_stream_with_memlimit(stream: &'a mut W, memlimit: usize) -> Self {
        Self {
            stream,
            buf: Vec::new(),
            memlimit,
            len: 0,
        }
    }

    // Append bytes
    pub fn append_bytes(&mut self, buf: &[u8]) {
        self.buf.extend_from_slice(buf);
        self.len += buf.len();
    }

    // Reset the internal dictionary
    pub fn reset(&mut self) -> io::Result<()> {
        self.stream.write_all(self.buf.as_slice())?;
        self.buf.clear();
        // TODO: clear the length ?
        Ok(())
    }
}

impl<'a, W> LZBuffer for LZAccumBuffer<'a, W>
where
    W: io::Write,
{
    fn len(&self) -> usize {
        self.len
    }

    // Retrieve the last byte or return a default
    fn last_or(&self, lit: u8) -> u8 {
        let buf_len = self.buf.len();
        if buf_len == 0 {
            lit
        } else {
            self.buf[buf_len - 1]
        }
    }

    // Retrieve the n-th last byte
    fn last_n(&self, dist: usize) -> error::Result<u8> {
        let buf_len = self.buf.len();
        if dist > buf_len {
            return Err(error::Error::LZMAError(format!(
                "Match distance {} is beyond output size {}",
                dist, buf_len
            )));
        }

        Ok(self.buf[buf_len - dist])
    }

    // Append a literal
    fn append_literal(&mut self, lit: u8) -> error::Result<()> {
        let new_len = self.len + 1;

        if new_len > self.memlimit {
            Err(error::Error::LZMAError(format!(
                "exceeded memory limit of {}",
                self.memlimit
            )))
        } else {
            self.buf.push(lit);
            self.len = new_len;
            Ok(())
        }
    }

    // Fetch an LZ sequence (length, distance) from inside the buffer
    fn append_lz(&mut self, len: usize, dist: usize) -> error::Result<()> {
        lzma_debug!("LZ {{ len: {}, dist: {} }}", len, dist);
        let buf_len = self.buf.len();
        if dist > buf_len {
            return Err(error::Error::LZMAError(format!(
                "LZ distance {} is beyond output size {}",
                dist, buf_len
            )));
        }

        let mut offset = buf_len - dist;
        for _ in 0..len {
            let x = self.buf[offset];
            self.buf.push(x);
            offset += 1;
        }
        self.len += len;
        Ok(())
    }

    // Flush the buffer to the output
    fn finish(self) -> io::Result<()> {
        self.stream.write_all(self.buf.as_slice())?;
        self.stream.flush()?;
        Ok(())
    }
}

// A circular buffer for LZ sequences
pub struct LZCircularBuffer<'a, W>
where
    W: 'a + io::Write,
{
    stream: &'a mut W, // Output sink
    buf: Vec<u8>,      // Circular buffer
    dict_size: usize,  // Length of the buffer
    memlimit: usize,   // Buffer memory limit
    cursor: usize,     // Current position
    len: usize,        // Total number of bytes sent through the buffer
}

impl<'a, W> LZCircularBuffer<'a, W>
where
    W: io::Write,
{
    pub fn from_stream_with_memlimit(stream: &'a mut W, dict_size: usize, memlimit: usize) -> Self {
        lzma_info!("Dict size in LZ buffer: {}", dict_size);
        Self {
            stream,
            buf: Vec::new(),
            dict_size,
            memlimit,
            cursor: 0,
            len: 0,
        }
    }

    fn get(&self, index: usize) -> u8 {
        *self.buf.get(index).unwrap_or(&0)
    }

    fn set(&mut self, index: usize, value: u8) -> error::Result<()> {
        let new_len = index + 1;

        if self.buf.len() < new_len {
            if new_len <= self.memlimit {
                self.buf.resize(new_len, 0);
            } else {
                return Err(error::Error::LZMAError(format!(
                    "exceeded memory limit of {}",
                    self.memlimit
                )));
            }
        }
        self.buf[index] = value;
        Ok(())
    }
}

impl<'a, W> LZBuffer for LZCircularBuffer<'a, W>
where
    W: io::Write,
{
    fn len(&self) -> usize {
        self.len
    }

    // Retrieve the last byte or return a default
    fn last_or(&self, lit: u8) -> u8 {
        if self.len == 0 {
            lit
        } else {
            self.get((self.dict_size + self.cursor - 1) % self.dict_size)
        }
    }

    // Retrieve the n-th last byte
    fn last_n(&self, dist: usize) -> error::Result<u8> {
        if dist > self.dict_size {
            return Err(error::Error::LZMAError(format!(
                "Match distance {} is beyond dictionary size {}",
                dist, self.dict_size
            )));
        }
        if dist > self.len {
            return Err(error::Error::LZMAError(format!(
                "Match distance {} is beyond output size {}",
                dist, self.len
            )));
        }

        let offset = (self.dict_size + self.cursor - dist) % self.dict_size;
        Ok(self.get(offset))
    }

    // Append a literal
    fn append_literal(&mut self, lit: u8) -> error::Result<()> {
        self.set(self.cursor, lit)?;
        self.cursor += 1;
        self.len += 1;

        // Flush the circular buffer to the output
        if self.cursor == self.dict_size {
            self.stream.write_all(self.buf.as_slice())?;
            self.cursor = 0;
        }

        Ok(())
    }

    // Fetch an LZ sequence (length, distance) from inside the buffer
    fn append_lz(&mut self, len: usize, dist: usize) -> error::Result<()> {
        lzma_debug!("LZ {{ len: {}, dist: {} }}", len, dist);
        if dist > self.dict_size {
            return Err(error::Error::LZMAError(format!(
                "LZ distance {} is beyond dictionary size {}",
                dist, self.dict_size
            )));
        }
        if dist > self.len {
            return Err(error::Error::LZMAError(format!(
                "LZ distance {} is beyond output size {}",
                dist, self.len
            )));
        }

        let mut offset = (self.dict_size + self.cursor - dist) % self.dict_size;
        for _ in 0..len {
            let x = self.get(offset);
            self.append_literal(x)?;
            offset += 1;
            if offset == self.dict_size {
                offset = 0
            }
        }
        Ok(())
    }

    // Flush the buffer to the output
    fn finish(self) -> io::Result<()> {
        if self.cursor > 0 {
            self.stream.write_all(&self.buf[0..self.cursor])?;
            self.stream.flush()?;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::{
    env,
    io::ErrorKind,
    os::unix::net::UnixStream,
    os::unix::prelude::FromRawFd,
    path::PathBuf,
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc, Mutex, MutexGuard,
    },
};

use wayland_backend::{
    client::{Backend, Handle, InvalidId, ObjectData, ObjectId, ReadEventsGuard, WaylandError},
    protocol::{Interface, ObjectInfo},
};

use nix::{fcntl, Error};

use crate::{EventQueue, Proxy};

/// The Wayland connection
///
/// This is the main type representing your connection to the Wayland server. Most operations require
/// access to either this type or the [`ConnectionHandle`], which can be accessed through the
/// [`handle()`](Connection::handle) method, and is given to you in most callbacks.
#[derive(Debug, Clone)]
pub struct Connection {
    backend: Arc<Mutex<Backend>>,
}

impl Connection {
    /// Access the connection handle
    pub fn handle(&self) -> ConnectionHandle {
        ConnectionHandle { inner: HandleInner::Guard(self.backend.lock().unwrap()) }
    }

    /// Try to connect to the Wayland server following the environment
    ///
    /// This is the standard way to initialize a Wayland connection.
    pub fn connect_to_env() -> Result<Connection, ConnectError> {
        let stream = if let Ok(txt) = env::var("WAYLAND_SOCKET") {
            // We should connect to the provided WAYLAND_SOCKET
            let fd = txt.parse::<i32>().map_err(|_| ConnectError::InvalidFd)?;
            // remove the variable so any child processes don't see it
            env::remove_var("WAYLAND_SOCKET");
            // set the CLOEXEC flag on this FD
            let flags = fcntl::fcntl(fd, fcntl::FcntlArg::F_GETFD);
            let result = flags
                .map(|f| fcntl::FdFlag::from_bits(f).unwrap() | fcntl::FdFlag::FD_CLOEXEC)
                .and_then(|f| fcntl::fcntl(fd, fcntl::FcntlArg::F_SETFD(f)));
            match result {
                Ok(_) => {
                    // setting the O_CLOEXEC worked
                    unsafe { FromRawFd::from_raw_fd(fd) }
                }
                Err(_) => {
                    // something went wrong in F_GETFD or F_SETFD
                    let _ = ::nix::unistd::close(fd);
                    return Err(ConnectError::InvalidFd);
                }
            }
        } else {
            let mut socket_path = env::var_os("XDG_RUNTIME_DIR")
                .map(Into::<PathBuf>::into)
                .ok_or(ConnectError::NoCompositor)?;
            socket_path.push(env::var_os("WAYLAND_DISPLAY").ok_or(ConnectError::NoCompositor)?);

            UnixStream::connect(socket_path).map_err(|_| ConnectError::NoCompositor)?
        };

        let backend = Backend::connect(stream).map_err(|_| ConnectError::NoWaylandLib)?;
        Ok(Connection { backend: Arc::new(Mutex::new(backend)) })
    }

    /// Initialize a Wayland connection from an already existing Unix stream
    pub fn from_socket(stream: UnixStream) -> Result<Connection, ConnectError> {
        let backend = Backend::connect(stream).map_err(|_| ConnectError::NoWaylandLib)?;
        Ok(Connection { backend: Arc::new(Mutex::new(backend)) })
    }

    /// Wrap an existing [`Backend`] into a Connection
    pub fn from_backend(backend: Arc<Mutex<Backend>>) -> Connection {
        Connection { backend }
    }

    /// Get the [`Backend`] underlying this Connection
    pub fn backend(&self) -> Arc<Mutex<Backend>> {
        self.backend.clone()
    }

    /// Flush pending outgoing events to the server
    ///
    /// This needs to be done regularly to ensure the server receives all your requests.
    pub fn flush(&self) -> Result<(), WaylandError> {
        self.backend.lock().unwrap().flush()
    }

    /// Start a synchronized read from the socket
    ///
    /// This is needed if you plan to wait on readiness of the Wayland socket using an event
    /// loop. See [`ReadEventsGuard`] for details. Once the events are received, you'll then
    /// need to dispatch them from the event queue using
    /// [`EventQueue::dispatch_pending()`](EventQueue::dispatch_pending).
    ///
    /// If you don't need to manage multiple event sources, see
    /// [`blocking_dispatch()`](Connection::blocking_dispatch) for a simpler mechanism.
    pub fn prepare_read(&self) -> Result<ReadEventsGuard, WaylandError> {
        ReadEventsGuard::try_new(self.backend.clone())
    }

    /// Block until events are received from the server
    ///
    /// This will flush the outgoing socket, and then block until events are received from the
    /// server and read them. You'll then need to invoke
    /// [`EventQueue::dispatch_pending()`](EventQueue::dispatch_pending) to dispatch them on
    /// their respective event queues. Alternatively,
    /// [`EventQueue::blocking_dispatch()`](EventQueue::blocking_dispatch) does both.
    pub fn blocking_dispatch(&self) -> Result<usize, WaylandError> {
        blocking_dispatch_impl(self.backend.clone())
    }

    /// Do a roundtrip to the server
    ///
    /// This method will block until the Wayland server has processed and answered all your
    /// preceding requests. This is notably useful during the initial setup of an app, to wait for
    /// the initial state from the server.
    pub fn roundtrip(&self) -> Result<usize, WaylandError> {
        let done = Arc::new(AtomicBool::new(false));
        {
            let mut backend = self.backend.lock().unwrap();
            let mut handle = ConnectionHandle::from_handle(backend.handle());
            let display = handle.display();
            let cb_done = done.clone();
            let sync_data = Arc::new(SyncData { done: cb_done });
            handle
                .send_request(
                    &display,
                    crate::protocol::wl_display::Request::Sync {},
                    Some(sync_data),
                )
                .map_err(|_| WaylandError::Io(Error::EPIPE.into()))?;
        }

        let mut dispatched = 0;

        while !done.load(Ordering::Acquire) {
            dispatched += blocking_dispatch_impl(self.backend.clone())?;
        }

        Ok(dispatched)
    }

    /// Create a new event queue
    pub fn new_event_queue<D>(&self) -> EventQueue<D> {
        EventQueue::new(self.backend.clone())
    }
}

pub(crate) fn blocking_dispatch_impl(backend: Arc<Mutex<Backend>>) -> Result<usize, WaylandError> {
    backend.lock().unwrap().flush()?;

    // first, prepare the read
    let guard = ReadEventsGuard::try_new(backend)?;

    // there is nothing to dispatch, wait for readiness
    loop {
        let mut fds = [nix::poll::PollFd::new(
            guard.connection_fd(),
            nix::poll::PollFlags::POLLIN | nix::poll::PollFlags::POLLERR,
        )];
        match nix::poll::poll(&mut fds, -1) {
            Ok(_) => break,
            Err(nix::errno::Errno::EINTR) => continue,
            Err(e) => return Err(WaylandError::Io(e.into())),
        }
    }

    // at this point the fd is ready
    match guard.read() {
        Ok(n) => Ok(n),
        // if we are still "wouldblock", that means that there was a dispatch from an other
        // thread with the C-based backend, spuriously return 0.
        Err(WaylandError::Io(e)) if e.kind() == ErrorKind::WouldBlock => Ok(0),
        Err(e) => Err(e),
    }
}

/// A handle to the Wayland connection
#[derive(Debug)]
pub struct ConnectionHandle<'a> {
    pub(crate) inner: HandleInner<'a>,
}

#[derive(Debug)]
pub(crate) enum HandleInner<'a> {
    Handle(&'a mut Handle),
    Guard(MutexGuard<'a, Backend>),
}

impl<'a> HandleInner<'a> {
    #[inline]
    pub(crate) fn handle(&mut self) -> &mut Handle {
        match self {
            HandleInner::Handle(handle) => handle,
            HandleInner::Guard(guard) => guard.handle(),
        }
    }
}

impl<'a> ConnectionHandle<'a> {
    pub(crate) fn from_handle(handle: &'a mut Handle) -> ConnectionHandle<'a> {
        ConnectionHandle { inner: HandleInner::Handle(handle) }
    }

    /// Get the `WlDisplay` associated with this connection
    pub fn display(&mut self) -> crate::protocol::wl_display::WlDisplay {
        let display_id = self.inner.handle().display_id();
        Proxy::from_id(self, display_id).unwrap()
    }

    /// Send a request associated with the provided object
    ///
    /// This is a low-level interface for sending requests, you will likely instead use
    /// the methods of the types representing each interface.
    pub fn send_request<I: Proxy>(
        &mut self,
        proxy: &I,
        request: I::Request,
        data: Option<Arc<dyn ObjectData>>,
    ) -> Result<ObjectId, InvalidId> {
        let msg = proxy.write_request(self, request)?;
        self.inner.handle().send_request(msg, data)
    }

    /// Create a placeholder id for request serialization
    ///
    /// This is a low-level interface for sending requests, you don't need to use it if you
    /// are using the methods of the types representing each interface.
    pub fn placeholder_id(&mut self, spec: Option<(&'static Interface, u32)>) -> ObjectId {
        self.inner.handle().placeholder_id(spec)
    }

    /// Create a null id for request serialization
    ///
    /// This is a low-level interface for sending requests, you don't need to use it if you
    /// are using the methods of the types representing each interface.
    pub fn null_id(&mut self) -> ObjectId {
        self.inner.handle().null_id()
    }

    /// Get the object data for a given object ID
    ///
    /// This is a low-level interface, a higher-level interface for manipulating object data
    /// is given as [`Proxy::data()`](crate::Proxy::data).
    pub fn get_object_data(&mut self, id: ObjectId) -> Result<Arc<dyn ObjectData>, InvalidId> {
        self.inner.handle().get_data(id)
    }

    /// Get the protocol information related to given object ID
    pub fn object_info(&mut self, id: ObjectId) -> Result<ObjectInfo, InvalidId> {
        self.inner.handle().info(id)
    }
}

#[derive(thiserror::Error, Debug)]
pub enum ConnectError {
    #[error("The wayland library could not be loaded")]
    NoWaylandLib,
    #[error("Could not find wayland compositor")]
    NoCompositor,
    #[error("WAYLAND_SOCKET was set but contained garbage")]
    InvalidFd,
}

/*
    wl_callback object data for wl_display.sync
*/

struct SyncData {
    done: Arc<AtomicBool>,
}

impl ObjectData for SyncData {
    fn event(
        self: Arc<Self>,
        _handle: &mut Handle,
        _msg: wayland_backend::protocol::Message<ObjectId>,
    ) -> Option<Arc<dyn ObjectData>> {
        self.done.store(true, Ordering::Release);
        None
    }

    fn destroyed(&self, _: ObjectId) {}
}
<commit_msg>client: expose protocol error<commit_after>use std::{
    env,
    io::ErrorKind,
    os::unix::net::UnixStream,
    os::unix::prelude::FromRawFd,
    path::PathBuf,
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc, Mutex, MutexGuard,
    },
};

use wayland_backend::{
    client::{Backend, Handle, InvalidId, ObjectData, ObjectId, ReadEventsGuard, WaylandError},
    protocol::{Interface, ObjectInfo, ProtocolError},
};

use nix::{fcntl, Error};

use crate::{EventQueue, Proxy};

/// The Wayland connection
///
/// This is the main type representing your connection to the Wayland server. Most operations require
/// access to either this type or the [`ConnectionHandle`], which can be accessed through the
/// [`handle()`](Connection::handle) method, and is given to you in most callbacks.
#[derive(Debug, Clone)]
pub struct Connection {
    backend: Arc<Mutex<Backend>>,
}

impl Connection {
    /// Access the connection handle
    pub fn handle(&self) -> ConnectionHandle {
        ConnectionHandle { inner: HandleInner::Guard(self.backend.lock().unwrap()) }
    }

    /// Try to connect to the Wayland server following the environment
    ///
    /// This is the standard way to initialize a Wayland connection.
    pub fn connect_to_env() -> Result<Connection, ConnectError> {
        let stream = if let Ok(txt) = env::var("WAYLAND_SOCKET") {
            // We should connect to the provided WAYLAND_SOCKET
            let fd = txt.parse::<i32>().map_err(|_| ConnectError::InvalidFd)?;
            // remove the variable so any child processes don't see it
            env::remove_var("WAYLAND_SOCKET");
            // set the CLOEXEC flag on this FD
            let flags = fcntl::fcntl(fd, fcntl::FcntlArg::F_GETFD);
            let result = flags
                .map(|f| fcntl::FdFlag::from_bits(f).unwrap() | fcntl::FdFlag::FD_CLOEXEC)
                .and_then(|f| fcntl::fcntl(fd, fcntl::FcntlArg::F_SETFD(f)));
            match result {
                Ok(_) => {
                    // setting the O_CLOEXEC worked
                    unsafe { FromRawFd::from_raw_fd(fd) }
                }
                Err(_) => {
                    // something went wrong in F_GETFD or F_SETFD
                    let _ = ::nix::unistd::close(fd);
                    return Err(ConnectError::InvalidFd);
                }
            }
        } else {
            let mut socket_path = env::var_os("XDG_RUNTIME_DIR")
                .map(Into::<PathBuf>::into)
                .ok_or(ConnectError::NoCompositor)?;
            socket_path.push(env::var_os("WAYLAND_DISPLAY").ok_or(ConnectError::NoCompositor)?);

            UnixStream::connect(socket_path).map_err(|_| ConnectError::NoCompositor)?
        };

        let backend = Backend::connect(stream).map_err(|_| ConnectError::NoWaylandLib)?;
        Ok(Connection { backend: Arc::new(Mutex::new(backend)) })
    }

    /// Initialize a Wayland connection from an already existing Unix stream
    pub fn from_socket(stream: UnixStream) -> Result<Connection, ConnectError> {
        let backend = Backend::connect(stream).map_err(|_| ConnectError::NoWaylandLib)?;
        Ok(Connection { backend: Arc::new(Mutex::new(backend)) })
    }

    /// Wrap an existing [`Backend`] into a Connection
    pub fn from_backend(backend: Arc<Mutex<Backend>>) -> Connection {
        Connection { backend }
    }

    /// Get the [`Backend`] underlying this Connection
    pub fn backend(&self) -> Arc<Mutex<Backend>> {
        self.backend.clone()
    }

    /// Flush pending outgoing events to the server
    ///
    /// This needs to be done regularly to ensure the server receives all your requests.
    pub fn flush(&self) -> Result<(), WaylandError> {
        self.backend.lock().unwrap().flush()
    }

    /// Start a synchronized read from the socket
    ///
    /// This is needed if you plan to wait on readiness of the Wayland socket using an event
    /// loop. See [`ReadEventsGuard`] for details. Once the events are received, you'll then
    /// need to dispatch them from the event queue using
    /// [`EventQueue::dispatch_pending()`](EventQueue::dispatch_pending).
    ///
    /// If you don't need to manage multiple event sources, see
    /// [`blocking_dispatch()`](Connection::blocking_dispatch) for a simpler mechanism.
    pub fn prepare_read(&self) -> Result<ReadEventsGuard, WaylandError> {
        ReadEventsGuard::try_new(self.backend.clone())
    }

    /// Block until events are received from the server
    ///
    /// This will flush the outgoing socket, and then block until events are received from the
    /// server and read them. You'll then need to invoke
    /// [`EventQueue::dispatch_pending()`](EventQueue::dispatch_pending) to dispatch them on
    /// their respective event queues. Alternatively,
    /// [`EventQueue::blocking_dispatch()`](EventQueue::blocking_dispatch) does both.
    pub fn blocking_dispatch(&self) -> Result<usize, WaylandError> {
        blocking_dispatch_impl(self.backend.clone())
    }

    /// Do a roundtrip to the server
    ///
    /// This method will block until the Wayland server has processed and answered all your
    /// preceding requests. This is notably useful during the initial setup of an app, to wait for
    /// the initial state from the server.
    pub fn roundtrip(&self) -> Result<usize, WaylandError> {
        let done = Arc::new(AtomicBool::new(false));
        {
            let mut backend = self.backend.lock().unwrap();
            let mut handle = ConnectionHandle::from_handle(backend.handle());
            let display = handle.display();
            let cb_done = done.clone();
            let sync_data = Arc::new(SyncData { done: cb_done });
            handle
                .send_request(
                    &display,
                    crate::protocol::wl_display::Request::Sync {},
                    Some(sync_data),
                )
                .map_err(|_| WaylandError::Io(Error::EPIPE.into()))?;
        }

        let mut dispatched = 0;

        while !done.load(Ordering::Acquire) {
            dispatched += blocking_dispatch_impl(self.backend.clone())?;
        }

        Ok(dispatched)
    }

    /// Create a new event queue
    pub fn new_event_queue<D>(&self) -> EventQueue<D> {
        EventQueue::new(self.backend.clone())
    }

    /// Retrive the protocol error that occured on the socket (if any)
    pub fn protocol_error(&self) -> Option<ProtocolError> {
        match dbg!(self.backend.lock().unwrap().handle().last_error())? {
            WaylandError::Protocol(err) => Some(err),
            WaylandError::Io(_) => None,
        }
    }
}

pub(crate) fn blocking_dispatch_impl(backend: Arc<Mutex<Backend>>) -> Result<usize, WaylandError> {
    backend.lock().unwrap().flush()?;

    // first, prepare the read
    let guard = ReadEventsGuard::try_new(backend)?;

    // there is nothing to dispatch, wait for readiness
    loop {
        let mut fds = [nix::poll::PollFd::new(
            guard.connection_fd(),
            nix::poll::PollFlags::POLLIN | nix::poll::PollFlags::POLLERR,
        )];
        match nix::poll::poll(&mut fds, -1) {
            Ok(_) => break,
            Err(nix::errno::Errno::EINTR) => continue,
            Err(e) => return Err(WaylandError::Io(e.into())),
        }
    }

    // at this point the fd is ready
    match guard.read() {
        Ok(n) => Ok(n),
        // if we are still "wouldblock", that means that there was a dispatch from an other
        // thread with the C-based backend, spuriously return 0.
        Err(WaylandError::Io(e)) if e.kind() == ErrorKind::WouldBlock => Ok(0),
        Err(e) => Err(e),
    }
}

/// A handle to the Wayland connection
#[derive(Debug)]
pub struct ConnectionHandle<'a> {
    pub(crate) inner: HandleInner<'a>,
}

#[derive(Debug)]
pub(crate) enum HandleInner<'a> {
    Handle(&'a mut Handle),
    Guard(MutexGuard<'a, Backend>),
}

impl<'a> HandleInner<'a> {
    #[inline]
    pub(crate) fn handle(&mut self) -> &mut Handle {
        match self {
            HandleInner::Handle(handle) => handle,
            HandleInner::Guard(guard) => guard.handle(),
        }
    }
}

impl<'a> ConnectionHandle<'a> {
    pub(crate) fn from_handle(handle: &'a mut Handle) -> ConnectionHandle<'a> {
        ConnectionHandle { inner: HandleInner::Handle(handle) }
    }

    /// Get the `WlDisplay` associated with this connection
    pub fn display(&mut self) -> crate::protocol::wl_display::WlDisplay {
        let display_id = self.inner.handle().display_id();
        Proxy::from_id(self, display_id).unwrap()
    }

    /// Send a request associated with the provided object
    ///
    /// This is a low-level interface for sending requests, you will likely instead use
    /// the methods of the types representing each interface.
    pub fn send_request<I: Proxy>(
        &mut self,
        proxy: &I,
        request: I::Request,
        data: Option<Arc<dyn ObjectData>>,
    ) -> Result<ObjectId, InvalidId> {
        let msg = proxy.write_request(self, request)?;
        self.inner.handle().send_request(msg, data)
    }

    /// Create a placeholder id for request serialization
    ///
    /// This is a low-level interface for sending requests, you don't need to use it if you
    /// are using the methods of the types representing each interface.
    pub fn placeholder_id(&mut self, spec: Option<(&'static Interface, u32)>) -> ObjectId {
        self.inner.handle().placeholder_id(spec)
    }

    /// Create a null id for request serialization
    ///
    /// This is a low-level interface for sending requests, you don't need to use it if you
    /// are using the methods of the types representing each interface.
    pub fn null_id(&mut self) -> ObjectId {
        self.inner.handle().null_id()
    }

    /// Get the object data for a given object ID
    ///
    /// This is a low-level interface, a higher-level interface for manipulating object data
    /// is given as [`Proxy::data()`](crate::Proxy::data).
    pub fn get_object_data(&mut self, id: ObjectId) -> Result<Arc<dyn ObjectData>, InvalidId> {
        self.inner.handle().get_data(id)
    }

    /// Get the protocol information related to given object ID
    pub fn object_info(&mut self, id: ObjectId) -> Result<ObjectInfo, InvalidId> {
        self.inner.handle().info(id)
    }
}

#[derive(thiserror::Error, Debug)]
pub enum ConnectError {
    #[error("The wayland library could not be loaded")]
    NoWaylandLib,
    #[error("Could not find wayland compositor")]
    NoCompositor,
    #[error("WAYLAND_SOCKET was set but contained garbage")]
    InvalidFd,
}

/*
    wl_callback object data for wl_display.sync
*/

struct SyncData {
    done: Arc<AtomicBool>,
}

impl ObjectData for SyncData {
    fn event(
        self: Arc<Self>,
        _handle: &mut Handle,
        _msg: wayland_backend::protocol::Message<ObjectId>,
    ) -> Option<Arc<dyn ObjectData>> {
        self.done.store(true, Ordering::Release);
        None
    }

    fn destroyed(&self, _: ObjectId) {}
}
<|endoftext|>


<commit_before>use std;
use ffi;

/// An enumeration type used to describe the format of pixels in a given bitmap. Note that
/// additional formats may be added in the future.
#[derive(Copy, Debug)]
pub enum PixelMode {
    /// This value is reserved.
    None,

    /// A monochrome bitmap, using 1 bit per pixel. Note that pixels are
    /// stored in most-significant order (MSB), which means that the left-most
    /// pixel in a byte has value 128.
    Mono,

    /// An 8-bit bitmap, generally used to represent anti-aliased glyph images.
    /// Each pixel is stored in one byte. Note that the number of `gray`
    /// levels is stored in the `num_grays` field of the FT_Bitmap structure
    /// (it generally is 256).
    Gray,

    /// A 2-bit per pixel bitmap, used to represent embedded anti-aliased
    /// bitmaps in font files according to the OpenType specification. We
    /// haven't found a single font using this format, however.
    Gray2,

    /// A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps in
    /// font files according to the OpenType specification. We haven't found a
    /// single font using this format, however.
    Gray4,

    /// An 8-bit bitmap, representing RGB or BGR decimated glyph images used
    /// for display on LCD displays; the bitmap is three times wider than the
    /// original glyph image. See also FT_RENDER_MODE_LCD.
    Lcd,

    /// An 8-bit bitmap, representing RGB or BGR decimated glyph images used for
    /// display on rotated LCD displays; the bitmap is three times taller than
    /// the original glyph image. See also FT_RENDER_MODE_LCD_V.
    LcdV,

    /// An image with four 8-bit channels per pixel, representing a color image
    /// (such as emoticons) with alpha channel. For each pixel, the format is
    /// BGRA, which means, the blue channel comes first in memory. The color
    /// channels are pre-multiplied and in the sRGB colorspace. For example,
    /// full red at half-translucent opacity will be represented as
    /// `00,00,80,80`, not `00,00,FF,80`. See also FT_LOAD_COLOR.
    Bgra,
}

#[allow(missing_copy_implementations)]
pub struct Bitmap {
    raw: *const ffi::FT_Bitmap,
}

impl Bitmap {
    pub fn from_raw(raw: *const ffi::FT_Bitmap) -> Bitmap {
        Bitmap {
            raw: raw,
        }
    }

    /// A typeless pointer to the bitmap buffer. This value should be aligned
    /// on 32-bit boundaries in most cases.
    pub fn buffer(&self) -> &[u8] {
        unsafe {
            std::slice::from_raw_buf(
                &(*self.raw).buffer,
                (self.width() * self.rows()) as usize,
            )
        }
    }

    /// The number of pixels in bitmap row.
    pub fn width(&self) -> i32 {
        unsafe {
            (*self.raw).width
        }
    }

    /// The number of bitmap rows.
    pub fn rows(&self) -> i32 {
        unsafe {
            (*self.raw).rows
        }
    }

    pub fn raw(&self) -> &ffi::FT_Bitmap {
        unsafe {
            &*self.raw
        }
    }

    /// The pixel mode, i.e., how pixel bits are stored. See `PixelMode` for
    /// possible values.
    pub fn pixel_mode(&self) -> PixelMode {
        unsafe {
            match (*self.raw).pixel_mode as u32 {
                ffi::FT_PIXEL_MODE_NONE  => PixelMode::None,
                ffi::FT_PIXEL_MODE_MONO  => PixelMode::Mono,
                ffi::FT_PIXEL_MODE_GRAY  => PixelMode::Gray,
                ffi::FT_PIXEL_MODE_GRAY2 => PixelMode::Gray2,
                ffi::FT_PIXEL_MODE_GRAY4 => PixelMode::Gray4,
                ffi::FT_PIXEL_MODE_LCD   => PixelMode::Lcd,
                ffi::FT_PIXEL_MODE_LCD_V => PixelMode::LcdV,
                ffi::FT_PIXEL_MODE_BGRA  => PixelMode::Bgra,
                _ => panic!("unexpected pixel mode"),
            }
        }
    }

    /// The pitch's absolute value is the number of bytes taken by one bitmap row, including
    /// padding. However, the pitch is positive when the bitmap has a ‘down’ flow, and negative
    /// when it has an ‘up’ flow. In all cases, the pitch is an offset to add to a bitmap pointer
    /// in order to go down one row.
    ///
    /// Note that ‘padding’ means the alignment of a bitmap to a byte border, and FreeType
    /// functions normally align to the smallest possible integer value.
    /// For the B/W rasterizer, ‘pitch’ is always an even number.
    ///
    /// To change the pitch of a bitmap (say, to make it a multiple of 4), use FT_Bitmap_Convert.
    /// Alternatively, you might use callback functions to directly render to the application's
    /// surface; see the file ‘example2.cpp’ in the tutorial for a demonstration.
    pub fn pitch(&self) -> isize {
        unsafe {
            (*self.raw).pitch as isize
        }
    }
}
<commit_msg>fix integer type of Bitmap pitch<commit_after>use std;
use ffi;

/// An enumeration type used to describe the format of pixels in a given bitmap. Note that
/// additional formats may be added in the future.
#[derive(Copy, Debug)]
pub enum PixelMode {
    /// This value is reserved.
    None,

    /// A monochrome bitmap, using 1 bit per pixel. Note that pixels are
    /// stored in most-significant order (MSB), which means that the left-most
    /// pixel in a byte has value 128.
    Mono,

    /// An 8-bit bitmap, generally used to represent anti-aliased glyph images.
    /// Each pixel is stored in one byte. Note that the number of `gray`
    /// levels is stored in the `num_grays` field of the FT_Bitmap structure
    /// (it generally is 256).
    Gray,

    /// A 2-bit per pixel bitmap, used to represent embedded anti-aliased
    /// bitmaps in font files according to the OpenType specification. We
    /// haven't found a single font using this format, however.
    Gray2,

    /// A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps in
    /// font files according to the OpenType specification. We haven't found a
    /// single font using this format, however.
    Gray4,

    /// An 8-bit bitmap, representing RGB or BGR decimated glyph images used
    /// for display on LCD displays; the bitmap is three times wider than the
    /// original glyph image. See also FT_RENDER_MODE_LCD.
    Lcd,

    /// An 8-bit bitmap, representing RGB or BGR decimated glyph images used for
    /// display on rotated LCD displays; the bitmap is three times taller than
    /// the original glyph image. See also FT_RENDER_MODE_LCD_V.
    LcdV,

    /// An image with four 8-bit channels per pixel, representing a color image
    /// (such as emoticons) with alpha channel. For each pixel, the format is
    /// BGRA, which means, the blue channel comes first in memory. The color
    /// channels are pre-multiplied and in the sRGB colorspace. For example,
    /// full red at half-translucent opacity will be represented as
    /// `00,00,80,80`, not `00,00,FF,80`. See also FT_LOAD_COLOR.
    Bgra,
}

#[allow(missing_copy_implementations)]
pub struct Bitmap {
    raw: *const ffi::FT_Bitmap,
}

impl Bitmap {
    pub fn from_raw(raw: *const ffi::FT_Bitmap) -> Bitmap {
        Bitmap {
            raw: raw,
        }
    }

    /// A typeless pointer to the bitmap buffer. This value should be aligned
    /// on 32-bit boundaries in most cases.
    pub fn buffer(&self) -> &[u8] {
        unsafe {
            std::slice::from_raw_buf(
                &(*self.raw).buffer,
                (self.width() * self.rows()) as usize,
            )
        }
    }

    /// The number of pixels in bitmap row.
    pub fn width(&self) -> i32 {
        unsafe {
            (*self.raw).width
        }
    }

    /// The number of bitmap rows.
    pub fn rows(&self) -> i32 {
        unsafe {
            (*self.raw).rows
        }
    }

    pub fn raw(&self) -> &ffi::FT_Bitmap {
        unsafe {
            &*self.raw
        }
    }

    /// The pixel mode, i.e., how pixel bits are stored. See `PixelMode` for
    /// possible values.
    pub fn pixel_mode(&self) -> PixelMode {
        unsafe {
            match (*self.raw).pixel_mode as u32 {
                ffi::FT_PIXEL_MODE_NONE  => PixelMode::None,
                ffi::FT_PIXEL_MODE_MONO  => PixelMode::Mono,
                ffi::FT_PIXEL_MODE_GRAY  => PixelMode::Gray,
                ffi::FT_PIXEL_MODE_GRAY2 => PixelMode::Gray2,
                ffi::FT_PIXEL_MODE_GRAY4 => PixelMode::Gray4,
                ffi::FT_PIXEL_MODE_LCD   => PixelMode::Lcd,
                ffi::FT_PIXEL_MODE_LCD_V => PixelMode::LcdV,
                ffi::FT_PIXEL_MODE_BGRA  => PixelMode::Bgra,
                _ => panic!("unexpected pixel mode"),
            }
        }
    }

    /// The pitch's absolute value is the number of bytes taken by one bitmap row, including
    /// padding. However, the pitch is positive when the bitmap has a ‘down’ flow, and negative
    /// when it has an ‘up’ flow. In all cases, the pitch is an offset to add to a bitmap pointer
    /// in order to go down one row.
    ///
    /// Note that ‘padding’ means the alignment of a bitmap to a byte border, and FreeType
    /// functions normally align to the smallest possible integer value.
    /// For the B/W rasterizer, ‘pitch’ is always an even number.
    ///
    /// To change the pitch of a bitmap (say, to make it a multiple of 4), use FT_Bitmap_Convert.
    /// Alternatively, you might use callback functions to directly render to the application's
    /// surface; see the file ‘example2.cpp’ in the tutorial for a demonstration.
    pub fn pitch(&self) -> i32 {
        unsafe {
            (*self.raw).pitch
        }
    }
}
<|endoftext|>


<commit_before>use irc;
use matrix;
use irc::protocol::{Command,Message};
use mio;
use mio::{EventLoop,Handler,Token,EventSet,PollOpt,Sender};
use std::thread;
use std::collections::HashMap;

const CLIENT: Token = Token(0);
const MATRIX: Token = Token(1);

pub struct Bridge {
    client: irc::streams::Client,
    matrix: matrix::client::Client,
    rooms: HashMap<matrix::events::RoomID, Room>
}

impl Handler for Bridge {
    type Timeout = ();
    type Message = irc::protocol::Message;

    fn ready(&mut self, event_loop: &mut EventLoop<Bridge>, token: Token, _: EventSet) {
        match token {
            CLIENT =>
                self.handle_client(event_loop),
            _ => unreachable!()
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Bridge>, msg: Self::Message) {
        println!("Got message from matrix! {:?}", msg);
        self.client.send(&msg);
    }
}

unsafe impl Sync for Bridge{}

struct Room {
    id: matrix::events::RoomID,
    canonical_alias: Option<String>,
    join_rules: Option<String>,
    members: Vec<matrix::events::UserID>
}

impl Room {
    fn new(id: matrix::events::RoomID) -> Self {
        Room {
            id: id,
            canonical_alias: None,
            join_rules: None,
            members: vec![]
        }
    }

    fn handle_event(&mut self, channel: &mio::Sender<irc::protocol::Message>, room_evt: matrix::events::RoomEvent) {
        match room_evt {
            matrix::events::RoomEvent::CanonicalAlias(name) => {
                let was_empty = self.canonical_alias == None;
                self.canonical_alias = Some(name.clone());
                if was_empty {
                    for ref u in &self.members {
                        self.send_join(u, channel);
                    }
                }
            },
            matrix::events::RoomEvent::JoinRules(rules) =>
                self.join_rules = Some(rules.clone()),
            matrix::events::RoomEvent::Membership(user, matrix::events::MembershipAction::Join) => {
                if self.canonical_alias != None {
                    self.send_join(&user, channel);
                }
                self.members.push(user);
            },
            matrix::events::RoomEvent::Create => (),
            matrix::events::RoomEvent::Aliases => (),
            matrix::events::RoomEvent::PowerLevels => (),
            matrix::events::RoomEvent::HistoryVisibility(_) => ()
        };
    }

    fn send_join(&self, user: &matrix::events::UserID, channel: &mio::Sender<irc::protocol::Message>) {
        channel.send(irc::protocol::Message {
            prefix: Some(format!("{}@anony.oob", user.nickname)),
            command: irc::protocol::Command::Join,
            args: vec![self.canonical_alias.clone().unwrap()],
            suffix: None
        });
    }
}

impl Bridge {
    pub fn room(&mut self, id: &matrix::events::RoomID) -> &mut Room {
        if !self.rooms.contains_key(id) {
            self.rooms.insert(id.clone(), Room::new(id.clone()));
        }
        match self.rooms.get_mut(id) {
            Some(room) => room,
            None => unreachable!()
        }
    }

    pub fn new(client: irc::streams::Client) -> Self {
        Bridge {
            client: client,
            matrix: matrix::client::Client::new(),
            rooms: HashMap::new()
        }
    }

    pub fn run(&mut self) {
        let mut events = EventLoop::new().unwrap();
        events.register(self.client.stream(), CLIENT, EventSet::all(), PollOpt::edge()).unwrap();
        events.run(self).unwrap();
    }

    fn handle_matrix(evt: matrix::events::Event, channel: &mio::Sender<irc::protocol::Message>) {
        match evt.data {
            /*matrix::events::EventData::Room(room_id, room_event) => {
                self.room(&room_id).handle_event(channel, room_event);
            },*/
            matrix::events::EventData::Text(text) => {
            },
            _ => println!("Unhandled {:?}", evt)
        }
    }

    fn poll_matrix(&mut self, channel: mio::Sender<irc::protocol::Message>) {
        let poll = self.matrix.pollAsync();
        thread::spawn(move|| {
            for evt in poll.send() {
                Bridge::handle_matrix(evt, &channel);
            };
        });
    }

    fn handle_client(&mut self, events: &mut EventLoop<Bridge>) {
        loop {
            match self.client.read_message() {
                None => return,
                Some(message) => {
                    println!("Got a message! {:?}", message);
                    match message.command {
                        Command::Pass => {
                            self.client.auth.set_password(message.args[0].clone())
                        }
                        Command::Nick => {
                            self.client.set_nickname(message.args[0].clone());
                        },
                        Command::User => {
                            println!("User logged in: {}", message.args[0]);
                            self.client.auth.set_username(message.args[0].clone());
                            let auth = self.client.auth.consume();
                            match (auth.username, auth.password) {
                                (Some(username), Some(password)) => {
                                    self.matrix.login(username.trim(), password.trim());
                                    self.client.welcome(username.trim());
                                    self.matrix.sync(|evt: matrix::events::Event| {
                                        Bridge::handle_matrix(evt, &events.channel());
                                    });
                                    self.poll_matrix(events.channel());
                                    println!("Logged in {:?}", username);
                                },
                                _ => panic!("Username and/or password missing")
                            };
                        },
                        Command::Join => {
                            self.client.join(&message.args[0]);
                        },
                        Command::Ping => {
                            self.client.pong();
                        },
                        Command::Quit => {
                            // FIXME: Logout of matrix and exit thread
                            return;
                        },
                        Command::Privmsg => {
                            let uid = matrix::events::UserID::from_str("@tdfischer:localhost");
                            let roomid = matrix::events::RoomID::from_str("!SNCDinqFeGteFrlCoN%3Alocalhost");
                            let evt = matrix::events::EventData::Text(
                                matrix::events::TextEvent::RoomMessage(
                                    uid, roomid, message.suffix.unwrap()));
                        },
                        _ =>
                            println!("unhandled {:?}", message)
                    }
                }
            }
        }
    }
}

<commit_msg>bridge: reimplement event bridging across threads<commit_after>use irc;
use matrix;
use irc::protocol::{Command,Message};
use mio;
use mio::{EventLoop,Handler,Token,EventSet,PollOpt,Sender};
use std::thread;
use std::collections::HashMap;

const CLIENT: Token = Token(0);
const MATRIX: Token = Token(1);

#[derive(Debug)]
pub enum Event {
    EndPoll,
    Matrix(matrix::events::Event)
}

pub struct Bridge {
    client: irc::streams::Client,
    matrix: matrix::client::Client,
    rooms: HashMap<matrix::events::RoomID, Room>
}

impl Handler for Bridge {
    type Timeout = ();
    type Message = Event;

    fn ready(&mut self, event_loop: &mut EventLoop<Bridge>, token: Token, _: EventSet) {
        match token {
            CLIENT =>
                self.handle_client(event_loop),
            _ => unreachable!()
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Bridge>, msg: Self::Message) {
        println!("Got message from matrix! {:?}", msg);
        match msg {
            Event::EndPoll => {
                self.poll_matrix(event_loop.channel());
            },
            Event::Matrix(e) =>
                self.handle_matrix(e)
        };
    }
}

unsafe impl Sync for Bridge{}

struct Room {
    id: matrix::events::RoomID,
    canonical_alias: Option<String>,
    join_rules: Option<String>,
    members: Vec<matrix::events::UserID>
}

impl Room {
    fn new(id: matrix::events::RoomID) -> Self {
        Room {
            id: id,
            canonical_alias: None,
            join_rules: None,
            members: vec![]
        }
    }

    fn handle_event<F>(&mut self, evt: matrix::events::RoomEvent, mut callback: F)
            where F: FnMut(irc::protocol::Message) {
        match evt {
            matrix::events::RoomEvent::CanonicalAlias(name) => {
                let was_empty = self.canonical_alias == None;
                self.canonical_alias = Some(name.clone());
                for ref user in &self.members {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@anony.oob", user.nickname)),
                        command: irc::protocol::Command::Join,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: None
                    });
                }
            },
            matrix::events::RoomEvent::JoinRules(rules) =>
                self.join_rules = Some(rules.clone()),
            matrix::events::RoomEvent::Membership(user, matrix::events::MembershipAction::Join) => {
                if self.canonical_alias != None {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@anony.oob", user.nickname)),
                        command: irc::protocol::Command::Join,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: None
                    });
                }
                self.members.push(user);
            },
            matrix::events::RoomEvent::Message(user, text) => {
                callback(irc::protocol::Message {
                    prefix: Some(format!("{}@anony.oob", user.nickname)),
                    command: irc::protocol::Command::Privmsg,
                    args: vec![self.canonical_alias.clone().unwrap()],
                    suffix: Some(text)
                });
            },
            matrix::events::RoomEvent::Create => (),
            matrix::events::RoomEvent::Aliases => (),
            matrix::events::RoomEvent::PowerLevels => (),
            matrix::events::RoomEvent::HistoryVisibility(_) => ()
        };
    }
}

impl Bridge {
    pub fn room(&mut self, id: &matrix::events::RoomID) -> &mut Room {
        if !self.rooms.contains_key(id) {
            self.rooms.insert(id.clone(), Room::new(id.clone()));
        }
        match self.rooms.get_mut(id) {
            Some(room) => room,
            None => unreachable!()
        }
    }

    pub fn new(client: irc::streams::Client) -> Self {
        Bridge {
            client: client,
            matrix: matrix::client::Client::new(),
            rooms: HashMap::new()
        }
    }

    pub fn run(&mut self) {
        let mut events = EventLoop::new().unwrap();
        events.register(self.client.stream(), CLIENT, EventSet::all(), PollOpt::edge()).unwrap();
        events.run(self).unwrap();
    }

    fn handle_matrix(&mut self, evt: matrix::events::Event) {
        let mut messages: Vec<irc::protocol::Message> = vec![];
        {
            let appendMsg = |msg: irc::protocol::Message| {
                messages.push(msg);
            };
            match evt.data {
                matrix::events::EventData::Room(room_id, room_event) => {
                    self.room(&room_id).handle_event(room_event, appendMsg);
                },
                _ => println!("Unhandled {:?}", evt)
            }
        }
        for ref msg in messages {
            self.client.send(msg);
        }
    }

    fn poll_matrix(&mut self, channel: mio::Sender<Event>) -> thread::JoinHandle<()> {
        let poll = self.matrix.pollAsync();
        thread::spawn(move|| {
            for evt in poll.send() {
                channel.send(Event::Matrix(evt));
            };
            channel.send(Event::EndPoll);
        })
    }

    fn start_matrix(&mut self, channel: mio::Sender<Event>) {
        self.matrix.sync(|evt: matrix::events::Event| {
            channel.send(Event::Matrix(evt));
        });
        self.poll_matrix(channel);
    }

    fn handle_client(&mut self, events: &mut EventLoop<Bridge>) {
        loop {
            match self.client.read_message() {
                None => return,
                Some(message) => {
                    println!("Got a message! {:?}", message);
                    match message.command {
                        Command::Pass => {
                            self.client.auth.set_password(message.args[0].clone())
                        }
                        Command::Nick => {
                            self.client.set_nickname(message.args[0].clone());
                        },
                        Command::User => {
                            println!("User logged in: {}", message.args[0]);
                            self.client.auth.set_username(message.args[0].clone());
                            let auth = self.client.auth.consume();
                            match (auth.username, auth.password) {
                                (Some(username), Some(password)) => {
                                    self.matrix.login(username.trim(), password.trim());
                                    self.client.welcome(username.trim());
                                    self.start_matrix(events.channel());
                                    println!("Logged in {:?}", username);
                                },
                                _ => panic!("Username and/or password missing")
                            };
                        },
                        Command::Join => {
                            self.client.join(&message.args[0]);
                        },
                        Command::Ping => {
                            self.client.pong();
                        },
                        Command::Quit => {
                            // FIXME: Logout of matrix and exit thread
                            return;
                        },
                        Command::Privmsg => {
                            let uid = matrix::events::UserID::from_str("@tdfischer:localhost");
                            let roomid = matrix::events::RoomID::from_str("!SNCDinqFeGteFrlCoN:localhost");
                            let evt = matrix::events::EventData::Room(
                                roomid,
                                matrix::events::RoomEvent::Message(
                                    uid, message.suffix.unwrap()));
                            self.matrix.send(evt);
                        },
                        _ =>
                            println!("unhandled {:?}", message)
                    }
                }
            }
        }
    }
}

<|endoftext|>


<commit_before>use unicode_width::UnicodeWidthStr;
use std::io::{self, Write};
use std::iter::FromIterator;

#[derive(Debug,Clone)]
pub enum Action {
    Insert {
        start: usize,
        text: Vec<char>,
    },
    Remove {
        start: usize,
        text: Vec<char>,
    },
}

impl Action {
    pub fn do_on(&self, buf: &mut Buffer) {
        match *self {
            Action::Insert { start, ref text } => buf.insert_raw(start, &text[..]),
            Action::Remove { start, ref text } => {
                buf.remove_raw(start, start + text.len());
            }
        }
    }

    pub fn undo(&self, buf: &mut Buffer) {
        match *self {
            Action::Insert { start, ref text } => {
                buf.remove_raw(start, start + text.len());
            }
            Action::Remove { start, ref text } => buf.insert_raw(start, &text[..]),
        }
    }
}

#[derive(Debug, Clone)]
pub struct Buffer {
    data: Vec<char>,
    actions: Vec<Action>,
    undone_actions: Vec<Action>,
}

impl From<Buffer> for String {
    fn from(buf: Buffer) -> Self {
        String::from_iter(buf.data)
    }
}

impl From<String> for Buffer {
    fn from(s: String) -> Self {
        Buffer::from_iter(s.chars())
    }
}

impl<'a> From<&'a str> for Buffer {
    fn from(s: &'a str) -> Self {
        Buffer::from_iter(s.chars())
    }
}

impl FromIterator<char> for Buffer {
    fn from_iter<T: IntoIterator<Item = char>>(t: T) -> Self {
        Buffer {
            data: t.into_iter().collect(),
            actions: Vec::new(),
            undone_actions: Vec::new(),
        }
    }
}

impl Buffer {
    pub fn new() -> Self {
        Buffer {
            data: Vec::new(),
            actions: Vec::new(),
            undone_actions: Vec::new(),
        }
    }

    pub fn clear_actions(&mut self) {
        self.actions.clear();
        self.undone_actions.clear();
    }

    pub fn undo(&mut self) -> bool {
        match self.actions.pop() {
            None => false,
            Some(act) => {
                act.undo(self);
                self.undone_actions.push(act);
                true
            }
        }
    }

    pub fn redo(&mut self) -> bool {
        match self.undone_actions.pop() {
            None => false,
            Some(act) => {
                act.do_on(self);
                self.actions.push(act);
                true
            }
        }
    }

    pub fn revert(&mut self) -> bool {
        if self.actions.len() == 0 {
            return false;
        }

        while self.undo() {}
        true
    }

    fn push_action(&mut self, act: Action) {
        self.actions.push(act);
        self.undone_actions.clear();
    }

    pub fn num_chars(&self) -> usize {
        self.data.len()
    }

    pub fn num_bytes(&self) -> usize {
        let s: String = self.clone().into();
        s.len()
    }

    pub fn width(&self) -> usize {
        self.range_width(0, self.num_chars())
    }

    pub fn char_before(&self, cursor: usize) -> Option<char> {
        if cursor == 0 {
            None
        } else {
            self.data.get(cursor - 1).cloned()
        }
    }

    pub fn char_after(&self, cursor: usize) -> Option<char> {
        self.data.get(cursor).cloned()
    }

    /// Returns the number of characters removed.
    pub fn remove(&mut self, start: usize, end: usize) -> usize {
        let s = self.remove_raw(start, end);
        let num_removed = s.len();
        let act = Action::Remove {
            start: start,
            text: s,
        };
        self.push_action(act);
        num_removed
    }

    pub fn insert(&mut self, start: usize, text: &[char]) {
        let act = Action::Insert {
            start: start,
            text: text.into(),
        };
        act.do_on(self);
        self.push_action(act);
    }

    pub fn range(&self, start: usize, end: usize) -> String {
        self.data[start..end].iter().cloned().collect()
    }

    pub fn range_chars(&self, start: usize, end: usize) -> Vec<char> {
        self.data[start..end].iter().cloned().collect()
    }

    pub fn range_width(&self, start: usize, end: usize) -> usize {
        self.range(start, end)[..].width()
    }

    pub fn chars(&self) -> ::std::slice::Iter<char> {
        self.data.iter()
    }

    pub fn truncate(&mut self, num: usize) {
        self.data.truncate(num);
    }

    pub fn print<W>(&self, out: &mut W) -> io::Result<()>
        where W: Write
    {
        let string: String = self.data.iter().cloned().collect();
        try!(out.write(string.as_bytes()));

        Ok(())
    }

    fn remove_raw(&mut self, start: usize, end: usize) -> Vec<char> {
        self.data.drain(start..end).collect()
    }

    fn insert_raw(&mut self, start: usize, text: &[char]) {
        for (i, &c) in text.iter().enumerate() {
            self.data.insert(start + i, c)
        }
    }
}
<commit_msg>impl fmt::Display for Buffer, closes #15<commit_after>use unicode_width::UnicodeWidthStr;
use std::io::{self, Write};
use std::iter::FromIterator;
use std::fmt::{self, Write as FmtWrite};

#[derive(Debug,Clone)]
pub enum Action {
    Insert {
        start: usize,
        text: Vec<char>,
    },
    Remove {
        start: usize,
        text: Vec<char>,
    },
}

impl Action {
    pub fn do_on(&self, buf: &mut Buffer) {
        match *self {
            Action::Insert { start, ref text } => buf.insert_raw(start, &text[..]),
            Action::Remove { start, ref text } => {
                buf.remove_raw(start, start + text.len());
            }
        }
    }

    pub fn undo(&self, buf: &mut Buffer) {
        match *self {
            Action::Insert { start, ref text } => {
                buf.remove_raw(start, start + text.len());
            }
            Action::Remove { start, ref text } => buf.insert_raw(start, &text[..]),
        }
    }
}

#[derive(Debug, Clone)]
pub struct Buffer {
    data: Vec<char>,
    actions: Vec<Action>,
    undone_actions: Vec<Action>,
}

impl From<Buffer> for String {
    fn from(buf: Buffer) -> Self {
        String::from_iter(buf.data)
    }
}

impl From<String> for Buffer {
    fn from(s: String) -> Self {
        Buffer::from_iter(s.chars())
    }
}

impl<'a> From<&'a str> for Buffer {
    fn from(s: &'a str) -> Self {
        Buffer::from_iter(s.chars())
    }
}

impl fmt::Display for Buffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for &c in &self.data {
            try!(f.write_char(c));
        }
        Ok(())
    }
}

impl FromIterator<char> for Buffer {
    fn from_iter<T: IntoIterator<Item = char>>(t: T) -> Self {
        Buffer {
            data: t.into_iter().collect(),
            actions: Vec::new(),
            undone_actions: Vec::new(),
        }
    }
}

impl Buffer {
    pub fn new() -> Self {
        Buffer {
            data: Vec::new(),
            actions: Vec::new(),
            undone_actions: Vec::new(),
        }
    }

    pub fn clear_actions(&mut self) {
        self.actions.clear();
        self.undone_actions.clear();
    }

    pub fn undo(&mut self) -> bool {
        match self.actions.pop() {
            None => false,
            Some(act) => {
                act.undo(self);
                self.undone_actions.push(act);
                true
            }
        }
    }

    pub fn redo(&mut self) -> bool {
        match self.undone_actions.pop() {
            None => false,
            Some(act) => {
                act.do_on(self);
                self.actions.push(act);
                true
            }
        }
    }

    pub fn revert(&mut self) -> bool {
        if self.actions.len() == 0 {
            return false;
        }

        while self.undo() {}
        true
    }

    fn push_action(&mut self, act: Action) {
        self.actions.push(act);
        self.undone_actions.clear();
    }

    pub fn num_chars(&self) -> usize {
        self.data.len()
    }

    pub fn num_bytes(&self) -> usize {
        let s: String = self.clone().into();
        s.len()
    }

    pub fn width(&self) -> usize {
        self.range_width(0, self.num_chars())
    }

    pub fn char_before(&self, cursor: usize) -> Option<char> {
        if cursor == 0 {
            None
        } else {
            self.data.get(cursor - 1).cloned()
        }
    }

    pub fn char_after(&self, cursor: usize) -> Option<char> {
        self.data.get(cursor).cloned()
    }

    /// Returns the number of characters removed.
    pub fn remove(&mut self, start: usize, end: usize) -> usize {
        let s = self.remove_raw(start, end);
        let num_removed = s.len();
        let act = Action::Remove {
            start: start,
            text: s,
        };
        self.push_action(act);
        num_removed
    }

    pub fn insert(&mut self, start: usize, text: &[char]) {
        let act = Action::Insert {
            start: start,
            text: text.into(),
        };
        act.do_on(self);
        self.push_action(act);
    }

    pub fn range(&self, start: usize, end: usize) -> String {
        self.data[start..end].iter().cloned().collect()
    }

    pub fn range_chars(&self, start: usize, end: usize) -> Vec<char> {
        self.data[start..end].iter().cloned().collect()
    }

    pub fn range_width(&self, start: usize, end: usize) -> usize {
        self.range(start, end)[..].width()
    }

    pub fn chars(&self) -> ::std::slice::Iter<char> {
        self.data.iter()
    }

    pub fn truncate(&mut self, num: usize) {
        self.data.truncate(num);
    }

    pub fn print<W>(&self, out: &mut W) -> io::Result<()>
        where W: Write
    {
        let string: String = self.data.iter().cloned().collect();
        try!(out.write(string.as_bytes()));

        Ok(())
    }

    fn remove_raw(&mut self, start: usize, end: usize) -> Vec<char> {
        self.data.drain(start..end).collect()
    }

    fn insert_raw(&mut self, start: usize, text: &[char]) {
        for (i, &c) in text.iter().enumerate() {
            self.data.insert(start + i, c)
        }
    }
}
<|endoftext|>


<commit_before>extern crate c_ares_sys;
extern crate libc;

use std::ffi::CStr;
use std::marker::PhantomData;
use std::mem;
use std::str;
use std::ptr;
use std::slice;

use types::AresError;
use utils::ares_error;

/// The result of a successful NAPTR lookup.
pub struct NAPTRResults {
    naptr_reply: *mut c_ares_sys::Struct_ares_naptr_reply,
    phantom: PhantomData<c_ares_sys::Struct_ares_naptr_reply>,
}

/// The contents of a single NAPTR record.
pub struct NAPTRResult<'a> {
    naptr_reply: *mut c_ares_sys::Struct_ares_naptr_reply,
    phantom: PhantomData<&'a c_ares_sys::Struct_ares_naptr_reply>,
}

impl NAPTRResults {
    #[cfg(feature = "old-cares")]
    pub fn parse_from(_data: &[u8]) -> Result<NAPTRResults, AresError> {
        panic!("NAPTR parsing not supported");
    }

    /// Obtain a `NAPTRResults` from the response to a NAPTR lookup.
    #[cfg(not(feature = "old-cares"))]
    pub fn parse_from(data: &[u8]) -> Result<NAPTRResults, AresError> {
        let mut naptr_reply: *mut c_ares_sys::Struct_ares_naptr_reply =
            ptr::null_mut();
        let parse_status = unsafe {
            c_ares_sys::ares_parse_naptr_reply(
                data.as_ptr(),
                data.len() as libc::c_int,
                &mut naptr_reply)
        };
        if parse_status != c_ares_sys::ARES_SUCCESS {
            Err(ares_error(parse_status))
        } else {
            let naptr_result = NAPTRResults::new(naptr_reply);
            Ok(naptr_result)
        }
    }

    fn new(
        reply: *mut c_ares_sys::Struct_ares_naptr_reply) -> NAPTRResults {
        NAPTRResults {
            naptr_reply: reply,
            phantom: PhantomData,
        }
    }

    /// Returns an iterator over the `NAPTRResult` values in this
    /// `NAPTRResults`.
    pub fn iter(&self) -> NAPTRResultsIterator {
        NAPTRResultsIterator {
            next: self.naptr_reply,
            phantom: PhantomData,
        }
    }
}

pub struct NAPTRResultsIterator<'a> {
    next: *mut c_ares_sys::Struct_ares_naptr_reply,
    phantom: PhantomData<&'a c_ares_sys::Struct_ares_naptr_reply>,
}

impl<'a> Iterator for NAPTRResultsIterator<'a> {
    type Item = NAPTRResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        let naptr_reply = self.next;
        if naptr_reply.is_null() {
            None
        } else {
            self.next = unsafe { (*naptr_reply).next };
            let naptr_result = NAPTRResult {
                naptr_reply: naptr_reply,
                phantom: PhantomData,
            };
            Some(naptr_result)
        }
    }
}

impl<'a> IntoIterator for &'a NAPTRResults {
    type Item = NAPTRResult<'a>;
    type IntoIter = NAPTRResultsIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        NAPTRResultsIterator {
            next: self.naptr_reply,
            phantom: PhantomData,
        }
    }
}

impl Drop for NAPTRResults {
    fn drop(&mut self) {
        unsafe {
            c_ares_sys::ares_free_data(self.naptr_reply as *mut libc::c_void);
        }
    }
}

unsafe impl Send for NAPTRResults { }
unsafe impl Sync for NAPTRResults { }
unsafe impl<'a> Send for NAPTRResult<'a> { }
unsafe impl<'a> Sync for NAPTRResult<'a> { }
unsafe impl<'a> Send for NAPTRResultsIterator<'a> { }
unsafe impl<'a> Sync for NAPTRResultsIterator<'a> { }

impl<'a> NAPTRResult<'a> {
    /// Returns the flags in this `NAPTRResult`.
    pub fn flags(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(
                (*self.naptr_reply).flags as *const libc::c_char);
            str::from_utf8(c_str.to_bytes()).unwrap()
        }
    }

    /// Returns the service name in this `NAPTRResult`.
    pub fn service_name(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(
                (*self.naptr_reply).service as *const libc::c_char);
            str::from_utf8(c_str.to_bytes()).unwrap()
        }
    }

    /// Returns the regular expression in this `NAPTRResult`.
    pub fn reg_exp(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(
                (*self.naptr_reply).regexp as *const libc::c_char);
            str::from_utf8(c_str.to_bytes()).unwrap()
        }
    }

    /// Returns the replacement pattern in this `NAPTRResult`.
    pub fn replacement_pattern(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr((*self.naptr_reply).replacement);
            str::from_utf8(c_str.to_bytes()).unwrap()
        }
    }

    /// Returns the order value in this `NAPTRResult`.
    pub fn order(&self) -> u16 {
        unsafe { (*self.naptr_reply).order }
    }

    /// Returns the preference value in this `NAPTRResult`.
    pub fn preference(&self) -> u16 {
        unsafe { (*self.naptr_reply).preference }
    }
}

pub unsafe extern "C" fn query_naptr_callback<F>(
    arg: *mut libc::c_void,
    status: libc::c_int,
    _timeouts: libc::c_int,
    abuf: *mut libc::c_uchar,
    alen: libc::c_int)
    where F: FnOnce(Result<NAPTRResults, AresError>) + 'static {
    let result = if status != c_ares_sys::ARES_SUCCESS {
        Err(ares_error(status))
    } else {
        let data = slice::from_raw_parts(abuf, alen as usize);
        NAPTRResults::parse_from(data)
    };
    let handler: Box<F> = mem::transmute(arg);
    handler(result);
}
<commit_msg>Whitespace<commit_after>extern crate c_ares_sys;
extern crate libc;

use std::ffi::CStr;
use std::marker::PhantomData;
use std::mem;
use std::str;
use std::ptr;
use std::slice;

use types::AresError;
use utils::ares_error;

/// The result of a successful NAPTR lookup.
pub struct NAPTRResults {
    naptr_reply: *mut c_ares_sys::Struct_ares_naptr_reply,
    phantom: PhantomData<c_ares_sys::Struct_ares_naptr_reply>,
}

/// The contents of a single NAPTR record.
pub struct NAPTRResult<'a> {
    naptr_reply: *mut c_ares_sys::Struct_ares_naptr_reply,
    phantom: PhantomData<&'a c_ares_sys::Struct_ares_naptr_reply>,
}

impl NAPTRResults {
    #[cfg(feature = "old-cares")]
    pub fn parse_from(_data: &[u8]) -> Result<NAPTRResults, AresError> {
        panic!("NAPTR parsing not supported");
    }

    /// Obtain a `NAPTRResults` from the response to a NAPTR lookup.
    #[cfg(not(feature = "old-cares"))]
    pub fn parse_from(data: &[u8]) -> Result<NAPTRResults, AresError> {
        let mut naptr_reply: *mut c_ares_sys::Struct_ares_naptr_reply =
            ptr::null_mut();
        let parse_status = unsafe {
            c_ares_sys::ares_parse_naptr_reply(
                data.as_ptr(),
                data.len() as libc::c_int,
                &mut naptr_reply)
        };
        if parse_status != c_ares_sys::ARES_SUCCESS {
            Err(ares_error(parse_status))
        } else {
            let naptr_result = NAPTRResults::new(naptr_reply);
            Ok(naptr_result)
        }
    }

    fn new(
        reply: *mut c_ares_sys::Struct_ares_naptr_reply) -> NAPTRResults {
        NAPTRResults {
            naptr_reply: reply,
            phantom: PhantomData,
        }
    }

    /// Returns an iterator over the `NAPTRResult` values in this
    /// `NAPTRResults`.
    pub fn iter(&self) -> NAPTRResultsIterator {
        NAPTRResultsIterator {
            next: self.naptr_reply,
            phantom: PhantomData,
        }
    }
}

pub struct NAPTRResultsIterator<'a> {
    next: *mut c_ares_sys::Struct_ares_naptr_reply,
    phantom: PhantomData<&'a c_ares_sys::Struct_ares_naptr_reply>,
}

impl<'a> Iterator for NAPTRResultsIterator<'a> {
    type Item = NAPTRResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        let naptr_reply = self.next;
        if naptr_reply.is_null() {
            None
        } else {
            self.next = unsafe { (*naptr_reply).next };
            let naptr_result = NAPTRResult {
                naptr_reply: naptr_reply,
                phantom: PhantomData,
            };
            Some(naptr_result)
        }
    }
}

impl<'a> IntoIterator for &'a NAPTRResults {
    type Item = NAPTRResult<'a>;
    type IntoIter = NAPTRResultsIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        NAPTRResultsIterator {
            next: self.naptr_reply,
            phantom: PhantomData,
        }
    }
}

impl Drop for NAPTRResults {
    fn drop(&mut self) {
        unsafe {
            c_ares_sys::ares_free_data(self.naptr_reply as *mut libc::c_void);
        }
    }
}

unsafe impl Send for NAPTRResults { }
unsafe impl Sync for NAPTRResults { }
unsafe impl<'a> Send for NAPTRResult<'a> { }
unsafe impl<'a> Sync for NAPTRResult<'a> { }
unsafe impl<'a> Send for NAPTRResultsIterator<'a> { }
unsafe impl<'a> Sync for NAPTRResultsIterator<'a> { }

impl<'a> NAPTRResult<'a> {
    /// Returns the flags in this `NAPTRResult`.
    pub fn flags(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(
                (*self.naptr_reply).flags as *const libc::c_char);
            str::from_utf8(c_str.to_bytes()).unwrap()
        }
    }

    /// Returns the service name in this `NAPTRResult`.
    pub fn service_name(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(
                (*self.naptr_reply).service as *const libc::c_char);
            str::from_utf8(c_str.to_bytes()).unwrap()
        }
    }

    /// Returns the regular expression in this `NAPTRResult`.
    pub fn reg_exp(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(
                (*self.naptr_reply).regexp as *const libc::c_char);
            str::from_utf8(c_str.to_bytes()).unwrap()
        }
    }

    /// Returns the replacement pattern in this `NAPTRResult`.
    pub fn replacement_pattern(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr((*self.naptr_reply).replacement);
            str::from_utf8(c_str.to_bytes()).unwrap()
        }
    }

    /// Returns the order value in this `NAPTRResult`.
    pub fn order(&self) -> u16 {
        unsafe { (*self.naptr_reply).order }
    }

    /// Returns the preference value in this `NAPTRResult`.
    pub fn preference(&self) -> u16 {
        unsafe { (*self.naptr_reply).preference }
    }
}

pub unsafe extern "C" fn query_naptr_callback<F>(
    arg: *mut libc::c_void,
    status: libc::c_int,
    _timeouts: libc::c_int,
    abuf: *mut libc::c_uchar,
    alen: libc::c_int)
    where F: FnOnce(Result<NAPTRResults, AresError>) + 'static {
    let result = if status != c_ares_sys::ARES_SUCCESS {
        Err(ares_error(status))
    } else {
        let data = slice::from_raw_parts(abuf, alen as usize);
        NAPTRResults::parse_from(data)
    };
    let handler: Box<F> = mem::transmute(arg);
    handler(result);
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Panic handling and stack unwinding

use core::fmt::{Arguments, Write};
use super::io::term;
use vga::Color;

#[lang = "panic_fmt"]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn rust_begin_unwind( args: Arguments
                                   , file: &'static str
                                   , line: usize )
                                   -> ! {
    write!(term::CONSOLE.lock()
                        .set_colors(Color::White, Color::Red)
                        .clear()
          , "Something has gone horribly wrong in {} at line {}. \
            \n{}\n\
            This is fine."
          , file, line, args
          );
    loop { }
}

#[lang = "stack_exhausted"]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn __morestack() -> ! {
    println!("stack exhausted");
    loop { }
}

#[allow(non_snake_case)]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn _Unwind_Resume() -> ! {
    println!("UNWIND!");
    loop { }
}

// #[lang = "begin_unwind"]
// #[no_mangle] #[inline(never)] #[cold]
// pub fn begin_unwind<M: Send>(msg: M
//                             , file_line: &(&'static str, usize))  -> !
// { loop { } }
<commit_msg>[kernel] update for compatibility with latest nightly<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Panic handling and stack unwinding

use core::fmt::{Arguments, Write};
use super::io::term;
use vga::Color;

#[lang = "panic_fmt"]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn rust_begin_unwind( args: Arguments
                                   , file: &'static str
                                   , line: usize )
                                   -> ! {
    write!(term::CONSOLE.lock()
                        .set_colors(Color::White, Color::Red)
                        .clear()
          , "Something has gone horribly wrong in {} at line {}. \
            \n{}\n\
            This is fine."
          , file, line, args
          );
    loop { }
}

// #[lang = "stack_exhausted"]
// #[no_mangle] #[inline(never)] #[cold]
// pub extern "C" fn __morestack() -> ! {
//     println!("stack exhausted");
//     loop { }
// }

#[allow(non_snake_case)]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn _Unwind_Resume() -> ! {
    println!("UNWIND!");
    loop { }
}

// #[lang = "begin_unwind"]
// #[no_mangle] #[inline(never)] #[cold]
// pub fn begin_unwind<M: Send>(msg: M
//                             , file_line: &(&'static str, usize))  -> !
// { loop { } }
<|endoftext|>