<commit_before>//! Main entry point to the library.
//! See examples for documentation on how to use this struct.

use std::{env, ptr};
use std::any::Any;
use std::cell::UnsafeCell;
use std::ffi::CStr;

use extensions::server_decoration::ServerDecorationManager;
use manager::{InputManager, InputManagerHandler, OutputManager, OutputManagerHandler,
              WlShellManager, WlShellManagerHandler};
use render::GenericRenderer;
use types::seat::Seats;

use wayland_sys::server::{wl_display, wl_event_loop, WAYLAND_SERVER_HANDLE};
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{wlr_backend, wlr_backend_autocreate, wlr_backend_destroy, wlr_backend_start,
                  wlr_compositor, wlr_compositor_create, wlr_wl_shell, wlr_wl_shell_create};
use wlroots_sys::wayland_server::sys::wl_display_init_shm;

/// Global compositor pointer, used to refer to the compositor state unsafely.
pub static mut COMPOSITOR_PTR: *mut Compositor = 0 as *mut _;

#[allow(dead_code)]
pub struct Compositor {
    /// User data.
    pub data: Box<Any>,
    /// The list of seats.
    ///
    /// This is stored here due to their complicated memory model.
    ///
    /// Please refer to the `Seat` and `Seats` documentation to learn how to use this.
    pub seats: Seats,
    /// Manager for the inputs.
    input_manager: Option<Box<InputManager>>,
    /// Manager for the outputs.
    output_manager: Option<Box<OutputManager>>,
    /// Manager for Wayland shells.
    wl_shell_manager: Option<Box<WlShellManager>>,
    /// Pointer to wl_shell global.
    /// If wl_shell_manager is `None`, this value will be `NULL`
    wl_shell_global: *mut wlr_wl_shell,
    /// Pointer to the wlr_compositor
    compositor: *mut wlr_compositor,
    /// Pointer to the wlroots backend in use.
    backend: *mut wlr_backend,
    /// Pointer to the wayland display.
    display: *mut wl_display,
    /// Pointer to the event loop.
    event_loop: *mut wl_event_loop,
    /// Shared memory buffer file descriptor.
    shm_fd: i32,
    /// Name of the Wayland socket that we are binding to.
    socket_name: String,
    /// Optional decoration manager extension.
    pub server_decoration_manager: Option<ServerDecorationManager>,
    /// The renderer used to draw things to the screen.
    pub renderer: Option<GenericRenderer>,
    /// The error from the panic, if there was one.
    panic_error: Option<Box<Any + Send>>
}

pub struct CompositorBuilder {
    input_manager_handler: Option<Box<InputManagerHandler>>,
    output_manager_handler: Option<Box<OutputManagerHandler>>,
    wl_shell_manager_handler: Option<Box<WlShellManagerHandler>>,
    gles2: bool,
    server_decoration_manager: bool
}

impl CompositorBuilder {
    /// Make a new compositor builder.
    ///
    /// Unless otherwise noted, each option is `false`/`None`.
    pub fn new() -> Self {
        CompositorBuilder { gles2: false,
                            server_decoration_manager: false,
                            input_manager_handler: None,
                            output_manager_handler: None,
                            wl_shell_manager_handler: None }
    }

    /// Set the handler for inputs.
    pub fn input_manager(mut self, input_manager_handler: Box<InputManagerHandler>) -> Self {
        self.input_manager_handler = Some(input_manager_handler);
        self
    }

    /// Set the handler for outputs.
    pub fn output_manager(mut self, output_manager_handler: Box<OutputManagerHandler>) -> Self {
        self.output_manager_handler = Some(output_manager_handler);
        self
    }

    /// Set the handler for Wayland shells.
    pub fn wl_shell_manager(mut self,
                            wl_shell_manager_handler: Box<WlShellManagerHandler>)
                            -> Self {
        self.wl_shell_manager_handler = Some(wl_shell_manager_handler);
        self
    }

    /// Decide whether or not to enable the GLES2 extension.
    pub fn gles2(mut self, gles2_renderer: bool) -> Self {
        self.gles2 = gles2_renderer;
        self
    }

    /// Decide whether or not to enable the server decoration manager protocol
    /// extension.
    pub fn server_decoration_manager(mut self, server_decoration_manager: bool) -> Self {
        self.server_decoration_manager = server_decoration_manager;
        self
    }

    /// Makes a new compositor that handles the setup of the graphical backend
    /// (e.g, Wayland, X11, or DRM).
    ///
    /// Also automatically opens the socket for clients to communicate to the
    /// compositor with.
    pub fn build_auto<D>(self, data: D) -> Compositor
        where D: Any + 'static
    {
        unsafe {
            let display =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_create,) as *mut wl_display;
            let event_loop =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_event_loop, display);
            let backend = wlr_backend_autocreate(display as *mut _);
            if backend.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Could not auto-create backend");
            }
            // Set up shared memory buffer for Wayland clients.
            let shm_fd = wl_display_init_shm(display as *mut _);
            // Create optional extensions.
            let server_decoration_manager = if self.server_decoration_manager {
                ServerDecorationManager::new(display)
            } else {
                None
            };
            let compositor;
            let renderer = if self.gles2 {
                let gles2 = GenericRenderer::gles2_renderer(backend);
                // Set up wlr_compositor
                let gles2_ptr = gles2.as_ptr();
                compositor = wlr_compositor_create(display as *mut _, gles2_ptr);
                Some(gles2)
            } else {
                compositor = wlr_compositor_create(display as *mut _, ptr::null_mut());
                None
            };

            // Set up input manager, if the user provided it.
            let input_manager = self.input_manager_handler.map(|handler| {
                let mut input_manager = InputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_input as *mut _ as _,
                              input_manager.add_listener() as *mut _ as _);
                input_manager
            });

            // Set up output manager, if the user provided it.
            let output_manager = self.output_manager_handler.map(|handler| {
                let mut output_manager = OutputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_output as *mut _ as _,
                              output_manager.add_listener() as *mut _ as _);
                output_manager
            });

            // Set up wl_shell handler and associated Wayland global,
            // if user provided a manager for it.
            let mut wl_shell_global = ptr::null_mut();
            let wl_shell_manager = self.wl_shell_manager_handler.map(|handler| {
                wl_shell_global = wlr_wl_shell_create(display as *mut _);
                let mut wl_shell_manager = WlShellManager::new(handler);
                wl_signal_add(&mut (*wl_shell_global).events.new_surface as *mut _ as _,
                              wl_shell_manager.add_listener() as *mut _ as _);
                wl_shell_manager
            });

            // Open the socket to the Wayland server.
            let socket = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_add_socket_auto, display);
            if socket.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Unable to open wayland socket");
            }
            let socket_name = CStr::from_ptr(socket).to_string_lossy().into_owned();
            wlr_log!(L_DEBUG,
                     "Running compositor on wayland display {}",
                     socket_name);
            env::set_var("_WAYLAND_DISPLAY", socket_name.clone());
            Compositor { data: Box::new(data),
                         seats: Seats::default(),
                         socket_name,
                         input_manager,
                         output_manager,
                         wl_shell_manager,
                         wl_shell_global,
                         compositor,
                         backend,
                         display,
                         event_loop,
                         shm_fd,
                         server_decoration_manager,
                         renderer,
                         panic_error: None }
        }
    }
}

impl Compositor {
    /// Enters the wayland event loop. Won't return until the compositor is
    /// shut off
    pub fn run(self) {
        unsafe {
            let compositor = UnsafeCell::new(self);
            if COMPOSITOR_PTR != 0 as _ {
                // NOTE Rationale for panicking:
                // * Nicer than an abort
                // * Not yet in C land
                panic!("A compositor is already running!")
            }
            COMPOSITOR_PTR = compositor.get();
            wlr_log!(L_INFO, "Starting compositor");
            if !wlr_backend_start((*compositor.get()).backend) {
                wlr_backend_destroy((*compositor.get()).backend);
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Failed to start backend");
            }
            env::set_var("WAYLAND_DISPLAY", (*COMPOSITOR_PTR).socket_name.clone());
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_display_run,
                          (*compositor.get()).display);
            match (*compositor.get()).panic_error.take() {
                None => {}
                Some(err) => {
                    // A panic occured, now we can re-throw it safely.
                    ::std::panic::resume_unwind(err)
                }
            }
        }
    }

    pub fn terminate(&mut self) {
        unsafe {
            COMPOSITOR_PTR = 0 as _;
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_terminate, self.display);
        }
    }

    pub unsafe fn display(&self) -> *mut wl_display {
        self.display
    }

    pub unsafe fn event_loop(&self) -> *mut wl_event_loop {
        self.event_loop
    }

    /// Saves the panic error information in the compositor, to be re-thrown
    /// later when we are out of the C callback stack.
    pub(crate) fn save_panic_error(&mut self, error: Box<Any + Send>) {
        self.panic_error = Some(error);
    }
}

/// Terminates the compositor.
/// If one is not running, does nothing
pub fn terminate() {
    unsafe {
        if COMPOSITOR_PTR != 0 as _ {
            (*COMPOSITOR_PTR).terminate();
            COMPOSITOR_PTR = 0 as _
        }
    }
}
<commit_msg>Added XDG shell v6 handler to compositor setup<commit_after>//! Main entry point to the library.
//! See examples for documentation on how to use this struct.

use std::{env, ptr};
use std::any::Any;
use std::cell::UnsafeCell;
use std::ffi::CStr;

use extensions::server_decoration::ServerDecorationManager;
use manager::{InputManager, InputManagerHandler, OutputManager, OutputManagerHandler,
              WlShellManager, WlShellManagerHandler, XdgV6ShellManager, XdgV6ShellManagerHandler};
use render::GenericRenderer;
use types::seat::Seats;

use wayland_sys::server::{wl_display, wl_event_loop, WAYLAND_SERVER_HANDLE};
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{wlr_backend, wlr_backend_autocreate, wlr_backend_destroy, wlr_backend_start,
                  wlr_compositor, wlr_compositor_create, wlr_wl_shell, wlr_wl_shell_create,
                  wlr_xdg_shell_v6, wlr_xdg_shell_v6_create};
use wlroots_sys::wayland_server::sys::wl_display_init_shm;

/// Global compositor pointer, used to refer to the compositor state unsafely.
pub static mut COMPOSITOR_PTR: *mut Compositor = 0 as *mut _;

#[allow(dead_code)]
pub struct Compositor {
    /// User data.
    pub data: Box<Any>,
    /// The list of seats.
    ///
    /// This is stored here due to their complicated memory model.
    ///
    /// Please refer to the `Seat` and `Seats` documentation to learn how to use this.
    pub seats: Seats,
    /// Manager for the inputs.
    input_manager: Option<Box<InputManager>>,
    /// Manager for the outputs.
    output_manager: Option<Box<OutputManager>>,
    /// Manager for Wayland shells.
    wl_shell_manager: Option<Box<WlShellManager>>,
    /// Manager for XDG shells v6.
    xdg_v6_shell_manager: Option<Box<XdgV6ShellManager>>,
    /// Pointer to wl_shell global.
    /// If wl_shell_manager is `None`, this value will be `NULL`.
    wl_shell_global: *mut wlr_wl_shell,
    /// Pointer to the xdg_shell_v6 global.
    /// If xdg_v6_shell_manager is `None`, this value will be `NULL`.
    xdg_v6_shell_global: *mut wlr_xdg_shell_v6,
    /// Pointer to the wlr_compositor.
    compositor: *mut wlr_compositor,
    /// Pointer to the wlroots backend in use.
    backend: *mut wlr_backend,
    /// Pointer to the wayland display.
    display: *mut wl_display,
    /// Pointer to the event loop.
    event_loop: *mut wl_event_loop,
    /// Shared memory buffer file descriptor.
    shm_fd: i32,
    /// Name of the Wayland socket that we are binding to.
    socket_name: String,
    /// Optional decoration manager extension.
    pub server_decoration_manager: Option<ServerDecorationManager>,
    /// The renderer used to draw things to the screen.
    pub renderer: Option<GenericRenderer>,
    /// The error from the panic, if there was one.
    panic_error: Option<Box<Any + Send>>
}

pub struct CompositorBuilder {
    input_manager_handler: Option<Box<InputManagerHandler>>,
    output_manager_handler: Option<Box<OutputManagerHandler>>,
    wl_shell_manager_handler: Option<Box<WlShellManagerHandler>>,
    xdg_v6_shell_manager_handler: Option<Box<XdgV6ShellManagerHandler>>,
    gles2: bool,
    server_decoration_manager: bool
}

impl CompositorBuilder {
    /// Make a new compositor builder.
    ///
    /// Unless otherwise noted, each option is `false`/`None`.
    pub fn new() -> Self {
        CompositorBuilder { gles2: false,
                            server_decoration_manager: false,
                            input_manager_handler: None,
                            output_manager_handler: None,
                            wl_shell_manager_handler: None,
                            xdg_v6_shell_manager_handler: None }
    }

    /// Set the handler for inputs.
    pub fn input_manager(mut self, input_manager_handler: Box<InputManagerHandler>) -> Self {
        self.input_manager_handler = Some(input_manager_handler);
        self
    }

    /// Set the handler for outputs.
    pub fn output_manager(mut self, output_manager_handler: Box<OutputManagerHandler>) -> Self {
        self.output_manager_handler = Some(output_manager_handler);
        self
    }

    /// Set the handler for Wayland shells.
    pub fn wl_shell_manager(mut self,
                            wl_shell_manager_handler: Box<WlShellManagerHandler>)
                            -> Self {
        self.wl_shell_manager_handler = Some(wl_shell_manager_handler);
        self
    }

    /// Set the handler for xdg v6 shells.
    pub fn xdg_shell_v6_manager(mut self,
                                xdg_v6_shell_manager_handler: Box<XdgV6ShellManagerHandler>)
                                -> Self {
        self.xdg_v6_shell_manager_handler = Some(xdg_v6_shell_manager_handler);
        self
    }

    /// Decide whether or not to enable the GLES2 extension.
    pub fn gles2(mut self, gles2_renderer: bool) -> Self {
        self.gles2 = gles2_renderer;
        self
    }

    /// Decide whether or not to enable the server decoration manager protocol
    /// extension.
    pub fn server_decoration_manager(mut self, server_decoration_manager: bool) -> Self {
        self.server_decoration_manager = server_decoration_manager;
        self
    }

    /// Makes a new compositor that handles the setup of the graphical backend
    /// (e.g, Wayland, X11, or DRM).
    ///
    /// Also automatically opens the socket for clients to communicate to the
    /// compositor with.
    pub fn build_auto<D>(self, data: D) -> Compositor
        where D: Any + 'static
    {
        unsafe {
            let display =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_create,) as *mut wl_display;
            let event_loop =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_event_loop, display);
            let backend = wlr_backend_autocreate(display as *mut _);
            if backend.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Could not auto-create backend");
            }
            // Set up shared memory buffer for Wayland clients.
            let shm_fd = wl_display_init_shm(display as *mut _);
            // Create optional extensions.
            let server_decoration_manager = if self.server_decoration_manager {
                ServerDecorationManager::new(display)
            } else {
                None
            };
            let compositor;
            let renderer = if self.gles2 {
                let gles2 = GenericRenderer::gles2_renderer(backend);
                // Set up wlr_compositor
                let gles2_ptr = gles2.as_ptr();
                compositor = wlr_compositor_create(display as *mut _, gles2_ptr);
                Some(gles2)
            } else {
                compositor = wlr_compositor_create(display as *mut _, ptr::null_mut());
                None
            };

            // Set up input manager, if the user provided it.
            let input_manager = self.input_manager_handler.map(|handler| {
                let mut input_manager = InputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_input as *mut _ as _,
                              input_manager.add_listener() as *mut _ as _);
                input_manager
            });

            // Set up output manager, if the user provided it.
            let output_manager = self.output_manager_handler.map(|handler| {
                let mut output_manager = OutputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_output as *mut _ as _,
                              output_manager.add_listener() as *mut _ as _);
                output_manager
            });

            // Set up wl_shell handler and associated Wayland global,
            // if user provided a manager for it.
            let mut wl_shell_global = ptr::null_mut();
            let wl_shell_manager = self.wl_shell_manager_handler.map(|handler| {
                wl_shell_global = wlr_wl_shell_create(display as *mut _);
                let mut wl_shell_manager = WlShellManager::new(handler);
                wl_signal_add(&mut (*wl_shell_global).events.new_surface as *mut _ as _,
                              wl_shell_manager.add_listener() as *mut _ as _);
                wl_shell_manager
            });

            // Set up the xdg_shell_v6 handler and associated Wayland global,
            // if user provided a manager for it.
            let mut xdg_v6_shell_global = ptr::null_mut();
            let xdg_v6_shell_manager = self.xdg_v6_shell_manager_handler.map(|handler| {
                xdg_v6_shell_global = wlr_xdg_shell_v6_create(display as *mut _);
                let mut xdg_v6_shell_manager = XdgV6ShellManager::new((vec![], handler));
                wl_signal_add(&mut (*xdg_v6_shell_global).events.new_surface as *mut _ as _,
                              xdg_v6_shell_manager.add_listener() as *mut _ as _);
                xdg_v6_shell_manager
            });

            // Open the socket to the Wayland server.
            let socket = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_add_socket_auto, display);
            if socket.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Unable to open wayland socket");
            }
            let socket_name = CStr::from_ptr(socket).to_string_lossy().into_owned();
            wlr_log!(L_DEBUG,
                     "Running compositor on wayland display {}",
                     socket_name);
            env::set_var("_WAYLAND_DISPLAY", socket_name.clone());
            Compositor { data: Box::new(data),
                         seats: Seats::default(),
                         socket_name,
                         input_manager,
                         output_manager,
                         wl_shell_manager,
                         wl_shell_global,
                         xdg_v6_shell_manager,
                         xdg_v6_shell_global,
                         compositor,
                         backend,
                         display,
                         event_loop,
                         shm_fd,
                         server_decoration_manager,
                         renderer,
                         panic_error: None }
        }
    }
}

impl Compositor {
    /// Enters the wayland event loop. Won't return until the compositor is
    /// shut off
    pub fn run(self) {
        unsafe {
            let compositor = UnsafeCell::new(self);
            if COMPOSITOR_PTR != 0 as _ {
                // NOTE Rationale for panicking:
                // * Nicer than an abort
                // * Not yet in C land
                panic!("A compositor is already running!")
            }
            COMPOSITOR_PTR = compositor.get();
            wlr_log!(L_INFO, "Starting compositor");
            if !wlr_backend_start((*compositor.get()).backend) {
                wlr_backend_destroy((*compositor.get()).backend);
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Failed to start backend");
            }
            env::set_var("WAYLAND_DISPLAY", (*COMPOSITOR_PTR).socket_name.clone());
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_display_run,
                          (*compositor.get()).display);
            match (*compositor.get()).panic_error.take() {
                None => {}
                Some(err) => {
                    // A panic occured, now we can re-throw it safely.
                    ::std::panic::resume_unwind(err)
                }
            }
        }
    }

    pub fn terminate(&mut self) {
        unsafe {
            COMPOSITOR_PTR = 0 as _;
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_terminate, self.display);
        }
    }

    pub unsafe fn display(&self) -> *mut wl_display {
        self.display
    }

    pub unsafe fn event_loop(&self) -> *mut wl_event_loop {
        self.event_loop
    }

    /// Saves the panic error information in the compositor, to be re-thrown
    /// later when we are out of the C callback stack.
    pub(crate) fn save_panic_error(&mut self, error: Box<Any + Send>) {
        self.panic_error = Some(error);
    }
}

/// Terminates the compositor.
/// If one is not running, does nothing
pub fn terminate() {
    unsafe {
        if COMPOSITOR_PTR != 0 as _ {
            (*COMPOSITOR_PTR).terminate();
            COMPOSITOR_PTR = 0 as _
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

//! Points are fixed positions in affine space with no length or direction. This
//! disinguishes them from vectors, which have a length and direction, but do
//! not have a fixed position.

use std::fmt;
use std::num::{one, zero};

use array::*;
use vector::*;
use partial_ord::PartOrdPrim;

/// A point in 2-dimensional space.
#[deriving(Eq, Clone, Hash)]
pub struct Point2<S> { pub x: S, pub y: S }

/// A point in 3-dimensional space.
#[deriving(Eq, Clone, Hash)]
pub struct Point3<S> { pub x: S, pub y: S, pub z: S }

impl<S: Num> Point2<S> {
    #[inline]
    pub fn new(x: S, y: S) -> Point2<S> {
        Point2 { x: x, y: y }
    }
}

impl<S: Num> Point3<S> {
    #[inline]
    pub fn new(x: S, y: S, z: S) -> Point3<S> {
        Point3 { x: x, y: y, z: z }
    }
}

impl<S: PartOrdPrim> Point3<S> {
    #[inline]
    pub fn from_homogeneous(v: &Vector4<S>) -> Point3<S> {
        let e = v.truncate().mul_s(one::<S>() / v.w);
        Point3::new(e.x.clone(), e.y.clone(), e.z.clone())  //FIXME
    }

    #[inline]
    pub fn to_homogeneous(&self) -> Vector4<S> {
        Vector4::new(self.x.clone(), self.y.clone(), self.z.clone(), one())
    }
}

/// Specifies the numeric operations for point types.
pub trait Point
<
    S: PartOrdPrim,
    V: Vector<S, Slice>,
    Slice
>
:   Array<S, Slice>
{
    #[inline] fn origin() -> Self{ build(|_i| zero::<S>()) }

    #[inline] fn from_vec(v: &V) -> Self { build(|i| v.i(i).clone()) }
    #[inline] fn to_vec(&self) -> V { build(|i| self.i(i).clone()) }

    #[inline] fn mul_s(&self, s: S) -> Self { build(|i| self.i(i).mul(&s)) }
    #[inline] fn div_s(&self, s: S) -> Self { build(|i| self.i(i).div(&s)) }
    #[inline] fn rem_s(&self, s: S) -> Self { build(|i| self.i(i).rem(&s)) }

    #[inline] fn add_v(&self, other: &V) -> Self { build(|i| self.i(i).add(other.i(i))) }
    #[inline] fn sub_p(&self, other: &Self) -> V { build(|i| self.i(i).sub(other.i(i))) }

    #[inline] fn mul_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.mul(&s)) }
    #[inline] fn div_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.div(&s)) }
    #[inline] fn rem_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.rem(&s)) }

    #[inline] fn add_self_v(&mut self, other: &V) { self.each_mut(|i, x| *x = x.add(other.i(i))) }

    /// This is a weird one, but its useful for plane calculations
    #[inline]
    fn dot(&self, v: &V) -> S {
        build::<S, Slice, V>(|i| self.i(i).mul(v.i(i))).comp_add()
    }
}

array!(impl<S> Point2<S> -> [S, ..2] _2)
array!(impl<S> Point3<S> -> [S, ..3] _3)

impl<S: PartOrdPrim> Point<S, Vector2<S>, [S, ..2]> for Point2<S> {}
impl<S: PartOrdPrim> Point<S, Vector3<S>, [S, ..3]> for Point3<S> {}

impl<S: fmt::Show> fmt::Show for Point2<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}, {}]", self.x, self.y)
    }
}

impl<S: fmt::Show> fmt::Show for Point3<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}, {}, {}]", self.x, self.y, self.z)
    }
}
<commit_msg>Document Point<commit_after>// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

//! Points are fixed positions in affine space with no length or direction. This
//! disinguishes them from vectors, which have a length and direction, but do
//! not have a fixed position.

use std::fmt;
use std::num::{one, zero};

use array::*;
use vector::*;
use partial_ord::PartOrdPrim;

/// A point in 2-dimensional space.
#[deriving(Eq, Clone, Hash)]
pub struct Point2<S> { pub x: S, pub y: S }

/// A point in 3-dimensional space.
#[deriving(Eq, Clone, Hash)]
pub struct Point3<S> { pub x: S, pub y: S, pub z: S }

impl<S: Num> Point2<S> {
    #[inline]
    pub fn new(x: S, y: S) -> Point2<S> {
        Point2 { x: x, y: y }
    }
}

impl<S: Num> Point3<S> {
    #[inline]
    pub fn new(x: S, y: S, z: S) -> Point3<S> {
        Point3 { x: x, y: y, z: z }
    }
}

impl<S: PartOrdPrim> Point3<S> {
    #[inline]
    pub fn from_homogeneous(v: &Vector4<S>) -> Point3<S> {
        let e = v.truncate().mul_s(one::<S>() / v.w);
        Point3::new(e.x.clone(), e.y.clone(), e.z.clone())  //FIXME
    }

    #[inline]
    pub fn to_homogeneous(&self) -> Vector4<S> {
        Vector4::new(self.x.clone(), self.y.clone(), self.z.clone(), one())
    }
}

/// Specifies the numeric operations for point types.
pub trait Point
<
    S: PartOrdPrim,
    V: Vector<S, Slice>,
    Slice
>
:   Array<S, Slice>
{
    /// Create a point at the origin.
    #[inline] fn origin() -> Self{ build(|_i| zero::<S>()) }

    /// Create a point from a vector.
    #[inline] fn from_vec(v: &V) -> Self { build(|i| v.i(i).clone()) }
    /// Convert a point to a vector.
    #[inline] fn to_vec(&self) -> V { build(|i| self.i(i).clone()) }

    /// Multiply each component by a scalar, returning the new point.
    #[inline] fn mul_s(&self, s: S) -> Self { build(|i| self.i(i).mul(&s)) }
    /// Divide each component by a scalar, returning the new point.
    #[inline] fn div_s(&self, s: S) -> Self { build(|i| self.i(i).div(&s)) }
    /// Subtract a scalar from each component, returning the new point.
    #[inline] fn rem_s(&self, s: S) -> Self { build(|i| self.i(i).rem(&s)) }

    /// Add a vector to this point, returning the new point.
    #[inline] fn add_v(&self, other: &V) -> Self { build(|i| self.i(i).add(other.i(i))) }
    /// Subtract another point from this one, returning a new vector.
    #[inline] fn sub_p(&self, other: &Self) -> V { build(|i| self.i(i).sub(other.i(i))) }

    /// Multiply each component by a scalar, in-place.
    #[inline] fn mul_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.mul(&s)) }
    /// Divide each component by a scalar, in-place.
    #[inline] fn div_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.div(&s)) }
    /// Take the remainder of each component by a scalar, in-place.
    #[inline] fn rem_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.rem(&s)) }

    /// Add a vector to this point, in-place.
    #[inline] fn add_self_v(&mut self, other: &V) { self.each_mut(|i, x| *x = x.add(other.i(i))) }

    /// This is a weird one, but its useful for plane calculations.
    #[inline]
    fn dot(&self, v: &V) -> S {
        build::<S, Slice, V>(|i| self.i(i).mul(v.i(i))).comp_add()
    }
}

array!(impl<S> Point2<S> -> [S, ..2] _2)
array!(impl<S> Point3<S> -> [S, ..3] _3)

impl<S: PartOrdPrim> Point<S, Vector2<S>, [S, ..2]> for Point2<S> {}
impl<S: PartOrdPrim> Point<S, Vector3<S>, [S, ..3]> for Point3<S> {}

impl<S: fmt::Show> fmt::Show for Point2<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}, {}]", self.x, self.y)
    }
}

impl<S: fmt::Show> fmt::Show for Point3<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}, {}, {}]", self.x, self.y, self.z)
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::net;
use std::io::Write;

pub struct Connection {
    stream: net::TcpStream
}

impl Connection {
    pub fn flush(&mut self) -> io::Result<()> {
        match self.stream.write(b"flush_all\r\n") {
            Ok(_) => {},
            Err(err) => return Err(err),
        }
        return self.stream.flush();
    }
}

pub fn connect()-> Result<Connection, io::Error>{
    match net::TcpStream::connect("127.0.0.1:11211") {
        Ok(stream) => return Ok(Connection{stream: stream}),
        Err(err) => return Err(err),
    }
}
<commit_msg>feat: use BufReader instead of TcpStream<commit_after>use std::net;
use std::io;
use std::io::Write;
use std::io::BufRead;

pub struct Connection {
    reader: io::BufReader<net::TcpStream>
}

impl Connection {
    pub fn flush(&mut self) -> io::Result<()> {
        match self.reader.get_ref().write(b"flush_all\r\n") {
            Ok(_) => {},
            Err(err) => return Err(err),
        }
        try!(self.reader.get_ref().flush());
        let mut s = String::new();
        let _ = self.reader.read_line(&mut s);
        s == "OK\r\n";  // TODO: assert it
        return Ok(());
    }
}

pub fn connect()-> Result<Connection, io::Error>{
    match net::TcpStream::connect("127.0.0.1:11211") {
        Ok(stream) => return Ok(Connection{reader: io::BufReader::new(stream)}),
        Err(err) => return Err(err),
    }
}
<|endoftext|>


<commit_before>/* Copyright 2015 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

use std::ptr;
use iup_sys::*;
use super::{Control, UnwrapHandle};
use super::handle_rc::HandleRc;
use super::attributes::{
    OrientationAttribute,
    set_str_attribute,
    get_str_attribute_slice,
};

pub trait Container : Control {
    fn append(&self, new_child: &Control) -> Result<(), ()> {
        unsafe {
            if IupAppend(self.handle(), new_child.handle()) == ptr::null_mut() {
                Err(())
            } else {
                Ok(())
            }
        }
    }

    fn insert(&self, ref_child: Option<&Control>, new_child: &Control) -> Result<(), ()> {
        unsafe {
            let ref_child = ref_child.map(|c| c.handle()).unwrap_or(ptr::null_mut());
            if IupInsert(self.handle(), ref_child, new_child.handle()) == ptr::null_mut() {
                Err(())
            } else {
                Ok(())
            }
        }
    }

    /// Returns the number of children of the specified control.
    ///
    /// Warning: Since children are stored as a linked list, getting the count is O(n).
    fn child_count(&self) -> usize {
        unsafe {
            IupGetChildCount(self.handle()) as usize
        }
    }
}

pub trait NonDialogContainer : Container {
    fn refresh_children(&self) {
        unsafe {
            IupRefreshChildren(self.handle());
        }
    }
}

// Be sure that the Vec is not dropped before the *mut *mut Ihandle is used.
fn wrapper_to_handles(controls: Option<&[&::Control]>)
-> (Option<Vec<*mut Ihandle>>, *mut *mut Ihandle)
{
    let mut controls: Option<Vec<_>> = controls.map(|slice| {
        let mut v: Vec<*mut Ihandle> = slice.iter().map(|c| c.handle()).collect();
        v.push(ptr::null_mut()); // array has to be null terminated
        v
    });
    let p = controls.as_mut().map(|v| v.as_mut_ptr()).unwrap_or(ptr::null_mut());
    (controls, p)
}

#[derive(Clone)]
pub struct Fill(HandleRc);

impl Fill {
    pub fn new() -> Fill {
        unsafe {
            ::iup_open();
            let handle = IupFill();
            Fill(HandleRc::new(handle))
        }
    }
}

impl_control_traits!(Fill);

#[macro_export]
macro_rules! fill { // This is a macro for consistency, even though it could just be a function.
    () => { Fill::new() };
}

#[derive(Clone)]
pub struct Hbox(HandleRc);

impl Hbox {
    pub fn new(children: Option<&[&::Control]>) -> Hbox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            Hbox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> Hbox {
        let handle = IupHboxv(children);
        Hbox(HandleRc::new(handle))
    }
}

impl_control_traits!(Hbox);

impl Container for Hbox {}

#[macro_export]
macro_rules! hbox {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { Hbox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { hbox!($($c),*) };
}

#[derive(Clone)]
pub struct Vbox(HandleRc);

impl Vbox {
    pub fn new(children: Option<&[&::Control]>) -> Vbox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            Vbox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> Vbox {
        let handle = IupVboxv(children);
        Vbox(HandleRc::new(handle))
    }
}

impl_control_traits!(Vbox);

impl Container for Vbox {}

#[macro_export]
macro_rules! vbox {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { Vbox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { vbox!($($c),*) };
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum NumDiv {
    Fixed(u32),
    Auto,
}

#[derive(Clone)]
pub struct GridBox(HandleRc);

impl GridBox {
    pub fn new(children: Option<&[&::Control]>) -> GridBox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            GridBox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> GridBox {
        let handle = IupGridBoxv(children);
        GridBox(HandleRc::new(handle))
    }

    pub fn alignment_lin(&self, line: u32) -> ::VAlignment {
        unsafe {
            let attr = format!("ALIGNMENTLIN{}", line);
            ::VAlignment::from_str(get_str_attribute_slice(self.handle(), &attr).as_bytes())
        }
    }

    pub fn set_alignment_lin(&self, line: u32, alignment: ::VAlignment) -> &Self {
        set_str_attribute(self.handle(), &format!("ALIGNMENTLIN{}", line), alignment.to_str());
        self
    }

    pub fn alignment_lin_all(&self) -> ::VAlignment {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "ALIGNMENTLIN");
            ::VAlignment::from_str(s.as_bytes())
        }
    }

    pub fn set_alignment_lin_all(&self, alignment: ::VAlignment) -> &Self {
        set_str_attribute(self.handle(), "ALIGNMENTLIN", alignment.to_str());
        self
    }

    pub fn alignment_col(&self, column: u32) -> ::HAlignment {
        unsafe {
            let attr = format!("ALIGNMENTCOL{}", column);
            ::HAlignment::from_str(get_str_attribute_slice(self.handle(), &attr).as_bytes())
        }
    }

    pub fn set_alignment_col(&self, column: u32, alignment: ::HAlignment) -> &Self {
        set_str_attribute(self.handle(), &format!("ALIGNMENTCOL{}", column), alignment.to_str());
        self
    }

    pub fn alignment_col_all(&self) -> ::HAlignment {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "ALIGNMENTCOL");
            ::HAlignment::from_str(s.as_bytes())
        }
    }

    pub fn set_alignment_col_all(&self, alignment: ::HAlignment) -> &Self {
        set_str_attribute(self.handle(), "ALIGNMENTCOL", alignment.to_str());
        self
    }

    pub fn num_div(&self) -> NumDiv {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMDIV");
            if s.as_bytes() == b"-1" {
                NumDiv::Auto
            } else {
                NumDiv::Fixed(s.parse().expect("could not convert NUMDIV to an integer"))
            }
        }
    }

    pub fn set_num_div(&self, num: NumDiv) -> &Self {
        match num {
            NumDiv::Fixed(i) => set_str_attribute(self.handle(), "NUMDIV", &i.to_string()),
            NumDiv::Auto => set_str_attribute(self.handle(), "NUMDIV", "AUTO"),
        };
        self
    }

    pub fn num_lin(&self) -> u32 {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMLIN");
            s.parse().expect("could not convert NUMLIN to an integer")
        }
    }

    pub fn num_col(&self) -> u32 {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMCOL");
            s.parse().expect("could not convert NUMLIN to an integer")
        }
    }

    pub fn fit_col_to_children(&self, column: u32) -> &Self {
        set_str_attribute(self.handle(), "FITTOCHILDREN\0", &format!("C{}\0", column));
        self
    }

    pub fn fit_lin_to_children(&self, line: u32) -> &Self {
        set_str_attribute(self.handle(), "FITTOCHILDREN\0", &format!("L{}\0", line));
        self
    }

    pub fn fit_all_to_children(&self) -> &Self {
        for line in 0..self.num_lin() {
            self.fit_lin_to_children(line);
        }
        for column in 0..self.num_col() {
            self.fit_col_to_children(column);
        }
        self
    }
}

impl_control_traits!(GridBox);

impl Container for GridBox {}

impl OrientationAttribute for GridBox {}

#[macro_export]
macro_rules! grid_box {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { GridBox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { grid_box!($($c),*) };
}
<commit_msg>Add getters and setters for the line/column that a GridBox uses for size<commit_after>/* Copyright 2015 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

use std::ptr;
use iup_sys::*;
use super::{Control, UnwrapHandle};
use super::handle_rc::HandleRc;
use super::attributes::{
    OrientationAttribute,
    set_str_attribute,
    get_str_attribute_slice,
};

pub trait Container : Control {
    fn append(&self, new_child: &Control) -> Result<(), ()> {
        unsafe {
            if IupAppend(self.handle(), new_child.handle()) == ptr::null_mut() {
                Err(())
            } else {
                Ok(())
            }
        }
    }

    fn insert(&self, ref_child: Option<&Control>, new_child: &Control) -> Result<(), ()> {
        unsafe {
            let ref_child = ref_child.map(|c| c.handle()).unwrap_or(ptr::null_mut());
            if IupInsert(self.handle(), ref_child, new_child.handle()) == ptr::null_mut() {
                Err(())
            } else {
                Ok(())
            }
        }
    }

    /// Returns the number of children of the specified control.
    ///
    /// Warning: Since children are stored as a linked list, getting the count is O(n).
    fn child_count(&self) -> usize {
        unsafe {
            IupGetChildCount(self.handle()) as usize
        }
    }
}

pub trait NonDialogContainer : Container {
    fn refresh_children(&self) {
        unsafe {
            IupRefreshChildren(self.handle());
        }
    }
}

// Be sure that the Vec is not dropped before the *mut *mut Ihandle is used.
fn wrapper_to_handles(controls: Option<&[&::Control]>)
-> (Option<Vec<*mut Ihandle>>, *mut *mut Ihandle)
{
    let mut controls: Option<Vec<_>> = controls.map(|slice| {
        let mut v: Vec<*mut Ihandle> = slice.iter().map(|c| c.handle()).collect();
        v.push(ptr::null_mut()); // array has to be null terminated
        v
    });
    let p = controls.as_mut().map(|v| v.as_mut_ptr()).unwrap_or(ptr::null_mut());
    (controls, p)
}

#[derive(Clone)]
pub struct Fill(HandleRc);

impl Fill {
    pub fn new() -> Fill {
        unsafe {
            ::iup_open();
            let handle = IupFill();
            Fill(HandleRc::new(handle))
        }
    }
}

impl_control_traits!(Fill);

#[macro_export]
macro_rules! fill { // This is a macro for consistency, even though it could just be a function.
    () => { Fill::new() };
}

#[derive(Clone)]
pub struct Hbox(HandleRc);

impl Hbox {
    pub fn new(children: Option<&[&::Control]>) -> Hbox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            Hbox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> Hbox {
        let handle = IupHboxv(children);
        Hbox(HandleRc::new(handle))
    }
}

impl_control_traits!(Hbox);

impl Container for Hbox {}

#[macro_export]
macro_rules! hbox {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { Hbox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { hbox!($($c),*) };
}

#[derive(Clone)]
pub struct Vbox(HandleRc);

impl Vbox {
    pub fn new(children: Option<&[&::Control]>) -> Vbox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            Vbox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> Vbox {
        let handle = IupVboxv(children);
        Vbox(HandleRc::new(handle))
    }
}

impl_control_traits!(Vbox);

impl Container for Vbox {}

#[macro_export]
macro_rules! vbox {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { Vbox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { vbox!($($c),*) };
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum NumDiv {
    Fixed(u32),
    Auto,
}

#[derive(Clone)]
pub struct GridBox(HandleRc);

impl GridBox {
    pub fn new(children: Option<&[&::Control]>) -> GridBox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            GridBox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> GridBox {
        let handle = IupGridBoxv(children);
        GridBox(HandleRc::new(handle))
    }

    pub fn alignment_lin(&self, line: u32) -> ::VAlignment {
        unsafe {
            let attr = format!("ALIGNMENTLIN{}", line);
            ::VAlignment::from_str(get_str_attribute_slice(self.handle(), &attr).as_bytes())
        }
    }

    pub fn set_alignment_lin(&self, line: u32, alignment: ::VAlignment) -> &Self {
        set_str_attribute(self.handle(), &format!("ALIGNMENTLIN{}", line), alignment.to_str());
        self
    }

    pub fn alignment_lin_all(&self) -> ::VAlignment {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "ALIGNMENTLIN");
            ::VAlignment::from_str(s.as_bytes())
        }
    }

    pub fn set_alignment_lin_all(&self, alignment: ::VAlignment) -> &Self {
        set_str_attribute(self.handle(), "ALIGNMENTLIN", alignment.to_str());
        self
    }

    pub fn alignment_col(&self, column: u32) -> ::HAlignment {
        unsafe {
            let attr = format!("ALIGNMENTCOL{}", column);
            ::HAlignment::from_str(get_str_attribute_slice(self.handle(), &attr).as_bytes())
        }
    }

    pub fn set_alignment_col(&self, column: u32, alignment: ::HAlignment) -> &Self {
        set_str_attribute(self.handle(), &format!("ALIGNMENTCOL{}", column), alignment.to_str());
        self
    }

    pub fn alignment_col_all(&self) -> ::HAlignment {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "ALIGNMENTCOL");
            ::HAlignment::from_str(s.as_bytes())
        }
    }

    pub fn set_alignment_col_all(&self, alignment: ::HAlignment) -> &Self {
        set_str_attribute(self.handle(), "ALIGNMENTCOL", alignment.to_str());
        self
    }

    pub fn num_div(&self) -> NumDiv {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMDIV");
            if s.as_bytes() == b"-1" {
                NumDiv::Auto
            } else {
                NumDiv::Fixed(s.parse().expect("could not convert NUMDIV to an integer"))
            }
        }
    }

    pub fn set_num_div(&self, num: NumDiv) -> &Self {
        match num {
            NumDiv::Fixed(i) => set_str_attribute(self.handle(), "NUMDIV", &i.to_string()),
            NumDiv::Auto => set_str_attribute(self.handle(), "NUMDIV", "AUTO"),
        };
        self
    }

    pub fn num_lin(&self) -> u32 {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMLIN");
            s.parse().expect("could not convert NUMLIN to an integer")
        }
    }

    pub fn num_col(&self) -> u32 {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMCOL");
            s.parse().expect("could not convert NUMLIN to an integer")
        }
    }

    pub fn fit_col_to_children(&self, column: u32) -> &Self {
        set_str_attribute(self.handle(), "FITTOCHILDREN\0", &format!("C{}\0", column));
        self
    }

    pub fn fit_lin_to_children(&self, line: u32) -> &Self {
        set_str_attribute(self.handle(), "FITTOCHILDREN\0", &format!("L{}\0", line));
        self
    }

    pub fn fit_all_to_children(&self) -> &Self {
        for line in 0..self.num_lin() {
            self.fit_lin_to_children(line);
        }
        for column in 0..self.num_col() {
            self.fit_col_to_children(column);
        }
        self
    }

    pub fn size_col(&self) -> u32 {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "SIZECOL\0");
            s.parse().expect("could not convert SIZECOL to an integer")
        }
    }

    pub fn set_size_col(&self, column: u32) -> &Self {
        set_str_attribute(self.handle(), "SIZECOL\0", &format!("{}\0", column));
        self
    }

    pub fn size_lin(&self) -> u32 {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "SIZELIN\0");
            s.parse().expect("could not convert SIZELIN to an integer")
        }
    }

    pub fn set_size_lin(&self, line: u32) -> &Self {
        set_str_attribute(self.handle(), "SIZELIN\0", &format!("{}\0", line));
        self
    }
}

impl_control_traits!(GridBox);

impl Container for GridBox {}

impl OrientationAttribute for GridBox {}

#[macro_export]
macro_rules! grid_box {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { GridBox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { grid_box!($($c),*) };
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_must_use, unused_imports, unstable)]

extern crate "rustc-serialize" as rustc_serialize;
extern crate log;

use utils;
use std::fmt;
use std::str;
use std::string;
use std::old_io::{File, Open, Append, Read, ReadWrite};
use std::old_io::TempDir;
use std::old_io::fs;
use std::old_io::fs::PathExtensions;
use std::old_io::{BufferedReader, BufferedWriter};
use std::old_path::BytesContainer;
use self::rustc_serialize::base64::{STANDARD, FromBase64, ToBase64};

/// A result type that's specfici to the Reader module.
/// TODO Decide if this is necessary
pub type ReaderResult<T, E> = Result<T, E>;

/// Reader struct of its basic properties.
pub struct Reader {
    /// Path to file where the Reader is created.
    path: Path,
    /// BufferedReader for reading the file. Initialized with the Path.
    read_buffer: BufferedReader<File>,
    /// BufferedWriter for writing to the file. Initialized with the Path.
    write_buffer: BufferedWriter<File>,
    /// Index counter to know how many records exist.
    id_count: u64,
}

/// ReaderFile traits
pub trait ReaderFile {
    // Opens a new File to the Path provided.
    // Returns a boxed File.
    fn open(&self) -> File;
    // Inserts a string to the database.
    fn insert_string(&mut self, String);
}

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

impl ToString for Reader {
    fn to_string(&self) -> String {
        format!("{:?}", self)
    }
}

impl Reader {
    /// Creates a new Reader from the Path provided.
    /// Opens a new BufferedReader and BufferedWriter (with Append mode) to the file.
    /// If the file doesn't exist, it is created.
    // TODO, create a .lock file to let other readers know the database is in use (see: #2).
    pub fn new(apath: &Path) -> Reader {
        Reader::file_lock_create(apath);
        // if file_lock exists, panic and crash with appropriate error.
        // Error: A .lock file already exists, if this is from a previous session, consider
        // deleting the .lock file.

        if !apath.exists() {
            let mut file = File::create(&apath.clone());
            file.write_line("0");
            file.flush();
        }

        let mut buffer_writer = match File::open_mode(&apath.clone(), Append, ReadWrite) {
                                    Ok(file)    => { BufferedWriter::new(file) },
                                    Err(..)     => { panic!("Failed to create a write buffer to file path: {}",
                                                            apath.display()) },
                                };

        let mut buffer_reader = match File::open_mode(&apath.clone(), Open, Read) {
                                    Ok(file)    => BufferedReader::new(file),
                                    Err(..)     => panic!("Failed to create a read buffer to file path: {}",
                                                            apath.display()),
                                };

        let current_record_count = match buffer_reader.read_line() {
                                                Ok(line)    => {
                                                    let first_line = utils::string_slice(line);
                                                    let input = first_line[0].parse::<u64>();
                                                    match input {
                                                        Ok(num) => num,
                                                        Err(..) => 0,
                                                    }
                                                },
                                                Err(..) => 0,
                                    };

        Reader {
            path: apath.clone(),
            read_buffer: buffer_reader,
            write_buffer: buffer_writer,
            id_count: current_record_count,
        }
    }

    /// This is a helder function that realistically shouldn't exist in production.
    /// Used primarily for "spilling" the entire database file into a Vec<String>
    fn spill(&mut self) -> Vec<String> {
        let mut result: Vec<String> = Vec::new();
        let mut buffer_reader = BufferedReader::new(File::open(&self.path.clone()));
        for line_iter in buffer_reader.lines() {
            result.push(line_iter.unwrap().trim().to_string());
        }
        return result;
    }

    /// Inserts a &str into the database.
    fn insert_str(&mut self, item: &str) {
        self.write_buffer.write_line(item);
        self.write_buffer.flush();
    }

    /// Inserts a byte array into the database.
    fn insert(&mut self, item: &[u8]) {
        self.write_buffer.write(item);
        self.write_buffer.flush();
    }

    /// Read a &str from the database
    fn read_line(&mut self) -> String {
        match self.read_buffer.read_line() {
            Ok(string)  => { string.to_string() },
            Err(..)     => {
                error!("Unable to read next line. BufferedReader error.");
                "".to_string()
            },
        }
    }

    fn file_lock_create(lockpath: &Path) -> (bool, Path) {

        if lockpath.exists() {
            return (true, lockpath.clone())
        }

        let mut filelock_path = lockpath.clone();

        // Remove the old name
        filelock_path.pop();
        // Surely, there's a less ugly way to take the filename of a Path and convert it to a string?!
        let mut filename_lock: String = str::from_utf8(lockpath.filename().unwrap()).unwrap().to_string();
        filename_lock.push_str(".lock");
        // Join the new filename with the path
        filelock_path = filelock_path.join(filename_lock);
        println!("{}", filelock_path.display());
        match File::create(&filelock_path) {
            Ok(..)  => (true, filelock_path),
            Err(..) => (false, filelock_path),
        }
    }

    fn file_lock_remove(&self, filelock: &Path) -> bool {
        fs::unlink(&filelock.clone());
        filelock.exists()
    }

}

impl ReaderFile for Reader {

    fn open(&self) -> File {
        match File::open_mode(&self.path, Open, ReadWrite) {
            Ok(file)    => file,
            Err(..)     => { panic!("File {} couldn't be opened!", &self.path.display()); },
        }
    }

    fn insert_string(&mut self, item: String) {
        self.insert_str(&*item);
    }

}

#[test]
fn test_open_file() {
    let reader = Reader::new(&Path::new("tests/base-test.txt"));
}

#[test]
fn test_create_file() {
    use std::rand;
    let mut path_str = String::from_str("tests/");
    path_str.push_str(&*rand::random::<usize>().to_string());
    path_str.push_str(".txt");

    let (tempdir, apath) = setup();
    let path = tempdir.path().join(rand::random::<usize>().to_string());

    //let path = Path::new(path_str);
    assert!(!path.exists());
    let reader = Reader::new(&path.clone());
    assert!(path.exists());
    fs::unlink(&path);
}

#[test]
fn test_read_file() {
    // We should output the entire contents of the database file we open
    // into standard output.
    let (tempdir, path) = setup();
    let mut reader = Reader::new(&path);
    let expected = vec!["10 11".to_string(), "20 21".to_string()];
    assert_eq!(expected, reader.spill());
}

#[test]
fn test_write_string_to_file() {
    let (tempdir, path) = setup();
    let mut reader = Reader::new(&path);
    let expected = vec!["10 11".to_string(), "20 21".to_string(), "30 31".to_string()];
    reader.insert_string("30 31".to_string());
    assert_eq![expected, reader.spill()];
}

#[test]
fn test_write_str_to_file() {
    let (tempdir, path) = setup();
    let mut reader = Reader::new(&path);
    let expected = vec!["10 11".to_string(), "20 21".to_string(), "30 31".to_string()];
    reader.insert_str("30 31");
    assert_eq![expected, reader.spill()];
}

#[test]
fn test_file_path_lock() {

    let (tempdir, path) = setup();

    let mut expected = path.clone();
    expected.pop();

    // Surely, there's a less ugly way to take the filename of a Path and convert it to a string?!
    let mut filename_lock: String = str::from_utf8(path.filename().unwrap()).unwrap().to_string();
    filename_lock.push_str(".lock");
    expected = expected.join(filename_lock);

    let reader = Reader::new(&expected.clone());
    assert!(expected.exists() && expected.is_file());
}

#[test]
fn test_reader_show() {
    let reader: Reader = Reader::new(&Path::new("./tests/file.txt"));
    assert_eq!("Reader: ( path: tests/file.txt )", reader.to_string());
}

/// Test setup code. Current functions:
/// - Create a new file with `TempDir` and a random name.
/// - Write a 2x2 matrix of records into the base-test.txt file
/// - Returns a tuple of `TempDir` and `Path` to the file.
/// - The path is for r/w access and `TempDir` is so that the directory
///   isn't deleted before the test is completed.
#[allow(dead_code, unused_must_use)]
fn setup() -> (TempDir, Path) {
    use std::rand;

    let tmpdir = match TempDir::new("txtdb-tests") {
        Ok(dir) => dir,
        Err(..) => panic!("Cannot create test directory. Tests will fail."),
    };

    let final_dir = tmpdir.path().join(rand::random::<usize>().to_string());

    let mut file = File::create(&final_dir.clone());
    file.write_str("10 11\n20 21\n");

    (tmpdir, final_dir)
}
<commit_msg>Added a counter update for the database metadata<commit_after>#![allow(dead_code, unused_must_use, unused_imports, unstable)]

extern crate "rustc-serialize" as rustc_serialize;
extern crate log;

use utils;
use std::fmt;
use std::str;
use std::string;
use std::old_io::{File, Open, Append, Read, Write, ReadWrite};
use std::old_io::TempDir;
use std::old_io::fs;
use std::old_io::fs::PathExtensions;
use std::old_io::{BufferedReader, BufferedWriter};
use std::old_path::BytesContainer;
use self::rustc_serialize::base64::{STANDARD, FromBase64, ToBase64};

/// A result type that's specfici to the Reader module.
/// TODO Decide if this is necessary
pub type ReaderResult<T, E> = Result<T, E>;

/// Reader struct of its basic properties.
pub struct Reader {
    /// Path to file where the Reader is created.
    path: Path,
    /// BufferedReader for reading the file. Initialized with the Path.
    read_buffer: BufferedReader<File>,
    /// BufferedWriter for writing to the file. Initialized with the Path.
    write_buffer: BufferedWriter<File>,
    /// Index counter to know how many records exist.
    id_count: u64,
}

/// ReaderFile traits
pub trait ReaderFile {
    // Opens a new File to the Path provided.
    // Returns a boxed File.
    fn open(&self) -> File;
    // Inserts a string to the database.
    fn insert_string(&mut self, String);
}

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

impl ToString for Reader {
    fn to_string(&self) -> String {
        format!("{:?}", self)
    }
}

impl Reader {
    /// Creates a new Reader from the Path provided.
    /// Opens a new BufferedReader and BufferedWriter (with Append mode) to the file.
    /// If the file doesn't exist, it is created.
    // TODO, create a .lock file to let other readers know the database is in use (see: #2).
    pub fn new(apath: &Path) -> Reader {
        Reader::file_lock_create(apath);
        // if file_lock exists, panic and crash with appropriate error.
        // Error: A .lock file already exists, if this is from a previous session, consider
        // deleting the .lock file.

        if !apath.exists() {
            let mut file = File::create(&apath.clone());
            file.write_line("0");
            file.flush();
        }

        let mut buffer_writer = match File::open_mode(&apath.clone(), Append, ReadWrite) {
                                    Ok(file)    => { BufferedWriter::new(file) },
                                    Err(..)     => {
                                        panic!("Failed to create a write buffer to file path: {}",
                                                apath.display())
                                    },
                                };

        let mut buffer_reader = match File::open_mode(&apath.clone(), Open, Read) {
                                    Ok(file)    => BufferedReader::new(file),
                                    Err(..)     => panic!("Failed to create a read buffer to file path: {}",
                                                            apath.display()),
                                };

        let current_record_count = match buffer_reader.read_line() {
                                        Ok(line)    => {
                                            let first_line = utils::string_slice(line);
                                            println!("This is our line read in: {:?}", first_line);
                                            let input = first_line[0].trim().parse::<u64>();
                                            match input {
                                                Ok(num) => num,
                                                Err(..) => {
                                                    println!("We're getting nothing sarge!");
                                                    0},
                                            }
                                        },
                                        Err(..) => {
                                            println!("Can't read a line!");
                                            0
                                        },
                                   };

        Reader {
            path: apath.clone(),
            read_buffer: buffer_reader,
            write_buffer: buffer_writer,
            id_count: current_record_count,
        }
    }

    /// This is a helder function that realistically shouldn't exist in production.
    /// Used primarily for "spilling" the entire database file into a Vec<String>
    fn spill(&mut self) -> Vec<String> {
        let mut result: Vec<String> = Vec::new();
        let mut buffer_reader = BufferedReader::new(File::open(&self.path.clone()));
        for line_iter in buffer_reader.lines() {
            result.push(line_iter.unwrap().trim().to_string());
        }
        return result;
    }

    /// Inserts a &str into the database.
    fn insert_str(&mut self, item: &str) {
        self.write_buffer.write_line(item);
        self.write_buffer.flush();
        self.id_count = self.id_count + 1;
        self.update_counter(self.id_count);
    }

    /// Inserts a byte array into the database.
    fn insert(&mut self, item: &[u8]) {
        self.write_buffer.write(item);
        self.write_buffer.flush();
        self.id_count = self.id_count + 1;
        self.update_counter(self.id_count);
    }

    /// Read a &str from the database
    fn read_line(&mut self) -> String {
        match self.read_buffer.read_line() {
            Ok(string)  => { string.to_string() },
            Err(..)     => {
                error!("Unable to read next line. BufferedReader error.");
                "".to_string()
            },
        }
    }

    fn file_lock_create(lockpath: &Path) -> (bool, Path) {
        if lockpath.exists() {
            return (true, lockpath.clone())
        }

        let mut filelock_path = lockpath.clone();

        // Remove the old name
        filelock_path.pop();
        // Surely, there's a less ugly way to take the filename of a Path and convert it to a string?!
        let mut filename_lock: String = str::from_utf8(lockpath.filename().unwrap()).unwrap().to_string();
        filename_lock.push_str(".lock");
        // Join the new filename with the path
        filelock_path = filelock_path.join(filename_lock);
        println!("{}", filelock_path.display());
        match File::create(&filelock_path) {
            Ok(..)  => (true, filelock_path),
            Err(..) => (false, filelock_path),
        }
    }

    fn file_lock_remove(&self, filelock: &Path) -> bool {
        fs::unlink(&filelock.clone());
        filelock.exists()
    }

    fn update_counter(&self, value: u64) {
        let file = File::open_mode(&self.path.clone(), Open, Write);
        let mut buffer_writer = BufferedWriter::new(file);
        buffer_writer.write_line(value.to_string().as_slice());
        buffer_writer.flush();
    }

}

impl ReaderFile for Reader {

    fn open(&self) -> File {
        match File::open_mode(&self.path, Open, ReadWrite) {
            Ok(file)    => file,
            Err(..)     => { panic!("File {} couldn't be opened!", &self.path.display()); },
        }
    }

    fn insert_string(&mut self, item: String) {
        self.insert_str(&*item);
    }

}

#[test]
fn test_open_file() {
    let reader = Reader::new(&Path::new("tests/base-test.txt"));
}

#[test]
fn test_create_file() {
    use std::rand;
    let mut path_str = String::from_str("tests/");
    path_str.push_str(&*rand::random::<usize>().to_string());
    path_str.push_str(".txt");

    let (tempdir, apath) = setup();
    let path = tempdir.path().join(rand::random::<usize>().to_string());

    //let path = Path::new(path_str);
    assert!(!path.exists());
    let reader = Reader::new(&path.clone());
    assert!(path.exists());
    fs::unlink(&path);
}

#[test]
fn test_read_file() {
    // We should output the entire contents of the database file we open
    // into standard output.
    let (tempdir, path) = setup();
    let mut reader = Reader::new(&path);
    let expected = vec!["10 11".to_string(), "20 21".to_string()];
    assert_eq!(expected, reader.spill());
}

#[test]
fn test_write_string_to_file() {
    let (tempdir, path) = setup();
    let mut reader = Reader::new(&path);
    let expected = vec!["10 11".to_string(), "20 21".to_string(), "30 31".to_string()];
    reader.insert_string("30 31".to_string());
    assert_eq![expected, reader.spill()];
}

#[test]
fn test_write_str_to_file() {
    let (tempdir, path) = setup();
    let mut reader = Reader::new(&path);
    let expected = vec!["10 11".to_string(), "20 21".to_string(), "30 31".to_string()];
    reader.insert_str("30 31");
    assert_eq![expected, reader.spill()];
}

#[test]
fn test_file_path_lock() {

    let (tempdir, path) = setup();

    let mut expected = path.clone();
    expected.pop();

    // Surely, there's a less ugly way to take the filename of a Path and convert it to a string?!
    let mut filename_lock: String = str::from_utf8(path.filename().unwrap()).unwrap().to_string();
    filename_lock.push_str(".lock");
    expected = expected.join(filename_lock);

    let reader = Reader::new(&expected.clone());
    assert!(expected.exists() && expected.is_file());
}

#[test]
fn test_reader_show() {
    let reader: Reader = Reader::new(&Path::new("./tests/file.txt"));
    assert_eq!("Reader: ( path: tests/file.txt )", reader.to_string());
}

/// Test setup code. Current functions:
/// - Create a new file with `TempDir` and a random name.
/// - Write a 2x2 matrix of records into the base-test.txt file
/// - Returns a tuple of `TempDir` and `Path` to the file.
/// - The path is for r/w access and `TempDir` is so that the directory
///   isn't deleted before the test is completed.
#[allow(dead_code, unused_must_use)]
fn setup() -> (TempDir, Path) {
    use std::rand;

    let tmpdir = match TempDir::new("txtdb-tests") {
        Ok(dir) => dir,
        Err(..) => panic!("Cannot create test directory. Tests will fail."),
    };

    let final_dir = tmpdir.path().join(rand::random::<usize>().to_string());

    let mut file = File::create(&final_dir.clone());
    file.write_str("10 11\n20 21\n");

    (tmpdir, final_dir)
}
<|endoftext|>


<commit_before>static START_ADDR: u16 = 0x200;
static MEM_SIZE: uint = 4096;
pub static DISPLAY_WIDTH: uint = 64;
pub static DISPLAY_HEIGHT: uint = 32;

static fontset: [[u8, .. 5], .. 0x10] = [
    [0xF0, 0x90, 0x90, 0x90, 0xF0], // 0
    [0x20, 0x60, 0x20, 0x20, 0x70], // 1
    [0xF0, 0x10, 0xF0, 0x80, 0xF0], // 2
    [0xF0, 0x10, 0xF0, 0x10, 0xF0], // 3
    [0x90, 0x90, 0xF0, 0x10, 0x10], // 4
    [0xF0, 0x80, 0xF0, 0x10, 0xF0], // 5
    [0xF0, 0x80, 0xF0, 0x90, 0xF0], // 6
    [0xF0, 0x10, 0x20, 0x40, 0x40], // 7
    [0xF0, 0x90, 0xF0, 0x90, 0xF0], // 8
    [0xF0, 0x90, 0xF0, 0x10, 0xF0], // 9
    [0xF0, 0x90, 0xF0, 0x90, 0x90], // A
    [0xE0, 0x90, 0xE0, 0x90, 0xE0], // B
    [0xF0, 0x80, 0x80, 0x80, 0xF0], // C
    [0xE0, 0x90, 0x90, 0x90, 0xE0], // D
    [0xF0, 0x80, 0xF0, 0x80, 0xF0], // E
    [0xF0, 0x80, 0xF0, 0x80, 0x80], // F
];

pub struct Chip8 {
    ram: [u8, .. MEM_SIZE],
    v: [u8, .. 16],
    i: u16,
    delay_timer: u8,
    sound_timer: u8,
    pc: u16,
    sp: u8,
    stack: [u16, .. 16],
    display: [u8, .. DISPLAY_WIDTH * DISPLAY_HEIGHT]
}

impl Chip8 {
    pub fn new() -> Chip8 {
        Chip8 {
            ram: [0u8, .. MEM_SIZE],
            v: [0u8, .. 16],
            i: 0u16,
            delay_timer: 0u8,
            sound_timer: 0u8,
            pc: START_ADDR,
            sp: 0,
            stack: [0u16, .. 16],
            display: [0u8, .. DISPLAY_WIDTH * DISPLAY_HEIGHT]
        }
    }

    pub fn load_rom(&mut self, rom: &[u8]) {
        use std::slice::bytes::copy_memory;
        let len = self.ram.len();
        copy_memory(self.ram.mut_slice(START_ADDR as uint, len), rom);
    }

    pub fn get_display(&self) -> [u8, .. DISPLAY_WIDTH * DISPLAY_HEIGHT] {
        self.display
    }

    pub fn do_cycle(&mut self) {
        let ins = self.get_ins();

        match ins & 0xF000 {
            0x1000 => self.jump_addr(ins & 0x0FFF),
            0x3000 => self.skip_next_vx_eq(((ins & 0x0F00) << 8) as uint, (ins & 0x00FF) as u8),
            0x7000 => self.add_vx_byte(((ins & 0x0F00) << 8) as uint, (ins & 0x00FF) as u8),
            0xA000 => self.set_i(ins & 0x0FFF),
            0xC000 => self.set_vx_rand_and(((ins & 0x0F00) << 8) as uint, (ins & 0x00FF) as u8),
            0xD000 => self.display_sprite(((ins & 0x0F00) << 8) as uint, ((ins & 0x00F0) << 8) as uint, ((ins & 0x000F) << 8) as uint),
            _ => fail!("Unkown instruction: {:x}", ins)
        }

        self.pc += 2;
    }

    fn get_ins(&self) -> u16 {
        let b1 = self.ram[self.pc as uint];
        let b2 = self.ram[(self.pc + 1) as uint];
        b1 as u16 << 8 | b2 as u16
    }

    fn set_i(&mut self, to: u16) {
        self.i = to;
    }

    fn set_vx_rand_and(&mut self, x: uint, to: u8) {
        use std::rand::{task_rng, Rng};
        let mut rgen = task_rng();
        self.v[x] = rgen.gen::<u8>() & to;
    }

    fn skip_next_vx_eq(&mut self, x: uint, to: u8) {
        if self.v[x] == to {
            self.pc += 2;
        }
    }

    fn display_sprite(&mut self, x: uint, y: uint, n: uint) {
        let bytes = self.ram.slice(self.i as uint, self.i as uint + n);
        let start = y * DISPLAY_WIDTH + x;
        let mut i = 0;

        for b in bytes.iter() {
            let before = self.display[start + i];
            self.display[start + i] ^= *b;

            if before != 0 && self.display[start + i] == 0 {
                self.v[0xf] = 1;
            } else {
                self.v[0xf] = 0;
            }

            i += 1;
        }
    }

    fn add_vx_byte(&mut self, x: uint, byte: u8) {
        self.v[x] = byte;
    }

    fn jump_addr(&mut self, addr: u16) {
        self.pc = addr;
    }
}
<commit_msg>Correctly bitshift arguments<commit_after>static START_ADDR: u16 = 0x200;
static MEM_SIZE: uint = 4096;
pub static DISPLAY_WIDTH: uint = 64;
pub static DISPLAY_HEIGHT: uint = 32;

static fontset: [[u8, .. 5], .. 0x10] = [
    [0xF0, 0x90, 0x90, 0x90, 0xF0], // 0
    [0x20, 0x60, 0x20, 0x20, 0x70], // 1
    [0xF0, 0x10, 0xF0, 0x80, 0xF0], // 2
    [0xF0, 0x10, 0xF0, 0x10, 0xF0], // 3
    [0x90, 0x90, 0xF0, 0x10, 0x10], // 4
    [0xF0, 0x80, 0xF0, 0x10, 0xF0], // 5
    [0xF0, 0x80, 0xF0, 0x90, 0xF0], // 6
    [0xF0, 0x10, 0x20, 0x40, 0x40], // 7
    [0xF0, 0x90, 0xF0, 0x90, 0xF0], // 8
    [0xF0, 0x90, 0xF0, 0x10, 0xF0], // 9
    [0xF0, 0x90, 0xF0, 0x90, 0x90], // A
    [0xE0, 0x90, 0xE0, 0x90, 0xE0], // B
    [0xF0, 0x80, 0x80, 0x80, 0xF0], // C
    [0xE0, 0x90, 0x90, 0x90, 0xE0], // D
    [0xF0, 0x80, 0xF0, 0x80, 0xF0], // E
    [0xF0, 0x80, 0xF0, 0x80, 0x80], // F
];

pub struct Chip8 {
    ram: [u8, .. MEM_SIZE],
    v: [u8, .. 16],
    i: u16,
    delay_timer: u8,
    sound_timer: u8,
    pc: u16,
    sp: u8,
    stack: [u16, .. 16],
    display: [u8, .. DISPLAY_WIDTH * DISPLAY_HEIGHT]
}

impl Chip8 {
    pub fn new() -> Chip8 {
        Chip8 {
            ram: [0u8, .. MEM_SIZE],
            v: [0u8, .. 16],
            i: 0u16,
            delay_timer: 0u8,
            sound_timer: 0u8,
            pc: START_ADDR,
            sp: 0,
            stack: [0u16, .. 16],
            display: [0u8, .. DISPLAY_WIDTH * DISPLAY_HEIGHT]
        }
    }

    pub fn load_rom(&mut self, rom: &[u8]) {
        use std::slice::bytes::copy_memory;
        let len = self.ram.len();
        copy_memory(self.ram.mut_slice(START_ADDR as uint, len), rom);
    }

    pub fn get_display(&self) -> [u8, .. DISPLAY_WIDTH * DISPLAY_HEIGHT] {
        self.display
    }

    pub fn do_cycle(&mut self) {
        let ins = self.get_ins();

        match ins & 0xF000 {
            0x1000 => self.jump_addr(ins & 0x0FFF),
            0x3000 => self.skip_next_vx_eq(((ins & 0x0F00) >> 8) as uint, (ins & 0x00FF) as u8),
            0x7000 => self.add_vx_byte(((ins & 0x0F00) >> 8) as uint, (ins & 0x00FF) as u8),
            0xA000 => self.set_i(ins & 0x0FFF),
            0xC000 => self.set_vx_rand_and(((ins & 0x0F00) >> 8) as uint, (ins & 0x00FF) as u8),
            0xD000 => self.display_sprite(((ins & 0x0F00) >> 8) as uint, ((ins & 0x00F0) >> 4) as uint, ((ins & 0x000F)) as uint),
            _ => fail!("Unkown instruction: {:x}", ins)
        }

        self.pc += 2;
    }

    fn get_ins(&self) -> u16 {
        let b1 = self.ram[self.pc as uint];
        let b2 = self.ram[(self.pc + 1) as uint];
        b1 as u16 << 8 | b2 as u16
    }

    fn set_i(&mut self, to: u16) {
        self.i = to;
    }

    fn set_vx_rand_and(&mut self, x: uint, to: u8) {
        use std::rand::{task_rng, Rng};
        let mut rgen = task_rng();
        self.v[x] = rgen.gen::<u8>() & to;
    }

    fn skip_next_vx_eq(&mut self, x: uint, to: u8) {
        if self.v[x] == to {
            self.pc += 2;
        }
    }

    fn display_sprite(&mut self, x: uint, y: uint, n: uint) {
        let bytes = self.ram.slice(self.i as uint, self.i as uint + n);
        let start = y * DISPLAY_WIDTH + x;
        let mut i = 0;

        for b in bytes.iter() {
            let before = self.display[start + i];
            self.display[start + i] ^= *b;

            if before != 0 && self.display[start + i] == 0 {
                self.v[0xf] = 1;
            } else {
                self.v[0xf] = 0;
            }

            i += 1;
        }
    }

    fn add_vx_byte(&mut self, x: uint, byte: u8) {
        self.v[x] = byte;
    }

    fn jump_addr(&mut self, addr: u16) {
        self.pc = addr;
    }
}
<|endoftext|>


<commit_before>use super::{LzfResult, LzfError};
use std::ptr;
use std::mem;

/// Decompress the given data, if possible.
/// The return value will be set to the error if compression fails.
///
/// The length of the output buffer can be specified.
/// If the output buffer is not large enough to hold the decompressed data,
/// BufferTooSmall is returned.
/// Otherwise the number of decompressed bytes
/// (i.e. the original length of the data) is returned.
///
/// If an error in the compressed data is detected, DataCorrupted is returned.
///
/// Example:
///
/// ```rust,no_run
/// let data = "[your-compressed-data]";
/// let decompressed = lzf::decompress(data.as_bytes(), 10);
/// ```
pub fn decompress(data: &[u8], out_len_should: usize) -> LzfResult<Vec<u8>> {
    let mut current_offset = 0;

    // We have sanity checks to not exceed this capacity.
    let mut output = Vec::with_capacity(out_len_should);
    unsafe { output.set_len(out_len_should) };
    let mut out_len: usize = 0;

    let in_len = data.len();

    while current_offset < in_len {
        let mut ctrl = data[current_offset] as usize;
        current_offset += 1;

        if ctrl < (1 << 5) {
            ctrl += 1;

            if out_len + ctrl > out_len_should {
                return Err(LzfError::BufferTooSmall);
            }

            if current_offset + ctrl > in_len {
                return Err(LzfError::DataCorrupted);
            }

            // We can simply memcpy everything from the input to the output
            unsafe {
                let (src, _): (*const u8, usize) = mem::transmute(&data[..]);
                let src = src.offset(current_offset as isize);
                let (dst, _): (*mut u8, usize) = mem::transmute(&output[..]);
                let dst = dst.offset((out_len) as isize);
                ptr::copy_nonoverlapping(src, dst, ctrl);

                current_offset += ctrl;
                out_len += ctrl;
            }
        } else {
            let mut len = ctrl >> 5;

            let mut ref_offset = (((ctrl & 0x1f) << 8) + 1) as i32;

            if len == 7 {
                len += data[current_offset] as usize;
                current_offset += 1;

                if current_offset >= in_len {
                    return Err(LzfError::DataCorrupted);
                }
            }

            ref_offset += data[current_offset] as i32;
            current_offset += 1;

            if out_len + len + 2 > out_len_should {
                return Err(LzfError::BufferTooSmall);
            }

            let mut ref_pos = (out_len as i32) - ref_offset;
            if ref_pos < 0 {
                return Err(LzfError::DataCorrupted);
            }

            let c = output[ref_pos as usize];
            output[out_len] = c;
            out_len += 1;
            ref_pos += 1;

            let c = output[ref_pos as usize];
            output[out_len] = c;
            out_len += 1;
            ref_pos += 1;

            while len > 0 {
                let c = output[ref_pos as usize];
                output[out_len] = c;
                out_len += 1;
                ref_pos += 1;
                len -= 1;
            }
        }
    }

    // Set the real length now, user might have passed a bigger buffer in the first place.
    unsafe { output.set_len(out_len) };

    Ok(output)
}

#[test]
fn test_decompress_lorem() {
    use super::compress;

    let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod \
                 tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At \
                 vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, \
                 no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit \
                 amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut \
                 labore et dolore magna aliquyam erat, sed diam voluptua.";

    let compressed = compress(lorem.as_bytes()).unwrap();

    let decompressed = decompress(&compressed[..], lorem.len()).unwrap();
    assert_eq!(lorem.as_bytes(), &decompressed[..]);

    let decompressed = decompress(&compressed[..], 1000).unwrap();
    assert_eq!(lorem.len(), decompressed.len());
}

#[test]
fn test_decompress_fails_with_short_buffer() {
    use super::compress;

    let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod \
                 tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At \
                 vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, \
                 no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit \
                 amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut \
                 labore et dolore magna aliquyam erat, sed diam voluptua.";

    let compressed = match compress(lorem.as_bytes()) {
        Ok(c) => c,
        Err(err) => panic!("Compression failed with error {:?}", err),
    };

    match decompress(&compressed, 10) {
        Ok(_) => panic!("Decompression worked. That should not happen"),
        Err(err) => assert_eq!(LzfError::BufferTooSmall, err),
    }
}

#[test]
fn test_decompress_fails_for_corrupted_data() {
    let lorem = "Lorem ipsum dolor sit amet";

    match decompress(lorem.as_bytes(), lorem.len()) {
        Ok(_) => panic!("Decompression worked. That should not happen"),
        Err(err) => assert_eq!(LzfError::DataCorrupted, err),
    }
}

#[test]
fn test_alice_wonderland() {
    use super::compress;

    let alice = "\r\n\r\n\r\n\r\n                ALICE'S ADVENTURES IN WONDERLAND\r\n";

    let compressed = match compress(alice.as_bytes()) {
        Ok(c) => c,
        Err(err) => panic!("Compression failed with error {:?}", err),
    };

    match decompress(&compressed, alice.len()) {
        Ok(decompressed) => {
            assert_eq!(alice.len(), decompressed.len());
            assert_eq!(alice.as_bytes(), &decompressed[..]);
        }
        Err(err) => panic!("Decompression failed with error {:?}", err),
    }
}
#[test]
fn easily_compressible() {
    // RDB regression
    let data = vec![1, 97, 97, 224, 187, 0, 1, 97, 97];
    let real_length = 200;

    let text = decompress(&data, real_length).unwrap();
    assert_eq!(200, text.len());
    assert_eq!(97, text[0]);
    assert_eq!(97, text[199]);
}
<commit_msg>docs: Nicer description message<commit_after>use super::{LzfResult, LzfError};
use std::ptr;
use std::mem;

/// Decompress the given data, if possible.
/// An error will be returned if decompression fails.
///
/// The length of the output buffer can be specified.
/// If the output buffer is not large enough to hold the decompressed data,
/// BufferTooSmall is returned.
/// Otherwise the number of decompressed bytes
/// (i.e. the original length of the data) is returned.
///
/// If an error in the compressed data is detected, DataCorrupted is returned.
///
/// Example:
///
/// ```rust,no_run
/// let data = "[your-compressed-data]";
/// let decompressed = lzf::decompress(data.as_bytes(), 10);
/// ```
pub fn decompress(data: &[u8], out_len_should: usize) -> LzfResult<Vec<u8>> {
    let mut current_offset = 0;

    // We have sanity checks to not exceed this capacity.
    let mut output = Vec::with_capacity(out_len_should);
    unsafe { output.set_len(out_len_should) };
    let mut out_len: usize = 0;

    let in_len = data.len();

    while current_offset < in_len {
        let mut ctrl = data[current_offset] as usize;
        current_offset += 1;

        if ctrl < (1 << 5) {
            ctrl += 1;

            if out_len + ctrl > out_len_should {
                return Err(LzfError::BufferTooSmall);
            }

            if current_offset + ctrl > in_len {
                return Err(LzfError::DataCorrupted);
            }

            // We can simply memcpy everything from the input to the output
            unsafe {
                let (src, _): (*const u8, usize) = mem::transmute(&data[..]);
                let src = src.offset(current_offset as isize);
                let (dst, _): (*mut u8, usize) = mem::transmute(&output[..]);
                let dst = dst.offset((out_len) as isize);
                ptr::copy_nonoverlapping(src, dst, ctrl);

                current_offset += ctrl;
                out_len += ctrl;
            }
        } else {
            let mut len = ctrl >> 5;

            let mut ref_offset = (((ctrl & 0x1f) << 8) + 1) as i32;

            if len == 7 {
                len += data[current_offset] as usize;
                current_offset += 1;

                if current_offset >= in_len {
                    return Err(LzfError::DataCorrupted);
                }
            }

            ref_offset += data[current_offset] as i32;
            current_offset += 1;

            if out_len + len + 2 > out_len_should {
                return Err(LzfError::BufferTooSmall);
            }

            let mut ref_pos = (out_len as i32) - ref_offset;
            if ref_pos < 0 {
                return Err(LzfError::DataCorrupted);
            }

            let c = output[ref_pos as usize];
            output[out_len] = c;
            out_len += 1;
            ref_pos += 1;

            let c = output[ref_pos as usize];
            output[out_len] = c;
            out_len += 1;
            ref_pos += 1;

            while len > 0 {
                let c = output[ref_pos as usize];
                output[out_len] = c;
                out_len += 1;
                ref_pos += 1;
                len -= 1;
            }
        }
    }

    // Set the real length now, user might have passed a bigger buffer in the first place.
    unsafe { output.set_len(out_len) };

    Ok(output)
}

#[test]
fn test_decompress_lorem() {
    use super::compress;

    let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod \
                 tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At \
                 vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, \
                 no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit \
                 amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut \
                 labore et dolore magna aliquyam erat, sed diam voluptua.";

    let compressed = compress(lorem.as_bytes()).unwrap();

    let decompressed = decompress(&compressed[..], lorem.len()).unwrap();
    assert_eq!(lorem.as_bytes(), &decompressed[..]);

    let decompressed = decompress(&compressed[..], 1000).unwrap();
    assert_eq!(lorem.len(), decompressed.len());
}

#[test]
fn test_decompress_fails_with_short_buffer() {
    use super::compress;

    let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod \
                 tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At \
                 vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, \
                 no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit \
                 amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut \
                 labore et dolore magna aliquyam erat, sed diam voluptua.";

    let compressed = match compress(lorem.as_bytes()) {
        Ok(c) => c,
        Err(err) => panic!("Compression failed with error {:?}", err),
    };

    match decompress(&compressed, 10) {
        Ok(_) => panic!("Decompression worked. That should not happen"),
        Err(err) => assert_eq!(LzfError::BufferTooSmall, err),
    }
}

#[test]
fn test_decompress_fails_for_corrupted_data() {
    let lorem = "Lorem ipsum dolor sit amet";

    match decompress(lorem.as_bytes(), lorem.len()) {
        Ok(_) => panic!("Decompression worked. That should not happen"),
        Err(err) => assert_eq!(LzfError::DataCorrupted, err),
    }
}

#[test]
fn test_alice_wonderland() {
    use super::compress;

    let alice = "\r\n\r\n\r\n\r\n                ALICE'S ADVENTURES IN WONDERLAND\r\n";

    let compressed = match compress(alice.as_bytes()) {
        Ok(c) => c,
        Err(err) => panic!("Compression failed with error {:?}", err),
    };

    match decompress(&compressed, alice.len()) {
        Ok(decompressed) => {
            assert_eq!(alice.len(), decompressed.len());
            assert_eq!(alice.as_bytes(), &decompressed[..]);
        }
        Err(err) => panic!("Decompression failed with error {:?}", err),
    }
}
#[test]
fn easily_compressible() {
    // RDB regression
    let data = vec![1, 97, 97, 224, 187, 0, 1, 97, 97];
    let real_length = 200;

    let text = decompress(&data, real_length).unwrap();
    assert_eq!(200, text.len());
    assert_eq!(97, text[0]);
    assert_eq!(97, text[199]);
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Read;

use templatewrapper::TemplateWrapper;

pub struct LiquidTemplate {
    template: String,
}

impl TemplateWrapper for LiquidTemplate {
    fn new(template_file: String) -> LiquidTemplate {

        let mut template = String::new();
        File::open(template_file).unwrap().read_to_string(&mut template);

        LiquidTemplate {
            template: template,
        }
    }
}
<commit_msg>Add Renderable to Liquid Wrapper<commit_after>extern crate liquid;

use std::fs::File;
use std::io::Read;

use templatewrapper::TemplateWrapper;

pub struct LiquidTemplate {
    template: String,
}

impl TemplateWrapper for LiquidTemplate {
    fn new(template_file: String) -> LiquidTemplate {

        let mut template = String::new();
        File::open(template_file).unwrap().read_to_string(&mut template);

        LiquidTemplate {
            template: template,
        }
    }
}

impl liquid::Renderable for LiquidTemplate {
    fn render(&self, context: &mut liquid::Context) -> Option<String> {
        let mut options : liquid::LiquidOptions = Default::default();
        let parsed = liquid::parse(&self.template, &mut options).unwrap();
        parsed.render(context)
    }
}

<|endoftext|>


<commit_before>use std::convert::TryFrom;
use std::fs::File;
use std::io;
use std::os::windows::fs::FileExt;

use super::{LogOffset, Result};

fn seek_read_exact<F: FileExt>(
    file: &mut F,
    mut buf: &mut [u8],
    mut offset: u64,
) -> Result<()> {
    while !buf.is_empty() {
        match file.seek_read(buf, offset) {
            Ok(0) => break,
            Ok(n) => {
                let tmp = buf;
                buf = &mut tmp[n..];
                offset += n as u64;
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(io::Error::new(
            io::ErrorKind::UnexpectedEof,
            "failed to fill whole buffer",
        ))
    } else {
        Ok(())
    }
}

fn seek_write_all<F: FileExt>(
    file: &mut F,
    mut buf: &[u8],
    mut offset: u64,
) -> Result<()> {
    while !buf.is_empty() {
        match file.seek_write(buf, offset) {
            Ok(0) => {
                return Err(io::Error::new(
                    io::ErrorKind::WriteZero,
                    "failed to write whole buffer",
                ));
            }
            Ok(n) => {
                buf = &buf[n..];
                offset += n as u64;
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(())
}

pub(crate) fn pread_exact_or_eof(
    file: &File,
    mut buf: &mut [u8],
    offset: LogOffset,
) -> Result<usize> {
    let mut total = 0_usize;
    while !buf.is_empty() {
        match file.seek_read(buf, offset + u64::try_from(total).unwrap()) {
            Ok(0) => break,
            Ok(n) => {
                total += n;
                let tmp = buf;
                buf = &mut tmp[n..];
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(total)
}

pub(crate) fn pread_exact(
    file: &File,
    buf: &mut [u8],
    offset: LogOffset,
) -> Result<()> {
    let mut f = file.try_clone()?;
    seek_read_exact(&mut f, buf, offset)
}

pub(crate) fn pwrite_all(
    file: &File,
    buf: &[u8],
    offset: LogOffset,
) -> Result<()> {
    let mut f = file.try_clone()?;
    seek_write_all(&mut f, buf, offset)
}
<commit_msg>Address some windows breakage<commit_after>use std::convert::TryFrom;
use std::fs::File;
use std::io;
use std::os::windows::fs::FileExt;

use super::{LogOffset, Result};

fn seek_read_exact<F: FileExt>(
    file: &mut F,
    mut buf: &mut [u8],
    mut offset: u64,
) -> Result<()> {
    while !buf.is_empty() {
        match file.seek_read(buf, offset) {
            Ok(0) => break,
            Ok(n) => {
                let tmp = buf;
                buf = &mut tmp[n..];
                offset += n as u64;
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e.into()),
        }
    }
    if !buf.is_empty() {
        Err(io::Error::new(
            io::ErrorKind::UnexpectedEof,
            "failed to fill whole buffer",
        )
        .into())
    } else {
        Ok(())
    }
}

fn seek_write_all<F: FileExt>(
    file: &mut F,
    mut buf: &[u8],
    mut offset: u64,
) -> Result<()> {
    while !buf.is_empty() {
        match file.seek_write(buf, offset) {
            Ok(0) => {
                return Err(io::Error::new(
                    io::ErrorKind::WriteZero,
                    "failed to write whole buffer",
                )
                .into());
            }
            Ok(n) => {
                buf = &buf[n..];
                offset += n as u64;
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e.into()),
        }
    }
    Ok(())
}

pub(crate) fn pread_exact_or_eof(
    file: &File,
    mut buf: &mut [u8],
    offset: LogOffset,
) -> Result<usize> {
    let mut total = 0_usize;
    while !buf.is_empty() {
        match file.seek_read(buf, offset + u64::try_from(total).unwrap()) {
            Ok(0) => break,
            Ok(n) => {
                total += n;
                let tmp = buf;
                buf = &mut tmp[n..];
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e.into()),
        }
    }
    Ok(total)
}

pub(crate) fn pread_exact(
    file: &File,
    buf: &mut [u8],
    offset: LogOffset,
) -> Result<()> {
    let mut f = file.try_clone()?;
    seek_read_exact(&mut f, buf, offset).map_err(From::from)
}

pub(crate) fn pwrite_all(
    file: &File,
    buf: &[u8],
    offset: LogOffset,
) -> Result<()> {
    let mut f = file.try_clone()?;
    seek_write_all(&mut f, buf, offset).map_err(From::from)
}
<|endoftext|>