<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Runs hardware devices in child processes.

use std::fmt::{self, Display};
use std::os::unix::io::{AsRawFd, RawFd};
use std::time::Duration;
use std::{self, io};

use io_jail::{self, Minijail};
use libc::{self, pid_t};
use msg_socket::{MsgOnSocket, MsgReceiver, MsgSender, MsgSocket};
use sys_util::{error, net::UnixSeqpacket};

use crate::BusDevice;

/// Errors for proxy devices.
#[derive(Debug)]
pub enum Error {
    ForkingJail(io_jail::Error),
    Io(io::Error),
}
pub type Result<T> = std::result::Result<T, Error>;

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            ForkingJail(e) => write!(f, "Failed to fork jail process: {}", e),
            Io(e) => write!(f, "IO error configuring proxy device {}.", e),
        }
    }
}

const SOCKET_TIMEOUT_MS: u64 = 2000;

#[derive(MsgOnSocket)]
enum Command {
    Read {
        len: u32,
        offset: u64,
    },
    Write {
        len: u32,
        offset: u64,
        data: [u8; 8],
    },
    ReadConfig(u32),
    WriteConfig {
        reg_idx: u32,
        offset: u32,
        len: u32,
        data: [u8; 4],
    },
    Shutdown,
    RunUserCommand,
}

#[derive(MsgOnSocket)]
enum CommandResult {
    Ok,
    ReadResult([u8; 8]),
    ReadConfigResult(u32),
}

fn child_proc<D: BusDevice, F: FnMut(&mut D)>(
    sock: UnixSeqpacket,
    device: &mut D,
    mut user_command: F,
) {
    let mut running = true;
    let sock = MsgSocket::<CommandResult, Command>::new(sock);

    while running {
        let cmd = match sock.recv() {
            Ok(cmd) => cmd,
            Err(err) => {
                error!("child device process failed recv: {}", err);
                break;
            }
        };

        let res = match cmd {
            Command::Read { len, offset } => {
                let mut buffer = [0u8; 8];
                device.read(offset, &mut buffer[0..len as usize]);
                sock.send(&CommandResult::ReadResult(buffer))
            }
            Command::Write { len, offset, data } => {
                let len = len as usize;
                device.write(offset, &data[0..len]);
                // Command::Write does not have a result.
                Ok(())
            }
            Command::ReadConfig(idx) => {
                let val = device.config_register_read(idx as usize);
                sock.send(&CommandResult::ReadConfigResult(val))
            }
            Command::WriteConfig {
                reg_idx,
                offset,
                len,
                data,
            } => {
                let len = len as usize;
                device.config_register_write(reg_idx as usize, offset as u64, &data[0..len]);
                // Command::WriteConfig does not have a result.
                Ok(())
            }
            Command::Shutdown => {
                running = false;
                sock.send(&CommandResult::Ok)
            }
            Command::RunUserCommand => {
                user_command(device);
                sock.send(&CommandResult::Ok)
            }
        };
        if let Err(e) = res {
            error!("child device process failed send: {}", e);
        }
    }
}

/// Wraps an inner `BusDevice` that is run inside a child process via fork.
///
/// Because forks are very unfriendly to destructors and all memory mappings and file descriptors
/// are inherited, this should be used as early as possible in the main process.
pub struct ProxyDevice {
    sock: MsgSocket<Command, CommandResult>,
    pid: pid_t,
    debug_label: String,
}

impl ProxyDevice {
    /// Takes the given device and isolates it into another process via fork before returning.
    ///
    /// The forked process will automatically be terminated when this is dropped, so be sure to keep
    /// a reference.
    ///
    /// # Arguments
    /// * `device` - The device to isolate to another process.
    /// * `jail` - The jail to use for isolating the given device.
    /// * `keep_fds` - File descriptors that will be kept open in the child.
    pub fn new<D: BusDevice>(
        device: D,
        jail: &Minijail,
        keep_fds: Vec<RawFd>,
    ) -> Result<ProxyDevice> {
        Self::new_with_user_command(device, jail, keep_fds, |_| {})
    }

    /// Similar to `ProxyDevice::new`, but adds an additional custom command to be run in the forked
    /// process when `run_user_command` is called.
    ///
    /// Note that the custom command closure is run in the main thread of the child process, which
    /// also services `BusDevice` requests. Therefore, do not run blocking calls in the closure
    /// without a timeout, or you will block any VCPU which touches this device, and every other
    /// thread which needs to lock this device's mutex.
    ///
    /// # Arguments
    /// * `device` - The device to isolate to another process.
    /// * `jail` - The jail to use for isolating the given device.
    /// * `keep_fds` - File descriptors that will be kept open in the child.
    /// * `user_command` - Closure to be run in the forked process.
    pub fn new_with_user_command<D: BusDevice, F: FnMut(&mut D)>(
        mut device: D,
        jail: &Minijail,
        mut keep_fds: Vec<RawFd>,
        user_command: F,
    ) -> Result<ProxyDevice> {
        let debug_label = device.debug_label();
        let (child_sock, parent_sock) = UnixSeqpacket::pair().map_err(Error::Io)?;

        keep_fds.push(child_sock.as_raw_fd());
        // Forking here is safe as long as the program is still single threaded.
        let pid = unsafe {
            match jail.fork(Some(&keep_fds)).map_err(Error::ForkingJail)? {
                0 => {
                    device.on_sandboxed();
                    child_proc(child_sock, &mut device, user_command);

                    // We're explicitly not using std::process::exit here to avoid the cleanup of
                    // stdout/stderr globals. This can cause cascading panics and SIGILL if a worker
                    // thread attempts to log to stderr after at_exit handlers have been run.
                    // TODO(crbug.com/992494): Remove this once device shutdown ordering is clearly
                    // defined.
                    //
                    // exit() is trivially safe.
                    // ! Never returns
                    libc::exit(0);
                }
                p => p,
            }
        };

        parent_sock
            .set_write_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS)))
            .map_err(Error::Io)?;
        parent_sock
            .set_read_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS)))
            .map_err(Error::Io)?;
        Ok(ProxyDevice {
            sock: MsgSocket::<Command, CommandResult>::new(parent_sock),
            pid,
            debug_label,
        })
    }

    pub fn pid(&self) -> pid_t {
        self.pid
    }

    /// Runs the callback given in `new_with_custom_command` in the child device process.
    pub fn run_user_command(&self) {
        self.sync_send(Command::RunUserCommand);
    }

    /// Send a command that does not expect a response from the child device process.
    fn send_no_result(&self, cmd: Command) {
        let res = self.sock.send(&cmd);
        if let Err(e) = res {
            error!(
                "failed write to child device process {}: {}",
                self.debug_label, e,
            );
        }
    }

    /// Send a command and read its response from the child device process.
    fn sync_send(&self, cmd: Command) -> Option<CommandResult> {
        self.send_no_result(cmd);
        match self.sock.recv() {
            Err(e) => {
                error!(
                    "failed read from child device process {}: {}",
                    self.debug_label, e,
                );
                None
            }
            Ok(r) => Some(r),
        }
    }
}

impl BusDevice for ProxyDevice {
    fn debug_label(&self) -> String {
        self.debug_label.clone()
    }

    fn config_register_write(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
        let len = data.len() as u32;
        let mut buffer = [0u8; 4];
        buffer[0..data.len()].clone_from_slice(data);
        let reg_idx = reg_idx as u32;
        let offset = offset as u32;
        self.send_no_result(Command::WriteConfig {
            reg_idx,
            offset,
            len,
            data: buffer,
        });
    }

    fn config_register_read(&self, reg_idx: usize) -> u32 {
        let res = self.sync_send(Command::ReadConfig(reg_idx as u32));
        if let Some(CommandResult::ReadConfigResult(val)) = res {
            val
        } else {
            0
        }
    }

    fn read(&mut self, offset: u64, data: &mut [u8]) {
        let len = data.len() as u32;
        if let Some(CommandResult::ReadResult(buffer)) =
            self.sync_send(Command::Read { len, offset })
        {
            let len = data.len();
            data.clone_from_slice(&buffer[0..len]);
        }
    }

    fn write(&mut self, offset: u64, data: &[u8]) {
        let mut buffer = [0u8; 8];
        let len = data.len() as u32;
        buffer[0..data.len()].clone_from_slice(data);
        self.send_no_result(Command::Write {
            len,
            offset,
            data: buffer,
        });
    }
}

impl Drop for ProxyDevice {
    fn drop(&mut self) {
        self.sync_send(Command::Shutdown);
    }
}
<commit_msg>devices: proxy: print failed command on error<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Runs hardware devices in child processes.

use std::fmt::{self, Display};
use std::os::unix::io::{AsRawFd, RawFd};
use std::time::Duration;
use std::{self, io};

use io_jail::{self, Minijail};
use libc::{self, pid_t};
use msg_socket::{MsgOnSocket, MsgReceiver, MsgSender, MsgSocket};
use sys_util::{error, net::UnixSeqpacket};

use crate::BusDevice;

/// Errors for proxy devices.
#[derive(Debug)]
pub enum Error {
    ForkingJail(io_jail::Error),
    Io(io::Error),
}
pub type Result<T> = std::result::Result<T, Error>;

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            ForkingJail(e) => write!(f, "Failed to fork jail process: {}", e),
            Io(e) => write!(f, "IO error configuring proxy device {}.", e),
        }
    }
}

const SOCKET_TIMEOUT_MS: u64 = 2000;

#[derive(Debug, MsgOnSocket)]
enum Command {
    Read {
        len: u32,
        offset: u64,
    },
    Write {
        len: u32,
        offset: u64,
        data: [u8; 8],
    },
    ReadConfig(u32),
    WriteConfig {
        reg_idx: u32,
        offset: u32,
        len: u32,
        data: [u8; 4],
    },
    Shutdown,
    RunUserCommand,
}

#[derive(MsgOnSocket)]
enum CommandResult {
    Ok,
    ReadResult([u8; 8]),
    ReadConfigResult(u32),
}

fn child_proc<D: BusDevice, F: FnMut(&mut D)>(
    sock: UnixSeqpacket,
    device: &mut D,
    mut user_command: F,
) {
    let mut running = true;
    let sock = MsgSocket::<CommandResult, Command>::new(sock);

    while running {
        let cmd = match sock.recv() {
            Ok(cmd) => cmd,
            Err(err) => {
                error!("child device process failed recv: {}", err);
                break;
            }
        };

        let res = match cmd {
            Command::Read { len, offset } => {
                let mut buffer = [0u8; 8];
                device.read(offset, &mut buffer[0..len as usize]);
                sock.send(&CommandResult::ReadResult(buffer))
            }
            Command::Write { len, offset, data } => {
                let len = len as usize;
                device.write(offset, &data[0..len]);
                // Command::Write does not have a result.
                Ok(())
            }
            Command::ReadConfig(idx) => {
                let val = device.config_register_read(idx as usize);
                sock.send(&CommandResult::ReadConfigResult(val))
            }
            Command::WriteConfig {
                reg_idx,
                offset,
                len,
                data,
            } => {
                let len = len as usize;
                device.config_register_write(reg_idx as usize, offset as u64, &data[0..len]);
                // Command::WriteConfig does not have a result.
                Ok(())
            }
            Command::Shutdown => {
                running = false;
                sock.send(&CommandResult::Ok)
            }
            Command::RunUserCommand => {
                user_command(device);
                sock.send(&CommandResult::Ok)
            }
        };
        if let Err(e) = res {
            error!("child device process failed send: {}", e);
        }
    }
}

/// Wraps an inner `BusDevice` that is run inside a child process via fork.
///
/// Because forks are very unfriendly to destructors and all memory mappings and file descriptors
/// are inherited, this should be used as early as possible in the main process.
pub struct ProxyDevice {
    sock: MsgSocket<Command, CommandResult>,
    pid: pid_t,
    debug_label: String,
}

impl ProxyDevice {
    /// Takes the given device and isolates it into another process via fork before returning.
    ///
    /// The forked process will automatically be terminated when this is dropped, so be sure to keep
    /// a reference.
    ///
    /// # Arguments
    /// * `device` - The device to isolate to another process.
    /// * `jail` - The jail to use for isolating the given device.
    /// * `keep_fds` - File descriptors that will be kept open in the child.
    pub fn new<D: BusDevice>(
        device: D,
        jail: &Minijail,
        keep_fds: Vec<RawFd>,
    ) -> Result<ProxyDevice> {
        Self::new_with_user_command(device, jail, keep_fds, |_| {})
    }

    /// Similar to `ProxyDevice::new`, but adds an additional custom command to be run in the forked
    /// process when `run_user_command` is called.
    ///
    /// Note that the custom command closure is run in the main thread of the child process, which
    /// also services `BusDevice` requests. Therefore, do not run blocking calls in the closure
    /// without a timeout, or you will block any VCPU which touches this device, and every other
    /// thread which needs to lock this device's mutex.
    ///
    /// # Arguments
    /// * `device` - The device to isolate to another process.
    /// * `jail` - The jail to use for isolating the given device.
    /// * `keep_fds` - File descriptors that will be kept open in the child.
    /// * `user_command` - Closure to be run in the forked process.
    pub fn new_with_user_command<D: BusDevice, F: FnMut(&mut D)>(
        mut device: D,
        jail: &Minijail,
        mut keep_fds: Vec<RawFd>,
        user_command: F,
    ) -> Result<ProxyDevice> {
        let debug_label = device.debug_label();
        let (child_sock, parent_sock) = UnixSeqpacket::pair().map_err(Error::Io)?;

        keep_fds.push(child_sock.as_raw_fd());
        // Forking here is safe as long as the program is still single threaded.
        let pid = unsafe {
            match jail.fork(Some(&keep_fds)).map_err(Error::ForkingJail)? {
                0 => {
                    device.on_sandboxed();
                    child_proc(child_sock, &mut device, user_command);

                    // We're explicitly not using std::process::exit here to avoid the cleanup of
                    // stdout/stderr globals. This can cause cascading panics and SIGILL if a worker
                    // thread attempts to log to stderr after at_exit handlers have been run.
                    // TODO(crbug.com/992494): Remove this once device shutdown ordering is clearly
                    // defined.
                    //
                    // exit() is trivially safe.
                    // ! Never returns
                    libc::exit(0);
                }
                p => p,
            }
        };

        parent_sock
            .set_write_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS)))
            .map_err(Error::Io)?;
        parent_sock
            .set_read_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS)))
            .map_err(Error::Io)?;
        Ok(ProxyDevice {
            sock: MsgSocket::<Command, CommandResult>::new(parent_sock),
            pid,
            debug_label,
        })
    }

    pub fn pid(&self) -> pid_t {
        self.pid
    }

    /// Runs the callback given in `new_with_custom_command` in the child device process.
    pub fn run_user_command(&self) {
        self.sync_send(&Command::RunUserCommand);
    }

    /// Send a command that does not expect a response from the child device process.
    fn send_no_result(&self, cmd: &Command) {
        let res = self.sock.send(cmd);
        if let Err(e) = res {
            error!(
                "failed write to child device process {}: {}",
                self.debug_label, e,
            );
        }
    }

    /// Send a command and read its response from the child device process.
    fn sync_send(&self, cmd: &Command) -> Option<CommandResult> {
        self.send_no_result(cmd);
        match self.sock.recv() {
            Err(e) => {
                error!(
                    "failed to read result of {:?} from child device process {}: {}",
                    cmd, self.debug_label, e,
                );
                None
            }
            Ok(r) => Some(r),
        }
    }
}

impl BusDevice for ProxyDevice {
    fn debug_label(&self) -> String {
        self.debug_label.clone()
    }

    fn config_register_write(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
        let len = data.len() as u32;
        let mut buffer = [0u8; 4];
        buffer[0..data.len()].clone_from_slice(data);
        let reg_idx = reg_idx as u32;
        let offset = offset as u32;
        self.send_no_result(&Command::WriteConfig {
            reg_idx,
            offset,
            len,
            data: buffer,
        });
    }

    fn config_register_read(&self, reg_idx: usize) -> u32 {
        let res = self.sync_send(&Command::ReadConfig(reg_idx as u32));
        if let Some(CommandResult::ReadConfigResult(val)) = res {
            val
        } else {
            0
        }
    }

    fn read(&mut self, offset: u64, data: &mut [u8]) {
        let len = data.len() as u32;
        if let Some(CommandResult::ReadResult(buffer)) =
            self.sync_send(&Command::Read { len, offset })
        {
            let len = data.len();
            data.clone_from_slice(&buffer[0..len]);
        }
    }

    fn write(&mut self, offset: u64, data: &[u8]) {
        let mut buffer = [0u8; 8];
        let len = data.len() as u32;
        buffer[0..data.len()].clone_from_slice(data);
        self.send_no_result(&Command::Write {
            len,
            offset,
            data: buffer,
        });
    }
}

impl Drop for ProxyDevice {
    fn drop(&mut self) {
        self.sync_send(&Command::Shutdown);
    }
}
<|endoftext|>


<commit_before>use atlas_cache::SubImageSpec;
use cache;
use calx::Rgba;
use calx::color::*;
use euclid::{rect, Rect, Vector2D, vec2};
use std::fmt;
use std::rc::Rc;
use vitral;

/// Monochrome layer in a single frame.
#[derive(Clone, PartialEq)]
pub struct Splat {
    pub image: vitral::ImageData<usize>,
    /// Draw offset for the splat.
    pub offset: Vector2D<f32>,
    pub color: Rgba,
    pub back_color: Rgba,
}

impl fmt::Debug for Splat {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Splat {{ {:?}+{:?} {:?} {:?} }}",
            self.image.tex_coords, self.offset, self.color, self.back_color
        )
    }
}

impl Splat {
    pub fn new(geom: &Geom, sheet: String, color: Rgba, back_color: Rgba) -> Splat {
        Splat {
            image: cache::get(&SubImageSpec {
                sheet_name: sheet,
                bounds: geom.bounds,
            }),
            offset: geom.offset,
            color: color,
            back_color: back_color,
        }
    }
}

/// Stack of monochrome splat layers making up a drawable colored image.
pub type Frame = Vec<Splat>;

/// Collection of drawable frames.
pub type Brush = Vec<Frame>;

pub struct Builder {
    color: Rgba,
    back_color: Rgba,
    sheet_name: String,
    // The inner splat vectors are the *columns* of the splat matrix, and the merge operation will
    // build frames from the *rows* of the matrix.
    //
    // This sort of structure is used so that it'll be easy to specify a brush that has both a
    // complex structure (wallform or blobform) and has multiple splats for each frame.
    splat_matrix: Vec<Vec<Splat>>,
    pub brush: Brush,
}

/// Builder structure for brushes.
///
/// Building the brush involves some complex standard sequences like blob and wall forms. It also
/// involves combining splats into frames. A complex form with frames consisting of multiple splats
/// is made using the column-adding functions for each splat and the calling `merge` or `finish` to
/// convert them into frames.
impl Builder {
    /// Start a new brush builder using the given sprite sheet from cache.
    ///
    /// You're expected to set up your sprite sheets so that a single brush is built from a single
    /// sheet.
    ///
    /// The default foreground color is white and the default background color is black.
    pub fn new(sheet_name: &str) -> Builder {
        Builder {
            color: WHITE,
            back_color: BLACK,
            sheet_name: sheet_name.to_string(),
            splat_matrix: Vec::new(),
            brush: Vec::new(),
        }
    }

    /// Set the foreground color for the brush.
    pub fn color<C: Into<Rgba>>(mut self, color: C) -> Builder {
        self.color = color.into();
        self
    }

    pub fn _sheet(mut self, sheet_name: &str) -> Builder {
        self.sheet_name = sheet_name.to_string();
        self
    }

    /// Set the foreground and background colors for the brush.
    pub fn colors<C: Into<Rgba>, D: Into<Rgba>>(mut self, color: C, back_color: D) -> Builder {
        self.color = color.into();
        self.back_color = back_color.into();
        self
    }

    fn make_splat(&self, geom: &Geom) -> Splat {
        Splat::new(geom, self.sheet_name.clone(), self.color, self.back_color)
    }

    /// Add a splat columnn to the current splat matrix.
    ///
    /// If a splat matrix exists, the column must match the height of the matrix. Otherwise the
    /// column will start a new splat matrix.
    pub fn splat<I: IntoIterator<Item = Geom>>(mut self, geom: I) -> Builder {
        let matrix_column = geom.into_iter()
            .map(|g| self.make_splat(&g))
            .collect::<Vec<Splat>>();
        assert!(
            self.splat_matrix.is_empty() || matrix_column.len() == self.splat_matrix[0].len(),
            "Splat frame count {} does not match previous parallel splats with count {}",
            matrix_column.len(),
            self.splat_matrix[0].len()
        );
        self.splat_matrix.push(matrix_column);
        self
    }

    /// Add a single-frame splat for a standard tile to the splat matrix.
    pub fn tile(self, x: u32, y: u32) -> Builder { self.splat(Geom::tile(x, y)) }

    /// Add an arbitrary sized rectangle.
    pub fn rect(self, x: u32, y: u32, w: u32, h: u32) -> Builder {
        self.splat(Some(Geom::new(0, 0, x, y, w, h)))
    }

    /// Add a simple mob that has a bobbing animation
    pub fn mob(self, x: u32, y: u32) -> Builder {
        self.splat(Some(Geom::new(16, 16, x, y, 32, 32)))
            .merge()
            .splat(Some(Geom::new(16, 18, x, y, 32, 32)))
    }

    /// Add a blobform splat column to the splat matrix.
    ///
    /// Blobs are built from three 96x32 strips. First one contains the vertical edges, the second
    /// contains the rear blob and the third contains the blob front. The vertical and rear
    /// frames are nondescript and will probably be reused extensively.
    ///
    /// Blob shaping is somewhat complicated and generates a large number of frames.
    pub fn blob(
        self,
        vert_x: u32,
        vert_y: u32,
        rear_x: u32,
        rear_y: u32,
        x: u32,
        y: u32,
    ) -> Builder {
        self.splat(Geom::blob(vert_x, vert_y, rear_x, rear_y, x, y))
    }

    /// Add a wallform splat column to the splat matrix.
    ///
    /// Wall tiles are chopped up from two 32x32 images. One contains the center pillar wallform
    /// and the other contains the two long sides wallform.
    pub fn wall(self, center_x: u32, center_y: u32, sides_x: u32, sides_y: u32) -> Builder {
        self.splat(Geom::wall(center_x, center_y, sides_x, sides_y))
    }

    /// Merge the rows in the current splat matrix to frames, clear the splat matrix.
    pub fn merge(mut self) -> Builder {
        assert!(
            !self.splat_matrix.is_empty(),
            "Merging without any splats specified"
        );
        let n = self.splat_matrix[0].len();

        for _ in 0..n {
            let mut frame = Vec::new();
            for i in &mut self.splat_matrix {
                frame.push(i.remove(0));
            }
            self.brush.push(frame);
        }

        self.splat_matrix.clear();
        self
    }

    /// Convert the builder into a finished brush.
    ///
    /// If the current splat matrix is not empty, it will be merged into frames first.
    pub fn finish(mut self) -> Rc<Brush> {
        if !self.splat_matrix.is_empty() {
            // A merge is pending, do it now.
            self = self.merge();
        }
        Rc::new(self.brush)
    }
}

/// Descriptor for extracting splats from a sprite sheet.
#[derive(Clone)]
pub struct Geom {
    /// Draw offset.
    offset: Vector2D<f32>,
    /// Coordinates on the sprite sheet image.
    bounds: Rect<u32>,
}

impl Geom {
    pub fn new(
        offset_x: i32,
        offset_y: i32,
        orig_x: u32,
        orig_y: u32,
        width: u32,
        height: u32,
    ) -> Geom {
        Geom {
            offset: vec2(offset_x as f32, offset_y as f32),
            bounds: rect(orig_x, orig_y, width, height),
        }
    }

    /// Single default sized tile.
    pub fn tile(x: u32, y: u32) -> Option<Geom> {
        // The BrushBuilder API expects all geom stuff to be IntoIter, so this returns Option for
        // one-shot iterable instead of a naked value.
        Some(Geom::new(16, 16, x, y, 32, 32))
    }

    /// Standard blobform tileset.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    pub fn blob(vert_x: u32, vert_y: u32, rear_x: u32, rear_y: u32, x: u32, y: u32) -> Vec<Geom> {
        vec![
            Geom::new(16, 16, vert_x, vert_y, 16, 32),       // 0: Top left    VERTICAL SIDES
            Geom::new(0, 16, vert_x + 16, vert_y, 16, 32),   // 1: Top right
            Geom::new(16, 16, vert_x + 32, vert_y, 16, 32),  // 2: Middle left
            Geom::new(0, 16, vert_x + 48, vert_y, 16, 32),   // 3: Middle right
            Geom::new(16, 16, vert_x + 64, vert_y, 16, 32),  // 4: Bottom left
            Geom::new(0, 16, vert_x + 80, vert_y, 16, 32),   // 5: Bottom right

            Geom::new(16, 16, rear_x, rear_y, 10, 32),       // 6: Left half       REAR PARTS

            Geom::new(6, 16, rear_x + 10, rear_y, 6, 32),    // 7: Front
            Geom::new(0, 16, rear_x + 16, rear_y, 6, 32),    // 8

            Geom::new(-6, 16, rear_x + 22, rear_y, 10, 32),  // 9: Right half

            Geom::new(16, 16, rear_x + 32, rear_y, 10, 32),  // 10: Y-axis slope
            Geom::new(6, 16, rear_x + 42, rear_y, 6, 32),    // 11
            Geom::new(0, 16, rear_x + 48, rear_y, 6, 32),    // 12
            Geom::new(-6, 16, rear_x + 54, rear_y, 10, 32),  // 13

            Geom::new(16, 16, rear_x + 64, rear_y, 10, 32),  // 14: X-axis slope
            Geom::new(6, 16, rear_x + 74, rear_y, 6, 32),    // 15
            Geom::new(0, 16, rear_x + 80, rear_y, 6, 32),    // 16
            Geom::new(-6, 16, rear_x + 86, rear_y, 10, 32),  // 17

            Geom::new(16, 16, x, y, 10, 32),                 // 18 Left half      FRONT PARTS

            Geom::new(6, 16, x + 10, y, 6, 32),              // 19: Front
            Geom::new(0, 16, x + 16, y, 6, 32),              // 20

            Geom::new(-6, 16, x + 22, y, 10, 32),            // 21: Right half

            Geom::new(16, 16, x + 32, y, 10, 32),            // 22: Y-axis slope
            Geom::new(6, 16, x + 42, y, 6, 32),              // 23
            Geom::new(0, 16, x + 48, y, 6, 32),              // 24
            Geom::new(-6, 16, x + 54, y, 10, 32),            // 25

            Geom::new(16, 16, x + 64, y, 10, 32),            // 26: X-axis slope
            Geom::new(6, 16, x + 74, y, 6, 32),              // 27
            Geom::new(0, 16, x + 80, y, 6, 32),              // 28
            Geom::new(-6, 16, x + 86, y, 10, 32),            // 29
        ]
    }

    /// Standard wallform tileset.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    pub fn wall(center_x: u32, center_y: u32, sides_x: u32, sides_y: u32) -> Vec<Geom> {
        vec![
            Geom::new(16, 16, center_x, center_y, 16, 32),       // 0
            Geom::new(0, 16, center_x + 16, center_y, 16, 32),   // 1
            Geom::new(16, 16, sides_x, sides_y, 16, 32),         // 2
            Geom::new(0, 16, sides_x + 16, sides_y, 16, 32),     // 3
        ]
    }
}
<commit_msg>Some gratuitous Vec allocation optimization<commit_after>use atlas_cache::SubImageSpec;
use cache;
use calx::Rgba;
use calx::color::*;
use euclid::{rect, Rect, Vector2D, vec2};
use std::fmt;
use std::rc::Rc;
use vitral;

/// Monochrome layer in a single frame.
#[derive(Clone, PartialEq)]
pub struct Splat {
    pub image: vitral::ImageData<usize>,
    /// Draw offset for the splat.
    pub offset: Vector2D<f32>,
    pub color: Rgba,
    pub back_color: Rgba,
}

impl fmt::Debug for Splat {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Splat {{ {:?}+{:?} {:?} {:?} }}",
            self.image.tex_coords, self.offset, self.color, self.back_color
        )
    }
}

impl Splat {
    pub fn new(geom: &Geom, sheet: String, color: Rgba, back_color: Rgba) -> Splat {
        Splat {
            image: cache::get(&SubImageSpec {
                sheet_name: sheet,
                bounds: geom.bounds,
            }),
            offset: geom.offset,
            color: color,
            back_color: back_color,
        }
    }
}

/// Stack of monochrome splat layers making up a drawable colored image.
pub type Frame = Vec<Splat>;

/// Collection of drawable frames.
pub type Brush = Vec<Frame>;

pub struct Builder {
    color: Rgba,
    back_color: Rgba,
    sheet_name: String,
    // The inner splat vectors are the *columns* of the splat matrix, and the merge operation will
    // build frames from the *rows* of the matrix.
    //
    // This sort of structure is used so that it'll be easy to specify a brush that has both a
    // complex structure (wallform or blobform) and has multiple splats for each frame.
    splat_matrix: Vec<Vec<Splat>>,
    pub brush: Brush,
}

/// Builder structure for brushes.
///
/// Building the brush involves some complex standard sequences like blob and wall forms. It also
/// involves combining splats into frames. A complex form with frames consisting of multiple splats
/// is made using the column-adding functions for each splat and the calling `merge` or `finish` to
/// convert them into frames.
impl Builder {
    /// Start a new brush builder using the given sprite sheet from cache.
    ///
    /// You're expected to set up your sprite sheets so that a single brush is built from a single
    /// sheet.
    ///
    /// The default foreground color is white and the default background color is black.
    pub fn new(sheet_name: &str) -> Builder {
        Builder {
            color: WHITE,
            back_color: BLACK,
            sheet_name: sheet_name.to_string(),
            splat_matrix: Vec::new(),
            brush: Vec::new(),
        }
    }

    /// Set the foreground color for the brush.
    pub fn color<C: Into<Rgba>>(mut self, color: C) -> Builder {
        self.color = color.into();
        self
    }

    pub fn _sheet(mut self, sheet_name: &str) -> Builder {
        self.sheet_name = sheet_name.to_string();
        self
    }

    /// Set the foreground and background colors for the brush.
    pub fn colors<C: Into<Rgba>, D: Into<Rgba>>(mut self, color: C, back_color: D) -> Builder {
        self.color = color.into();
        self.back_color = back_color.into();
        self
    }

    fn make_splat(&self, geom: &Geom) -> Splat {
        Splat::new(geom, self.sheet_name.clone(), self.color, self.back_color)
    }

    /// Add a splat columnn to the current splat matrix.
    ///
    /// If a splat matrix exists, the column must match the height of the matrix. Otherwise the
    /// column will start a new splat matrix.
    pub fn splat<I: IntoIterator<Item = Geom>>(mut self, geom: I) -> Builder {
        let matrix_column = geom.into_iter()
            .map(|g| self.make_splat(&g))
            .collect::<Vec<Splat>>();
        assert!(
            self.splat_matrix.is_empty() || matrix_column.len() == self.splat_matrix[0].len(),
            "Splat frame count {} does not match previous parallel splats with count {}",
            matrix_column.len(),
            self.splat_matrix[0].len()
        );
        self.splat_matrix.push(matrix_column);
        self
    }

    /// Add a single-frame splat for a standard tile to the splat matrix.
    pub fn tile(self, x: u32, y: u32) -> Builder { self.splat(Geom::tile(x, y)) }

    /// Add an arbitrary sized rectangle.
    pub fn rect(self, x: u32, y: u32, w: u32, h: u32) -> Builder {
        self.splat(Some(Geom::new(0, 0, x, y, w, h)))
    }

    /// Add a simple mob that has a bobbing animation
    pub fn mob(self, x: u32, y: u32) -> Builder {
        self.splat(Some(Geom::new(16, 16, x, y, 32, 32)))
            .merge()
            .splat(Some(Geom::new(16, 18, x, y, 32, 32)))
    }

    /// Add a blobform splat column to the splat matrix.
    ///
    /// Blobs are built from three 96x32 strips. First one contains the vertical edges, the second
    /// contains the rear blob and the third contains the blob front. The vertical and rear
    /// frames are nondescript and will probably be reused extensively.
    ///
    /// Blob shaping is somewhat complicated and generates a large number of frames.
    pub fn blob(
        self,
        vert_x: u32,
        vert_y: u32,
        rear_x: u32,
        rear_y: u32,
        x: u32,
        y: u32,
    ) -> Builder {
        self.splat(Geom::blob(vert_x, vert_y, rear_x, rear_y, x, y))
    }

    /// Add a wallform splat column to the splat matrix.
    ///
    /// Wall tiles are chopped up from two 32x32 images. One contains the center pillar wallform
    /// and the other contains the two long sides wallform.
    pub fn wall(self, center_x: u32, center_y: u32, sides_x: u32, sides_y: u32) -> Builder {
        self.splat(Geom::wall(center_x, center_y, sides_x, sides_y))
    }

    /// Merge the rows in the current splat matrix to frames, clear the splat matrix.
    pub fn merge(mut self) -> Builder {
        assert!(
            !self.splat_matrix.is_empty(),
            "Merging without any splats specified"
        );
        let n = self.splat_matrix[0].len();

        for _ in 0..n {
            let mut frame = Vec::with_capacity(self.splat_matrix.len());
            for i in &mut self.splat_matrix {
                frame.push(i.remove(0));
            }
            self.brush.push(frame);
        }

        self.splat_matrix.clear();
        self
    }

    /// Convert the builder into a finished brush.
    ///
    /// If the current splat matrix is not empty, it will be merged into frames first.
    pub fn finish(mut self) -> Rc<Brush> {
        if !self.splat_matrix.is_empty() {
            // A merge is pending, do it now.
            self = self.merge();
        }
        Rc::new(self.brush)
    }
}

/// Descriptor for extracting splats from a sprite sheet.
#[derive(Clone)]
pub struct Geom {
    /// Draw offset.
    offset: Vector2D<f32>,
    /// Coordinates on the sprite sheet image.
    bounds: Rect<u32>,
}

impl Geom {
    pub fn new(
        offset_x: i32,
        offset_y: i32,
        orig_x: u32,
        orig_y: u32,
        width: u32,
        height: u32,
    ) -> Geom {
        Geom {
            offset: vec2(offset_x as f32, offset_y as f32),
            bounds: rect(orig_x, orig_y, width, height),
        }
    }

    /// Single default sized tile.
    pub fn tile(x: u32, y: u32) -> Option<Geom> {
        // The BrushBuilder API expects all geom stuff to be IntoIter, so this returns Option for
        // one-shot iterable instead of a naked value.
        Some(Geom::new(16, 16, x, y, 32, 32))
    }

    /// Standard blobform tileset.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    pub fn blob(vert_x: u32, vert_y: u32, rear_x: u32, rear_y: u32, x: u32, y: u32) -> Vec<Geom> {
        vec![
            Geom::new(16, 16, vert_x, vert_y, 16, 32),       // 0: Top left    VERTICAL SIDES
            Geom::new(0, 16, vert_x + 16, vert_y, 16, 32),   // 1: Top right
            Geom::new(16, 16, vert_x + 32, vert_y, 16, 32),  // 2: Middle left
            Geom::new(0, 16, vert_x + 48, vert_y, 16, 32),   // 3: Middle right
            Geom::new(16, 16, vert_x + 64, vert_y, 16, 32),  // 4: Bottom left
            Geom::new(0, 16, vert_x + 80, vert_y, 16, 32),   // 5: Bottom right

            Geom::new(16, 16, rear_x, rear_y, 10, 32),       // 6: Left half       REAR PARTS

            Geom::new(6, 16, rear_x + 10, rear_y, 6, 32),    // 7: Front
            Geom::new(0, 16, rear_x + 16, rear_y, 6, 32),    // 8

            Geom::new(-6, 16, rear_x + 22, rear_y, 10, 32),  // 9: Right half

            Geom::new(16, 16, rear_x + 32, rear_y, 10, 32),  // 10: Y-axis slope
            Geom::new(6, 16, rear_x + 42, rear_y, 6, 32),    // 11
            Geom::new(0, 16, rear_x + 48, rear_y, 6, 32),    // 12
            Geom::new(-6, 16, rear_x + 54, rear_y, 10, 32),  // 13

            Geom::new(16, 16, rear_x + 64, rear_y, 10, 32),  // 14: X-axis slope
            Geom::new(6, 16, rear_x + 74, rear_y, 6, 32),    // 15
            Geom::new(0, 16, rear_x + 80, rear_y, 6, 32),    // 16
            Geom::new(-6, 16, rear_x + 86, rear_y, 10, 32),  // 17

            Geom::new(16, 16, x, y, 10, 32),                 // 18 Left half      FRONT PARTS

            Geom::new(6, 16, x + 10, y, 6, 32),              // 19: Front
            Geom::new(0, 16, x + 16, y, 6, 32),              // 20

            Geom::new(-6, 16, x + 22, y, 10, 32),            // 21: Right half

            Geom::new(16, 16, x + 32, y, 10, 32),            // 22: Y-axis slope
            Geom::new(6, 16, x + 42, y, 6, 32),              // 23
            Geom::new(0, 16, x + 48, y, 6, 32),              // 24
            Geom::new(-6, 16, x + 54, y, 10, 32),            // 25

            Geom::new(16, 16, x + 64, y, 10, 32),            // 26: X-axis slope
            Geom::new(6, 16, x + 74, y, 6, 32),              // 27
            Geom::new(0, 16, x + 80, y, 6, 32),              // 28
            Geom::new(-6, 16, x + 86, y, 10, 32),            // 29
        ]
    }

    /// Standard wallform tileset.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    pub fn wall(center_x: u32, center_y: u32, sides_x: u32, sides_y: u32) -> Vec<Geom> {
        vec![
            Geom::new(16, 16, center_x, center_y, 16, 32),       // 0
            Geom::new(0, 16, center_x + 16, center_y, 16, 32),   // 1
            Geom::new(16, 16, sides_x, sides_y, 16, 32),         // 2
            Geom::new(0, 16, sides_x + 16, sides_y, 16, 32),     // 3
        ]
    }
}
<|endoftext|>


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

use bytes::{Buf, BufMut, BytesMut};
use logger::*;

use std::borrow::Borrow;
use std::io::{self, Cursor, Error, Read, Write};

#[derive(Debug)]
/// A bi-directional buffer
pub struct Buffer {
    rx: BytesMut,
    tx: BytesMut,
}

impl Buffer {
    /// Creates a new `Buffer`
    pub fn new(rx: usize, tx: usize) -> Buffer {
        Buffer {
            rx: BytesMut::with_capacity(rx),
            tx: BytesMut::with_capacity(tx),
        }
    }

    /// Writes from this `Buffer` to some sink which implements `Write`
    pub fn write_to<T: Write>(&mut self, sink: &mut T) -> io::Result<Option<usize>> {
        let buffer: &[u8] = self.tx.borrow();
        match sink.try_write_buf(&mut Cursor::new(buffer)) {
            Ok(Some(b)) => {
                if b == buffer.len() {
                    trace!("tx: {} mut_remaining", self.tx.remaining_mut());
                    self.tx.advance(b);
                    Ok(Some(b))
                } else {
                    self.tx.advance(b);
                    debug!("connection buffer not flushed completely");
                    Err(io::Error::new(io::ErrorKind::Other, "incomplete"))
                }
            }
            Ok(None) => Err(io::Error::new(io::ErrorKind::Other, "spurious flush")),
            Err(e) => Err(e),
        }
    }

    /// Reads from a source implementing `Read` into this `Buffer`
    pub fn read_from<T: Read>(&mut self, source: &mut T) -> io::Result<Option<usize>> {
        // loop the read operation and grow the buffer as necessary
        let mut bytes = 0;
        loop {
            if let Some(count) = source.try_read_buf(&mut self.rx)? {
                bytes += count;
                if self.rx.has_remaining_mut() {
                    break;
                } else {
                    self.rx.reserve(4096);
                }
            } else {
                return Ok(None);
            }
        }
        Ok(Some(bytes))
    }

    /// Clear the `Buffer`
    pub fn clear(&mut self) {
        self.rx.clear();
        self.tx.clear();
    }

    /// return a reference to the bytes in the rx buffer
    /// useful for zero-copy response handling
    pub fn rx_buffer(&self) -> &[u8] {
        self.rx.borrow()
    }

    /// return a mutable reference to the tx buffer
    /// use to write bytes to the buffer without copying
    pub fn tx_buffer(&mut self) -> &mut BytesMut {
        &mut self.tx
    }
}

impl Write for Buffer {
    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
        self.tx.extend_from_slice(buf);
        Ok(buf.len())
    }

    fn flush(&mut self) -> Result<(), Error> {
        Ok(())
    }
}

impl Read for Buffer {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
        let mut buffer: Cursor<&[u8]> = Cursor::new(self.rx.borrow());
        buffer.read(buf)
    }
}

pub trait TryRead {
    fn try_read_buf<B: BufMut>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
    where
        Self: Sized,
    {
        // Reads the length of the slice supplied by buf.mut_bytes into the buffer
        // This is not guaranteed to consume an entire datagram or segment.
        // If your protocol is msg based (instead of continuous stream) you should
        // ensure that your buffer is large enough to hold an entire segment
        // (1532 bytes if not jumbo frames)
        let res = self.try_read(unsafe { buf.bytes_mut() });

        if let Ok(Some(cnt)) = res {
            unsafe {
                buf.advance_mut(cnt);
            }
        }

        res
    }

    fn try_read(&mut self, buf: &mut [u8]) -> io::Result<Option<usize>>;
}

pub trait TryWrite {
    fn try_write_buf<B: Buf>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
    where
        Self: Sized,
    {
        let res = self.try_write(buf.bytes());

        if let Ok(Some(cnt)) = res {
            buf.advance(cnt);
        }

        res
    }

    fn try_write(&mut self, buf: &[u8]) -> io::Result<Option<usize>>;
}

impl<T: Read> TryRead for T {
    fn try_read(&mut self, dst: &mut [u8]) -> io::Result<Option<usize>> {
        self.read(dst).map_non_block()
    }
}

impl<T: Write> TryWrite for T {
    fn try_write(&mut self, src: &[u8]) -> io::Result<Option<usize>> {
        self.write(src).map_non_block()
    }
}

/// A helper trait to provide the `map_non_block` function on Results.
trait MapNonBlock<T> {
    /// Maps a `Result<T>` to a `Result<Option<T>>` by converting
    /// operation-would-block errors into `Ok(None)`.
    fn map_non_block(self) -> io::Result<Option<T>>;
}

impl<T> MapNonBlock<T> for io::Result<T> {
    fn map_non_block(self) -> io::Result<Option<T>> {
        use std::io::ErrorKind::WouldBlock;

        match self {
            Ok(value) => Ok(Some(value)),
            Err(err) => {
                if let WouldBlock = err.kind() {
                    Ok(None)
                } else {
                    Err(err)
                }
            }
        }
    }
}

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

    #[test]
    fn write_and_write_to() {
        let mut buffer = Buffer::new(4096, 4096);

        let messages: Vec<&[u8]> = vec![
            b"break the ice",
            b"he hath eaten me out of house and home",
            b"brevity is the soul of wit",
        ];

        for message in messages {
            buffer.write(message).expect("write failed");
            let mut sink = Vec::new();
            if let Ok(Some(len)) = buffer.write_to(&mut sink) {
                assert_eq!(sink.len(), len);
                assert_eq!(sink, message);
            }
        }
    }

    #[test]
    fn read_from_and_read() {
        let mut buffer = Buffer::new(4096, 4096);

        let mut messages: Vec<&[u8]> = vec![
            b"break the ice",
            b"he hath eaten me out of house and home",
            b"brevity is the soul of wit",
        ];

        for message in &mut messages {
            let check = message.clone();
            buffer.read_from(message).expect("read from failed");
            let mut sink = vec![0; 4096];
            if let Ok(len) = buffer.read(&mut sink) {
                sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
                assert_eq!(sink.len(), len); // sink contains the number of bytes read into it
                assert_eq!(sink.len(), check.len()); // sink has same number of bytes as check string
                assert_eq!(sink.as_slice(), check); // sink has same data as check string
                buffer.clear();
            }
        }
    }

    #[test]
    fn read_from_multiple() {
        let mut buffer = Buffer::new(4096, 4096);

        let mut messages: Vec<&[u8]> = vec![b"brave ", b"new ", b"world"];

        for message in &mut messages {
            buffer.read_from(message).expect("read from failed");
        }

        let check = b"brave new world";
        let mut sink = vec![0; 4096];
        if let Ok(len) = buffer.read(&mut sink) {
            sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
            assert_eq!(sink.len(), len); // sink contains the number of bytes read into it
            assert_eq!(sink.len(), check.len()); // sink has same number of bytes as check string
            assert_eq!(sink.as_slice(), check); // sink has same data as check string
            buffer.clear();
        }
        sink.clear();
        if let Ok(len) = buffer.read(&mut sink) {
            assert_eq!(len, 0);
            sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
            assert_eq!(sink.len(), len); // sink contains the number of bytes read into it
            assert_eq!(sink.as_slice(), b""); // sink has same data as check string
            buffer.clear();
        }
    }

    #[test]
    fn write_to_multiple() {
        let mut buffer = Buffer::new(4096, 4096);

        buffer.write(b"DEAD").expect("write failed");

        let check = b"DEAD";

        let mut sink = Vec::new();
        assert_eq!(buffer.write_to(&mut sink).unwrap().unwrap(), 4);
        assert_eq!(sink.len(), check.len());
        assert_eq!(sink.as_slice(), check);

        buffer.write(b"BEEF").expect("write failed");

        let check = b"BEEF";

        let mut sink = Vec::new();
        assert_eq!(buffer.write_to(&mut sink).unwrap().unwrap(), 4);
        assert_eq!(sink.len(), check.len());
        assert_eq!(sink.as_slice(), check);

        buffer.write(b"DEAD").expect("write failed");
        buffer.write(b"BEEF").expect("write failed");

        let check = b"DEADBEEF";

        let mut sink = Vec::new();
        assert_eq!(buffer.write_to(&mut sink).unwrap().unwrap(), 8);
        assert_eq!(sink.len(), check.len());
        assert_eq!(sink.as_slice(), check);
    }

    #[test]
    fn partial_read() {
        let mut buffer = Buffer::new(4096, 4096);

        let mut messages: Vec<&[u8]> = vec![b"DEAD", b"BEEF"];

        buffer
            .read_from(&mut messages[0])
            .expect("read from failed");

        // reading first time should have the contents we just wrote
        let mut sink = vec![0; 4096];
        if let Ok(len) = buffer.read(&mut sink) {
            sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
            assert_eq!(sink.len(), 4); // sink has same number of bytes as check string
            assert_eq!(sink.as_slice(), b"DEAD"); // sink has same data as check string
        }

        // reading again gives us the same result
        let mut sink = vec![0; 4096];
        if let Ok(len) = buffer.read(&mut sink) {
            sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
            assert_eq!(sink.len(), 4); // sink has same number of bytes as check string
            assert_eq!(sink.as_slice(), b"DEAD"); // sink has same data as check string
        }

        // append to the buffer and read to get all written data
        buffer
            .read_from(&mut messages[1])
            .expect("read from failed");
        let mut sink = vec![0; 4096];
        if let Ok(len) = buffer.read(&mut sink) {
            sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
            assert_eq!(sink.len(), 8); // sink has same number of bytes as check string
            assert_eq!(sink.as_slice(), b"DEADBEEF"); // sink has same data as check string
        }
    }
}
<commit_msg>buffer: license headers<commit_after>// Copyright 2019 Twitter, Inc.
// Licensed under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0

use bytes::{Buf, BufMut, BytesMut};
use logger::*;

use std::borrow::Borrow;
use std::io::{self, Cursor, Error, Read, Write};

#[derive(Debug)]
/// A bi-directional buffer
pub struct Buffer {
    rx: BytesMut,
    tx: BytesMut,
}

impl Buffer {
    /// Creates a new `Buffer`
    pub fn new(rx: usize, tx: usize) -> Buffer {
        Buffer {
            rx: BytesMut::with_capacity(rx),
            tx: BytesMut::with_capacity(tx),
        }
    }

    /// Writes from this `Buffer` to some sink which implements `Write`
    pub fn write_to<T: Write>(&mut self, sink: &mut T) -> io::Result<Option<usize>> {
        let buffer: &[u8] = self.tx.borrow();
        match sink.try_write_buf(&mut Cursor::new(buffer)) {
            Ok(Some(b)) => {
                if b == buffer.len() {
                    trace!("tx: {} mut_remaining", self.tx.remaining_mut());
                    self.tx.advance(b);
                    Ok(Some(b))
                } else {
                    self.tx.advance(b);
                    debug!("connection buffer not flushed completely");
                    Err(io::Error::new(io::ErrorKind::Other, "incomplete"))
                }
            }
            Ok(None) => Err(io::Error::new(io::ErrorKind::Other, "spurious flush")),
            Err(e) => Err(e),
        }
    }

    /// Reads from a source implementing `Read` into this `Buffer`
    pub fn read_from<T: Read>(&mut self, source: &mut T) -> io::Result<Option<usize>> {
        // loop the read operation and grow the buffer as necessary
        let mut bytes = 0;
        loop {
            if let Some(count) = source.try_read_buf(&mut self.rx)? {
                bytes += count;
                if self.rx.has_remaining_mut() {
                    break;
                } else {
                    self.rx.reserve(4096);
                }
            } else {
                return Ok(None);
            }
        }
        Ok(Some(bytes))
    }

    /// Clear the `Buffer`
    pub fn clear(&mut self) {
        self.rx.clear();
        self.tx.clear();
    }

    /// return a reference to the bytes in the rx buffer
    /// useful for zero-copy response handling
    pub fn rx_buffer(&self) -> &[u8] {
        self.rx.borrow()
    }

    /// return a mutable reference to the tx buffer
    /// use to write bytes to the buffer without copying
    pub fn tx_buffer(&mut self) -> &mut BytesMut {
        &mut self.tx
    }
}

impl Write for Buffer {
    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
        self.tx.extend_from_slice(buf);
        Ok(buf.len())
    }

    fn flush(&mut self) -> Result<(), Error> {
        Ok(())
    }
}

impl Read for Buffer {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
        let mut buffer: Cursor<&[u8]> = Cursor::new(self.rx.borrow());
        buffer.read(buf)
    }
}

pub trait TryRead {
    fn try_read_buf<B: BufMut>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
    where
        Self: Sized,
    {
        // Reads the length of the slice supplied by buf.mut_bytes into the buffer
        // This is not guaranteed to consume an entire datagram or segment.
        // If your protocol is msg based (instead of continuous stream) you should
        // ensure that your buffer is large enough to hold an entire segment
        // (1532 bytes if not jumbo frames)
        let res = self.try_read(unsafe { buf.bytes_mut() });

        if let Ok(Some(cnt)) = res {
            unsafe {
                buf.advance_mut(cnt);
            }
        }

        res
    }

    fn try_read(&mut self, buf: &mut [u8]) -> io::Result<Option<usize>>;
}

pub trait TryWrite {
    fn try_write_buf<B: Buf>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
    where
        Self: Sized,
    {
        let res = self.try_write(buf.bytes());

        if let Ok(Some(cnt)) = res {
            buf.advance(cnt);
        }

        res
    }

    fn try_write(&mut self, buf: &[u8]) -> io::Result<Option<usize>>;
}

impl<T: Read> TryRead for T {
    fn try_read(&mut self, dst: &mut [u8]) -> io::Result<Option<usize>> {
        self.read(dst).map_non_block()
    }
}

impl<T: Write> TryWrite for T {
    fn try_write(&mut self, src: &[u8]) -> io::Result<Option<usize>> {
        self.write(src).map_non_block()
    }
}

/// A helper trait to provide the `map_non_block` function on Results.
trait MapNonBlock<T> {
    /// Maps a `Result<T>` to a `Result<Option<T>>` by converting
    /// operation-would-block errors into `Ok(None)`.
    fn map_non_block(self) -> io::Result<Option<T>>;
}

impl<T> MapNonBlock<T> for io::Result<T> {
    fn map_non_block(self) -> io::Result<Option<T>> {
        use std::io::ErrorKind::WouldBlock;

        match self {
            Ok(value) => Ok(Some(value)),
            Err(err) => {
                if let WouldBlock = err.kind() {
                    Ok(None)
                } else {
                    Err(err)
                }
            }
        }
    }
}

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

    #[test]
    fn write_and_write_to() {
        let mut buffer = Buffer::new(4096, 4096);

        let messages: Vec<&[u8]> = vec![
            b"break the ice",
            b"he hath eaten me out of house and home",
            b"brevity is the soul of wit",
        ];

        for message in messages {
            buffer.write(message).expect("write failed");
            let mut sink = Vec::new();
            if let Ok(Some(len)) = buffer.write_to(&mut sink) {
                assert_eq!(sink.len(), len);
                assert_eq!(sink, message);
            }
        }
    }

    #[test]
    fn read_from_and_read() {
        let mut buffer = Buffer::new(4096, 4096);

        let mut messages: Vec<&[u8]> = vec![
            b"break the ice",
            b"he hath eaten me out of house and home",
            b"brevity is the soul of wit",
        ];

        for message in &mut messages {
            let check = message.clone();
            buffer.read_from(message).expect("read from failed");
            let mut sink = vec![0; 4096];
            if let Ok(len) = buffer.read(&mut sink) {
                sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
                assert_eq!(sink.len(), len); // sink contains the number of bytes read into it
                assert_eq!(sink.len(), check.len()); // sink has same number of bytes as check string
                assert_eq!(sink.as_slice(), check); // sink has same data as check string
                buffer.clear();
            }
        }
    }

    #[test]
    fn read_from_multiple() {
        let mut buffer = Buffer::new(4096, 4096);

        let mut messages: Vec<&[u8]> = vec![b"brave ", b"new ", b"world"];

        for message in &mut messages {
            buffer.read_from(message).expect("read from failed");
        }

        let check = b"brave new world";
        let mut sink = vec![0; 4096];
        if let Ok(len) = buffer.read(&mut sink) {
            sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
            assert_eq!(sink.len(), len); // sink contains the number of bytes read into it
            assert_eq!(sink.len(), check.len()); // sink has same number of bytes as check string
            assert_eq!(sink.as_slice(), check); // sink has same data as check string
            buffer.clear();
        }
        sink.clear();
        if let Ok(len) = buffer.read(&mut sink) {
            assert_eq!(len, 0);
            sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
            assert_eq!(sink.len(), len); // sink contains the number of bytes read into it
            assert_eq!(sink.as_slice(), b""); // sink has same data as check string
            buffer.clear();
        }
    }

    #[test]
    fn write_to_multiple() {
        let mut buffer = Buffer::new(4096, 4096);

        buffer.write(b"DEAD").expect("write failed");

        let check = b"DEAD";

        let mut sink = Vec::new();
        assert_eq!(buffer.write_to(&mut sink).unwrap().unwrap(), 4);
        assert_eq!(sink.len(), check.len());
        assert_eq!(sink.as_slice(), check);

        buffer.write(b"BEEF").expect("write failed");

        let check = b"BEEF";

        let mut sink = Vec::new();
        assert_eq!(buffer.write_to(&mut sink).unwrap().unwrap(), 4);
        assert_eq!(sink.len(), check.len());
        assert_eq!(sink.as_slice(), check);

        buffer.write(b"DEAD").expect("write failed");
        buffer.write(b"BEEF").expect("write failed");

        let check = b"DEADBEEF";

        let mut sink = Vec::new();
        assert_eq!(buffer.write_to(&mut sink).unwrap().unwrap(), 8);
        assert_eq!(sink.len(), check.len());
        assert_eq!(sink.as_slice(), check);
    }

    #[test]
    fn partial_read() {
        let mut buffer = Buffer::new(4096, 4096);

        let mut messages: Vec<&[u8]> = vec![b"DEAD", b"BEEF"];

        buffer
            .read_from(&mut messages[0])
            .expect("read from failed");

        // reading first time should have the contents we just wrote
        let mut sink = vec![0; 4096];
        if let Ok(len) = buffer.read(&mut sink) {
            sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
            assert_eq!(sink.len(), 4); // sink has same number of bytes as check string
            assert_eq!(sink.as_slice(), b"DEAD"); // sink has same data as check string
        }

        // reading again gives us the same result
        let mut sink = vec![0; 4096];
        if let Ok(len) = buffer.read(&mut sink) {
            sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
            assert_eq!(sink.len(), 4); // sink has same number of bytes as check string
            assert_eq!(sink.as_slice(), b"DEAD"); // sink has same data as check string
        }

        // append to the buffer and read to get all written data
        buffer
            .read_from(&mut messages[1])
            .expect("read from failed");
        let mut sink = vec![0; 4096];
        if let Ok(len) = buffer.read(&mut sink) {
            sink.truncate(len); // we need to shrink our buffer to match the bytes we've read
            assert_eq!(sink.len(), 8); // sink has same number of bytes as check string
            assert_eq!(sink.as_slice(), b"DEADBEEF"); // sink has same data as check string
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Cleanup docs a bit<commit_after><|endoftext|>


<commit_before><commit_msg>export mutex guard<commit_after><|endoftext|>


<commit_before>use std::intrinsics::TypeId;
use std::cell::RefCell;
use std::rc::{Rc, Weak};
use std::fmt::{Formatter, Show, Result};
use std::collections::hashmap::HashMap;
use std::any::{Any, AnyRefExt, AnyMutRefExt};
use std::mem;
use uuid::Uuid;

/// Toplevel container of the entity component system.
pub struct World<T> {
    data: Rc<RefCell<WorldData<T>>>,
}

impl<T: System> World<T> {
    /// Create a world coupled with an application specific system object
    pub fn new(master_system: T) -> World<T> {
        let ret = World {
            data: Rc::new(RefCell::new(WorldData::new(master_system))),
        };
        ret.data.borrow_mut().master_system.register(&ret);
        ret
    }

    /// Wrap an EntityId struct into an entity handle that has a backreference
    /// to the world object.
    fn wrap(&self, id: EntityId) -> Entity<T> {
        Entity {
            world: self.data.downgrade(),
            id: id
        }
    }

    /// Create a new entity bound to this world
    pub fn new_entity(&mut self) -> Entity<T> {
        let id = EntityId {
            idx: self.data.borrow_mut().get_idx(),
            uuid: Uuid::new_v4(),
        };
        self.data.borrow_mut().register_new_entity(id);
        let ret = self.wrap(id);
        self.data.borrow_mut().master_system.added(&ret);
        ret
    }

    pub fn system<'a>(&'a self) -> &'a T {
        unsafe { mem::transmute(&self.data.borrow().master_system) }
    }

    pub fn system_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { mem::transmute(&self.data.borrow_mut().master_system) }
    }

    pub fn find_entity(&self, uuid: &Uuid) -> Option<Entity<T>> {
        match self.data.borrow().uuids.find(uuid) {
            Some(idx) => Some(self.wrap(EntityId { uuid: *uuid, idx: *idx })),
            None => None
        }
    }
}

/// Callback interface for application data connected to the component system
/// world.
pub trait System {
    /// Callback for initially attaching the system to a world
    fn register(&mut self, world: &World<Self>);
    /// Callback for adding a new entity to world
    fn added(&mut self, e: &Entity<Self>);
    /// Callback for a component being added or removed in an entity. Note that
    /// this is not called when the data of an existing component is written
    /// to, only if the component is replaced or removed.
    fn changed<C>(&mut self, e: &Entity<Self>, component: Option<&C>);
    /// Callback for an entity being deleted
    fn deleted(&mut self, e: &Entity<Self>);
}

#[deriving(Clone)]
pub struct Entity<T> {
    world: Weak<RefCell<WorldData<T>>>,
    id: EntityId,
}

impl<T> Show for Entity<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self.id)
    }
}

impl<T: System> Entity<T> {
    /// Add or reset a component in the entity. Causes a "changed" call to the
    /// world system.
    pub fn set_component<C: 'static+Clone>(&mut self, comp: C) {
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .set_component(self, Some(comp));
    }

    /// Remove a component from the entity. Causes a "changed" call to the
    /// world system.
    pub fn remove_component<C: 'static+Clone>(&mut self) {
        let comp : Option<C> = None;
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .set_component(self, comp);
    }

    /// Delete the entity from the world. Causes a "deleted" call to the world
    /// system.
    pub fn delete(&mut self) {
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .delete_entity(self);
    }

    /// Query whether the entity has a type of component.
    pub fn has<'a, C: 'static>(&self) -> bool {
        self.world.upgrade().unwrap().borrow()
            .comp_ref::<'a, C>(self.id).is_some()
    }

    /// Get an access proxy to the entity's component if the entity has that
    /// component.
    pub fn into<C: 'static>(&self) -> Option<CompProxyMut<T, C>> {
        if self.has::<C>() {
            Some(CompProxyMut {
                world: self.world.clone(),
                id: self.id
            })
        } else {
            None
        }
    }

    /// Return unique identifier for this entity.
    pub fn uuid(&self) -> Uuid {
        self.id.uuid
    }

    /// Return a handle to the world.
    pub fn world(&self) -> World<T> {
        World { data: self.world.upgrade().unwrap() }
    }
}

/// Access proxy to entity components. The implementation RefCell (mutable)
/// borrow internally, so using this carelessly may lead to runtime borrow
/// errors. You should generally keep access to the concrete entity data short
/// in scope and low in the call stack to prevent unexpected borrow failures.
pub struct CompProxyMut<T, C> {
    world: Weak<RefCell<WorldData<T>>>,
    id: EntityId,
}

impl<T: System, C: 'static> Deref<C> for CompProxyMut<T, C> {
    fn deref<'a>(&'a self) -> &'a C {
        self.world.upgrade().unwrap().borrow()
            .comp_ref::<'a, C>(self.id).unwrap()
    }
}

impl<T: System, C: 'static> DerefMut<C> for CompProxyMut<T, C> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut C {
        self.world.upgrade().unwrap().borrow_mut()
            .comp_ref_mut::<'a, C>(self.id).unwrap()
    }
}

#[deriving(PartialEq, Clone, Show)]
struct EntityId {
    uuid: Uuid,
    idx: uint,
}

struct WorldData<T> {
    // XXX: This is much less efficient than it could be. A serious
    // implementation would use unboxed vecs for the components and would
    // provide lookup methods faster than a HashMap find to access the
    // components
    components: HashMap<TypeId, Vec<Option<Box<Any>>>>,

    next_idx: uint,
    reusable_idxs: Vec<uint>,
    uuids: HashMap<Uuid, uint>,

    master_system: T,
}

impl<T: System> WorldData<T> {
    fn new(master_system: T) -> WorldData<T> {
        WorldData {
            components: HashMap::new(),
            next_idx: 0,
            reusable_idxs: vec!(),
            uuids: HashMap::new(),
            master_system: master_system,
        }
    }

    fn register_new_entity(&mut self, id: EntityId) {
        assert!(!self.uuids.contains_key(&id.uuid),
            "New entity clobbering existing one");
        self.uuids.insert(id.uuid, id.idx);
    }

    fn delete_entity(&mut self, e: &Entity<T>) {
        self.check_entity(e.id);
        self.uuids.remove(&e.id.uuid);

        for (_, c) in self.components.mut_iter() {
            if c.len() > e.id.idx {
                c.as_mut_slice()[e.id.idx] = None;
            }
        }

        self.reusable_idxs.push(e.id.idx);

        self.master_system.deleted(e);
    }

    /// Return the next unused reusable entity id.
    fn get_idx(&mut self) -> uint {
        match self.reusable_idxs.pop() {
            None => {
                let ret = self.next_idx;
                self.next_idx += 1;
                ret
            }
            Some(idx) => idx
        }
    }

    fn check_entity(&self, id: EntityId) {
        assert!(self.uuids.contains_key(&id.uuid), "Unknown entity UUID");
        assert!(*self.uuids.find(&id.uuid).unwrap() == id.idx, "Entity UUID mismatch");
    }

    fn set_component<C: 'static+Clone>(&mut self, e: &Entity<T>, comp: Option<C>) {
        self.check_entity(e.id);
        let type_id = TypeId::of::<C>();
        // We haven't seen this kind of component yet.
        if !self.components.contains_key(&type_id) {
            self.components.insert(type_id, vec!());
        }

        let bin = self.components.find_mut(&type_id).unwrap();

        // XXX: grow_set didn't work.
        while bin.len() <= e.id.idx { bin.push(None); }
        bin.as_mut_slice()[e.id.idx] = match comp {
            None => None,
            Some(c) => Some(box c as Box<Any>),
        };

        match bin.as_mut_slice()[e.id.idx] {
            None => self.master_system.changed::<C>(e, None),
            Some(ref c) => self.master_system.changed(e, Some(&c)),
        };
    }

    fn comp_ref<'a, C: 'static>(
        &self, id: EntityId) -> Option<&'a C> {
        self.check_entity(id);
        let type_id = TypeId::of::<C>();
        match self.components.find(&type_id) {
            None => { None }
            Some(bin) => {
                if id.idx < bin.len() {
                    match bin.get(id.idx) {
                        &Some(ref c) => { unsafe { Some(mem::transmute(c.as_ref::<C>().unwrap())) } }
                        &None => None
                    }
                } else {
                    None
                }
            }
        }
    }

    fn comp_ref_mut<'a, C: 'static>(
        &mut self, id: EntityId) -> Option<&'a mut C> {
        self.check_entity(id);
        let type_id = TypeId::of::<C>();
        match self.components.find_mut(&type_id) {
            None => { None }
            Some(bin) => {
                if id.idx < bin.len() {
                    match bin.get_mut(id.idx) {
                        &Some(ref mut c) => {
                            unsafe { Some(mem::transmute(c.as_mut::<C>().unwrap())) }
                        }
                        &None => None
                    }
                } else {
                    None
                }
            }
        }
    }
}

<commit_msg>Comment style<commit_after>use std::intrinsics::TypeId;
use std::cell::RefCell;
use std::rc::{Rc, Weak};
use std::fmt::{Formatter, Show, Result};
use std::collections::hashmap::HashMap;
use std::any::{Any, AnyRefExt, AnyMutRefExt};
use std::mem;
use uuid::Uuid;

/// Toplevel container of the entity component system.
pub struct World<T> {
    data: Rc<RefCell<WorldData<T>>>,
}

impl<T: System> World<T> {
    /// Create a world coupled with an application specific system object.
    pub fn new(master_system: T) -> World<T> {
        let ret = World {
            data: Rc::new(RefCell::new(WorldData::new(master_system))),
        };
        ret.data.borrow_mut().master_system.register(&ret);
        ret
    }

    /// Wrap an EntityId struct into an entity handle that has a backreference
    /// to the world object.
    fn wrap(&self, id: EntityId) -> Entity<T> {
        Entity {
            world: self.data.downgrade(),
            id: id
        }
    }

    /// Create a new entity bound to this world.
    pub fn new_entity(&mut self) -> Entity<T> {
        let id = EntityId {
            idx: self.data.borrow_mut().get_idx(),
            uuid: Uuid::new_v4(),
        };
        self.data.borrow_mut().register_new_entity(id);
        let ret = self.wrap(id);
        self.data.borrow_mut().master_system.added(&ret);
        ret
    }

    pub fn system<'a>(&'a self) -> &'a T {
        unsafe { mem::transmute(&self.data.borrow().master_system) }
    }

    pub fn system_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { mem::transmute(&self.data.borrow_mut().master_system) }
    }

    pub fn find_entity(&self, uuid: &Uuid) -> Option<Entity<T>> {
        match self.data.borrow().uuids.find(uuid) {
            Some(idx) => Some(self.wrap(EntityId { uuid: *uuid, idx: *idx })),
            None => None
        }
    }
}

/// Callback interface for application data connected to the component system
/// world.
pub trait System {
    /// Callback for initially attaching the system to a world.
    fn register(&mut self, world: &World<Self>);
    /// Callback for adding a new entity to world.
    fn added(&mut self, e: &Entity<Self>);
    /// Callback for a component being added or removed in an entity. Note that
    /// this is not called when the data of an existing component is written
    /// to, only if the component is replaced or removed.
    fn changed<C>(&mut self, e: &Entity<Self>, component: Option<&C>);
    /// Callback for an entity being deleted.
    fn deleted(&mut self, e: &Entity<Self>);
}

#[deriving(Clone)]
pub struct Entity<T> {
    world: Weak<RefCell<WorldData<T>>>,
    id: EntityId,
}

impl<T> Show for Entity<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self.id)
    }
}

impl<T: System> Entity<T> {
    /// Add or reset a component in the entity. Causes a "changed" call to the
    /// world system.
    pub fn set_component<C: 'static+Clone>(&mut self, comp: C) {
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .set_component(self, Some(comp));
    }

    /// Remove a component from the entity. Causes a "changed" call to the
    /// world system.
    pub fn remove_component<C: 'static+Clone>(&mut self) {
        let comp : Option<C> = None;
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .set_component(self, comp);
    }

    /// Delete the entity from the world. Causes a "deleted" call to the world
    /// system.
    pub fn delete(&mut self) {
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .delete_entity(self);
    }

    /// Query whether the entity has a type of component.
    pub fn has<'a, C: 'static>(&self) -> bool {
        self.world.upgrade().unwrap().borrow()
            .comp_ref::<'a, C>(self.id).is_some()
    }

    /// Get an access proxy to the entity's component if the entity has that
    /// component.
    pub fn into<C: 'static>(&self) -> Option<CompProxyMut<T, C>> {
        if self.has::<C>() {
            Some(CompProxyMut {
                world: self.world.clone(),
                id: self.id
            })
        } else {
            None
        }
    }

    /// Return unique identifier for this entity.
    pub fn uuid(&self) -> Uuid {
        self.id.uuid
    }

    /// Return a handle to the world.
    pub fn world(&self) -> World<T> {
        World { data: self.world.upgrade().unwrap() }
    }
}

/// Access proxy to entity components. The implementation RefCell (mutable)
/// borrow internally, so using this carelessly may lead to runtime borrow
/// errors. You should generally keep access to the concrete entity data short
/// in scope and low in the call stack to prevent unexpected borrow failures.
pub struct CompProxyMut<T, C> {
    world: Weak<RefCell<WorldData<T>>>,
    id: EntityId,
}

impl<T: System, C: 'static> Deref<C> for CompProxyMut<T, C> {
    fn deref<'a>(&'a self) -> &'a C {
        self.world.upgrade().unwrap().borrow()
            .comp_ref::<'a, C>(self.id).unwrap()
    }
}

impl<T: System, C: 'static> DerefMut<C> for CompProxyMut<T, C> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut C {
        self.world.upgrade().unwrap().borrow_mut()
            .comp_ref_mut::<'a, C>(self.id).unwrap()
    }
}

#[deriving(PartialEq, Clone, Show)]
struct EntityId {
    uuid: Uuid,
    idx: uint,
}

struct WorldData<T> {
    // XXX: This is much less efficient than it could be. A serious
    // implementation would use unboxed vecs for the components and would
    // provide lookup methods faster than a HashMap find to access the
    // components
    components: HashMap<TypeId, Vec<Option<Box<Any>>>>,

    next_idx: uint,
    reusable_idxs: Vec<uint>,
    uuids: HashMap<Uuid, uint>,

    master_system: T,
}

impl<T: System> WorldData<T> {
    fn new(master_system: T) -> WorldData<T> {
        WorldData {
            components: HashMap::new(),
            next_idx: 0,
            reusable_idxs: vec!(),
            uuids: HashMap::new(),
            master_system: master_system,
        }
    }

    fn register_new_entity(&mut self, id: EntityId) {
        assert!(!self.uuids.contains_key(&id.uuid),
            "New entity clobbering existing one");
        self.uuids.insert(id.uuid, id.idx);
    }

    fn delete_entity(&mut self, e: &Entity<T>) {
        self.check_entity(e.id);
        self.uuids.remove(&e.id.uuid);

        for (_, c) in self.components.mut_iter() {
            if c.len() > e.id.idx {
                c.as_mut_slice()[e.id.idx] = None;
            }
        }

        self.reusable_idxs.push(e.id.idx);

        self.master_system.deleted(e);
    }

    /// Return the next unused reusable entity id.
    fn get_idx(&mut self) -> uint {
        match self.reusable_idxs.pop() {
            None => {
                let ret = self.next_idx;
                self.next_idx += 1;
                ret
            }
            Some(idx) => idx
        }
    }

    fn check_entity(&self, id: EntityId) {
        assert!(self.uuids.contains_key(&id.uuid), "Unknown entity UUID");
        assert!(*self.uuids.find(&id.uuid).unwrap() == id.idx, "Entity UUID mismatch");
    }

    fn set_component<C: 'static+Clone>(&mut self, e: &Entity<T>, comp: Option<C>) {
        self.check_entity(e.id);
        let type_id = TypeId::of::<C>();
        // We haven't seen this kind of component yet.
        if !self.components.contains_key(&type_id) {
            self.components.insert(type_id, vec!());
        }

        let bin = self.components.find_mut(&type_id).unwrap();

        // XXX: grow_set didn't work.
        while bin.len() <= e.id.idx { bin.push(None); }
        bin.as_mut_slice()[e.id.idx] = match comp {
            None => None,
            Some(c) => Some(box c as Box<Any>),
        };

        match bin.as_mut_slice()[e.id.idx] {
            None => self.master_system.changed::<C>(e, None),
            Some(ref c) => self.master_system.changed(e, Some(&c)),
        };
    }

    fn comp_ref<'a, C: 'static>(
        &self, id: EntityId) -> Option<&'a C> {
        self.check_entity(id);
        let type_id = TypeId::of::<C>();
        match self.components.find(&type_id) {
            None => { None }
            Some(bin) => {
                if id.idx < bin.len() {
                    match bin.get(id.idx) {
                        &Some(ref c) => { unsafe { Some(mem::transmute(c.as_ref::<C>().unwrap())) } }
                        &None => None
                    }
                } else {
                    None
                }
            }
        }
    }

    fn comp_ref_mut<'a, C: 'static>(
        &mut self, id: EntityId) -> Option<&'a mut C> {
        self.check_entity(id);
        let type_id = TypeId::of::<C>();
        match self.components.find_mut(&type_id) {
            None => { None }
            Some(bin) => {
                if id.idx < bin.len() {
                    match bin.get_mut(id.idx) {
                        &Some(ref mut c) => {
                            unsafe { Some(mem::transmute(c.as_mut::<C>().unwrap())) }
                        }
                        &None => None
                    }
                } else {
                    None
                }
            }
        }
    }
}

<|endoftext|>


<commit_before>mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "716394d6581b60c75cfdd88b8e5b876f2db88b62";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
    // Rustc loses some attributes
    // https://github.com/rust-lang/rust/issues/84879
    "src/test/ui/proc-macro/issue-81555.rs",

    // Compile-fail expr parameter in const generic position: f::<1 + 2>()
    "src/test/ui/const-generics/closing-args-token.rs",
    "src/test/ui/const-generics/const-expression-parameter.rs",

    // Deprecated anonymous parameter syntax in traits
    "src/test/ui/issues/issue-13105.rs",
    "src/test/ui/issues/issue-13775.rs",
    "src/test/ui/issues/issue-34074.rs",
    "src/test/ui/proc-macro/trait-fn-args-2015.rs",

    // Excessive nesting
    "src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs",

    // Not actually test cases
    "src/test/rustdoc-ui/test-compile-fail2.rs",
    "src/test/rustdoc-ui/test-compile-fail3.rs",
    "src/test/ui/include-single-expr-helper.rs",
    "src/test/ui/include-single-expr-helper-1.rs",
    "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "src/test/ui/lint/expansion-time-include.rs",
    "src/test/ui/macros/auxiliary/macro-comma-support.rs",
    "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
    "src/test/ui/parser/auxiliary/issue-21146-inc.rs",
];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    if path.starts_with("src/test/compile-fail") || path.starts_with("src/test/rustfix") {
        return false;
    }

    if path.starts_with("src/test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE.contains(&path)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust");
    for exclude in EXCLUDE {
        if !test_src.join(exclude).exists() {
            missing += "\ntests/rust/";
            missing += exclude;
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<commit_msg>Test against rust repo sources corresponding to nightly-2021-09-02<commit_after>mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "50171c310cd15e1b2d3723766ce64e2e4d6696fc";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
    // TODO: to be categorized
    "src/test/debuginfo/function-names.rs",
    "src/test/pretty/anonymous-types.rs",
    "src/test/ui/associated-types/associated-type-destructuring-assignment.rs",
    "src/test/ui/associated-types/associated-type-struct-construction.rs",
    "src/test/ui/let-else/let-else-run-pass.rs",
    "src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs",
    "src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs",
    "src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs",
    "src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs",
    "src/test/ui/rfc-2632-const-trait-impl/syntax.rs",
    "src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs",
    "src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs",
    "src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs",
    "src/tools/rustfmt/tests/coverage/target/comments.rs",
    "src/tools/rustfmt/tests/parser/issue-4126/invalid.rs",
    "src/tools/rustfmt/tests/parser/issue_4418.rs",
    "src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs",
    "src/tools/rustfmt/tests/source/attrib.rs",
    "src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs",
    "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs",
    "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/true.rs",
    "src/tools/rustfmt/tests/source/issue-3639.rs",
    "src/tools/rustfmt/tests/source/let_else.rs",
    "src/tools/rustfmt/tests/source/match.rs",
    "src/tools/rustfmt/tests/source/trait.rs",
    "src/tools/rustfmt/tests/source/type.rs",
    "src/tools/rustfmt/tests/target/attrib-block-expr.rs",
    "src/tools/rustfmt/tests/target/attrib.rs",
    "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs",
    "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs",
    "src/tools/rustfmt/tests/target/let_else.rs",
    "src/tools/rustfmt/tests/target/match.rs",
    "src/tools/rustfmt/tests/target/trait.rs",
    "src/tools/rustfmt/tests/target/type.rs",

    // Rustc loses some attributes
    // https://github.com/rust-lang/rust/issues/84879
    "src/test/ui/proc-macro/issue-81555.rs",

    // Compile-fail expr parameter in const generic position: f::<1 + 2>()
    "src/test/ui/const-generics/early/closing-args-token.rs",
    "src/test/ui/const-generics/early/const-expression-parameter.rs",

    // Deprecated anonymous parameter syntax in traits
    "src/test/ui/issues/issue-13105.rs",
    "src/test/ui/issues/issue-13775.rs",
    "src/test/ui/issues/issue-34074.rs",
    "src/test/ui/proc-macro/trait-fn-args-2015.rs",

    // Excessive nesting
    "src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs",

    // Not actually test cases
    "src/test/rustdoc-ui/test-compile-fail2.rs",
    "src/test/rustdoc-ui/test-compile-fail3.rs",
    "src/test/ui/include-single-expr-helper.rs",
    "src/test/ui/include-single-expr-helper-1.rs",
    "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "src/test/ui/lint/expansion-time-include.rs",
    "src/test/ui/macros/auxiliary/macro-comma-support.rs",
    "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
    "src/test/ui/parser/auxiliary/issue-21146-inc.rs",
];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    if path.starts_with("src/test/compile-fail") || path.starts_with("src/test/rustfix") {
        return false;
    }

    if path.starts_with("src/test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE.contains(&path)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust");
    for exclude in EXCLUDE {
        if !test_src.join(exclude).exists() {
            missing += "\ntests/rust/";
            missing += exclude;
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<|endoftext|>


<commit_before><commit_msg>chroot: add more tests<commit_after><|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate mimir;
extern crate docker_wrapper;
extern crate hyper;
extern crate rs_es;
extern crate serde_json;
#[macro_use]
extern crate log;
#[macro_use]
extern crate mdo;

use docker_wrapper::*;

mod bano2mimir_test;
mod osm2mimir_test;
mod rubber_test;
mod bragi_test;
use serde_json::value::Value;
use hyper::client::response::Response;

trait ToJson {
    fn to_json(self) -> Value;
}
impl ToJson for Response {
    fn to_json(self) -> Value {
        match serde_json::from_reader(self) {
            Ok(v) => v,
            Err(e) => {
                panic!("could not get json value from response: {:?}", e);
            }
        }
    }
}

pub struct ElasticSearchWrapper<'a> {
    docker_wrapper: &'a DockerWrapper,
    pub rubber: mimir::rubber::Rubber,
}

impl<'a> ElasticSearchWrapper<'a> {
    pub fn host(&self) -> String {
        self.docker_wrapper.host()
    }

    pub fn init(&mut self) {
        self.rubber.delete_index(&"_all".to_string()).unwrap();
    }

    //    A way to watch if indexes are built might be curl http://localhost:9200/_stats
    //    then _all/total/segments/index_writer_memory_in_bytes( or version_map_memory_in_bytes)
    // 	  should be == 0 if indexes are ok (no refresh needed)
    pub fn refresh(&self) {
        info!("Refreshing ES indexes");

        let res = hyper::client::Client::new()
                      .get(&format!("{}/_refresh", self.host()))
                      .send()
                      .unwrap();
        assert!(res.status == hyper::Ok, "Error ES refresh: {:?}", res);
    }

    pub fn new(docker_wrapper: &DockerWrapper) -> ElasticSearchWrapper {
        let mut es_wrapper = ElasticSearchWrapper {
            docker_wrapper: docker_wrapper,
            rubber: mimir::rubber::Rubber::new(&docker_wrapper.host()),
        };
        es_wrapper.init();
        es_wrapper
    }

    /// simple search on an index
    /// assert that the result is OK and transform it to a json Value
    pub fn search(&self, word: &str) -> serde_json::Value {
        let res = self.rubber.get(&format!("munin/_search?q={}", word)).unwrap();
        assert!(res.status == hyper::Ok);
        res.to_json()
    }
}

/// Main test method (regroups all tests)
/// All tests are done sequentially,
/// and use the same docker in order to avoid multiple inits
/// (ES cleanup is handled by es_wrapper)
#[test]
fn all_tests() {
    mimir::logger_init().unwrap();
    let docker_wrapper = DockerWrapper::new().unwrap();

    // we call all tests here
    bano2mimir_test::bano2mimir_sample_test(ElasticSearchWrapper::new(&docker_wrapper));
    osm2mimir_test::osm2mimir_sample_test(ElasticSearchWrapper::new(&docker_wrapper));
    rubber_test::rubber_zero_downtime_test(ElasticSearchWrapper::new(&docker_wrapper));
    rubber_test::rubber_custom_id(ElasticSearchWrapper::new(&docker_wrapper));
    bragi_test::bragi_tests(ElasticSearchWrapper::new(&docker_wrapper));
}
<commit_msg>add test osm2mimir_bano2mimir_test<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate mimir;
extern crate docker_wrapper;
extern crate hyper;
extern crate rs_es;
extern crate serde_json;
#[macro_use]
extern crate log;
#[macro_use]
extern crate mdo;

use docker_wrapper::*;

mod bano2mimir_test;
mod osm2mimir_test;
mod osm2mimir_bano2mimir_test;
mod rubber_test;
mod bragi_test;
use serde_json::value::Value;
use hyper::client::response::Response;

trait ToJson {
    fn to_json(self) -> Value;
}
impl ToJson for Response {
    fn to_json(self) -> Value {
        match serde_json::from_reader(self) {
            Ok(v) => v,
            Err(e) => {
                panic!("could not get json value from response: {:?}", e);
            }
        }
    }
}

pub struct ElasticSearchWrapper<'a> {
    docker_wrapper: &'a DockerWrapper,
    pub rubber: mimir::rubber::Rubber,
}

impl<'a> ElasticSearchWrapper<'a> {
    pub fn host(&self) -> String {
        self.docker_wrapper.host()
    }

    pub fn init(&mut self) {
        self.rubber.delete_index(&"_all".to_string()).unwrap();
    }

    //    A way to watch if indexes are built might be curl http://localhost:9200/_stats
    //    then _all/total/segments/index_writer_memory_in_bytes( or version_map_memory_in_bytes)
    // 	  should be == 0 if indexes are ok (no refresh needed)
    pub fn refresh(&self) {
        info!("Refreshing ES indexes");

        let res = hyper::client::Client::new()
                      .get(&format!("{}/_refresh", self.host()))
                      .send()
                      .unwrap();
        assert!(res.status == hyper::Ok, "Error ES refresh: {:?}", res);
    }

    pub fn new(docker_wrapper: &DockerWrapper) -> ElasticSearchWrapper {
        let mut es_wrapper = ElasticSearchWrapper {
            docker_wrapper: docker_wrapper,
            rubber: mimir::rubber::Rubber::new(&docker_wrapper.host()),
        };
        es_wrapper.init();
        es_wrapper
    }

    /// simple search on an index
    /// assert that the result is OK and transform it to a json Value
    pub fn search(&self, word: &str) -> serde_json::Value {
        let res = self.rubber.get(&format!("munin/_search?q={}", word)).unwrap();
        assert!(res.status == hyper::Ok);
        res.to_json()
    }
}

/// Main test method (regroups all tests)
/// All tests are done sequentially,
/// and use the same docker in order to avoid multiple inits
/// (ES cleanup is handled by es_wrapper)
#[test]
fn all_tests() {
    mimir::logger_init().unwrap();
    let docker_wrapper = DockerWrapper::new().unwrap();

    // we call all tests here
    bano2mimir_test::bano2mimir_sample_test(ElasticSearchWrapper::new(&docker_wrapper));
    osm2mimir_test::osm2mimir_sample_test(ElasticSearchWrapper::new(&docker_wrapper));
    osm2mimir_bano2mimir_test::osm2mimir_bano2mimir_test(ElasticSearchWrapper::new(&docker_wrapper));
    rubber_test::rubber_zero_downtime_test(ElasticSearchWrapper::new(&docker_wrapper));
    rubber_test::rubber_custom_id(ElasticSearchWrapper::new(&docker_wrapper));
    bragi_test::bragi_tests(ElasticSearchWrapper::new(&docker_wrapper));
}
<|endoftext|>